Sync to upstream

This commit is contained in:
ds22x 2021-03-12 22:12:30 +01:00
commit 0a8c563cfb
243 changed files with 29870 additions and 31960 deletions

206
.cirrus.yml Normal file
View File

@ -0,0 +1,206 @@
# vim: sts=2 sw=2 ai
################################################################################
# snes9x
################################################################################
snes9x_linux-gtk-amd64_task:
container:
image: gcc:latest
setup_script:
- git submodule update --init --recursive
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install meson gettext libsdl2-dev libgtkmm-3.0-dev libgtk-3-dev libminizip-dev portaudio19-dev glslang-dev
compile_script:
- meson build gtk --buildtype=release --strip
- ninja -j2 -C build
package_script:
- mkdir snes9x
- cp -ar build/snes9x-gtk README.md LICENSE docs data gtk/AUTHORS snes9x/
- tar -caf "snes9x-gtk-${CIRRUS_CHANGE_IN_REPO}.txz" snes9x
build_artifacts:
path: "snes9x-gtk-${CIRRUS_CHANGE_IN_REPO}.txz"
snes9x_linux-x11-amd64_task:
container:
image: gcc:latest
setup_script:
- apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install libxv-dev libxinerama-dev
compile_script:
- cd unix
- touch configure
- ./configure
- make -j2
package_script:
- mkdir snes9x
- cp -ar unix/snes9x unix/docs unix/snes9x.conf.default README.md LICENSE data snes9x/
- tar -caf "snes9x-x11-${CIRRUS_CHANGE_IN_REPO}.txz" snes9x
build_artifacts:
path: "snes9x-x11-${CIRRUS_CHANGE_IN_REPO}.txz"
snes9x_freebsd-x11-amd64_task:
freebsd_instance:
image: freebsd-12-1-release-amd64
setup_script:
- pkg install -y gmake pkgconf minizip libX11 libXext
compile_script:
- cd unix
- touch configure
- ./configure
- gmake -j2
package_script:
- mkdir snes9x
- cp -a unix/snes9x unix/docs unix/snes9x.conf.default README.md LICENSE data snes9x/
- tar -caf "snes9x-x11-${CIRRUS_CHANGE_IN_REPO}.txz" snes9x
build_artifacts:
path: "snes9x-x11-${CIRRUS_CHANGE_IN_REPO}.txz"
snes9x_macOS-amd64_task:
osx_instance:
image: mojave-xcode
compile_script:
- xcodebuild -project macosx/snes9x.xcodeproj -target Snes9x -configuration Release build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO
package_script:
- mkdir snes9x
- cp -R macosx/build/Release/Snes9x.app macosx/docs README.md LICENSE snes9x/
- zip -r "snes9x-${CIRRUS_CHANGE_IN_REPO}.zip" snes9x
build_artifacts:
path: "snes9x-${CIRRUS_CHANGE_IN_REPO}.zip"
################################################################################
# libretro
################################################################################
libretro_linux-amd64_task:
container:
image: gcc:latest
compile_script:
- make -j2 -C libretro
build_artifacts:
path: "libretro/snes9x_libretro.so"
libretro_linux-i386_task:
container:
image: dockcross/linux-x86
compile_script:
- make -j2 -C libretro
build_artifacts:
path: "libretro/snes9x_libretro.so"
libretro_linux-armhf_task:
container:
image: dockcross/linux-armv7
compile_script:
- make -j2 -C libretro
build_artifacts:
path: "libretro/snes9x_libretro.so"
libretro_linux-armv7-neon-hf_task:
container:
image: dockcross/linux-armv7
compile_script:
- make -j2 -C libretro platform=unix-armv7-neon-hardfloat
build_artifacts:
path: "libretro/snes9x_libretro.so"
libretro_linux-arm64_task:
container:
image: dockcross/linux-arm64
compile_script:
- make -j2 -C libretro
build_artifacts:
path: "libretro/snes9x_libretro.so"
libretro_android-arm_task:
container:
image: dockcross/android-arm
compile_script:
- make -j2 -C libretro platform=unix
build_artifacts:
path: "libretro/snes9x_libretro.so"
libretro_android-arm64_task:
container:
image: dockcross/android-arm64
compile_script:
- make -j2 -C libretro platform=unix-arm64
build_artifacts:
path: "libretro/snes9x_libretro.so"
libretro_emscripten_task:
container:
image: gcc:latest
compile_script:
- make -j2 -C libretro platform=emscripten
build_artifacts:
path: "libretro/snes9x_libretro_emscripten.bc"
libretro_macOS-amd64_task:
osx_instance:
image: mojave-xcode
compile_script:
- make -j2 -C libretro
build_artifacts:
path: "libretro/snes9x_libretro.dylib"
libretro_nintendo-wii_task:
container:
image: devkitpro/devkitppc
compile_script:
- make -j2 -C libretro platform=wii
build_artifacts:
path: "libretro/snes9x_libretro_wii.a"
libretro_nintendo-switch-libnx_task:
container:
image: devkitpro/devkita64
compile_script:
- make -j2 -C libretro platform=libnx
build_artifacts:
path: "libretro/snes9x_libretro_libnx.a"
libretro_nintendo-ngc_task:
container:
image: devkitpro/devkitppc
compile_script:
- make -j2 -C libretro platform=ngc
build_artifacts:
path: "libretro/snes9x_libretro_ngc.a"
libretro_playstation-psp_task:
container:
image: bkcsoft/psptoolchain
compile_script:
- make -j2 -C libretro platform=unix
build_artifacts:
path: "libretro/snes9x_libretro.so"

8
.gitignore vendored
View File

@ -495,3 +495,11 @@ healthchecksdb
MigrationBackup/
# End of https://www.gitignore.io/api/c,c++,xcode,visualstudio
# vim
*.swp
# OS X temporary files
.DS_Store
*.lock
profile

4
.gitmodules vendored
View File

@ -10,6 +10,6 @@
[submodule "shaders/SPIRV-Cross"]
path = shaders/SPIRV-Cross
url = https://github.com/KhronosGroup/SPIRV-Cross.git
[submodule "win32/glslang/src"]
path = win32/glslang/src
[submodule "shaders/glslang"]
path = shaders/glslang
url = https://github.com/KhronosGroup/glslang.git

View File

@ -4,3 +4,58 @@
This is the official source code repository for the Snes9x project.
Please check the [Wiki](https://github.com/snes9xgit/snes9x/wiki) for additional information.
## Nightly builds
Download nightly builds from continuous integration:
### snes9x
| OS | status |
|---------------|--------------------------------------------------|
| Windows | [![Status][s9x-win-all]][appveyor] |
| Linux (GTK) | [![Status][snes9x_linux-gtk-amd64]][cirrus-ci] |
| Linux (X11) | [![Status][snes9x_linux-x11-amd64]][cirrus-ci] |
| FreeBSD (X11) | [![Status][snes9x_freebsd-x11-amd64]][cirrus-ci] |
| macOS | [![Status][snes9x_macOS-amd64]][cirrus-ci] |
[appveyor]: https://ci.appveyor.com/project/snes9x/snes9x
[cirrus-ci]: http://cirrus-ci.com/github/snes9xgit/snes9x
[s9x-win-all]: https://ci.appveyor.com/api/projects/status/github/snes9xgit/snes9x?branch=master&svg=true
[snes9x_linux-gtk-amd64]: https://api.cirrus-ci.com/github/snes9xgit/snes9x.svg?task=snes9x_linux-gtk-amd64
[snes9x_linux-x11-amd64]: https://api.cirrus-ci.com/github/snes9xgit/snes9x.svg?task=snes9x_linux-x11-amd64
[snes9x_freebsd-x11-amd64]: https://api.cirrus-ci.com/github/snes9xgit/snes9x.svg?task=snes9x_freebsd-x11-amd64
[snes9x_macOS-amd64]: https://api.cirrus-ci.com/github/snes9xgit/snes9x.svg?task=snes9x_macOS-amd64
### libretro core
| OS | status |
|---------------------|---------------------------------------------------------|
| Linux/amd64 | [![Status][libretro_linux-amd64]][cirrus-ci] |
| Linux/i386 | [![Status][libretro_linux-i386]][cirrus-ci] |
| Linux/armhf | [![Status][libretro_linux-armhf]][cirrus-ci] |
| Linux/armv7-neon-hf | [![Status][libretro_linux-armv7-neon-hf]][cirrus-ci] |
| Linux/arm64 | [![Status][libretro_linux-arm64]][cirrus-ci] |
| Android/arm | [![Status][libretro_android-arm]][cirrus-ci] |
| Android/arm64 | [![Status][libretro_android-arm64]][cirrus-ci] |
| Emscripten | [![Status][libretro_emscripten]][cirrus-ci] |
| macOS/amd64 | [![Status][libretro_macOS-amd64]][cirrus-ci] |
| Nintendo Wii | [![Status][libretro_nintendo-wii]][cirrus-ci] |
| Nintendo Switch | [![Status][libretro_nintendo-switch-libnx]][cirrus-ci] |
| Nintendo GameCube | [![Status][libretro_nintendo-ngc]][cirrus-ci] |
| PSP | [![Status][libretro_playstation-psp]][cirrus-ci] |
[libretro_linux-amd64]: https://api.cirrus-ci.com/github/snes9xgit/snes9x.svg?task=libretro_linux-amd64
[libretro_linux-i386]: https://api.cirrus-ci.com/github/snes9xgit/snes9x.svg?task=libretro_linux-i386
[libretro_linux-armhf]: https://api.cirrus-ci.com/github/snes9xgit/snes9x.svg?task=libretro_linux-armhf
[libretro_linux-armv7-neon-hf]: https://api.cirrus-ci.com/github/snes9xgit/snes9x.svg?task=libretro_linux-armv7-neon-hf
[libretro_linux-arm64]: https://api.cirrus-ci.com/github/snes9xgit/snes9x.svg?task=libretro_linux-arm64
[libretro_android-arm]: https://api.cirrus-ci.com/github/snes9xgit/snes9x.svg?task=libretro_android-arm
[libretro_android-arm64]: https://api.cirrus-ci.com/github/snes9xgit/snes9x.svg?task=libretro_android-arm64
[libretro_emscripten]: https://api.cirrus-ci.com/github/snes9xgit/snes9x.svg?task=libretro_emscripten
[libretro_macOS-amd64]: https://api.cirrus-ci.com/github/snes9xgit/snes9x.svg?task=libretro_macOS-amd64
[libretro_nintendo-wii]: https://api.cirrus-ci.com/github/snes9xgit/snes9x.svg?task=libretro_nintendo-wii
[libretro_nintendo-switch-libnx]: https://api.cirrus-ci.com/github/snes9xgit/snes9x.svg?task=libretro_nintendo-switch-libnx
[libretro_nintendo-ngc]: https://api.cirrus-ci.com/github/snes9xgit/snes9x.svg?task=libretro_nintendo-ngc
[libretro_playstation-psp]: https://api.cirrus-ci.com/github/snes9xgit/snes9x.svg?task=libretro_playstation-psp

View File

@ -43,8 +43,7 @@ build_script:
- if "%config%"=="libretro Release" msbuild libretro\libretro-win32.vcxproj /t:build /p:Configuration="%config%";Platform="%platform%" /m /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
after_build:
- ps: $env:gitrev = git describe --tags
- ps: $env:my_version = "$env:gitrev"
- ps: $env:my_version = "$env:APPVEYOR_BUILD_VERSION-$($env:APPVEYOR_REPO_COMMIT.substring(0,7))"
- set package_name=snes9x-%my_version%-%arch%
- if exist artifacts rmdir /s /q artifacts
- mkdir artifacts

67
compat.cpp Normal file
View File

@ -0,0 +1,67 @@
#include <cstring>
#include "port.h"
void _splitpath(const char *path, char *drive, char *dir, char *fname, char *ext)
{
char *slash = strrchr((char *)path, SLASH_CHAR);
char *dot = strrchr((char *)path, '.');
*drive = '\0';
if (dot && slash && dot < slash)
{
dot = 0;
}
if (!slash)
{
*dir = '\0';
strcpy(fname, path);
if (dot)
{
fname[dot - path] = '\0';
strcpy(ext, dot + 1);
}
else
{
*ext = '\0';
}
}
else
{
strcpy(dir, path);
dir[slash - path] = '\0';
strcpy(fname, slash + 1);
if (dot)
{
fname[(dot - slash) - 1] = '\0';
strcpy(ext, dot + 1);
}
else
{
*ext = '\0';
}
}
}
void _makepath(char *path, const char *drive, const char *dir, const char *fname, const char *ext)
{
if (dir && *dir)
{
strcpy(path, dir);
strcat(path, "/");
}
else
*path = '\0';
strcat(path, fname);
if (ext && *ext)
{
if (*ext != '.')
strcat(path, ".");
strcat(path, ext);
}
}

View File

@ -452,7 +452,7 @@ void ConfigFile::ClearLines()
}
}
bool ConfigFile::ConfigEntry::section_then_key_less::operator()(const ConfigEntry &a, const ConfigEntry &b) const {
bool ConfigFile::ConfigEntry::section_then_key_less::operator()(const ConfigEntry &a, const ConfigEntry &b) const{
if(curConfigFile && a.section!=b.section){
const int sva = curConfigFile->GetSectionSize(a.section);
const int svb = curConfigFile->GetSectionSize(b.section);

View File

@ -94,15 +94,15 @@ class ConfigFile {
};
struct key_less {
bool operator()(const ConfigEntry &a, const ConfigEntry &b) const {
bool operator()(const ConfigEntry &a, const ConfigEntry &b) const{
if(a.section!=b.section) return a.section<b.section;
return a.key<b.key;
}
};
struct line_less {
bool operator()(const ConfigEntry &a, const ConfigEntry &b) const {
if(a.line==b.line) return (b.val.empty() && !a.val.empty()) || a.key<b.key;
bool operator()(const ConfigEntry &a, const ConfigEntry &b) const{
if(a.line==b.line) return (b.val.empty() && !a.val.empty()) || a.key<b.key;
if(b.line<0) return true;
if(a.line<0) return false;
return a.line<b.line;

View File

@ -2269,11 +2269,9 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
break;
case LoadFreezeFile:
S9xUnfreezeGame(S9xChooseFilename(TRUE));
break;
case SaveFreezeFile:
S9xFreezeGame(S9xChooseFilename(FALSE));
break;
case LoadOopsFile:
@ -2414,15 +2412,15 @@ void S9xApplyCommand (s9xcommand_t cmd, int16 data1, int16 data2)
break;
case BeginRecordingMovie:
if (S9xMovieActive())
S9xMovieStop(FALSE);
S9xMovieCreate(S9xChooseMovieFilename(FALSE), 0xFF, MOVIE_OPT_FROM_RESET, NULL, 0);
// if (S9xMovieActive())
// S9xMovieStop(FALSE);
// S9xMovieCreate(S9xChooseMovieFilename(FALSE), 0xFF, MOVIE_OPT_FROM_RESET, NULL, 0);
break;
case LoadMovie:
if (S9xMovieActive())
S9xMovieStop(FALSE);
S9xMovieOpen(S9xChooseMovieFilename(TRUE), FALSE);
// if (S9xMovieActive())
// S9xMovieStop(FALSE);
// S9xMovieOpen(S9xChooseMovieFilename(TRUE), FALSE);
break;
case EndRecordingMovie:
@ -3515,11 +3513,17 @@ void S9xControlPreSaveState (struct SControlSnapshot *s)
for (int k = 0; k < 2; k++)
COPY(mp5[j].pads[k]);
assert(i == sizeof(s->internal));
#undef COPY
#define COPY(x) { memcpy((char *) s->internal_macs + i, &(x), sizeof(x)); i += sizeof(x); }
i = 0;
COPY(macsrifle.x);
COPY(macsrifle.y);
COPY(macsrifle.buttons);
assert(i == sizeof(s->internal) + sizeof(s->internal_macs));
assert(i == sizeof(s->internal_macs));
#undef COPY
@ -3594,11 +3598,15 @@ void S9xControlPostLoadState (struct SControlSnapshot *s)
if (s->ver > 3)
{
#undef COPY
#define COPY(x) { memcpy(&(x), (char *) s->internal_macs + i, sizeof(x)); i += sizeof(x); }
i = 0;
COPY(macsrifle.x);
COPY(macsrifle.y);
COPY(macsrifle.buttons);
assert(i == sizeof(s->internal) + sizeof(s->internal_macs));
assert(i == sizeof(s->internal_macs));
}
#undef COPY

View File

@ -40,7 +40,6 @@ void S9xInitDisplay (int, char **);
void S9xDeinitDisplay (void);
void S9xTextMode (void);
void S9xGraphicsMode (void);
void S9xSetPalette (void);
void S9xToggleSoundChannel (int);
bool8 S9xOpenSnapshotFile (const char *, bool8, STREAM *);
void S9xCloseSnapshotFile (STREAM);
@ -48,7 +47,6 @@ const char * S9xStringInput (const char *);
const char * S9xGetDirectory (enum s9x_getdirtype);
const char * S9xGetFilename (const char *, enum s9x_getdirtype);
const char * S9xGetFilenameInc (const char *, enum s9x_getdirtype);
const char * S9xChooseFilename (bool8);
const char * S9xBasename (const char *);
// Routines the port has to implement if it uses command-line

View File

@ -298,14 +298,6 @@
<p>
Called when Snes9x wants to know the directory <code>dirtype</code>.
</p>
<h3><code>const char *S9xChooseFilename (bool8 read_only)</code></h3>
<p>
If your port can match Snes9x's built-in <code>LoadFreezeFile</code>/<code>SaveFreezeFile</code> command (see <code>controls.cpp</code>), you may choose to use this function. Otherwise return <code>NULL</code>.
</p>
<h3><code>const char *S9xChooseMovieFilename (bool8 read_only)</code></h3>
<p>
If your port can match Snes9x's built-in <code>BeginRecordingMovie</code>/<code>LoadMovie</code> command (see <code>controls.cpp</code>), you may choose to use this function. Otherwise return <code>NULL</code>.
</p>
<h3><code>const char *S9xBasename (const char *path)</code></h3>
<p>
Called when Snes9x wants to know the name of the ROM image. Typically, extract the filename from <code>path</code> and return it.
@ -318,10 +310,6 @@
<p>
If your port can match Snes9x's built-in <code>SoundChannelXXX</code> command (see <code>controls.cpp</code>), you may choose to use this function. Otherwise return <code>NULL</code>. Basically, turn on/off the sound channel <code>c</code> (0-7), and turn on all channels if <code>c</code> is 8.
</p>
<h3><code>void S9xSetPalette (void)</code></h3>
<p>
Called when the SNES color palette has changed. Use this function if your system needs to change its color palette to match the SNES's. Otherwise, leave it empty.
</p>
<h3><code>void S9xSyncSpeed (void)</code></h3>
<p>
Called at the end of <code>S9xMainLoop</code> function, when emulating one frame has been done. You should adjust the frame rate in this function.

View File

@ -221,7 +221,6 @@ void S9xEndScreenRefresh (void)
{
uint32 saved = PPU.CGDATA[0];
IPPU.ColorsChanged = FALSE;
S9xSetPalette();
PPU.CGDATA[0] = saved;
}
@ -796,7 +795,7 @@ static void DrawOBJS (int D)
BG.InterlaceLine = GFX.InterlaceFrame ? 8 : 0;
GFX.Z1 = 2;
int sprite_limit = (Settings.MaxSpriteTilesPerLine == 128) ? 128 : 32;
for (uint32 Y = GFX.StartY, Offset = Y * GFX.PPL; Y <= GFX.EndY; Y++, Offset += GFX.PPL)
{
int I = 0;

1
gfx.h
View File

@ -216,7 +216,6 @@ bool8 S9xInitUpdate (void);
bool8 S9xDeinitUpdate (int, int);
bool8 S9xContinueUpdate (int, int);
void S9xReRefresh (void);
void S9xSetPalette (void);
void S9xSyncSpeed (void);
// called instead of S9xDisplayString if set to non-NULL

BIN
gtk/data/mini_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -1,13 +1,15 @@
project('snes9x-gtk',
['c', 'cpp'],
version: '1.60',
default_options: ['cpp_std=c++11'])
meson_version: '>=0.46.0',
default_options: ['cpp_std=c++17'])
args = ['-DSNES9X_GTK', '-DUNZIP_SUPPORT', '-DNETPLAY_SUPPORT', '-DJMA_SUPPORT', '-Wall', '-W', '-Wno-unused-parameter']
srcs = []
deps = []
includes = ['../apu/bapu', '../', 'src']
warns = []
libs = []
prefix = get_option('prefix')
localedir = join_paths(prefix, get_option('localedir'))
@ -23,12 +25,9 @@ args += [ '-DDATADIR="' + appdatadir + '"', '-DSNES9XLOCALEDIR="' + localedir +
subdir('data')
subdir('po')
glib_dep = dependency('glib-2.0', version: '> 2.28')
gthread_dep = dependency('gthread-2.0', version: '>= 2.6')
gobject_dep = dependency('gobject-2.0', version: '>= 2.6')
sdl2_dep = dependency('sdl2')
deps += [ glib_dep, gthread_dep, gobject_dep, sdl2_dep ]
deps += sdl2_dep
c_compiler = meson.get_compiler('c')
@ -36,18 +35,12 @@ if c_compiler.version().version_compare('>=7.0.0') and c_compiler.get_id() == 'g
args += '-Wno-format-truncation'
endif
if get_option('gtk3') and not get_option('gtk2')
message('Building with GTK+-3.0')
gtk_dep = dependency('gtk+-3.0', version: '>= 3.22')
gtk_ver = 3
else
message('Building with GTK+-2.0')
gtk_dep = dependency('gtk+-2.0', version: '>= 2.16')
gtk_ver = 2
endif
gtk_dep = dependency('gtkmm-3.0', version: '>= 3.22')
deps += gtk_dep
gthread_dep = dependency('gthread-2.0')
deps += gthread_dep
x11_dep = c_compiler.find_library('X11')
xext_dep = c_compiler.find_library('Xext')
dl_dep = c_compiler.find_library('dl')
@ -62,7 +55,7 @@ opengl = get_option('opengl')
if opengl
opengl_dep = dependency('epoxy', required: false)
if opengl_dep.found()
if opengl_dep.found()
args += '-DUSE_OPENGL'
srcs += [ 'src/gtk_display_driver_opengl.cpp',
'src/gtk_display_driver_opengl.h',
@ -79,52 +72,101 @@ if opengl
endif
slang = get_option('slang')
if slang and opengl
spirv_cross_hpp = join_paths(meson.source_root(), '../shaders/SPIRV-Cross/spirv_cross.hpp')
if not meson.get_compiler('cpp').compiles('#include "' + spirv_cross_hpp + '"')
slang = false
warns += 'Slang support needs the SPIRV-Cross directory in ../shaders'
warns += 'It can be downloaded with:'
warns += ' git submodule init ../shaders/SPIRV-Cross'
warns += ' git submodule update ../shaders/SPIRV-Cross'
endif
endif
glslang_args = ['-w', '-fno-exceptions', '-DNV_EXTENSIONS', '-DAMD_EXTENSIONS', '-DGLSLANG_OSINCLUDE_UNIX', '-DENABLE_OPT=0']
if slang and opengl
glslang_dep = c_compiler.find_library('glslang', required: false)
spirv_dep = c_compiler.find_library('SPIRV', required: false)
osdependent_dep = c_compiler.find_library('OSDependent', required: false)
ogl_compiler_dep = c_compiler.find_library('OGLCompiler', required: false)
spv_remapper_dep = c_compiler.find_library('SPVRemapper', required: false)
OSDependent_src = ['../shaders/glslang/glslang/OSDependent/Unix/ossource.cpp']
OSDependent_lib = static_library('OSDependent',
OSDependent_src,
include_directories: include_directories('../shaders/glslang'),
cpp_args: glslang_args)
libs += OSDependent_lib
if glslang_dep.found() and spirv_dep.found() and osdependent_dep.found() and ogl_compiler_dep.found() and spv_remapper_dep.found()
deps += [glslang_dep, spirv_dep, osdependent_dep, ogl_compiler_dep, spv_remapper_dep]
glslang_src = [
'../shaders/glslang/glslang/MachineIndependent/glslang_tab.cpp',
'../shaders/glslang/glslang/MachineIndependent/attribute.cpp',
'../shaders/glslang/glslang/MachineIndependent/Constant.cpp',
'../shaders/glslang/glslang/MachineIndependent/iomapper.cpp',
'../shaders/glslang/glslang/MachineIndependent/InfoSink.cpp',
'../shaders/glslang/glslang/MachineIndependent/Initialize.cpp',
'../shaders/glslang/glslang/MachineIndependent/IntermTraverse.cpp',
'../shaders/glslang/glslang/MachineIndependent/Intermediate.cpp',
'../shaders/glslang/glslang/MachineIndependent/ParseContextBase.cpp',
'../shaders/glslang/glslang/MachineIndependent/ParseHelper.cpp',
'../shaders/glslang/glslang/MachineIndependent/PoolAlloc.cpp',
'../shaders/glslang/glslang/MachineIndependent/RemoveTree.cpp',
'../shaders/glslang/glslang/MachineIndependent/Scan.cpp',
'../shaders/glslang/glslang/MachineIndependent/ShaderLang.cpp',
'../shaders/glslang/glslang/MachineIndependent/SymbolTable.cpp',
'../shaders/glslang/glslang/MachineIndependent/Versions.cpp',
'../shaders/glslang/glslang/MachineIndependent/intermOut.cpp',
'../shaders/glslang/glslang/MachineIndependent/limits.cpp',
'../shaders/glslang/glslang/MachineIndependent/linkValidate.cpp',
'../shaders/glslang/glslang/MachineIndependent/parseConst.cpp',
'../shaders/glslang/glslang/MachineIndependent/reflection.cpp',
'../shaders/glslang/glslang/MachineIndependent/preprocessor/Pp.cpp',
'../shaders/glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp',
'../shaders/glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp',
'../shaders/glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp',
'../shaders/glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp',
'../shaders/glslang/glslang/MachineIndependent/propagateNoContraction.cpp',
'../shaders/glslang/glslang/GenericCodeGen/CodeGen.cpp',
'../shaders/glslang/glslang/GenericCodeGen/Link.cpp',
'../shaders/glslang/StandAlone/ResourceLimits.cpp'
]
args += ['-DUSE_SLANG', '-DSPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS']
srcs += ['../shaders/slang.cpp']
srcs += ['../shaders/SPIRV-Cross/spirv_cfg.cpp',
'../shaders/SPIRV-Cross/spirv_cfg.hpp',
'../shaders/SPIRV-Cross/spirv_common.hpp',
'../shaders/SPIRV-Cross/spirv_cross.cpp',
'../shaders/SPIRV-Cross/spirv_cross.hpp',
'../shaders/SPIRV-Cross/spirv_glsl.cpp',
'../shaders/SPIRV-Cross/spirv_glsl.hpp',
'../shaders/SPIRV-Cross/spirv_cross_parsed_ir.cpp',
'../shaders/SPIRV-Cross/spirv_cross_parsed_ir.hpp',
'../shaders/SPIRV-Cross/spirv_parser.cpp',
'../shaders/SPIRV-Cross/spirv_parser.hpp',
'../shaders/SPIRV-Cross/spirv.hpp']
else
slang = false
warns += 'glslang libraries not found. Slang shaders will be disabled.'
endif
glslang_lib = static_library('glslang',
glslang_src,
include_directories: include_directories('../shaders/glslang'),
cpp_args: glslang_args)
libs += glslang_lib
OGLCompilersDLL_src = ['../shaders/glslang/OGLCompilersDLL/InitializeDll.cpp']
OGLCompilersDLL_lib = static_library('OGLCompilersDLL',
OGLCompilersDLL_src,
include_directories: include_directories('../shaders/glslang'),
cpp_args: glslang_args)
libs += OGLCompilersDLL_lib
SPIRV_src = [
'../shaders/glslang/SPIRV/GlslangToSpv.cpp',
'../shaders/glslang/SPIRV/InReadableOrder.cpp',
'../shaders/glslang/SPIRV/Logger.cpp',
'../shaders/glslang/SPIRV/SpvBuilder.cpp',
'../shaders/glslang/SPIRV/SpvPostProcess.cpp',
'../shaders/glslang/SPIRV/SpvTools.cpp',
'../shaders/glslang/SPIRV/disassemble.cpp',
'../shaders/glslang/SPIRV/SPVRemapper.cpp',
'../shaders/glslang/SPIRV/doc.cpp'
]
SPIRV_lib = static_library('SPIRV',
SPIRV_src,
include_directories: include_directories('../shaders/glslang'),
cpp_args: glslang_args)
libs += SPIRV_lib
args += ['-DUSE_SLANG',
'-DSPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS']
srcs += ['../shaders/slang.cpp']
srcs += ['../shaders/SPIRV-Cross/spirv_cfg.cpp',
'../shaders/SPIRV-Cross/spirv_cfg.hpp',
'../shaders/SPIRV-Cross/spirv_common.hpp',
'../shaders/SPIRV-Cross/spirv_cross.cpp',
'../shaders/SPIRV-Cross/spirv_cross.hpp',
'../shaders/SPIRV-Cross/spirv_glsl.cpp',
'../shaders/SPIRV-Cross/spirv_glsl.hpp',
'../shaders/SPIRV-Cross/spirv_cross_parsed_ir.cpp',
'../shaders/SPIRV-Cross/spirv_cross_parsed_ir.hpp',
'../shaders/SPIRV-Cross/spirv_parser.cpp',
'../shaders/SPIRV-Cross/spirv_parser.hpp',
'../shaders/SPIRV-Cross/spirv.hpp']
includes += '../shaders/glslang'
endif
wayland = get_option('wayland')
if wayland and gtk_ver == 3
if wayland
wayland_dep = dependency('wayland-egl', required: false)
if wayland_dep.found()
args += '-DUSE_WAYLAND'
srcs += ['src/gtk_wayland_egl_context.cpp', 'src/gtk_wayland_egl_context.h']
@ -138,7 +180,7 @@ endif
xv = get_option('xv')
if xv
xv_dep = dependency('xv', required: false)
if xv_dep.found()
args += '-DUSE_XV'
srcs += ['src/gtk_display_driver_xv.cpp', 'src/gtk_display_driver_xv.h']
@ -152,7 +194,7 @@ endif
portaudio = get_option('portaudio')
if portaudio
portaudio_dep = dependency('portaudio-2.0', version: '>= 10', required: false)
if portaudio_dep.found()
args += '-DUSE_PORTAUDIO'
srcs += ['src/gtk_sound_driver_portaudio.cpp', 'src/gtk_sound_driver_portaudio.h']
@ -177,7 +219,7 @@ endif
alsa = get_option('alsa')
if alsa
alsa_dep = dependency('alsa', required: false)
if alsa_dep.found()
args += '-DUSE_ALSA'
srcs += ['src/gtk_sound_driver_alsa.cpp', 'src/gtk_sound_driver_alsa.h']
@ -191,7 +233,7 @@ endif
pulseaudio = get_option('pulseaudio')
if pulseaudio
pulseaudio_dep = dependency('libpulse', required: false)
if pulseaudio_dep.found()
args += '-DUSE_PULSEAUDIO'
srcs += ['src/gtk_sound_driver_pulse.cpp', 'src/gtk_sound_driver_pulse.h']
@ -225,7 +267,7 @@ else
includes += '../unzip'
srcs += ['../unzip/unzip.c', '../unzip/ioapi.c', '../unzip/zip.c']
endif
zlib = get_option('zlib')
if zlib
zlib_dep = dependency('zlib', required: false)
@ -317,7 +359,7 @@ srcs += [
'../filter/snes_ntsc.h',
'../filter/snes_ntsc_impl.h',
'../filter/snes_ntsc.c',
'src/gtk_2_3_compat.h',
'src/gtk_compat.h',
'src/gtk_sound_driver_sdl.h',
'src/gtk_sound_driver_sdl.cpp',
'../fxinst.cpp',
@ -379,10 +421,13 @@ srcs += [
'../netplay.cpp',
'../server.cpp',
'../loadzip.cpp',
'../compat.cpp',
'src/gtk_netplay_dialog.cpp',
'src/gtk_netplay_dialog.h',
'src/gtk_netplay.cpp',
'src/gtk_netplay.h'
'src/gtk_netplay.h',
'src/background_particles.cpp',
'src/background_particles.h'
]
libjma_srcs = [
@ -397,26 +442,33 @@ libjma_srcs = [
'../jma/winout.cpp'
]
libjma = static_library('jma',
libjma_srcs,
c_args: args,
cpp_args: [args, '-fexceptions'],
libjma = static_library('jma',
libjma_srcs,
c_args: args,
cpp_args: args,
include_directories: include_directories(includes))
libs += libjma
sourcify = executable('sourcify', 'src/sourcify.c', native: true)
gtk_snes9x_ui_cpp = custom_target('sourcify',
input: 'src/snes9x.ui',
gtk_snes9x_ui_cpp = custom_target('sourcify',
input: 'src/snes9x.ui',
output: 'gtk_snes9x_ui.cpp',
command: [sourcify, '@INPUT@', '@OUTPUT@', 'snes9x_ui'])
snes9x_gtk = executable('snes9x-gtk',
srcs,
mini_icon = custom_target('mini_icon',
input: 'data/mini_icon.png',
output: 'mini_icon.cpp',
command: [sourcify, '@INPUT@', '@OUTPUT@', 'mini_icon'])
snes9x_gtk = executable('snes9x-gtk',
srcs,
gtk_snes9x_ui_cpp,
c_args: args,
cpp_args: [args, '-fno-exceptions', '-fno-rtti'],
mini_icon,
c_args: args,
cpp_args: args,
dependencies: deps,
include_directories: include_directories(includes),
link_with: libjma,
link_with: libs,
install: true)
summary = [
@ -426,7 +478,6 @@ summary = [
' appdatadir: ' + appdatadir,
' localedir: ' + localedir,
'[Options] Build type: ' + get_option('buildtype'),
' GTK+ version: ' + gtk_ver.to_string(),
' Wayland: ' + wayland.to_string(),
' OpenGL: ' + opengl.to_string(),
' slang shaders: ' + slang.to_string(),

View File

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

View File

@ -6,3 +6,4 @@ ja
pt_BR
ru
sr@latin
zh_CN

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1836
gtk/po/snes9x-gtk.pot Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1853
gtk/po/zh_CN.po Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,192 @@
#include "background_particles.h"
#include <cstring>
#include <cmath>
#include <cstdio>
#include <random>
static const double pi = 3.141592;
namespace Background
{
Particles::Particles(enum Mode mode)
{
this->mode = Invalid;
setmode(mode);
}
Particles::~Particles()
{
}
void Particles::setmode(enum Mode mode)
{
if (mode == this->mode)
return;
std::random_device device;
mt.seed(device());
output.resize(256 * 224 * 2);
gameimage.resize(256 * 224 * 2);
uint16_t r, g, b;
if (mode == Snow)
{
r = 0; g = 2; b = 6;
}
else
{
r = 0; g = 0; b = 0;
}
for (int i = 0; i < 256 * 224; i++)
{
output[i] = (r << 11) | (g << 6) | (b);
}
particles.clear();
this->mode = mode;
std::uniform_real_distribution<double> real(-0.8, 0.8);
wind = real(mt);
for (int l = 0; l < 32; l++)
{
int mixr = r + (l / 31.0) * (31 - r);
int mixg = g + (l / 31.0) * (31 - g);
int mixb = b + (l / 31.0) * (31 - b);
color_table[l] = (mixr << 11) | (mixg << 6) | mixb;
}
}
void Particles::copyto(uint16_t *dst, int pitch)
{
for (int y = 0; y < 224; y++)
{
memcpy((uint8_t *)dst + y * pitch, &output[y * 256], 512);
}
}
void Particles::set_game_image(uint16_t *src, int pitch)
{
for (int y = 0; y < 224; y++)
memcpy(&gameimage[y * 256], &src[y * pitch / 2], 512);
}
void Particles::advance()
{
if (mode == Snow)
advance_snow();
else
advance_starfield();
}
inline void Particles::setpixel(int x, int y, uint16_t l)
{
output[x + (y << 8)] = color_table[l];
}
void Particles::advance_starfield()
{
rate = 0.5;
std::uniform_real_distribution<double> realrand(0.0, 1.0);
if (realrand(mt) <= rate)
{
Particle pt;
double angle = realrand(mt) * 2 * pi;
pt.dx = cos(angle);
pt.dy = sin(angle) * 0.7;
pt.x = 128.5 + pt.dx * 5.0;
pt.y = 112.5 + pt.dy * 5.0;
pt.intensity = 0;
particles.push_back(pt);
}
for (auto p = particles.begin(); p != particles.end(); p++)
{
setpixel(p->x - 0.5, p->y - 0.5, 0);
setpixel(p->x + 0.5, p->y + 0.5, 0);
setpixel(p->x + 0.5, p->y - 0.5, 0);
setpixel(p->x - 0.5, p->y + 0.5, 0);
p->x += p->dx;
p->y += p->dy;
if ((int)p->x < 1 || (int)p->x > 255 || (int)p->y < 1 || (int)p->y > 223)
{
p = particles.erase(p);
continue;
}
p->intensity = (p->intensity + 1);
if (p->intensity > 63)
p->intensity = 63;
uint16_t lum = p->intensity >> 1;
// primitive bilinear filter effect
double dx = p->x - 0.5;
dx = dx - floor(dx);
double dy = p->y - 0.5;
dy = dy - floor(dy);
uint16_t cul = (1.0 - dx) * (1.0 - dy) * lum;
uint16_t cur = (dx) * (1.0 - dy) * lum;
uint16_t cll = (1.0 - dx) * (dy)*lum;
uint16_t clr = (dx) * (dy)*lum;
setpixel(p->x - 0.5, p->y - 0.5, cul);
setpixel(p->x + 0.5, p->y - 0.5, cur);
setpixel(p->x - 0.5, p->y + 0.5, cll);
setpixel(p->x + 0.5, p->y + 0.5, clr);
}
}
void Particles::advance_snow()
{
rate = 1.0;
std::uniform_real_distribution<double> realrand;
realrand = std::uniform_real_distribution<double>(-0.01, std::nextafter(0.01, 1.0));
wind += realrand(mt);
if (wind < -0.8)
wind = -0.8;
if (wind > 0.8)
wind = 0.8;
for (double new_snowflakes = rate; new_snowflakes >= 1.0; new_snowflakes -= 1.0)
{
Particle pt;
realrand = std::uniform_real_distribution<double>(0.0, 1.0);
pt.x = ((wind + 0.8) / 1.6) * -192.0 + realrand(mt) * 384.0;
pt.y = 0.0;
pt.dx = 0.0;
pt.dy = 0.6 + (realrand(mt) * 0.8);
std::uniform_int_distribution<int> intrand(8, 31);
pt.intensity = intrand(mt);
particles.push_back(pt);
}
for (auto p = particles.begin(); p != particles.end(); p++)
{
if (p->x > 0.0 && p->x < 256.0)
setpixel(p->x, p->y, 0);
p->x += wind;
p->y += p->dy;
if ((int)p->y > 223)
{
p = particles.erase(p);
}
else if (p->x > 0.0 && p->x < 256.0)
setpixel(p->x, p->y, p->intensity);
}
}
} // namespace Background

View File

@ -0,0 +1,54 @@
#ifndef __BACKGROUND_PARTICLES_H
#define __BACKGROUND_PARTICLES_H
#include <vector>
#include <list>
#include <cstdint>
#include <random>
namespace Background
{
class Particles
{
public:
double rate = 0.5;
enum Mode
{
Stars,
Snow,
Invalid
};
struct Particle
{
double x, y, dx, dy;
unsigned int intensity;
};
Particles(enum Mode = Stars);
~Particles();
void advance();
void copyto(uint16_t *dst, int pitch);
enum Mode getmode();
void setmode(enum Mode);
void set_game_image(uint16_t *src, int pitch);
std::vector<uint16_t> output;
private:
inline void setpixel(int x, int y, uint16_t l);
void advance_snow();
void advance_starfield();
std::minstd_rand mt;
std::uniform_real_distribution<double> dis;
std::vector<uint16_t> gameimage;
std::list<Particle> particles;
enum Mode mode;
double wind;
uint16_t color_table[32];
};
} // namespace Background
#endif // __BACKGROUND_PARTICLES_H

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

@ -14,31 +14,35 @@
#include "gtk_sound.h"
#include "gtk_display.h"
#include "conffile.h"
#include "cheats.h"
#include "apu/apu.h"
#include "netplay.h"
#include "controls.h"
static bool directory_exists (std::string str)
static bool directory_exists(std::string str)
{
DIR *dir;
dir = opendir (str.c_str ());
dir = opendir(str.c_str());
if (dir)
{
closedir (dir);
closedir(dir);
return true;
}
return false;
}
std::string get_config_dir ()
std::string get_config_dir()
{
// Find config directory
char *env_home = getenv ("HOME");
char *env_xdg_config_home = getenv ("XDG_CONFIG_HOME");
char *env_home = getenv("HOME");
char *env_xdg_config_home = getenv("XDG_CONFIG_HOME");
if (!env_home && !env_xdg_config_home)
{
return std::string (".snes9x");
return std::string{".snes9x"};
}
std::string config;
@ -51,30 +55,29 @@ std::string get_config_dir ()
(legacy += env_home) += "/.snes9x";
}
else
config = std::string (env_xdg_config_home) + "/snes9x";
config = std::string(env_xdg_config_home) + "/snes9x";
if (directory_exists (legacy) && !directory_exists(config))
if (directory_exists(legacy) && !directory_exists(config))
return legacy;
return config;
}
std::string get_config_file_name ()
std::string get_config_file_name()
{
return get_config_dir () + "/snes9x.conf";
return get_config_dir() + "/snes9x.conf";
}
void S9xParsePortConfig (ConfigFile &conf, int pass)
void S9xParsePortConfig(ConfigFile &conf, int pass)
{
}
Snes9xConfig::Snes9xConfig ()
Snes9xConfig::Snes9xConfig()
{
joystick = NULL;
joystick_threshold = 40;
}
int Snes9xConfig::load_defaults ()
int Snes9xConfig::load_defaults()
{
full_screen_on_open = false;
change_display_resolution = false;
@ -103,12 +106,12 @@ int Snes9xConfig::load_defaults ()
default_esc_behavior = 1;
prevent_screensaver = false;
sound_driver = 0;
sound_buffer_size = 32;
sound_playback_rate = 5;
sound_buffer_size = 48;
sound_playback_rate = 7;
sound_input_rate = 31950;
auto_input_rate = true;
last_directory.clear ();
last_shader_directory.clear ();
last_directory.clear();
last_shader_directory.clear();
window_width = -1;
window_height = -1;
preferences_width = -1;
@ -117,11 +120,11 @@ int Snes9xConfig::load_defaults ()
shader_parameters_height = -1;
enable_icons = true;
current_display_tab = 0;
sram_directory.clear ();
export_directory.clear ();
savestate_directory.clear ();
cheat_directory.clear ();
patch_directory.clear ();
sram_directory.clear();
export_directory.clear();
savestate_directory.clear();
cheat_directory.clear();
patch_directory.clear();
screensaver_needs_reset = false;
ntsc_setup = snes_ntsc_composite;
ntsc_scanline_intensity = 1;
@ -134,12 +137,12 @@ int Snes9xConfig::load_defaults ()
netplay_send_rom = false;
netplay_default_port = 6096;
netplay_max_frame_loss = 10;
netplay_last_rom.clear ();
netplay_last_host.clear ();
netplay_last_rom.clear();
netplay_last_host.clear();
netplay_last_port = 6096;
modal_dialogs = true;
current_save_slot = 0;
S9xCheatsEnable ();
S9xCheatsEnable();
rewind_granularity = 5;
rewind_buffer_size = 0;
@ -149,9 +152,9 @@ int Snes9xConfig::load_defaults ()
sync_to_vblank = true;
use_pbos = true;
pbo_format = 0;
npot_textures = false;
npot_textures = true;
use_shaders = false;
shader_filename.clear ();
shader_filename.clear();
use_glfinish = false;
use_sync_control = false;
#endif
@ -194,447 +197,440 @@ int Snes9xConfig::load_defaults ()
Settings.TwoClockCycles = 12;
#endif
memset (pad, 0, sizeof (JoypadBinding) * NUM_JOYPADS);
memset (shortcut, 0, sizeof (Binding) * NUM_EMU_LINKS);
for (auto &joypad : pad)
{
joypad.data.fill(Binding());
}
shortcut.fill(Binding());
return 0;
}
void Snes9xConfig::joystick_register_centers ()
void Snes9xConfig::joystick_register_centers()
{
for (int i = 0; joystick[i] != NULL; i++)
joystick[i]->register_centers ();
for (auto &j : joystick)
j.register_centers();
}
void Snes9xConfig::flush_joysticks ()
void Snes9xConfig::flush_joysticks()
{
int i;
for (i = 0; joystick[i] != NULL; i++)
joystick[i]->flush ();
for (auto &j : joystick)
j.flush();
}
void Snes9xConfig::set_joystick_mode (int mode)
void Snes9xConfig::set_joystick_mode(int mode)
{
int i;
for (i = 0; joystick[i] != NULL; i++)
joystick[i]->mode = mode;
for (auto &j : joystick)
j.mode = mode;
}
static inline void outbool (ConfigFile &cf, const char *key, bool value, const char *comment = "")
int Snes9xConfig::save_config_file()
{
cf.SetBool (key, value, "true", "false", comment);
}
int Snes9xConfig::save_config_file ()
{
char key[PATH_MAX];
char buffer[PATH_MAX];
ConfigFile cf;
std::string section;
#undef z
#define z "Display::"
outbool (cf, z"FullscreenOnOpen", full_screen_on_open,"Set the screen resolution after opening a ROM");
outbool (cf, z"ChangeDisplayResolution", change_display_resolution, "Set the resolution in fullscreen mode");
cf.SetInt (z"VideoMode", xrr_index, "Platform-specific video mode number");
outbool (cf, z"ScaleToFit", scale_to_fit, "Scale the image to fit the window size");
outbool (cf, z"MaintainAspectRatio", maintain_aspect_ratio, "Resize the screen to the proportions set by aspect ratio option");
cf.SetInt (z"AspectRatio", aspect_ratio, "0: uncorrected, 1: uncorrected integer scale, 2: 4:3, 3: 4/3 integer scale, 4: NTSC/PAL, 5: NTSC/PAL integer scale");
cf.SetInt (z"SoftwareScaleFilter", scale_method, "Build-specific number of filter used for software scaling");
cf.SetInt (z"ScanlineFilterIntensity", scanline_filter_intensity, "0: 0%, 1: 12.5%, 2: 25%, 3: 50%, 4: 100%");
outbool (cf, z"ShowOverscanArea", overscan);
cf.SetInt (z"HiresEffect", hires_effect, "0: Downscale to low-res, 1: Leave as-is, 2: Upscale low-res screens");
cf.SetInt (z"ForceInvertedByteOrder", force_inverted_byte_order);
outbool (cf, z"Multithreading", multithreading, "Apply filters using multiple threads");
cf.SetInt (z"NumberOfThreads", num_threads);
cf.SetInt (z"HardwareAcceleration", hw_accel, "0: None, 1: OpenGL, 2: XVideo");
outbool (cf, z"BilinearFilter", Settings.BilinearFilter, "Smoothes scaled image");
cf.SetInt (z"SplashBackground", splash_image, "0: Black, 1: Color bars, 2: Pattern, 3: Blue, 4: Default");
auto outbool = [&](std::string name, bool b, std::string comment = "") {
cf.SetBool((section + "::" + name).c_str(), b, "true", "false", comment.c_str());
};
#undef z
#define z "NTSC::"
cf.SetString (z"Hue", std::to_string (ntsc_setup.hue));
cf.SetString (z"Saturation", std::to_string (ntsc_setup.saturation));
cf.SetString (z"Contrast", std::to_string (ntsc_setup.contrast));
cf.SetString (z"Brightness", std::to_string (ntsc_setup.brightness));
cf.SetString (z"Sharpness", std::to_string (ntsc_setup.sharpness));
cf.SetString (z"Artifacts", std::to_string (ntsc_setup.artifacts));
cf.SetString (z"Gamma", std::to_string (ntsc_setup.gamma));
cf.SetString (z"Bleed", std::to_string (ntsc_setup.bleed));
cf.SetString (z"Fringing", std::to_string (ntsc_setup.fringing));
cf.SetString (z"Resolution", std::to_string (ntsc_setup.resolution));
outbool (cf, z"MergeFields", ntsc_setup.merge_fields);
cf.SetInt (z"ScanlineIntensity", ntsc_scanline_intensity);
auto outstring = [&](std::string name, std::string str, std::string comment = "") {
cf.SetString((section + "::" + name).c_str(), str, comment.c_str());
};
auto outint = [&](std::string name, int i, std::string comment = "") {
cf.SetInt((section + "::" + name).c_str(), i, comment.c_str());
};
section = "Display";
outbool("FullscreenOnOpen", full_screen_on_open, "Set the screen resolution after opening a ROM");
outbool("ChangeDisplayResolution", change_display_resolution, "Set the resolution in fullscreen mode");
outbool("ScaleToFit", scale_to_fit, "Scale the image to fit the window size");
outbool("ShowOverscanArea", overscan);
outbool("MaintainAspectRatio", maintain_aspect_ratio, "Resize the screen to the proportions set by aspect ratio option");
outbool("Multithreading", multithreading, "Apply filters using multiple threads");
outbool("BilinearFilter", Settings.BilinearFilter, "Smoothes scaled image");
outbool("ForceInvertedByteOrder", force_inverted_byte_order);
outint("VideoMode", xrr_index, "Platform-specific video mode number");
outint("AspectRatio", aspect_ratio, "0: uncorrected, 1: uncorrected integer scale, 2: 4:3, 3: 4/3 integer scale, 4: NTSC/PAL, 5: NTSC/PAL integer scale");
outint("SoftwareScaleFilter", scale_method, "Build-specific number of filter used for software scaling");
outint("ScanlineFilterIntensity", scanline_filter_intensity, "0: 0%, 1: 12.5%, 2: 25%, 3: 50%, 4: 100%");
outint("HiresEffect", hires_effect, "0: Downscale to low-res, 1: Leave as-is, 2: Upscale low-res screens");
outint("NumberOfThreads", num_threads);
outint("HardwareAcceleration", hw_accel, "0: None, 1: OpenGL, 2: XVideo");
outint("SplashBackground", splash_image, "0: Black, 1: Color bars, 2: Pattern, 3: Blue, 4: Default");
section = "NTSC";
outstring("Hue", std::to_string(ntsc_setup.hue));
outstring("Saturation", std::to_string(ntsc_setup.saturation));
outstring("Contrast", std::to_string(ntsc_setup.contrast));
outstring("Brightness", std::to_string(ntsc_setup.brightness));
outstring("Sharpness", std::to_string(ntsc_setup.sharpness));
outstring("Artifacts", std::to_string(ntsc_setup.artifacts));
outstring("Gamma", std::to_string(ntsc_setup.gamma));
outstring("Bleed", std::to_string(ntsc_setup.bleed));
outstring("Fringing", std::to_string(ntsc_setup.fringing));
outstring("Resolution", std::to_string(ntsc_setup.resolution));
outbool("MergeFields", ntsc_setup.merge_fields);
outint("ScanlineIntensity", ntsc_scanline_intensity);
#ifdef USE_OPENGL
#undef z
#define z "OpenGL::"
outbool (cf, z"VSync", sync_to_vblank);
outbool (cf, z"glFinish", use_glfinish);
outbool (cf, z"SyncControl", use_sync_control);
outbool (cf, z"UsePixelBufferObjects", use_pbos);
cf.SetInt (z"PixelBufferObjectBitDepth", pbo_format);
outbool (cf, z"UseNonPowerOfTwoTextures", npot_textures);
outbool (cf, z"EnableCustomShaders", use_shaders);
cf.SetString (z"ShaderFile", shader_filename);
section = "OpenGL";
outbool("VSync", sync_to_vblank);
outbool("glFinish", use_glfinish);
outbool("SyncControl", use_sync_control);
outbool("UseNonPowerOfTwoTextures", npot_textures);
outbool("EnableCustomShaders", use_shaders);
outbool("UsePixelBufferObjects", use_pbos);
outint("PixelBufferObjectBitDepth", pbo_format);
outstring("ShaderFile", shader_filename);
#endif
#undef z
#define z "Sound::"
outbool (cf, z"MuteSound", mute_sound);
outbool (cf, z"MuteSoundDuringTurbo", mute_sound_turbo);
cf.SetInt (z"BufferSize", sound_buffer_size, "Buffer size in milliseconds");
cf.SetInt (z"Driver", sound_driver);
cf.SetInt (z"InputRate", sound_input_rate);
outbool (cf, z"DynamicRateControl", Settings.DynamicRateControl);
cf.SetInt (z"DynamicRateControlLimit", Settings.DynamicRateLimit);
outbool (cf, z"AutomaticInputRate", auto_input_rate, "Guess input rate by asking the monitor what its refresh rate is");
cf.SetInt (z"PlaybackRate", gui_config->sound_playback_rate, "1: 8000Hz, 2: 11025Hz, 3: 16000Hz, 4: 22050Hz, 5: 32000Hz, 6: 44100Hz, 7: 48000Hz");
section = "Sound";
outbool("MuteSound", mute_sound);
outbool("MuteSoundDuringTurbo", mute_sound_turbo);
outint("BufferSize", sound_buffer_size, "Buffer size in milliseconds");
outint("Driver", sound_driver);
outint("InputRate", sound_input_rate);
outbool("DynamicRateControl", Settings.DynamicRateControl);
outint("DynamicRateControlLimit", Settings.DynamicRateLimit);
outbool("AutomaticInputRate", auto_input_rate, "Guess input rate by asking the monitor what its refresh rate is");
outint("PlaybackRate", gui_config->sound_playback_rate, "1: 8000Hz, 2: 11025Hz, 3: 16000Hz, 4: 22050Hz, 5: 32000Hz, 6: 44100Hz, 7: 48000Hz");
#undef z
#define z "Files::"
section = "Files";
outstring("LastDirectory", last_directory);
outstring("LastShaderDirectory", last_shader_directory);
outstring("SRAMDirectory", sram_directory);
outstring("SaveStateDirectory", savestate_directory);
outstring("CheatDirectory", cheat_directory);
outstring("PatchDirectory", patch_directory);
outstring("ExportDirectory", export_directory);
cf.SetString (z"LastDirectory", last_directory);
cf.SetString (z"LastShaderDirectory", last_shader_directory);
cf.SetString (z"SRAMDirectory", sram_directory);
cf.SetString (z"SaveStateDirectory", savestate_directory);
cf.SetString (z"CheatDirectory", cheat_directory);
cf.SetString (z"PatchDirectory", patch_directory);
cf.SetString (z"ExportDirectory", export_directory);
#undef z
#define z "Window State::"
cf.SetInt (z"MainWidth", window_width);
cf.SetInt (z"MainHeight", window_height);
cf.SetInt (z"PreferencesWidth", preferences_width);
cf.SetInt (z"PreferencesHeight", preferences_height);
cf.SetInt (z"ShaderParametersWidth", shader_parameters_width);
cf.SetInt (z"ShaderParametersHeight", shader_parameters_height);
cf.SetInt (z"CurrentDisplayTab", current_display_tab);
outbool (cf, z"UIVisible", ui_visible);
outbool (cf, z"EnableIcons", enable_icons);
section = "Window State";
outint("MainWidth", window_width);
outint("MainHeight", window_height);
outint("PreferencesWidth", preferences_width);
outint("PreferencesHeight", preferences_height);
outint("ShaderParametersWidth", shader_parameters_width);
outint("ShaderParametersHeight", shader_parameters_height);
outint("CurrentDisplayTab", current_display_tab);
outbool("UIVisible", ui_visible);
outbool("EnableIcons", enable_icons);
if (default_esc_behavior != ESC_TOGGLE_MENUBAR)
outbool (cf, z"Fullscreen", 0);
outbool("Fullscreen", 0);
else
outbool (cf, z"Fullscreen", fullscreen);
outbool("Fullscreen", fullscreen);
#undef z
#define z "Netplay::"
outbool (cf, z"ActAsServer", netplay_is_server);
outbool (cf, z"UseResetToSync", netplay_sync_reset);
outbool (cf, z"SendROM", netplay_send_rom);
cf.SetInt (z"DefaultPort", netplay_default_port);
cf.SetInt (z"MaxFrameLoss", netplay_max_frame_loss);
cf.SetInt (z"LastUsedPort", netplay_last_port);
cf.SetString (z"LastUsedROM", netplay_last_rom);
cf.SetString (z"LastUsedHost", netplay_last_host);
section = "Netplay";
outbool("ActAsServer", netplay_is_server);
outbool("UseResetToSync", netplay_sync_reset);
outbool("SendROM", netplay_send_rom);
outint("DefaultPort", netplay_default_port);
outint("MaxFrameLoss", netplay_max_frame_loss);
outint("LastUsedPort", netplay_last_port);
outstring("LastUsedROM", netplay_last_rom);
outstring("LastUsedHost", netplay_last_host);
#undef z
#define z "Behavior::"
outbool (cf, z"PauseEmulationWhenFocusLost", pause_emulation_on_switch);
cf.SetInt (z"DefaultESCKeyBehavior", default_esc_behavior);
outbool (cf, z"PreventScreensaver", prevent_screensaver);
outbool (cf, z"UseModalDialogs", modal_dialogs);
cf.SetInt (z"RewindBufferSize", rewind_buffer_size, "Amount of memory (in MB) to use for rewinding");
cf.SetInt (z"RewindGranularity", rewind_granularity, "Only save rewind snapshots every N frames");
cf.SetInt (z"CurrentSaveSlot", current_save_slot);
section = "Behavior";
outbool("PauseEmulationWhenFocusLost", pause_emulation_on_switch);
outint("DefaultESCKeyBehavior", default_esc_behavior);
outbool("PreventScreensaver", prevent_screensaver);
outbool("UseModalDialogs", modal_dialogs);
outint("RewindBufferSize", rewind_buffer_size, "Amount of memory (in MB) to use for rewinding");
outint("RewindGranularity", rewind_granularity, "Only save rewind snapshots every N frames");
outint("CurrentSaveSlot", current_save_slot);
#undef z
#define z "Emulation::"
outbool (cf, z"EmulateTransparency", Settings.Transparency);
outbool (cf, z"DisplayTime", Settings.DisplayTime);
outbool (cf, z"DisplayFrameRate", Settings.DisplayFrameRate);
outbool (cf, z"DisplayPressedKeys", Settings.DisplayPressedKeys);
cf.SetInt (z"SpeedControlMethod", Settings.SkipFrames, "0: Time the frames to 50 or 60Hz, 1: Same, but skip frames if too slow, 2: Synchronize to the sound buffer, 3: Unlimited, except potentially by vsync");
cf.SetInt (z"SaveSRAMEveryNSeconds", Settings.AutoSaveDelay);
outbool (cf, z"BlockInvalidVRAMAccess", Settings.BlockInvalidVRAMAccessMaster);
outbool (cf, z"AllowDPadContradictions", Settings.UpAndDown, "Allow the D-Pad to press both up + down at the same time, or left + right");
section = "Emulation";
outbool("EmulateTransparency", Settings.Transparency);
outbool("DisplayTime", Settings.DisplayTime);
outbool("DisplayFrameRate", Settings.DisplayFrameRate);
outbool("DisplayPressedKeys", Settings.DisplayPressedKeys);
outint("SpeedControlMethod", Settings.SkipFrames, "0: Time the frames to 50 or 60Hz, 1: Same, but skip frames if too slow, 2: Synchronize to the sound buffer, 3: Unlimited, except potentially by vsync");
outint("SaveSRAMEveryNSeconds", Settings.AutoSaveDelay);
outbool("BlockInvalidVRAMAccess", Settings.BlockInvalidVRAMAccessMaster);
outbool("AllowDPadContradictions", Settings.UpAndDown, "Allow the D-Pad to press both up + down at the same time, or left + right");
#undef z
#define z "Hacks::"
cf.SetInt (z"SuperFXClockMultiplier", Settings.SuperFXClockMultiplier);
cf.SetInt (z"SoundInterpolationMethod", Settings.InterpolationMethod, "0: None, 1: Linear, 2: Gaussian (what the hardware uses), 3: Cubic, 4: Sinc");
outbool (cf, z"RemoveSpriteLimit", Settings.MaxSpriteTilesPerLine == 34 ? 0 : 1);
outbool (cf, z"OverclockCPU", Settings.OneClockCycle == 6 ? 0 : 1);
outbool (cf, z"EchoBufferHack", Settings.SeparateEchoBuffer, "Prevents echo buffer from overwriting APU RAM");
section = "Hacks";
outint("SuperFXClockMultiplier", Settings.SuperFXClockMultiplier);
outint("SoundInterpolationMethod", Settings.InterpolationMethod, "0: None, 1: Linear, 2: Gaussian (what the hardware uses), 3: Cubic, 4: Sinc");
outbool("RemoveSpriteLimit", Settings.MaxSpriteTilesPerLine == 34 ? 0 : 1);
outbool("OverclockCPU", Settings.OneClockCycle == 6 ? 0 : 1);
outbool("EchoBufferHack", Settings.SeparateEchoBuffer, "Prevents echo buffer from overwriting APU RAM");
#undef z
#define z "Input::"
section = "Input";
controllers controller = CTL_NONE;
int8 id[4];
for (int i = 0; i < 2; i++)
{
const char *output_string;
snprintf (buffer, PATH_MAX, z"ControllerPort%d", i);
S9xGetController (i, &controller, &id[0], &id[1], &id[2], &id[3]);
std::string name;
std::string value;
name = "ControllerPort" + std::to_string(i);
S9xGetController(i, &controller, &id[0], &id[1], &id[2], &id[3]);
switch (controller)
{
case CTL_JOYPAD:
output_string = "joypad";
value = "joypad";
break;
case CTL_MOUSE:
output_string = "mouse";
value = "mouse";
break;
case CTL_SUPERSCOPE:
output_string = "superscope";
value = "superscope";
break;
case CTL_MP5:
output_string = "multitap";
value = "multitap";
break;
case CTL_JUSTIFIER:
output_string = "justifier";
value = "justifier";
break;
default:
output_string = "none";
value = "none";
}
cf.SetString (buffer, output_string);
outstring(name, value);
}
cf.SetInt (z"JoystickThreshold", joystick_threshold);
#undef z
outint("JoystickThreshold", joystick_threshold);
for (int i = 0; i < NUM_JOYPADS; i++)
{
Binding *joypad = (Binding *) &pad[i];
auto &joypad = pad[i];
for (int j = 0; j < NUM_JOYPAD_LINKS; j++)
{
snprintf (key, PATH_MAX, "Joypad %d::%s", i, b_links[j].snes9x_name);
joypad[j].to_string (buffer, false);
cf.SetString (key, std::string (buffer));
section = "Joypad " + std::to_string(i);
outstring(b_links[j].snes9x_name, joypad.data[j].as_string());
}
}
section = "Shortcuts";
for (int i = NUM_JOYPAD_LINKS; b_links[i].snes9x_name; i++)
{
snprintf (key, PATH_MAX, "Shortcuts::%s", b_links[i].snes9x_name);
shortcut[i - NUM_JOYPAD_LINKS].to_string (buffer, false);
cf.SetString (key, std::string (buffer));
outstring(b_links[i].snes9x_name, shortcut[i - NUM_JOYPAD_LINKS].as_string());
}
cf.SetNiceAlignment (true);
cf.SetShowComments (true);
cf.SaveTo (get_config_file_name ().c_str ());
cf.SetNiceAlignment(true);
cf.SetShowComments(true);
cf.SaveTo(get_config_file_name().c_str());
return 0;
}
int Snes9xConfig::load_config_file ()
int Snes9xConfig::load_config_file()
{
struct stat file_info;
std::string path;
ConfigFile cf;
char key[PATH_MAX];
ConfigFile cf;
load_defaults ();
load_defaults();
path = get_config_dir ();
std::string path = get_config_dir();
if (stat (path.c_str (), &file_info))
if (stat(path.c_str(), &file_info))
{
if (mkdir (path.c_str (), 0755))
if (mkdir(path.c_str(), 0755))
{
fprintf (stderr,
_("Couldn't create config directory: %s\n"),
path.c_str ());
fprintf(stderr,
_("Couldn't create config directory: %s\n"),
path.c_str());
return -1;
}
}
else
{
if (!(file_info.st_mode & 0700))
chmod (path.c_str (), file_info.st_mode | 0700);
chmod(path.c_str(), file_info.st_mode | 0700);
}
path = get_config_file_name ();
path = get_config_file_name();
if (stat (path.c_str (), &file_info))
if (stat(path.c_str(), &file_info))
{
save_config_file ();
save_config_file();
}
if (!cf.LoadFile (path.c_str ()))
if (!cf.LoadFile(path.c_str()))
return -1;
std::string none;
#define inbool(key, var) { if (cf.Exists (key)) var = cf.GetBool (key); }
#define inint(key, var) { if (cf.Exists(key)) var = cf.GetInt (key); }
#define infloat(key, var) { if (cf.Exists(key)) var = atof (cf.GetString (key, none).c_str()); }
#define instr(key, var) var = cf.GetString (key, none);
std::string section;
#undef z
#define z "Display::"
inbool (z"FullscreenOnOpen", full_screen_on_open);
inbool (z"ChangeDisplayResolution", change_display_resolution);
inint (z"VideoMode", xrr_index);
inbool (z"ScaleToFit", scale_to_fit);
inbool (z"MaintainAspectRatio", maintain_aspect_ratio);
inint (z"AspectRatio", aspect_ratio);
inint (z"SoftwareScaleFilter", scale_method);
inint (z"ScanlineFilterIntensity", scanline_filter_intensity);
inbool (z"ShowOverscanArea", overscan);
inint (z"HiresEffect", hires_effect);
inint (z"ForceInvertedByteOrder", force_inverted_byte_order);
inbool (z"Multithreading", multithreading);
inint (z"NumberOfThreads", num_threads);
inint (z"HardwareAcceleration", hw_accel);
inbool (z"BilinearFilter", Settings.BilinearFilter);
inint (z"SplashBackground", splash_image);
auto inbool = [&](std::string name, auto &b) {
if (cf.Exists((section + "::" + name).c_str()))
b = cf.GetBool((section + "::" + name).c_str());
};
#undef z
#define z "NTSC::"
infloat (z"Hue", ntsc_setup.hue);
infloat (z"Saturation", ntsc_setup.saturation);
infloat (z"Contrast", ntsc_setup.contrast);
infloat (z"Brightness", ntsc_setup.brightness);
infloat (z"Sharpness", ntsc_setup.sharpness);
infloat (z"Artifacts", ntsc_setup.artifacts);
infloat (z"Gamma", ntsc_setup.gamma);
infloat (z"Bleed", ntsc_setup.bleed);
infloat (z"Fringing", ntsc_setup.fringing);
infloat (z"Resolution", ntsc_setup.resolution);
inbool (z"MergeFields", ntsc_setup.merge_fields);
inint (z"ScanlineIntensity", ntsc_scanline_intensity);
auto inint = [&](std::string name, auto &i) {
if (cf.Exists((section + "::" + name).c_str()))
i = cf.GetInt((section + "::" + name).c_str());
};
auto indouble = [&](std::string name, double &d) {
if (cf.Exists((section + "::" + name).c_str()))
d = atof(cf.GetString((section + "::" + name).c_str()));
};
auto instr = [&](std::string name, std::string &str) {
str = cf.GetString((section + "::" + name).c_str(), none);
};
section = "Display";
inbool("FullscreenOnOpen", full_screen_on_open);
inbool("ChangeDisplayResolution", change_display_resolution);
inint("VideoMode", xrr_index);
inbool("ScaleToFit", scale_to_fit);
inbool("MaintainAspectRatio", maintain_aspect_ratio);
inint("AspectRatio", aspect_ratio);
inint("SoftwareScaleFilter", scale_method);
inint("ScanlineFilterIntensity", scanline_filter_intensity);
inbool("ShowOverscanArea", overscan);
inint("HiresEffect", hires_effect);
inbool("ForceInvertedByteOrder", force_inverted_byte_order);
inbool("Multithreading", multithreading);
inint("NumberOfThreads", num_threads);
inint("HardwareAcceleration", hw_accel);
inbool("BilinearFilter", Settings.BilinearFilter);
inint("SplashBackground", splash_image);
section = "NTSC";
indouble("Hue", ntsc_setup.hue);
indouble("Saturation", ntsc_setup.saturation);
indouble("Contrast", ntsc_setup.contrast);
indouble("Brightness", ntsc_setup.brightness);
indouble("Sharpness", ntsc_setup.sharpness);
indouble("Artifacts", ntsc_setup.artifacts);
indouble("Gamma", ntsc_setup.gamma);
indouble("Bleed", ntsc_setup.bleed);
indouble("Fringing", ntsc_setup.fringing);
indouble("Resolution", ntsc_setup.resolution);
inbool("MergeFields", ntsc_setup.merge_fields);
inint("ScanlineIntensity", ntsc_scanline_intensity);
#ifdef USE_OPENGL
#undef z
#define z "OpenGL::"
inbool (z"VSync", sync_to_vblank);
inbool (z"glFinish", use_glfinish);
inbool (z"SyncControl", use_sync_control);
inbool (z"UsePixelBufferObjects", use_pbos);
inint (z"PixelBufferObjectBitDepth", pbo_format);
inbool (z"UseNonPowerOfTwoTextures", npot_textures);
inbool (z"EnableCustomShaders", use_shaders);
instr (z"ShaderFile", shader_filename);
section = "OpenGL";
inbool("VSync", sync_to_vblank);
inbool("glFinish", use_glfinish);
inbool("SyncControl", use_sync_control);
inbool("UsePixelBufferObjects", use_pbos);
inint("PixelBufferObjectBitDepth", pbo_format);
inbool("UseNonPowerOfTwoTextures", npot_textures);
inbool("EnableCustomShaders", use_shaders);
instr("ShaderFile", shader_filename);
#endif
#undef z
#define z "Sound::"
inbool (z"MuteSound", mute_sound);
inbool (z"MuteSoundDuringTurbo", mute_sound_turbo);
inint (z"BufferSize", sound_buffer_size);
inint (z"Driver", sound_driver);
inint (z"InputRate", sound_input_rate);
inbool (z"DynamicRateControl", Settings.DynamicRateControl);
inint (z"DynamicRateControlLimit", Settings.DynamicRateLimit);
inbool (z"AutomaticInputRate", auto_input_rate);
inint (z"PlaybackRate", gui_config->sound_playback_rate);
section = "Sound";
inbool("MuteSound", mute_sound);
inbool("MuteSoundDuringTurbo", mute_sound_turbo);
inint("BufferSize", sound_buffer_size);
inint("Driver", sound_driver);
inint("InputRate", sound_input_rate);
inbool("DynamicRateControl", Settings.DynamicRateControl);
inint("DynamicRateControlLimit", Settings.DynamicRateLimit);
inbool("AutomaticInputRate", auto_input_rate);
inint("PlaybackRate", gui_config->sound_playback_rate);
#undef z
#define z "Files::"
instr (z"LastDirectory", last_directory);
instr (z"LastShaderDirectory", last_shader_directory);
instr (z"SRAMDirectory", sram_directory);
instr (z"SaveStateDirectory", savestate_directory);
instr (z"CheatDirectory", cheat_directory);
instr (z"PatchDirectory", patch_directory);
instr (z"ExportDirectory", export_directory);
section = "Files";
instr("LastDirectory", last_directory);
instr("LastShaderDirectory", last_shader_directory);
instr("SRAMDirectory", sram_directory);
instr("SaveStateDirectory", savestate_directory);
instr("CheatDirectory", cheat_directory);
instr("PatchDirectory", patch_directory);
instr("ExportDirectory", export_directory);
#undef z
#define z "Window State::"
section = "Window State";
inint("MainWidth", window_width);
inint("MainHeight", window_height);
inint("PreferencesWidth", preferences_width);
inint("PreferencesHeight", preferences_height);
inint("ShaderParametersWidth", shader_parameters_width);
inint("ShaderParametersHeight", shader_parameters_height);
inint("CurrentDisplayTab", current_display_tab);
inbool("UIVisible", ui_visible);
inbool("Fullscreen", fullscreen);
inbool("EnableIcons", enable_icons);
inint (z"MainWidth", window_width);
inint (z"MainHeight", window_height);
inint (z"PreferencesWidth", preferences_width);
inint (z"PreferencesHeight", preferences_height);
inint (z"ShaderParametersWidth", shader_parameters_width);
inint (z"ShaderParametersHeight", shader_parameters_height);
inint (z"CurrentDisplayTab", current_display_tab);
inbool (z"UIVisible", ui_visible);
inbool (z"Fullscreen", fullscreen);
inbool (z"EnableIcons", enable_icons);
section = "Netplay";
inbool("ActAsServer", netplay_is_server);
inbool("UseResetToSync", netplay_sync_reset);
inbool("SendROM", netplay_send_rom);
inint("DefaultPort", netplay_default_port);
inint("MaxFrameLoss", netplay_max_frame_loss);
inint("LastUsedPort", netplay_last_port);
instr("LastUsedROM", netplay_last_rom);
instr("LastUsedHost", netplay_last_host);
#undef z
#define z "Netplay::"
inbool (z"ActAsServer", netplay_is_server);
inbool (z"UseResetToSync", netplay_sync_reset);
inbool (z"SendROM", netplay_send_rom);
inint (z"DefaultPort", netplay_default_port);
inint (z"MaxFrameLoss", netplay_max_frame_loss);
inint (z"LastUsedPort", netplay_last_port);
instr (z"LastUsedROM", netplay_last_rom);
instr (z"LastUsedHost", netplay_last_host);
section = "Behavior";
inbool("PauseEmulationWhenFocusLost", pause_emulation_on_switch);
inint("DefaultESCKeyBehavior", default_esc_behavior);
inbool("PreventScreensaver", prevent_screensaver);
inbool("UseModalDialogs", modal_dialogs);
inint("RewindBufferSize", rewind_buffer_size);
inint("RewindGranularity", rewind_granularity);
inint("CurrentSaveSlot", current_save_slot);
#undef z
#define z "Behavior::"
inbool (z"PauseEmulationWhenFocusLost", pause_emulation_on_switch);
inint (z"DefaultESCKeyBehavior", default_esc_behavior);
inbool (z"PreventScreensaver", prevent_screensaver);
inbool (z"UseModalDialogs", modal_dialogs);
inint (z"RewindBufferSize", rewind_buffer_size);
inint (z"RewindGranularity", rewind_granularity);
inint (z"CurrentSaveSlot", current_save_slot);
section = "Emulation";
inbool("EmulateTransparency", Settings.Transparency);
inbool("DisplayTime", Settings.DisplayTime);
inbool("DisplayFrameRate", Settings.DisplayFrameRate);
inbool("DisplayPressedKeys", Settings.DisplayPressedKeys);
inint("SpeedControlMethod", Settings.SkipFrames);
inint("SaveSRAMEveryNSeconds", Settings.AutoSaveDelay);
inbool("BlockInvalidVRAMAccess", Settings.BlockInvalidVRAMAccessMaster);
inbool("AllowDPadContradictions", Settings.UpAndDown);
#undef z
#define z "Emulation::"
inbool (z"EmulateTransparency", Settings.Transparency);
inbool (z"DisplayTime", Settings.DisplayTime);
inbool (z"DisplayFrameRate", Settings.DisplayFrameRate);
inbool (z"DisplayPressedKeys", Settings.DisplayPressedKeys);
inint (z"SpeedControlMethod", Settings.SkipFrames);
inint (z"SaveSRAMEveryNSeconds", Settings.AutoSaveDelay);
inbool (z"BlockInvalidVRAMAccess", Settings.BlockInvalidVRAMAccessMaster);
inbool (z"AllowDPadContradictions", Settings.UpAndDown);
#undef z
#define z "Hacks::"
inint (z"SuperFXClockMultiplier", Settings.SuperFXClockMultiplier);
inint (z"SoundInterpolationMethod", Settings.InterpolationMethod);
section = "Hacks";
inint("SuperFXClockMultiplier", Settings.SuperFXClockMultiplier);
inint("SoundInterpolationMethod", Settings.InterpolationMethod);
bool RemoveSpriteLimit = false;
inbool (z"RemoveSpriteLimit", RemoveSpriteLimit);
inbool("RemoveSpriteLimit", RemoveSpriteLimit);
bool OverclockCPU = false;
inbool (z"OverclockCPU", OverclockCPU);
inbool (z"EchoBufferHack", Settings.SeparateEchoBuffer);
inbool("OverclockCPU", OverclockCPU);
inbool("EchoBufferHack", Settings.SeparateEchoBuffer);
#undef z
#define z "Input::"
section = "Input";
for (int i = 0; i < 2; i++)
{
snprintf (key, PATH_MAX, z"ControllerPort%d", i);
std::string tmp = cf.GetString (key, "");
std::string name = "ControllerPort" + std::to_string(i);
std::string value;
instr(name, value);
if (tmp.find ("joypad") != std::string::npos)
S9xSetController (i, CTL_JOYPAD, i, 0, 0, 0);
else if (tmp.find ("multitap") != std::string::npos)
S9xSetController (i, CTL_MP5, i, i + 1, i + 2, i + 3);
else if (tmp.find ("superscope") != std::string::npos)
S9xSetController (i, CTL_SUPERSCOPE, 0, 0, 0, 0);
else if (tmp.find ("mouse") != std::string::npos)
S9xSetController (i, CTL_MOUSE, i, 0, 0, 0);
else if (tmp.find ("none") != std::string::npos)
S9xSetController (i, CTL_NONE, 0, 0, 0, 0);
if (value.find("joypad") != std::string::npos)
S9xSetController(i, CTL_JOYPAD, i, 0, 0, 0);
else if (value.find("multitap") != std::string::npos)
S9xSetController(i, CTL_MP5, i, i + 1, i + 2, i + 3);
else if (value.find("superscope") != std::string::npos)
S9xSetController(i, CTL_SUPERSCOPE, 0, 0, 0, 0);
else if (value.find("mouse") != std::string::npos)
S9xSetController(i, CTL_MOUSE, i, 0, 0, 0);
else if (value.find("none") != std::string::npos)
S9xSetController(i, CTL_NONE, 0, 0, 0, 0);
}
inint (z"JoystickThreshold", joystick_threshold);
#undef z
inint("JoystickThreshold", joystick_threshold);
std::string buffer;
for (int i = 0; i < NUM_JOYPADS; i++)
{
Binding *joypad = (Binding *) &pad[i];
auto &joypad = pad[i];
section = "Joypad " + std::to_string(i);
for (int j = 0; j < NUM_JOYPAD_LINKS; j++)
{
snprintf (key, PATH_MAX, "Joypad %d::%s", i, b_links[j].snes9x_name);
instr (key, buffer);
joypad[j] = Binding (buffer.c_str ());
instr(b_links[j].snes9x_name, buffer);
joypad.data[j] = Binding(buffer.c_str());
}
}
section = "Shortcuts";
for (int i = NUM_JOYPAD_LINKS; b_links[i].snes9x_name; i++)
{
snprintf (key, PATH_MAX, "Shortcuts::%s", b_links[i].snes9x_name);
instr (key, buffer);
shortcut[i - NUM_JOYPAD_LINKS] = Binding (buffer.c_str ());
instr(b_links[i].snes9x_name, buffer);
shortcut[i - NUM_JOYPAD_LINKS] = Binding(buffer.c_str());
}
/* Validation */
@ -658,13 +654,13 @@ int Snes9xConfig::load_config_file ()
}
#ifndef ALLOW_CPU_OVERCLOCK
Settings.OneClockCycle = 6;
Settings.OneSlowClockCycle = 8;
Settings.TwoClockCycles = 12;
Settings.MaxSpriteTilesPerLine = 34;
Settings.SeparateEchoBuffer = false;
Settings.InterpolationMethod = 2;
Settings.BlockInvalidVRAMAccessMaster = true;
Settings.OneClockCycle = 6;
Settings.OneSlowClockCycle = 8;
Settings.TwoClockCycles = 12;
Settings.MaxSpriteTilesPerLine = 34;
Settings.SeparateEchoBuffer = false;
Settings.InterpolationMethod = 2;
Settings.BlockInvalidVRAMAccessMaster = true;
#endif
if (default_esc_behavior != ESC_TOGGLE_MENUBAR)
@ -696,11 +692,11 @@ int Snes9xConfig::load_config_file ()
else
Settings.SoundSync = false;
hires_effect = CLAMP (hires_effect, 0, 2);
Settings.DynamicRateLimit = CLAMP (Settings.DynamicRateLimit, 1, 1000);
Settings.SuperFXClockMultiplier = CLAMP (Settings.SuperFXClockMultiplier, 50, 400);
ntsc_scanline_intensity = MIN (ntsc_scanline_intensity, 4);
scanline_filter_intensity = MIN (scanline_filter_intensity, 3);
hires_effect = CLAMP(hires_effect, 0, 2);
Settings.DynamicRateLimit = CLAMP(Settings.DynamicRateLimit, 1, 1000);
Settings.SuperFXClockMultiplier = CLAMP(Settings.SuperFXClockMultiplier, 50, 400);
ntsc_scanline_intensity = MIN(ntsc_scanline_intensity, 4);
scanline_filter_intensity = MIN(scanline_filter_intensity, 3);
return 0;
}
@ -714,14 +710,14 @@ void Snes9xConfig::rebind_keys()
for (int joypad_i = 0; joypad_i < NUM_JOYPADS; joypad_i++)
{
Binding *bin = (Binding *)&pad[joypad_i];
auto &bin = pad[joypad_i].data;
for (int button_i = 0; button_i < NUM_JOYPAD_LINKS; button_i++)
{
int dupe;
for (dupe = button_i + 1; dupe < NUM_JOYPAD_LINKS; dupe++)
{
if (bin[button_i].matches(bin[dupe]) && bin[button_i].hex() != 0)
if (bin[button_i] == bin[dupe] && bin[button_i].hex() != 0)
break;
}
if (dupe < NUM_JOYPAD_LINKS || bin[button_i].hex() == 0)
@ -733,7 +729,7 @@ void Snes9xConfig::rebind_keys()
bool ismulti = false;
for (dupe = button_i - 1; dupe > 0; dupe--)
{
if (bin[button_i].matches(bin[dupe]))
if (bin[button_i] == bin[dupe])
{
ismulti = true;
string += ",Joypad" + std::to_string((joypad_i % 5) + 1) + " ";

View File

@ -7,12 +7,13 @@
#ifndef __GTK_CONFIG_H
#define __GTK_CONFIG_H
#include "gtk_control.h"
#include "filter/snes_ntsc.h"
#include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h>
#include <string>
#include "gtk_control.h"
#include "filter/snes_ntsc.h"
#include <array>
enum {
HWA_NONE = 0,
@ -44,20 +45,22 @@ enum {
SPLASH_IMAGE_SMTPE = 1,
SPLASH_IMAGE_PATTERN = 2,
SPLASH_IMAGE_BLUE = 3,
SPLASH_IMAGE_COMBO = 4
SPLASH_IMAGE_COMBO = 4,
SPLASH_IMAGE_STARFIELD = 5,
SPLASH_IMAGE_SNOW = 6
};
class Snes9xConfig
{
public:
Snes9xConfig ();
int load_config_file ();
int save_config_file ();
int load_defaults ();
void rebind_keys ();
void flush_joysticks ();
void set_joystick_mode (int mode);
void joystick_register_centers ();
Snes9xConfig();
int load_config_file();
int save_config_file();
int load_defaults();
void rebind_keys();
void flush_joysticks();
void set_joystick_mode(int mode);
void joystick_register_centers();
/* Screen options */
bool full_screen_on_open;
@ -108,8 +111,8 @@ class Snes9xConfig
std::string last_shader_directory;
/* Controls */
JoypadBinding pad[NUM_JOYPADS];
Binding shortcut[NUM_EMU_LINKS];
std::array<JoypadBinding, NUM_JOYPADS> pad;
std::array<Binding, NUM_EMU_LINKS> shortcut;
/* Netplay */
bool netplay_is_server;
@ -164,11 +167,11 @@ class Snes9xConfig
bool use_sync_control;
#endif
JoyDevice **joystick;
std::vector<JoyDevice> joystick;
int joystick_threshold;
};
std::string get_config_dir ();
std::string get_config_file_name ();
std::string get_config_dir();
std::string get_config_file_name();
#endif /* __GTK_CONFIG_H */

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -11,46 +11,22 @@
class S9xDisplayDriver
{
public:
virtual ~S9xDisplayDriver() {}
virtual void refresh (int width, int height) = 0;
virtual int init () = 0;
virtual void deinit () = 0;
virtual void clear_buffers () = 0;
virtual void update (int width, int height, int yoffset) = 0;
virtual uint16 *get_next_buffer () = 0;
virtual uint16 *get_current_buffer () = 0;
virtual void push_buffer (uint16 *src) = 0;
virtual void *get_parameters () = 0;
virtual void save (const char *filename) = 0;
virtual bool is_ready () = 0;
public:
virtual ~S9xDisplayDriver()
{
}
virtual void refresh(int width, int height) = 0;
virtual int init() = 0;
virtual void deinit() = 0;
virtual void update(uint16_t *buffer, int width, int height, int stride_in_pixels) = 0;
virtual void *get_parameters() = 0;
virtual void save(const char *filename) = 0;
virtual bool is_ready() = 0;
/* Namespaced sizing constants */
static const int image_width = 1024;
static const int image_height = 478;
static const int image_bpp = 2;
static const int scaled_max_width = 1024;
static const int scaled_max_height = 956;
static const int image_size = image_width * image_height * image_bpp;
static const int image_padded_size = (image_width + 8) *
(image_height + 8 + 30) *
image_bpp;
static const int image_padded_offset = (image_width + 8) * (4 + 30) + 4;
static const int scaled_size = scaled_max_width *
scaled_max_height *
image_bpp;
static const int scaled_padded_size = (scaled_max_width + 8) *
(scaled_max_height + 8) *
image_bpp;
static const int scaled_padded_offset = (scaled_max_width + 8) * 4 + 4;
protected:
Snes9xWindow *window;
Snes9xConfig *config;
GtkWidget *drawing_area;
uint8_t *padded_buffer[4];
uint8_t *buffer[4];
protected:
Snes9xWindow *window;
Snes9xConfig *config;
Gtk::DrawingArea *drawing_area;
};
#endif /* __GTK_DISPLAY_DRIVER_H*/

View File

@ -4,161 +4,102 @@
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
#include "gtk_2_3_compat.h"
#include "gtk_compat.h"
#include <cairo.h>
#include "gtk_display.h"
#include "gtk_display_driver_gtk.h"
#include "snes9x.h"
S9xGTKDisplayDriver::S9xGTKDisplayDriver (Snes9xWindow *window,
Snes9xConfig *config)
S9xGTKDisplayDriver::S9xGTKDisplayDriver(Snes9xWindow *window,
Snes9xConfig *config)
{
this->window = window;
this->config = config;
this->drawing_area = GTK_WIDGET (window->drawing_area);
this->drawing_area = window->drawing_area;
}
void
S9xGTKDisplayDriver::update (int width, int height, int yoffset)
void S9xGTKDisplayDriver::update(uint16_t *buffer, int width, int height, int stride_in_pixels)
{
int final_pitch;
uint8 *final_buffer;
GtkAllocation allocation;
if (width <= 0)
return;
gtk_widget_get_allocation (drawing_area, &allocation);
if (config->scale_method > 0)
{
uint8 *src_buffer = (uint8 *) padded_buffer[0];
uint8 *dst_buffer = (uint8 *) padded_buffer[1];
int src_pitch = image_width * image_bpp;
int dst_pitch = scaled_max_width * image_bpp;
src_buffer += (src_pitch * yoffset);
S9xFilter (src_buffer,
src_pitch,
dst_buffer,
dst_pitch,
width,
height);
final_buffer = (uint8 *) padded_buffer[1];
final_pitch = dst_pitch;
}
else
{
final_buffer = (uint8 *) padded_buffer[0];
final_pitch = image_width * image_bpp;
final_buffer += (final_pitch * yoffset);
}
S9xRect dst = S9xApplyAspect(width, height, allocation.width, allocation.height);
output (final_buffer, final_pitch, dst.x, dst.y, width, height, dst.w, dst.h);
S9xRect dst = S9xApplyAspect(width, height, drawing_area->get_width(), drawing_area->get_height());
output(buffer, stride_in_pixels * 2, dst.x, dst.y, width, height, dst.w, dst.h);
}
void
S9xGTKDisplayDriver::output (void *src,
int src_pitch,
int x,
int y,
int width,
int height,
int dst_width,
int dst_height)
void S9xGTKDisplayDriver::output(void *src,
int src_pitch,
int x,
int y,
int width,
int height,
int dst_width,
int dst_height)
{
if (last_known_width != dst_width || last_known_height != dst_height)
{
clear ();
clear();
last_known_width = dst_width;
last_known_height = dst_height;
}
cairo_t *cr = window->get_cairo ();
cairo_t *cr = window->get_cairo();
cairo_surface_t *surface;
surface = cairo_image_surface_create_for_data ((unsigned char *) src, CAIRO_FORMAT_RGB16_565, width, height, src_pitch);
surface = cairo_image_surface_create_for_data((unsigned char *)src, CAIRO_FORMAT_RGB16_565, width, height, src_pitch);
cairo_set_source_surface (cr, surface, 0, 0);
cairo_set_source_surface(cr, surface, 0, 0);
if (width != dst_width || height != dst_height)
{
cairo_matrix_t matrix;
cairo_pattern_t *pattern = cairo_get_source (cr);;
cairo_pattern_t *pattern = cairo_get_source(cr);
;
cairo_matrix_init_identity (&matrix);
cairo_matrix_scale (&matrix,
(double) width / (double) dst_width,
(double) height / (double) dst_height);
cairo_matrix_translate (&matrix, -x, -y);
cairo_pattern_set_matrix (pattern, &matrix);
cairo_pattern_set_filter (pattern,
Settings.BilinearFilter
? CAIRO_FILTER_BILINEAR
: CAIRO_FILTER_NEAREST);
cairo_matrix_init_identity(&matrix);
cairo_matrix_scale(&matrix,
(double)width / (double)dst_width,
(double)height / (double)dst_height);
cairo_matrix_translate(&matrix, -x, -y);
cairo_pattern_set_matrix(pattern, &matrix);
cairo_pattern_set_filter(pattern,
Settings.BilinearFilter
? CAIRO_FILTER_BILINEAR
: CAIRO_FILTER_NEAREST);
}
cairo_rectangle (cr, x, y, dst_width, dst_height);
cairo_fill (cr);
cairo_rectangle(cr, x, y, dst_width, dst_height);
cairo_fill(cr);
cairo_surface_finish (surface);
cairo_surface_destroy (surface);
cairo_surface_finish(surface);
cairo_surface_destroy(surface);
window->release_cairo ();
window->set_mouseable_area (x, y, width, height);
window->release_cairo();
window->set_mouseable_area(x, y, width, height);
}
int
S9xGTKDisplayDriver::init ()
int S9xGTKDisplayDriver::init()
{
buffer[0] = new uint8_t[image_padded_size];
buffer[1] = new uint8_t[scaled_padded_size];
padded_buffer[0] = &buffer[0][image_padded_offset];
padded_buffer[1] = &buffer[1][scaled_padded_offset];
memset (buffer[0], 0, image_padded_size);
memset (buffer[1], 0, scaled_padded_size);
GFX.Screen = (uint16 *) padded_buffer[0];
GFX.Pitch = image_width * image_bpp;
return 0;
}
void
S9xGTKDisplayDriver::deinit ()
void S9xGTKDisplayDriver::deinit()
{
padded_buffer[0] = NULL;
padded_buffer[1] = NULL;
delete[] buffer[0];
delete[] buffer[1];
}
void
S9xGTKDisplayDriver::clear ()
void S9xGTKDisplayDriver::clear()
{
int width, height;
GtkAllocation allocation;
int width = drawing_area->get_width();
int height = drawing_area->get_height();
gtk_widget_get_allocation (drawing_area, &allocation);
width = allocation.width;
height = allocation.height;
cairo_t *cr = window->get_cairo();
cairo_t *cr = window->get_cairo ();
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
if (window->last_width <= 0 || window->last_height <= 0)
{
cairo_paint (cr);
window->release_cairo ();
cairo_paint(cr);
window->release_cairo();
return;
}
@ -171,53 +112,27 @@ S9xGTKDisplayDriver::clear ()
if (dst.x > 0)
{
cairo_rectangle (cr, 0, dst.y, dst.x, dst.h);
cairo_rectangle(cr, 0, dst.y, dst.x, dst.h);
}
if (dst.x + dst.w < width)
{
cairo_rectangle (cr, dst.x + dst.w, dst.y, width - (dst.x + dst.w), dst.h);
cairo_rectangle(cr, dst.x + dst.w, dst.y, width - (dst.x + dst.w), dst.h);
}
if (dst.y > 0)
{
cairo_rectangle (cr, 0, 0, width, dst.y);
cairo_rectangle(cr, 0, 0, width, dst.y);
}
if (dst.y + dst.h < height)
{
cairo_rectangle (cr, 0, dst.y + dst.h, width, height - (dst.y + dst.h));
cairo_rectangle(cr, 0, dst.y + dst.h, width, height - (dst.y + dst.h));
}
cairo_fill (cr);
cairo_fill(cr);
window->release_cairo ();
window->release_cairo();
}
void
S9xGTKDisplayDriver::refresh (int width, int height)
void S9xGTKDisplayDriver::refresh(int width, int height)
{
clear ();
}
uint16 *
S9xGTKDisplayDriver::get_next_buffer ()
{
return (uint16 *) padded_buffer[0];
}
uint16 *
S9xGTKDisplayDriver::get_current_buffer ()
{
return (uint16 *) padded_buffer[0];
}
void
S9xGTKDisplayDriver::push_buffer (uint16 *src)
{
memmove (GFX.Screen, src, image_size);
}
void
S9xGTKDisplayDriver::clear_buffers ()
{
memset (buffer[0], 0, image_padded_size);
memset (buffer[1], 0, scaled_padded_size);
}
clear();
}

View File

@ -12,33 +12,37 @@
class S9xGTKDisplayDriver : public S9xDisplayDriver
{
public:
S9xGTKDisplayDriver (Snes9xWindow *window, Snes9xConfig *config);
void refresh (int width, int height);
int init ();
void deinit ();
void clear_buffers ();
void update (int width, int height, int yoffset);
uint16 *get_next_buffer ();
uint16 *get_current_buffer ();
void push_buffer (uint16 *src);
void *get_parameters () { return NULL; }
void save (const char *filename) { }
bool is_ready () { return true; }
public:
S9xGTKDisplayDriver(Snes9xWindow *window, Snes9xConfig *config);
void refresh(int width, int height);
int init();
void deinit();
void update(uint16_t *buffer, int width, int height, int stride_in_pixels);
void *get_parameters()
{
return NULL;
}
void save(const char *filename)
{
}
bool is_ready()
{
return true;
}
private:
void clear ();
void output (void *src,
int src_pitch,
int x,
int y,
int width,
int height,
int dst_width,
int dst_height);
private:
void clear();
void output(void *src,
int src_pitch,
int x,
int y,
int width,
int height,
int dst_width,
int dst_height);
int last_known_width;
int last_known_height;
int last_known_width;
int last_known_height;
};
#endif /* __GTK_DISPLAY_DRIVER_GTK_H */

View File

@ -4,7 +4,7 @@
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
#include "gtk_2_3_compat.h"
#include "gtk_compat.h"
#include <dlfcn.h>
#include <sys/stat.h>
#include <fcntl.h>
@ -65,14 +65,14 @@ static const GLchar *stock_fragment_shader_140 =
"}\n";
static GLfloat coords[] = { -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, };
static GLfloat coords[] = { -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, };
static void S9xViewportCallback (int src_width, int src_height,
int viewport_x, int viewport_y,
int viewport_width, int viewport_height,
int *out_x, int *out_y,
int *out_width, int *out_height)
static void S9xViewportCallback(int src_width, int src_height,
int viewport_x, int viewport_y,
int viewport_width, int viewport_height,
int *out_x, int *out_y,
int *out_width, int *out_height)
{
S9xRect dst = S9xApplyAspect(src_width, src_height, viewport_width, viewport_height);
*out_x = dst.x + viewport_x;
@ -81,202 +81,126 @@ static void S9xViewportCallback (int src_width, int src_height,
*out_height = dst.h;
}
S9xOpenGLDisplayDriver::S9xOpenGLDisplayDriver (Snes9xWindow *window,
Snes9xConfig *config)
S9xOpenGLDisplayDriver::S9xOpenGLDisplayDriver(Snes9xWindow *window, Snes9xConfig *config)
{
this->window = window;
this->config = config;
this->drawing_area = GTK_WIDGET (window->drawing_area);
this->drawing_area = window->drawing_area;
}
void S9xOpenGLDisplayDriver::update (int width, int height, int yoffset)
void S9xOpenGLDisplayDriver::update(uint16_t *buffer, int width, int height, int stride_in_pixels)
{
uint8 *final_buffer = NULL;
int final_pitch;
void *pbo_map = NULL;
Gtk::Allocation allocation = drawing_area->get_allocation();
GtkAllocation allocation;
gtk_widget_get_allocation (drawing_area, &allocation);
if (output_window_width != allocation.width ||
output_window_height != allocation.height)
if (output_window_width != allocation.get_width() ||
output_window_height != allocation.get_height())
{
resize ();
resize();
}
#if GTK_CHECK_VERSION(3,10,0)
int gdk_scale_factor = gdk_window_get_scale_factor (gdk_window);
int scale_factor = drawing_area->get_scale_factor();
allocation.width *= gdk_scale_factor;
allocation.height *= gdk_scale_factor;
#endif
allocation.set_width(allocation.get_width() * scale_factor);
allocation.set_height(allocation.get_height() * scale_factor);
if (!legacy)
glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, texmap);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texmap);
GLint filter = Settings.BilinearFilter ? GL_LINEAR : GL_NEAREST;
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
GLint clamp = (using_glsl_shaders || !npot) ? GL_CLAMP_TO_BORDER : GL_CLAMP_TO_EDGE;
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp);
glClear (GL_COLOR_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT);
if (config->scale_method > 0)
{
uint8 *src_buffer = (uint8 *) padded_buffer[0];
int src_pitch = image_width * image_bpp;
uint8 *dst_buffer;
int dst_pitch;
S9xRect content = S9xApplyAspect(width, height, allocation.get_width(), allocation.get_height());
glViewport(content.x, allocation.get_height() - content.y - content.h, content.w, content.h);
window->set_mouseable_area(content.x, content.y, content.w, content.h);
src_buffer += (src_pitch * yoffset);
dst_buffer = (uint8 *) padded_buffer[1];
dst_pitch = scaled_max_width * image_bpp;
final_buffer = (uint8 *) padded_buffer[1];
final_pitch = scaled_max_width * image_bpp;
S9xFilter (src_buffer,
src_pitch,
dst_buffer,
dst_pitch,
width,
height);
}
else
{
final_buffer = (uint8 *) padded_buffer[0];
final_pitch = image_width * image_bpp;
final_buffer += (final_pitch * yoffset);
}
S9xRect r = S9xApplyAspect(width, height, allocation.width, allocation.height);
glViewport (r.x, allocation.height - r.y - r.h, r.w, r.h);
window->set_mouseable_area (r.x, r.y, r.w, r.h);
update_texture_size (width, height);
update_texture_size(width, height);
if (using_pbos)
{
void *pbo_memory = NULL;
GLbitfield bits = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
if (config->pbo_format == 16)
{
glBindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo);
glBufferData (GL_PIXEL_UNPACK_BUFFER,
width * height * 2,
NULL,
GL_STREAM_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
glBufferData(GL_PIXEL_UNPACK_BUFFER, width * height * 2, NULL, GL_STREAM_DRAW);
if (version >= 30)
pbo_map = glMapBufferRange (
GL_PIXEL_UNPACK_BUFFER, 0, width * height * 2,
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT |
GL_MAP_UNSYNCHRONIZED_BIT);
pbo_memory = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, width * height * 2, bits);
else
pbo_map = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
pbo_memory = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
for (int y = 0; y < height; y++)
{
memcpy ((uint8 *) pbo_map + (width * y * 2),
final_buffer + (y * final_pitch),
width * image_bpp);
uint16 *dst = (uint16_t *)pbo_memory + (width * y);
uint16 *src = &buffer[y * stride_in_pixels];
memcpy(dst, src, width * 2);
}
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glUnmapBuffer (GL_PIXEL_UNPACK_BUFFER);
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB,
GL_UNSIGNED_SHORT_5_6_5, BUFFER_OFFSET(0));
glPixelStorei (GL_UNPACK_ROW_LENGTH, width);
glTexSubImage2D (GL_TEXTURE_2D,
0,
0,
0,
width,
height,
GL_RGB,
GL_UNSIGNED_SHORT_5_6_5,
BUFFER_OFFSET (0));
glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
else /* 32-bit color */
{
glBindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo);
glBufferData (GL_PIXEL_UNPACK_BUFFER,
width * height * 4,
NULL,
GL_STREAM_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
glBufferData(GL_PIXEL_UNPACK_BUFFER, width * height * 4, NULL, GL_STREAM_DRAW);
if (version >= 30)
pbo_map = glMapBufferRange (
GL_PIXEL_UNPACK_BUFFER, 0, width * height * 4,
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT |
GL_MAP_UNSYNCHRONIZED_BIT);
pbo_memory = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, width * height * 4, bits);
else
pbo_map = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
pbo_memory = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
/* Pixel swizzling in software */
S9xSetEndianess (ENDIAN_NORMAL);
S9xConvert (final_buffer,
pbo_map,
final_pitch,
width * 4,
width,
height,
32);
S9xSetEndianess(ENDIAN_NORMAL);
S9xConvert(buffer, pbo_memory, stride_in_pixels * 2, width * 4, width, height, 32);
glUnmapBuffer (GL_PIXEL_UNPACK_BUFFER);
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glPixelStorei (GL_UNPACK_ROW_LENGTH, width);
glTexSubImage2D (GL_TEXTURE_2D,
0,
0,
0,
width,
height,
GL_BGRA,
GL_UNSIGNED_BYTE,
BUFFER_OFFSET (0));
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));
glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
}
else
{
glPixelStorei (GL_UNPACK_ROW_LENGTH, final_pitch / image_bpp);
glTexSubImage2D (GL_TEXTURE_2D,
0,
0,
0,
width,
height,
GL_RGB,
GL_UNSIGNED_SHORT_5_6_5,
final_buffer);
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride_in_pixels * 2);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, buffer);
}
if (using_glsl_shaders)
{
glsl_shader->render (texmap, width, height, r.x, allocation.height - r.y - r.h, r.w, r.h, S9xViewportCallback);
swap_buffers ();
glsl_shader->render(texmap, width, height, content.x, allocation.get_height() - content.y - content.h, content.w, content.h, S9xViewportCallback);
swap_buffers();
return;
}
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
swap_buffers ();
swap_buffers();
}
void *S9xOpenGLDisplayDriver::get_parameters ()
void *S9xOpenGLDisplayDriver::get_parameters()
{
if (using_glsl_shaders && glsl_shader)
{
return (void *) &glsl_shader->param;
return (void *)&glsl_shader->param;
}
return NULL;
}
void S9xOpenGLDisplayDriver::save (const char *filename)
void S9xOpenGLDisplayDriver::save(const char *filename)
{
if (using_glsl_shaders && glsl_shader)
{
@ -284,82 +208,65 @@ void S9xOpenGLDisplayDriver::save (const char *filename)
}
}
void S9xOpenGLDisplayDriver::clear_buffers ()
{
memset (buffer[0], 0, image_padded_size);
memset (buffer[1], 0, scaled_padded_size);
glPixelStorei (GL_UNPACK_ROW_LENGTH, scaled_max_width);
glTexSubImage2D (GL_TEXTURE_2D,
0,
0,
0,
MIN(scaled_max_width, texture_width),
MIN(scaled_max_height, texture_height),
GL_RGB,
GL_UNSIGNED_SHORT_5_6_5,
buffer[1]);
}
void S9xOpenGLDisplayDriver::update_texture_size (int width, int height)
void S9xOpenGLDisplayDriver::update_texture_size(int width, int height)
{
if (width != texture_width || height != texture_height)
{
if (npot)
{
glBindTexture (GL_TEXTURE_2D, texmap);
glBindTexture(GL_TEXTURE_2D, texmap);
if (using_pbos && config->pbo_format == 32)
{
glTexImage2D (GL_TEXTURE_2D,
0,
GL_RGBA,
width,
height,
0,
GL_BGRA,
GL_UNSIGNED_BYTE,
NULL);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGBA,
width,
height,
0,
GL_BGRA,
GL_UNSIGNED_BYTE,
NULL);
}
else
{
glTexImage2D (GL_TEXTURE_2D,
0,
GL_RGB565,
width,
height,
0,
GL_RGB,
GL_UNSIGNED_SHORT_5_6_5,
NULL);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB565,
width,
height,
0,
GL_RGB,
GL_UNSIGNED_SHORT_5_6_5,
NULL);
}
coords[9] = 1.0f;
coords[9] = 1.0f;
coords[10] = 1.0f;
coords[11] = 1.0f;
coords[14] = 1.0f;
}
else
{
coords[9] = height / 1024.0f;
coords[10] = width / 1024.0f;
coords[9] = height / 1024.0f;
coords[10] = width / 1024.0f;
coords[11] = height / 1024.0f;
coords[14] = width / 1024.0f;
coords[14] = width / 1024.0f;
}
texture_width = width;
texture_width = width;
texture_height = height;
if (!legacy)
{
glBindBuffer (GL_ARRAY_BUFFER, coord_buffer);
glBufferData (GL_ARRAY_BUFFER, sizeof (GLfloat) * 16, coords, GL_STATIC_DRAW);
glBindBuffer (GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, coord_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, coords, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
else
{
glVertexPointer (2, GL_FLOAT, 0, coords);
glTexCoordPointer (2, GL_FLOAT, 0, &coords[8]);
glVertexPointer(2, GL_FLOAT, 0, coords);
glTexCoordPointer(2, GL_FLOAT, 0, &coords[8]);
}
}
}
@ -417,7 +324,7 @@ bool S9xOpenGLDisplayDriver::opengl_defaults()
if (config->use_shaders)
{
if (legacy || !load_shaders (config->shader_filename.c_str ()))
if (legacy || !load_shaders(config->shader_filename.c_str()))
{
config->use_shaders = false;
}
@ -433,169 +340,171 @@ bool S9xOpenGLDisplayDriver::opengl_defaults()
if (legacy)
{
glEnableClientState (GL_VERTEX_ARRAY);
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
glEnable (GL_TEXTURE_2D);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glVertexPointer (2, GL_FLOAT, 0, coords);
glTexCoordPointer (2, GL_FLOAT, 0, &coords[8]);
glVertexPointer(2, GL_FLOAT, 0, coords);
glTexCoordPointer(2, GL_FLOAT, 0, &coords[8]);
}
else
{
stock_program = glCreateProgram ();
stock_program = glCreateProgram();
GLuint vertex_shader = glCreateShader (GL_VERTEX_SHADER);
GLuint fragment_shader = glCreateShader (GL_FRAGMENT_SHADER);
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
if (version < 30)
{
glShaderSource (vertex_shader, 1, &stock_vertex_shader_110, NULL);
glShaderSource (fragment_shader, 1, &stock_fragment_shader_110, NULL);
glShaderSource(vertex_shader, 1, &stock_vertex_shader_110, NULL);
glShaderSource(fragment_shader, 1, &stock_fragment_shader_110, NULL);
}
else
{
glShaderSource (vertex_shader, 1, &stock_vertex_shader_140, NULL);
glShaderSource (fragment_shader, 1, &stock_fragment_shader_140, NULL);
glShaderSource(vertex_shader, 1, &stock_vertex_shader_140, NULL);
glShaderSource(fragment_shader, 1, &stock_fragment_shader_140, NULL);
}
glCompileShader (vertex_shader);
glAttachShader (stock_program, vertex_shader);
glCompileShader (fragment_shader);
glAttachShader (stock_program, fragment_shader);
glCompileShader(vertex_shader);
glAttachShader(stock_program, vertex_shader);
glCompileShader(fragment_shader);
glAttachShader(stock_program, fragment_shader);
glBindAttribLocation (stock_program, 0, "in_position");
glBindAttribLocation (stock_program, 1, "in_texcoord");
glBindAttribLocation(stock_program, 0, "in_position");
glBindAttribLocation(stock_program, 1, "in_texcoord");
glLinkProgram (stock_program);
glUseProgram (stock_program);
glLinkProgram(stock_program);
glUseProgram(stock_program);
glDeleteShader (vertex_shader);
glDeleteShader (fragment_shader);
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
GLint texture_uniform = glGetUniformLocation (stock_program, "texmap");
glUniform1i (texture_uniform, 0);
GLint texture_uniform = glGetUniformLocation(stock_program, "texmap");
glUniform1i(texture_uniform, 0);
if (core)
{
GLuint vao;
glGenVertexArrays (1, &vao);
glBindVertexArray (vao);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
}
glGenBuffers (1, &coord_buffer);
glBindBuffer (GL_ARRAY_BUFFER, coord_buffer);
glBufferData (GL_ARRAY_BUFFER, sizeof (GLfloat) * 16, coords, GL_STATIC_DRAW);
glGenBuffers(1, &coord_buffer);
glBindBuffer(GL_ARRAY_BUFFER, coord_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, coords, GL_STATIC_DRAW);
glEnableVertexAttribArray (0);
glVertexAttribPointer (0, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET (0));
glEnableVertexAttribArray (1);
glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET (32));
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(32));
glBindBuffer (GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
if (config->use_pbos)
{
glGenBuffers (1, &pbo);
glGenTextures (1, &texmap);
glGenBuffers(1, &pbo);
glGenTextures(1, &texmap);
glBindTexture (GL_TEXTURE_2D, texmap);
glTexImage2D (GL_TEXTURE_2D,
0,
config->pbo_format == 16 ? GL_RGB565 : GL_RGBA,
texture_width,
texture_height,
0,
config->pbo_format == 16 ? GL_RGB : GL_BGRA,
config->pbo_format == 16 ? GL_UNSIGNED_SHORT_5_6_5 : GL_UNSIGNED_BYTE,
NULL);
glBindTexture(GL_TEXTURE_2D, texmap);
glTexImage2D(GL_TEXTURE_2D,
0,
config->pbo_format == 16 ? GL_RGB565 : GL_RGBA,
texture_width,
texture_height,
0,
config->pbo_format == 16 ? GL_RGB : GL_BGRA,
config->pbo_format == 16 ? GL_UNSIGNED_SHORT_5_6_5 : GL_UNSIGNED_BYTE,
NULL);
glBindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo);
glBufferData (GL_PIXEL_UNPACK_BUFFER,
texture_width * texture_height * 3,
NULL,
GL_STREAM_DRAW);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
glBufferData(GL_PIXEL_UNPACK_BUFFER,
texture_width * texture_height * 3,
NULL,
GL_STREAM_DRAW);
glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
else
{
glGenTextures (1, &texmap);
glGenTextures(1, &texmap);
glBindTexture (GL_TEXTURE_2D, texmap);
glTexImage2D (GL_TEXTURE_2D,
0,
GL_RGB565,
texture_width,
texture_height,
0,
GL_RGB,
GL_UNSIGNED_SHORT_5_6_5,
NULL);
glBindTexture(GL_TEXTURE_2D, texmap);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB565,
texture_width,
texture_height,
0,
GL_RGB,
GL_UNSIGNED_SHORT_5_6_5,
NULL);
}
glClearColor (0.0, 0.0, 0.0, 0.0);
glClearColor(0.0, 0.0, 0.0, 0.0);
return true;
}
void S9xOpenGLDisplayDriver::refresh (int width, int height)
void S9xOpenGLDisplayDriver::refresh(int width, int height)
{
resize ();
resize();
}
void S9xOpenGLDisplayDriver::resize ()
void S9xOpenGLDisplayDriver::resize()
{
context->resize ();
context->swap_interval (config->sync_to_vblank);
context->resize();
context->swap_interval(config->sync_to_vblank);
output_window_width = context->width;
output_window_height = context->height;
}
bool S9xOpenGLDisplayDriver::create_context()
{
gdk_window = gtk_widget_get_window (drawing_area);
gdk_window = drawing_area->get_window()->gobj();
GdkDisplay *gdk_display = drawing_area->get_display()->gobj();
#ifdef GDK_WINDOWING_WAYLAND
if (GDK_IS_WAYLAND_WINDOW (gdk_window))
if (GDK_IS_WAYLAND_WINDOW(gdk_window))
{
if (!wl.attach(GTK_WIDGET(drawing_area->gobj())))
return false;
context = &wl;
}
#endif
#ifdef GDK_WINDOWING_X11
if (GDK_IS_X11_WINDOW (gdk_window))
if (GDK_IS_X11_WINDOW(gdk_window))
{
if (!glx.attach(gdk_x11_display_get_xdisplay(gdk_display), gdk_x11_window_get_xid(gdk_window)))
return false;
context = &glx;
}
#endif
if (!context->attach (drawing_area))
return false;
if (!context->create_context ())
if (!context->create_context())
return false;
output_window_width = context->width;
output_window_height = context->height;
context->make_current ();
context->make_current();
legacy = false;
version = epoxy_gl_version ();
version = epoxy_gl_version();
if (version < 20)
{
printf ("OpenGL version is only %d.%d. Recommended version is 2.0.\n",
version / 10,
version % 10);
printf("OpenGL version is only %d.%d. Recommended version is 2.0.\n",
version / 10,
version % 10);
legacy = true;
}
int profile_mask = 0;
glGetIntegerv (GL_CONTEXT_PROFILE_MASK, &profile_mask);
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile_mask);
if (profile_mask & GL_CONTEXT_CORE_PROFILE_BIT)
core = true;
else
@ -604,113 +513,79 @@ bool S9xOpenGLDisplayDriver::create_context()
return true;
}
int S9xOpenGLDisplayDriver::init ()
int S9xOpenGLDisplayDriver::init()
{
initialized = false;
if (!create_context ())
if (!create_context())
{
return -1;
}
if (!opengl_defaults ())
if (!opengl_defaults())
{
return -1;
}
buffer[0] = new uint8_t[image_padded_size];
buffer[1] = new uint8_t[scaled_padded_size];
clear_buffers ();
padded_buffer[0] = &buffer[0][image_padded_offset];
padded_buffer[1] = &buffer[1][scaled_padded_offset];
GFX.Screen = (uint16 *) padded_buffer[0];
GFX.Pitch = image_width * image_bpp;
context->swap_interval (config->sync_to_vblank);
context->swap_interval(config->sync_to_vblank);
initialized = true;
return 0;
}
uint16 *S9xOpenGLDisplayDriver::get_next_buffer ()
void S9xOpenGLDisplayDriver::swap_buffers()
{
return (uint16 *) padded_buffer[0];
}
void S9xOpenGLDisplayDriver::push_buffer (uint16 *src)
{
memmove (padded_buffer[0], src, image_size);
}
uint16 *S9xOpenGLDisplayDriver::get_current_buffer ()
{
return (uint16 *) padded_buffer[0];
}
void S9xOpenGLDisplayDriver::swap_buffers ()
{
context->swap_buffers ();
context->swap_buffers();
if (config->use_glfinish && !config->use_sync_control)
{
usleep (0);
glFinish ();
usleep(0);
glFinish();
}
}
void S9xOpenGLDisplayDriver::deinit ()
void S9xOpenGLDisplayDriver::deinit()
{
if (!initialized)
return;
if (using_glsl_shaders)
{
window->enable_widget ("shader_parameters_item", false);
gtk_shader_parameters_dialog_close ();
window->enable_widget("shader_parameters_item", false);
gtk_shader_parameters_dialog_close();
glsl_shader->destroy();
delete glsl_shader;
}
GFX.Screen = NULL;
padded_buffer[0] = NULL;
padded_buffer[1] = NULL;
delete[] buffer[0];
delete[] buffer[1];
if (using_pbos)
{
glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
glDeleteBuffers (1, &pbo);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glDeleteBuffers(1, &pbo);
}
glDeleteTextures (1, &texmap);
glDeleteTextures(1, &texmap);
}
int S9xOpenGLDisplayDriver::query_availability ()
int S9xOpenGLDisplayDriver::query_availability()
{
GdkDisplay *gdk_display = gdk_display_get_default ();
GdkDisplay *gdk_display = gdk_display_get_default();
#ifdef GDK_WINDOWING_WAYLAND
if (GDK_IS_WAYLAND_DISPLAY (gdk_display))
if (GDK_IS_WAYLAND_DISPLAY(gdk_display))
{
return 1;
}
#endif
#ifdef GDK_WINDOWING_X11
if (GDK_IS_X11_DISPLAY (gdk_display))
if (GDK_IS_X11_DISPLAY(gdk_display))
{
Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display);
Display *dpy = GDK_DISPLAY_XDISPLAY(gdk_display);
if (glXQueryExtension (dpy, NULL, NULL) == True)
if (glXQueryExtension(dpy, NULL, NULL) == True)
{
return 1;
return 1;
}
}
#endif
@ -721,7 +596,7 @@ int S9xOpenGLDisplayDriver::query_availability ()
return 0;
}
bool S9xOpenGLDisplayDriver::is_ready ()
bool S9xOpenGLDisplayDriver::is_ready()
{
if (context->ready())
{

View File

@ -14,7 +14,7 @@
#include "gtk_opengl_context.h"
#include "gtk_2_3_compat.h"
#include "gtk_compat.h"
#ifdef GDK_WINDOWING_X11
#include "gtk_glx_context.h"
#endif
@ -24,61 +24,57 @@
#include "shaders/glsl.h"
#define BUFFER_OFFSET(i) ((char *) (i))
#define BUFFER_OFFSET(i) ((char *)(i))
class S9xOpenGLDisplayDriver : public S9xDisplayDriver
{
public:
S9xOpenGLDisplayDriver (Snes9xWindow *window, Snes9xConfig *config);
void refresh (int width, int height);
int init ();
void deinit ();
void clear_buffers ();
void update (int width, int height, int yoffset);
uint16 *get_next_buffer ();
uint16 *get_current_buffer ();
void push_buffer (uint16 *src);
void *get_parameters ();
void save (const char *filename);
static int query_availability ();
bool is_ready ();
public:
S9xOpenGLDisplayDriver(Snes9xWindow *window, Snes9xConfig *config);
void refresh(int width, int height);
int init();
void deinit();
void update(uint16_t *buffer, int width, int height, int stride_in_pixels);
void *get_parameters();
void save(const char *filename);
static int query_availability();
bool is_ready();
private:
bool opengl_defaults ();
void swap_buffers ();
bool load_shaders (const char *);
void update_texture_size (int width, int height);
bool create_context ();
void resize ();
private:
bool opengl_defaults();
void swap_buffers();
bool load_shaders(const char *);
void update_texture_size(int width, int height);
bool create_context();
void resize();
GLuint stock_program;
GLuint coord_buffer;
GLint texture_width;
GLint texture_height;
GLuint texmap;
GLuint pbo;
GLuint stock_program;
GLuint coord_buffer;
GLint texture_width;
GLint texture_height;
GLuint texmap;
GLuint pbo;
bool legacy;
bool core;
int version;
bool npot;
bool using_pbos;
bool initialized;
bool legacy;
bool core;
int version;
bool npot;
bool using_pbos;
bool initialized;
bool using_glsl_shaders;
GLSLShader *glsl_shader;
bool using_glsl_shaders;
GLSLShader *glsl_shader;
GdkWindow *gdk_window;
int output_window_width;
int output_window_height;
GdkWindow *gdk_window;
int output_window_width;
int output_window_height;
OpenGLContext *context;
OpenGLContext *context;
#ifdef GDK_WINDOWING_X11
GTKGLXContext glx;
GTKGLXContext glx;
#endif
#ifdef GDK_WINDOWING_WAYLAND
WaylandEGLContext wl;
WaylandEGLContext wl;
#endif
};

View File

@ -4,7 +4,7 @@
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
#include "gtk_2_3_compat.h"
#include "gtk_compat.h"
#include <X11/extensions/XShm.h>
#include <X11/extensions/Xv.h>
#include <X11/extensions/Xvlib.h>
@ -14,43 +14,43 @@
#include "gtk_display.h"
#include "gtk_display_driver_xv.h"
static int
get_inv_shift (uint32 mask, int bpp)
static int get_inv_shift(uint32 mask, int bpp)
{
int i;
/* Find mask */
for (i = 0; (i < bpp) && !(mask & (1 << i)); i++) {};
for (i = 0; (i < bpp) && !(mask & (1 << i)); i++)
{
};
/* Find start of mask */
for (; (i < bpp) && (mask & (1 << i)); i++) {};
for (; (i < bpp) && (mask & (1 << i)); i++)
{
};
return (bpp - i);
}
S9xXVDisplayDriver::S9xXVDisplayDriver (Snes9xWindow *window,
Snes9xConfig *config)
S9xXVDisplayDriver::S9xXVDisplayDriver(Snes9xWindow *window, Snes9xConfig *config)
{
this->window = window;
this->config = config;
this->drawing_area = GTK_WIDGET (window->drawing_area);
display =
gdk_x11_display_get_xdisplay (gtk_widget_get_display (drawing_area));
last_known_width = last_known_height = -1;
this->drawing_area = window->drawing_area;
display = gdk_x11_display_get_xdisplay(drawing_area->get_display()->gobj());
last_known_width = -1;
last_known_height = -1;
}
void
S9xXVDisplayDriver::resize_window (int width, int height)
void S9xXVDisplayDriver::resize_window(int width, int height)
{
gdk_window_destroy (gdk_window);
create_window (width, height);
gdk_window_destroy(gdk_window);
create_window(width, height);
}
void
S9xXVDisplayDriver::create_window (int width, int height)
void S9xXVDisplayDriver::create_window(int width, int height)
{
GdkWindowAttr window_attr;
memset (&window_attr, 0, sizeof (GdkWindowAttr));
memset(&window_attr, 0, sizeof(GdkWindowAttr));
window_attr.event_mask = GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
window_attr.width = width;
window_attr.height = height;
@ -58,95 +58,64 @@ S9xXVDisplayDriver::create_window (int width, int height)
window_attr.y = 0;
window_attr.wclass = GDK_INPUT_OUTPUT;
window_attr.window_type = GDK_WINDOW_CHILD;
window_attr.visual = gdk_x11_screen_lookup_visual (gtk_widget_get_screen (drawing_area), vi->visualid);
window_attr.visual = gdk_x11_screen_lookup_visual(drawing_area->get_screen()->gobj(), vi->visualid);
gdk_window = gdk_window_new (gtk_widget_get_window (drawing_area),
&window_attr,
GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL);
gdk_window_set_user_data (gdk_window, (gpointer) drawing_area);
gdk_window = gdk_window_new(drawing_area->get_window()->gobj(),
&window_attr,
GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL);
gdk_window_show (gdk_window);
xwindow = gdk_x11_window_get_xid (gdk_window);
gdk_window_set_user_data(gdk_window, (gpointer)drawing_area->gobj());
gdk_window_show(gdk_window);
xwindow = gdk_x11_window_get_xid(gdk_window);
output_window_width = width;
output_window_height = height;
}
void
S9xXVDisplayDriver::update (int width, int height, int yoffset)
void S9xXVDisplayDriver::update(uint16_t *buffer, int width, int height, int stride_in_pixels)
{
int current_width, current_height, final_pitch;
uint8 *final_buffer;
GtkAllocation allocation;
int current_width, current_height;
gtk_widget_get_allocation (drawing_area, &allocation);
auto allocation = drawing_area->get_allocation();
if (output_window_width != allocation.width ||
output_window_height != allocation.height)
if (output_window_width != allocation.get_width() ||
output_window_height != allocation.get_height())
{
resize_window (allocation.width, allocation.height);
resize_window(allocation.get_width(), allocation.get_height());
}
#if GTK_CHECK_VERSION(3,10,0)
int gdk_scale_factor = gdk_window_get_scale_factor (gdk_window);
int scale_factor = drawing_area->get_scale_factor();
allocation.width *= gdk_scale_factor;
allocation.height *= gdk_scale_factor;
allocation.set_width(allocation.get_width() * scale_factor);
allocation.set_height(allocation.get_height() * scale_factor);
#endif
current_width = allocation.get_width();
current_height = allocation.get_height();
current_width = allocation.width;
current_height = allocation.height;
if (config->scale_method > 0)
{
uint8 *src_buffer = (uint8 *) padded_buffer[0];
uint8 *dst_buffer = (uint8 *) padded_buffer[1];
int src_pitch = image_width * image_bpp;
int dst_pitch = scaled_max_width * image_bpp;
src_buffer += (src_pitch * yoffset);
S9xFilter (src_buffer,
src_pitch,
dst_buffer,
dst_pitch,
width,
height);
final_buffer = (uint8 *) padded_buffer[1];
final_pitch = dst_pitch;
}
else
{
final_buffer = (uint8 *) padded_buffer[0];
final_pitch = image_width * image_bpp;
final_buffer += (final_pitch * yoffset);
}
update_image_size (width, height);
update_image_size(width, height);
if (format == FOURCC_YUY2)
{
S9xConvertYUV (final_buffer,
(uint8 *) xv_image->data,
final_pitch,
2 * xv_image->width,
width + (width < xv_image->width ? (width % 2) + 4 : 0),
height + (height < xv_image->height ? 4 : 0));
S9xConvertYUV(buffer,
(uint8 *)xv_image->data,
stride_in_pixels * 2,
2 * xv_image->width,
width + (width < xv_image->width ? (width % 2) + 4 : 0),
height + (height < xv_image->height ? 4 : 0));
}
else
{
S9xConvertMask (final_buffer,
(uint8 *) xv_image->data,
final_pitch,
bytes_per_pixel * xv_image->width,
width + (width < xv_image->width ? (width % 2) + 4 : 0),
height + (height < xv_image->height ? 4 : 0),
rshift,
gshift,
bshift,
bpp);
S9xConvertMask(buffer,
(uint8 *)xv_image->data,
stride_in_pixels * 2,
bytes_per_pixel * xv_image->width,
width + (width < xv_image->width ? (width % 2) + 4 : 0),
height + (height < xv_image->height ? 4 : 0),
rshift,
gshift,
bshift,
bpp);
}
S9xRect dst = S9xApplyAspect(width, height, current_width, current_height);
@ -155,60 +124,59 @@ S9xXVDisplayDriver::update (int width, int height, int yoffset)
{
last_known_width = dst.w;
last_known_height = dst.h;
clear ();
clear();
}
XvShmPutImage (display,
xv_portid,
xwindow,
XDefaultGC (display, XDefaultScreen (display)),
xv_image,
0,
0,
width,
height,
dst.x,
dst.y,
dst.w,
dst.h,
False);
XvShmPutImage(display,
xv_portid,
xwindow,
XDefaultGC(display, XDefaultScreen(display)),
xv_image,
0,
0,
width,
height,
dst.x,
dst.y,
dst.w,
dst.h,
False);
top_level->set_mouseable_area (dst.x, dst.y, dst.w, dst.h);
top_level->set_mouseable_area(dst.x, dst.y, dst.w, dst.h);
XSync (display, False);
XSync(display, False);
}
void
S9xXVDisplayDriver::update_image_size (int width, int height)
void S9xXVDisplayDriver::update_image_size(int width, int height)
{
if (desired_width != width || desired_height != height)
if (xv_image_width != width || xv_image_height != height)
{
XShmDetach (display, &shm);
XSync (display, 0);
XShmDetach(display, &shm);
XSync(display, 0);
shmctl (shm.shmid, IPC_RMID, 0);
shmdt (shm.shmaddr);
shmctl(shm.shmid, IPC_RMID, 0);
shmdt(shm.shmaddr);
xv_image = XvShmCreateImage (display,
xv_portid,
format,
0,
width,
height,
&shm);
xv_image = XvShmCreateImage(display,
xv_portid,
format,
0,
width,
height,
&shm);
shm.shmid = shmget (IPC_PRIVATE, xv_image->data_size, IPC_CREAT | 0777);
shm.shmid = shmget(IPC_PRIVATE, xv_image->data_size, IPC_CREAT | 0777);
for (int tries = 0; tries <= 10; tries++)
{
shm.shmaddr = (char *) shmat (shm.shmid, 0, 0);
shm.shmaddr = (char *)shmat(shm.shmid, 0, 0);
if (shm.shmaddr == (void *) -1 && tries >= 10)
if (shm.shmaddr == (void *)-1 && tries >= 10)
{
/* Can't recover, send exit. */
fprintf (stderr, "Couldn't reallocate shared memory.\n");
S9xExit ();
fprintf(stderr, "Couldn't reallocate shared memory.\n");
exit(1);
}
else if (shm.shmaddr != (void *) -1)
else if (shm.shmaddr != (void *)-1)
{
break;
}
@ -218,50 +186,48 @@ S9xXVDisplayDriver::update_image_size (int width, int height)
xv_image->data = shm.shmaddr;
XShmAttach (display, &shm);
XShmAttach(display, &shm);
desired_width = width;
desired_height = height;
xv_image_width = width;
xv_image_height = height;
}
}
int
S9xXVDisplayDriver::init ()
int S9xXVDisplayDriver::init()
{
int depth = 0, num_formats, num_attrs, highest_formats = 0;
int depth = 0, num_formats, num_attrs, highest_formats = 0;
XvImageFormatValues *formats = NULL;
XvAdaptorInfo *adaptors;
XvAttribute *port_attr;
VisualID visualid = None;
unsigned int num_adaptors = 0;
GdkScreen *screen;
GdkWindow *root;
XvAdaptorInfo *adaptors;
XvAttribute *port_attr;
VisualID visualid = None;
unsigned int num_adaptors = 0;
GdkScreen *screen;
GdkWindow *root;
/* Setup XV */
gtk_widget_realize (drawing_area);
gtk_widget_realize(GTK_WIDGET(drawing_area->gobj()));
display = gdk_x11_display_get_xdisplay (gtk_widget_get_display (drawing_area));
screen = gtk_widget_get_screen (drawing_area);
root = gdk_screen_get_root_window (screen);
display = gdk_x11_display_get_xdisplay(drawing_area->get_display()->gobj());
screen = drawing_area->get_screen()->gobj();
root = gdk_screen_get_root_window(screen);
xv_portid = -1;
if ((XvQueryAdaptors (display,
gdk_x11_window_get_xid (root),
&num_adaptors,
&adaptors)) != Success)
if ((XvQueryAdaptors(display,
gdk_x11_window_get_xid(root),
&num_adaptors,
&adaptors)) != Success)
{
fprintf (stderr, "No Xv compatible adaptors.\n");
fprintf(stderr, "No Xv compatible adaptors.\n");
}
for (int i = 0; i < (int) num_adaptors; i++)
for (int i = 0; i < (int)num_adaptors; i++)
{
if (adaptors[i].type & XvInputMask &&
adaptors[i].type & XvImageMask)
{
formats = XvListImageFormats (display,
adaptors[i].base_id,
&num_formats);
formats = XvListImageFormats(display,
adaptors[i].base_id,
&num_formats);
if (num_formats > highest_formats)
{
@ -270,30 +236,30 @@ S9xXVDisplayDriver::init ()
visualid = adaptors[i].formats->visual_id;
}
free (formats);
free(formats);
}
}
XvFreeAdaptorInfo (adaptors);
XvFreeAdaptorInfo(adaptors);
if (xv_portid < 0)
{
fprintf (stderr, "Could not open Xv output port.\n");
fprintf(stderr, "Could not open Xv output port.\n");
return -1;
}
/* Set XV_AUTOPAINT_COLORKEY _only_ if available */
port_attr = XvQueryPortAttributes (display, xv_portid, &num_attrs);
port_attr = XvQueryPortAttributes(display, xv_portid, &num_attrs);
for (int i = 0; i < num_attrs; i++)
{
if (!strcmp (port_attr[i].name, "XV_AUTOPAINT_COLORKEY"))
if (!strcmp(port_attr[i].name, "XV_AUTOPAINT_COLORKEY"))
{
Atom colorkey;
colorkey = XInternAtom (display, "XV_AUTOPAINT_COLORKEY", True);
colorkey = XInternAtom(display, "XV_AUTOPAINT_COLORKEY", True);
if (colorkey != None)
XvSetPortAttribute (display, xv_portid, colorkey, 1);
XvSetPortAttribute(display, xv_portid, colorkey, 1);
}
}
@ -301,9 +267,9 @@ S9xXVDisplayDriver::init ()
format = -1;
bpp = 100;
formats = XvListImageFormats (display,
xv_portid,
&num_formats);
formats = XvListImageFormats(display,
xv_portid,
&num_formats);
for (int i = 0; i < num_formats; i++)
{
@ -316,12 +282,12 @@ S9xXVDisplayDriver::init ()
bytes_per_pixel = (bpp == 15) ? 2 : bpp >> 3;
depth = formats[i].depth;
this->rshift = get_inv_shift (formats[i].red_mask, bpp);
this->gshift = get_inv_shift (formats[i].green_mask, bpp);
this->bshift = get_inv_shift (formats[i].blue_mask, bpp);
this->rshift = get_inv_shift(formats[i].red_mask, bpp);
this->gshift = get_inv_shift(formats[i].green_mask, bpp);
this->bshift = get_inv_shift(formats[i].blue_mask, bpp);
/* Check for red-blue inversion on SiliconMotion drivers */
if (formats[i].red_mask == 0x001f &&
if (formats[i].red_mask == 0x001f &&
formats[i].blue_mask == 0x7c00)
{
int copy = this->rshift;
@ -331,9 +297,9 @@ S9xXVDisplayDriver::init ()
/* on big-endian Xv still seems to like LSB order */
if (config->force_inverted_byte_order)
S9xSetEndianess (ENDIAN_SWAPPED);
S9xSetEndianess(ENDIAN_SWAPPED);
else
S9xSetEndianess (ENDIAN_NORMAL);
S9xSetEndianess(ENDIAN_NORMAL);
}
}
}
@ -350,16 +316,16 @@ S9xXVDisplayDriver::init ()
if (formats[i].byte_order == LSBFirst)
{
if (config->force_inverted_byte_order)
S9xSetEndianess (ENDIAN_SWAPPED);
S9xSetEndianess(ENDIAN_SWAPPED);
else
S9xSetEndianess (ENDIAN_NORMAL);
S9xSetEndianess(ENDIAN_NORMAL);
}
else
{
if (config->force_inverted_byte_order)
S9xSetEndianess (ENDIAN_NORMAL);
S9xSetEndianess(ENDIAN_NORMAL);
else
S9xSetEndianess (ENDIAN_SWAPPED);
S9xSetEndianess(ENDIAN_SWAPPED);
}
break;
@ -367,11 +333,11 @@ S9xXVDisplayDriver::init ()
}
}
free (formats);
free(formats);
if (format == -1)
{
fprintf (stderr, "No compatible formats found for Xv.\n");
fprintf(stderr, "No compatible formats found for Xv.\n");
return -1;
}
@ -384,19 +350,19 @@ S9xXVDisplayDriver::init ()
int y, u, v;
r = ((color & 0xf800) >> 8) | ((color >> 13) & 0x7);
g = ((color & 0x07e0) >> 3) | ((color >> 9 ) & 0x3);
b = ((color & 0x001F) << 3) | ((color >> 3 ) & 0x7);
g = ((color & 0x07e0) >> 3) | ((color >> 9) & 0x3);
b = ((color & 0x001F) << 3) | ((color >> 3) & 0x7);
y = (int) ((0.257 * ((double) r)) + (0.504 * ((double) g)) + (0.098 * ((double) b)) + 16.0);
u = (int) ((-0.148 * ((double) r)) + (-0.291 * ((double) g)) + (0.439 * ((double) b)) + 128.0);
v = (int) ((0.439 * ((double) r)) + (-0.368 * ((double) g)) + (-0.071 * ((double) b)) + 128.0);
y = (int)((0.257 * ((double)r)) + (0.504 * ((double)g)) + (0.098 * ((double)b)) + 16.0);
u = (int)((-0.148 * ((double)r)) + (-0.291 * ((double)g)) + (0.439 * ((double)b)) + 128.0);
v = (int)((0.439 * ((double)r)) + (-0.368 * ((double)g)) + (-0.071 * ((double)b)) + 128.0);
y_table[color] = CLAMP (y, 0, 255);
u_table[color] = CLAMP (u, 0, 255);
v_table[color] = CLAMP (v, 0, 255);
y_table[color] = CLAMP(y, 0, 255);
u_table[color] = CLAMP(u, 0, 255);
v_table[color] = CLAMP(v, 0, 255);
}
S9xRegisterYUVTables (y_table, u_table, v_table);
S9xRegisterYUVTables(y_table, u_table, v_table);
}
/* Create a sub-window */
@ -406,42 +372,42 @@ S9xXVDisplayDriver::init ()
vi_template.visualid = visualid;
vi_template.depth = depth;
vi_template.visual = NULL;
vi = XGetVisualInfo (display, VisualIDMask | VisualDepthMask, &vi_template, &vi_num_items);
vi = XGetVisualInfo(display, VisualIDMask | VisualDepthMask, &vi_template, &vi_num_items);
if (!vi)
{
vi_template.depth = 0;
vi = XGetVisualInfo (display, VisualIDMask, &vi_template, &vi_num_items);
vi = XGetVisualInfo(display, VisualIDMask, &vi_template, &vi_num_items);
if (!vi)
{
fprintf (stderr, "Couldn't map visual.\n");
fprintf(stderr, "Couldn't map visual.\n");
return -1;
}
}
xcolormap = XCreateColormap (display,
gdk_x11_window_get_xid (gtk_widget_get_window (drawing_area)),
xcolormap = XCreateColormap(display,
gdk_x11_window_get_xid(drawing_area->get_window()->gobj()),
vi->visual,
AllocNone);
create_window (1, 1);
gdk_window_hide (gdk_window);
create_window(1, 1);
gdk_window_hide(gdk_window);
/* Allocate a shared memory image. */
xv_image = XvShmCreateImage (display,
xv_portid,
format,
0,
scaled_max_width,
scaled_max_width,
&shm);
xv_image = XvShmCreateImage(display,
xv_portid,
format,
0,
512,
512,
&shm);
shm.shmid = shmget (IPC_PRIVATE, xv_image->data_size, IPC_CREAT | 0777);
shm.shmaddr = (char *) shmat (shm.shmid, 0, 0);
if (shm.shmaddr == (void *) -1)
shm.shmid = shmget(IPC_PRIVATE, xv_image->data_size, IPC_CREAT | 0777);
shm.shmaddr = (char *)shmat(shm.shmid, 0, 0);
if (shm.shmaddr == (void *)-1)
{
fprintf (stderr, "Could not attach shared memory segment.\n");
fprintf(stderr, "Could not attach shared memory segment.\n");
return -1;
}
@ -449,71 +415,38 @@ S9xXVDisplayDriver::init ()
xv_image->data = shm.shmaddr;
XShmAttach (display, &shm);
XShmAttach(display, &shm);
desired_width = scaled_max_width;
desired_height = scaled_max_width;
buffer[0] = new uint8_t[image_padded_size];
buffer[1] = new uint8_t[scaled_padded_size];
padded_buffer[0] = &buffer[0][image_padded_offset];
padded_buffer[1] = &buffer[1][scaled_padded_offset];
memset (buffer[0], 0, image_padded_size);
memset (buffer[1], 0, scaled_padded_size);
clear_buffers ();
/* Give Snes9x core a pointer to draw on */
GFX.Screen = (uint16 *) padded_buffer[0];
GFX.Pitch = image_width * image_bpp;
xv_image_width = 512;
xv_image_height = 512;
return 0;
}
void
S9xXVDisplayDriver::deinit ()
void S9xXVDisplayDriver::deinit()
{
gdk_window_destroy (gdk_window);
gdk_window_destroy(gdk_window);
XShmDetach (display, &shm);
XSync (display, 0);
XShmDetach(display, &shm);
XSync(display, 0);
XFreeColormap (display, xcolormap);
XFree (vi);
XFreeColormap(display, xcolormap);
XFree(vi);
delete[] buffer[0];
delete[] buffer[1];
shmctl (shm.shmid, IPC_RMID, 0);
shmdt (shm.shmaddr);
padded_buffer[0] = NULL;
padded_buffer[1] = NULL;
shmctl(shm.shmid, IPC_RMID, 0);
shmdt(shm.shmaddr);
}
void
S9xXVDisplayDriver::clear ()
void S9xXVDisplayDriver::clear()
{
int width, height;
GtkAllocation allocation;
GC xgc = XDefaultGC (display, XDefaultScreen (display));
GC xgc = XDefaultGC(display, XDefaultScreen(display));
gtk_widget_get_allocation (drawing_area, &allocation);
#if GTK_CHECK_VERSION(3,10,0)
int gdk_scale_factor = gdk_window_get_scale_factor (gdk_window);
allocation.width *= gdk_scale_factor;
allocation.height *= gdk_scale_factor;
#endif
width = allocation.width;
height = allocation.height;
int width = drawing_area->get_width() * drawing_area->get_scale_factor();
int height = drawing_area->get_height() * drawing_area->get_scale_factor();
if (window->last_width <= 0 || window->last_height <= 0)
{
XDrawRectangle (display, xwindow, xgc, 0, 0, width, height);
XDrawRectangle(display, xwindow, xgc, 0, 0, width, height);
return;
}
@ -521,107 +454,58 @@ S9xXVDisplayDriver::clear ()
S9xRect dst;
dst.w = window->last_width;
dst.h = window->last_height;
get_filter_scale (dst.w, dst.h);
dst = S9xApplyAspect (dst.w, dst.h, width, height);
get_filter_scale(dst.w, dst.h);
dst = S9xApplyAspect(dst.w, dst.h, width, height);
if (dst.x > 0)
{
XFillRectangle (display, xwindow, xgc, 0, dst.y, dst.x, dst.h);
XFillRectangle(display, xwindow, xgc, 0, dst.y, dst.x, dst.h);
}
if (dst.x + dst.w < width)
{
XFillRectangle (display, xwindow, xgc, dst.x + dst.w, dst.y, width - (dst.x + dst.w), dst.h);
XFillRectangle(display, xwindow, xgc, dst.x + dst.w, dst.y, width - (dst.x + dst.w), dst.h);
}
if (dst.y > 0)
{
XFillRectangle (display, xwindow, xgc, 0, 0, width, dst.y);
XFillRectangle(display, xwindow, xgc, 0, 0, width, dst.y);
}
if (dst.y + dst.h < height)
{
XFillRectangle (display, xwindow, xgc, 0, dst.y + dst.h, width, height - (dst.y + dst.h));
XFillRectangle(display, xwindow, xgc, 0, dst.y + dst.h, width, height - (dst.y + dst.h));
}
XSync (display, False);
XSync(display, False);
}
void
S9xXVDisplayDriver::refresh (int width, int height)
void S9xXVDisplayDriver::refresh(int width, int height)
{
clear ();
clear();
}
uint16 *
S9xXVDisplayDriver::get_next_buffer ()
{
return (uint16 *) padded_buffer[0];
}
uint16 *
S9xXVDisplayDriver::get_current_buffer ()
{
return get_next_buffer ();
}
void
S9xXVDisplayDriver::push_buffer (uint16 *src)
{
memmove (GFX.Screen, src, image_size * image_bpp);
}
void
S9xXVDisplayDriver::clear_buffers ()
{
uint32 black;
uint8 *color;
memset (buffer[0], 0, image_padded_size);
memset (buffer[1], 0, scaled_padded_size);
/* Construct value byte-order independently */
if (format == FOURCC_YUY2)
{
color = (uint8 *) &black;
*color++ = y_table[0];
*color++ = u_table[0];
*color++ = y_table[0];
*color++ = v_table[0];
for (int i = 0; i < xv_image->data_size >> 2; i++)
{
*(((uint32 *) xv_image->data) + i) = black;
}
}
else
{
memset (xv_image->data, 0, xv_image->data_size);
}
}
int
S9xXVDisplayDriver::query_availability ()
int S9xXVDisplayDriver::query_availability()
{
unsigned int p_version,
p_release,
p_request_base,
p_event_base,
p_error_base;
Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
p_release,
p_request_base,
p_event_base,
p_error_base;
Display *display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
if (!display)
return 0;
/* Test if XV and SHM are feasible */
if (!XShmQueryExtension (display))
if (!XShmQueryExtension(display))
{
return 0;
}
if (XvQueryExtension (display,
&p_version,
&p_release,
&p_request_base,
&p_event_base,
&p_error_base) != Success)
if (XvQueryExtension(display,
&p_version,
&p_release,
&p_request_base,
&p_event_base,
&p_error_base) != Success)
{
return 0;
}

View File

@ -7,63 +7,67 @@
#ifndef __GTK_DISPLAY_DRIVER_XV_H
#define __GTK_DISPLAY_DRIVER_XV_H
#include "gtk_s9x.h"
#include "gtk_display_driver.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/XShm.h>
#include <X11/extensions/Xvlib.h>
#include "gtk_s9x.h"
#include "gtk_display_driver.h"
const uint32 FOURCC_YUY2 = 0x32595559;
class S9xXVDisplayDriver : public S9xDisplayDriver
{
public:
S9xXVDisplayDriver (Snes9xWindow *window, Snes9xConfig *config);
void refresh (int width, int height);
int init ();
void deinit ();
void clear_buffers ();
void update (int width, int height, int yoffset);
uint16 *get_next_buffer ();
uint16 *get_current_buffer ();
void push_buffer (uint16 *src);
void *get_parameters () { return NULL; }
void save (const char *filename) { }
static int query_availability ();
bool is_ready () { return true; }
public:
S9xXVDisplayDriver(Snes9xWindow *window, Snes9xConfig *config);
void refresh(int width, int height);
int init();
void deinit();
void update(uint16_t *buffer, int width, int height, int stride_in_pixels);
void *get_parameters()
{
return NULL;
}
void save(const char *filename)
{
}
static int query_availability();
bool is_ready()
{
return true;
}
private:
void clear ();
void update_image_size (int width, int height);
void resize_window (int width, int height);
void create_window (int width, int height);
private:
void clear();
void update_image_size(int width, int height);
void resize_window(int width, int height);
void create_window(int width, int height);
Display *display;
Window xwindow;
Colormap xcolormap;
XVisualInfo *vi;
GdkWindow *gdk_window;
Display *display;
Window xwindow;
Colormap xcolormap;
XVisualInfo *vi;
GdkWindow *gdk_window;
XvImage *xv_image;
int xv_portid;
XShmSegmentInfo shm;
XvImage *xv_image;
int xv_portid;
XShmSegmentInfo shm;
int output_window_width;
int output_window_height;
int last_known_width;
int last_known_height;
int desired_width;
int desired_height;
int format;
int bpp;
int bytes_per_pixel;
int rshift, gshift, bshift;
int output_window_width;
int output_window_height;
int last_known_width;
int last_known_height;
int xv_image_width;
int xv_image_height;
int format;
int bpp;
int bytes_per_pixel;
int rshift, gshift, bshift;
uint8 y_table[65536];
uint8 u_table[65536];
uint8 v_table[65536];
uint8 y_table[65536];
uint8 u_table[65536];
uint8 v_table[65536];
};
#endif /* __GTK_DISPLAY_DRIVER_XV_H */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 581 B

View File

@ -285,7 +285,7 @@
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="button7">
<object class="GtkButton" id="cheats_close">
<property name="label">gtk-close</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
@ -351,7 +351,7 @@
<property name="border_width">5</property>
<property name="spacing">5</property>
<child>
<object class="GtkButton" id="button4">
<object class="GtkButton" id="add_code">
<property name="label">gtk-add</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
@ -369,7 +369,7 @@
</packing>
</child>
<child>
<object class="GtkButton" id="button5">
<object class="GtkButton" id="remove_code">
<property name="label">gtk-remove</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
@ -551,7 +551,7 @@
</object>
</child>
<action-widgets>
<action-widget response="0">button7</action-widget>
<action-widget response="0">cheats_close</action-widget>
</action-widgets>
</object>
<object class="GtkDialog" id="frame_advance_dialog">
@ -823,6 +823,12 @@
<row>
<col id="0" translatable="yes">Color bars and patterns</col>
</row>
<row>
<col id="0" translatable="yes">Starfield</col>
</row>
<row>
<col id="0" translatable="yes">Snow</col>
</row>
</data>
</object>
<object class="GtkListStore" id="liststore1">
@ -2268,7 +2274,7 @@
</packing>
</child>
<child>
<object class="GtkButton" id="button11">
<object class="GtkButton" id="clear_netplay">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
@ -2695,7 +2701,7 @@
</packing>
</child>
<child>
<object class="GtkButton" id="button8">
<object class="GtkButton" id="about_button">
<property name="label">gtk-about</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
@ -4197,11 +4203,11 @@
</child>
<child>
<object class="GtkCheckButton" id="mute_sound_turbo_check">
<property name="label" translatable="yes">Mute sound when using turbo</property>
<property name="label" translatable="yes">Mute sound when using turbo or rewind</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Disables output of sound when using turbo</property>
<property name="tooltip_text" translatable="yes">Disables output of sound when using turbo or rewind</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</object>
@ -5440,7 +5446,7 @@
</packing>
</child>
<child>
<object class="GtkButton" id="button6">
<object class="GtkButton" id="reset_current_joypad">
<property name="label" translatable="yes">_Reset</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
@ -5496,7 +5502,7 @@
</packing>
</child>
<child>
<object class="GtkButton" id="button12">
<object class="GtkButton" id="swap_with">
<property name="label" translatable="yes">_Swap</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
@ -9314,7 +9320,7 @@
<action-widget response="-6">cancel_button</action-widget>
<action-widget response="-10">ok_button</action-widget>
<action-widget response="-5">button1</action-widget>
<action-widget response="0">button8</action-widget>
<action-widget response="0">about_button</action-widget>
</action-widgets>
</object>
<object class="GtkTextBuffer" id="textbuffer1">

View File

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

View File

@ -61,4 +61,5 @@ SOURCES_CXX := $(CORE_DIR)/apu/apu.cpp \
$(CORE_DIR)/sha256.cpp \
$(CORE_DIR)/bml.cpp \
$(CORE_DIR)/movie.cpp \
$(CORE_DIR)/compat.cpp \
$(CORE_DIR)/libretro/libretro.cpp

View File

@ -97,7 +97,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='libretro Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>../;../apu/bapu;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>../;../apu/bapu;../libretro;libretro-common/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>__WIN32__;__LIBRETRO__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@ -120,7 +120,7 @@
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>../;../apu/bapu;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>../;../apu/bapu;../libretro;libretro-common/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>__WIN32__;__LIBRETRO__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@ -143,7 +143,7 @@
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>../;../apu/bapu;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>../;../apu/bapu;../libretro;libretro-common/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>__WIN32__;__LIBRETRO__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
@ -170,7 +170,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<AdditionalIncludeDirectories>../;../apu/bapu;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>../;../apu/bapu;../libretro;libretro-common/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>__WIN32__;__LIBRETRO__;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>

View File

@ -609,10 +609,10 @@ static void update_variables(void)
var.key = "snes9x_echo_buffer_hack";
var.value = NULL;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var))
Settings.SeparateEchoBuffer = !strcmp(var.value, "disabled") ? false : true;
else
else
Settings.SeparateEchoBuffer = false;
var.key = "snes9x_blargg";
@ -1135,7 +1135,7 @@ bool retro_load_game(const struct retro_game_info *game)
if (rom_loaded)
{
/* If we're in RGB565 format, switch frontend to that */
if (RED_SHIFT_BITS == 11)
if (RED_SHIFT_BITS == 11)
{
enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565;
if (!environ_cb || !environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt))
@ -1152,7 +1152,7 @@ bool retro_load_game(const struct retro_game_info *game)
for(int lcv = 0; lcv < 0x20000; lcv++)
Memory.RAM[lcv] = rand() % 256;
}
// restore disabled sound channels
if (disabled_channels)
{
@ -1393,7 +1393,7 @@ void retro_init(void)
S9xUnmapAllControls();
map_buttons();
check_system_specs();
if (environ_cb(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL))
libretro_supports_bitmasks = true;
}
@ -1728,7 +1728,7 @@ static void report_buttons()
for (int i = BTN_FIRST; i <= BTN_LAST; i++)
S9xReportButton(MAKE_BUTTON(port * offset + j + 1, i), joy_bits & (1 << i));
}
}
break;
case RETRO_DEVICE_MOUSE:
@ -1894,7 +1894,7 @@ void retro_deinit()
free(screen_buffer);
free(ntsc_screen_buffer);
libretro_supports_bitmasks = false;
libretro_supports_bitmasks = false;
}
@ -2007,7 +2007,7 @@ bool retro_unserialize(const void* data, size_t size)
{
S9xSetSoundControl(disabled_channels^0xFF);
}
return true;
}
@ -2165,7 +2165,6 @@ const char* S9xGetDirectory(s9x_getdirtype type)
return "";
}
void S9xInitInputDevices() {}
const char* S9xChooseFilename(unsigned char) { return ""; }
void S9xHandlePortCommand(s9xcommand_t, short, short) {}
bool S9xPollButton(uint32, bool*) { return false; }
void S9xToggleSoundChannel(int) {}
@ -2175,12 +2174,10 @@ bool8 S9xInitUpdate() { return TRUE; }
void S9xExtraUsage() {}
bool8 S9xOpenSoundDevice() { return TRUE; }
bool S9xPollAxis(uint32, short*) { return FALSE; }
void S9xSetPalette() {}
void S9xParseArg(char**, int&, int) {}
void S9xExit() {}
bool S9xPollPointer(uint32, short*, short*) { return false; }
const char *S9xChooseMovieFilename(unsigned char) { return NULL; }
void S9xMessage(int type, int, const char* s)
{
if (!log_cb) return;
@ -2233,66 +2230,3 @@ void S9xAutoSaveSRAM()
{
return;
}
#ifndef __WIN32__
// S9x weirdness.
void _splitpath (const char *path, char *drive, char *dir, char *fname, char *ext)
{
*drive = 0;
const char *slash = strrchr(path, SLASH_CHAR),
*dot = strrchr(path, '.');
if (dot && slash && dot < slash)
dot = NULL;
if (!slash)
{
*dir = 0;
strcpy(fname, path);
if (dot)
{
fname[dot - path] = 0;
strcpy(ext, dot + 1);
}
else
*ext = 0;
}
else
{
strcpy(dir, path);
dir[slash - path] = 0;
strcpy(fname, slash + 1);
if (dot)
{
fname[dot - slash - 1] = 0;
strcpy(ext, dot + 1);
}
else
*ext = 0;
}
}
void _makepath (char *path, const char *, const char *dir, const char *fname, const char *ext)
{
if (dir && *dir)
{
strcpy(path, dir);
strcat(path, SLASH_STR);
}
else
*path = 0;
strcat(path, fname);
if (ext && *ext)
{
strcat(path, ".");
strcat(path, ext);
}
}
#endif // __WIN32__

3
macosx/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
Build
.DS_Store
xcuserdata

View File

@ -1,118 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en-US">
<head>
<meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
<meta http-equiv="content-style-type" content="text/css">
<meta name="description" content="References">
<link href="../sty/style.css" rel="stylesheet">
<title>References</title>
</head>
<body>
<h2>References</h2>
<h3>Preferences Dialog</h3>
<h4>Graphics Tab</h4>
<dl>
<dt>Full Screen Mode</dt>
<dd>Toggles full screen/windowed mode. Press esc key to hide full screen window and pause the game.</dd>
<dt>Switch Monitor Resolution</dt>
<dd>Toggles between scaling full screen graphics to the current screen resolution or changing the screen resolution to fit Snes9x's needs.</dd>
<dt>Show Frame Rate</dt>
<dd>Toggles display of the frame rate on/off.</dd>
<dt>Transparency Effects</dt>
<dd>Toggles transparency effects on/off. Transparency effect is used in almost all games so this option is just for hack.</dd>
<dt>Video Mode</dt>
<dd>Choose the image scaling filter which is applied to the raw SNES image.</dd>
<dt>Multitask</dt>
<dd>When this option is on, the rendering process is separated from the emulation thread (except blocky and smooth modes).</dd>
<dt>Keep Overscanned Height</dt>
<dd>Keeps the screen height always 239/478, for some games that change screen height frequently.</dd>
<dt>Sync to Vertical Blank</dt>
<dd>Synchronizes the render timing to the monitor's vertical refresh rate.</dd>
<dt>Stretch Image in Full Screen Mode</dt>
<dd>Stretches the image to fill the screen in full screen mode.</dd>
<dt>Aspect Ratio</dt>
<dd>The aspect ratio of above option: the left is proportional and the right is full width of the monitor.</dd>
<dt>Use Core Image</dt>
<dd>Applies additional Core Image effect after the image filter is applied.</dd>
<dt>Filter...</dt>
<dd>Choose the Core Image filter.</dd>
<dt>Use 32 Bit Color</dt>
<dd>Uses 16,777,216 colors.</dd>
<dt>Use Screen Curvature</dt>
<dd>Adds a warp effect like a CRT-based television.</dd>
<dt>Warp</dt>
<dd>The degree of curvature.</dd>
</dl>
<h4>Sound Tab</h4>
<dl>
<dt>Synchronize</dt>
<dd>Tries and ensures all available samples are buffered so there are no overruns.</dd>
<dt>16 Bit Playback</dt>
<dd>Enables 16-bit playback instead of 8-bit.</dd>
<dt>Stereo</dt>
<dd>Enables stereo sound instead of mono.</dd>
<dt>Reverse Stereo</dt>
<dd>Swaps the left and right stereo channels.</dd>
<dt>Effect...</dt>
<dd>Opens 'Sound Effect' dialog.</dd>
<dt>Playback Rate</dt>
<dd>The real SNES is 32040 Hz. Any values other than 32040 Hz will cause resampling.</dd>
<dt>Output Interval</dt>
<dd>Make sure this value is smaller than the mix buffer length.</dd>
<dt>Mix Buffer Length</dt>
<dd>Too short length will cause crackling noise.</dd>
<dt>Allow Lag</dt>
<dd>Safer from crackling noise, but time-lag becomes more noticeable.</dd>
<dt>Volume</dt>
<dd>Volume of the whole Snes9x sounds.</dd>
<dt>Input Rate</dt>
<dd>Adjusts the sound rate through resampling. For every Input Rate samples generated by the SNES, Playback Rate samples will be produced.</dd>
</dl>
<h4>File Tab</h4>
<dl>
<dt>Save Data in</dt>
<dd>Choose the folder where Snes9x will look for files.</dd>
<dt>Auto Save SRAM</dt>
<dd>Updates SRAM file when SRAM contents are modified. This may cause frequent disk access.</dd>
</dl>
<h4>Accuracy Tab</h4>
<dl>
<dt>HDMA Timing Hack</dt>
<dd>Changes HDMA timing and will 'fix' some games' glitches, but breaks many other games. The default value is 100.</dd>
<dt>Skip CPU Emulation Until the Next Event Comes</dt>
<dd>Skips internal CPU emulation for speed-ups until the next event comes.</dd>
<dt>Allow Invalid VRAM Access</dt>
<dd>Allows to write to VRAM outside blank periods.</dd>
<dt>Apply Specific Game Hacks</dt>
<dd>Applies special hacks for games that can't be emulated correctly.</dd>
<dt>Frame Skip</dt>
<dd>Adjust this value if your Mac is slow.</dd>
<dt>Speed in Turbo Mode</dt>
<dd>The speed when turbo mode is on. Modify in-game with Fn+T, Fn+Y.</dd>
</dl>
<h4>Others Tab</h4>
<dl>
<dt>Toggle Turbo Button</dt>
<dd>Sets 'Turbo' button as a toggle switch.</dd>
<dt>Show Onscreen Information</dt>
<dd>Shows messages from Snes9x on the game screen. When off, messages are put in the standard console.</dd>
<dt>Open Choose ROM Image Dialog at Startup</dt>
<dd>Choose whether open dialog should be shown when Snes9x is launched.</dd>
<dt>Show Dates and Times in Freeze State Selection Screen</dt>
<dd>Shows time stamps on thumbnails in freeze/defrost screen.</dd>
<dt>Save Window Size and Position</dt>
<dd>Saves the sizes and positions of the game window and dialogs so they come back to the same place.</dd>
<dt>Use IPS / UPS Patch</dt>
<dd>When this option is on, Snes9x automatically loads the .ips or .ups file and patch the ROM image.</dd>
<dt>Boot Up BS Games from BS-X</dt>
<dd>When this option is on, BS-X ROM is loaded first, then you launch BS games from the menu in BS-X.</dd>
<dt>When in Background</dt>
<dd>Choose the behavior of Snes9x when it is in back of other applications.</dd>
<dt>Music Box</dt>
<dd>Choose the behavior of Music Box: 'Sound Emulation Only' to only emulate the music system, and 'Whole Emulation' to also emulate the CPU. Music that depends on the CPU running will not sound right without 'Whole Emulation.'</dd>
</dl>
<div style="text-align:center; margin-top:3em"><p>
&lt;<a href="13.html">Prev</a>&nbsp;&nbsp;<a href="../index.html">Top</a>&nbsp;&nbsp;<a href="15.html">Next</a>&gt;
</p></div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -51,7 +51,7 @@
/*****************************************************/
#if !TARGET_RT_MAC_CFM
#include <IOKit/hid/IOHIDLib.h>
#endif TARGET_RT_MAC_CFM
#endif // TARGET_RT_MAC_CFM
//#include <IOKit/hid/IOHIDUsageTables.h>
#if 0 // NOTE: These are now in <IOKit/hid/IOHIDUsageTables.h>
@ -109,7 +109,7 @@ typedef enum IOHIDReportType {
// Notes: This is a MachO function pointer. If you're using CFM you have to call MachOFunctionPointerForCFMFunctionPointer.
typedef void( *IOHIDCallbackFunction ) ( void* target, unsigned long result, void* refcon, void* sender );
typedef void* IOHIDEventStruct;
#endif TARGET_RT_MAC_CFM
#endif // TARGET_RT_MAC_CFM
// Device and Element Interfaces

View File

@ -160,7 +160,7 @@
</dict>
</array>
<key>CFBundleExecutable</key>
<string>Snes9x</string>
<string>Snes9x (i386)</string>
<key>CFBundleGetInfoString</key>
<string>Snes9x 1.60, Copyright 1996-2019 Snes9x developers.</string>
<key>CFBundleHelpBookFolder</key>
@ -170,7 +170,7 @@
<key>CFBundleIconFile</key>
<string>APPL.icns</string>
<key>CFBundleIdentifier</key>
<string>com.snes9x.macos.snes9x</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>

View File

@ -1,189 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>jma</string>
</array>
<key>CFBundleTypeName</key>
<string>JMA archive</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>JMAf</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSTypeIsPackage</key>
<false/>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>sfc</string>
<string>smc</string>
<string>swc</string>
<string>fig</string>
<string>gd3</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>CART.icns</string>
<key>CFBundleTypeName</key>
<string>Snes9x ROM Image</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>CART</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSTypeIsPackage</key>
<false/>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>srm</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>SRAM.icns</string>
<key>CFBundleTypeName</key>
<string>Snes9x SRAM Data</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>SRAM</string>
</array>
<key>CFBundleTypeRole</key>
<string>None</string>
<key>LSTypeIsPackage</key>
<false/>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>frz</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>SAVE.icns</string>
<key>CFBundleTypeName</key>
<string>Snes9x Freeze Data</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>SAVE</string>
</array>
<key>CFBundleTypeRole</key>
<string>None</string>
<key>LSTypeIsPackage</key>
<false/>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>smv</string>
</array>
<key>CFBundleTypeName</key>
<string>Snes9x Movie Data</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>SMOV</string>
</array>
<key>CFBundleTypeRole</key>
<string>None</string>
<key>LSTypeIsPackage</key>
<false/>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>spc</string>
</array>
<key>CFBundleTypeName</key>
<string>Snes9x SPC Data</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>SSPC</string>
</array>
<key>CFBundleTypeRole</key>
<string>None</string>
<key>LSTypeIsPackage</key>
<false/>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>cht</string>
</array>
<key>CFBundleTypeName</key>
<string>Snes9x Cheat Data</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>SCHT</string>
</array>
<key>CFBundleTypeRole</key>
<string>None</string>
<key>LSTypeIsPackage</key>
<false/>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>rtc</string>
</array>
<key>CFBundleTypeName</key>
<string>Snes9x RTC Data</string>
<key>CFBundleTypeOSTypes</key>
<array>
<string>SRTC</string>
</array>
<key>CFBundleTypeRole</key>
<string>None</string>
<key>LSTypeIsPackage</key>
<false/>
</dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>*</string>
</array>
<key>CFBundleTypeOSTypes</key>
<array>
<string>****</string>
</array>
<key>CFBundleTypeRole</key>
<string>None</string>
<key>LSTypeIsPackage</key>
<false/>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>Snes9x (i386)</string>
<key>CFBundleGetInfoString</key>
<string>Snes9x 1.60, Copyright 1996-2019 Snes9x developers.</string>
<key>CFBundleHelpBookFolder</key>
<string>Snes9x Help</string>
<key>CFBundleHelpBookName</key>
<string>Snes9x Help</string>
<key>CFBundleIconFile</key>
<string>APPL.icns</string>
<key>CFBundleIdentifier</key>
<string>com.snes9x.macos.snes9x</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Snes9x</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.60</string>
<key>CFBundleSignature</key>
<string>~9X~</string>
<key>CFBundleVersion</key>
<string>1.60</string>
<key>CSResourcesFileMapped</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,28 @@
/*
* EndianStuff.h
* stackimport
*
* Created by Mr. Z. on 10/06/06.
* Copyright 2006 Mr Z. All rights reserved.
*
*/
#pragma once
#include <stdint.h>
#if RECLASSIFICATION_BUILD_BIG_ENDIAN
#define BIG_ENDIAN_16(value) (value)
#define BIG_ENDIAN_32(value) (value)
#else
#define BIG_ENDIAN_16(value) \
(((((uint16_t)(value))<<8) & 0xFF00) | \
((((uint16_t)(value))>>8) & 0x00FF))
#define BIG_ENDIAN_32(value) \
(((((uint32_t)(value))<<24) & 0xFF000000) | \
((((uint32_t)(value))<< 8) & 0x00FF0000) | \
((((uint32_t)(value))>> 8) & 0x0000FF00) | \
((((uint32_t)(value))>>24) & 0x000000FF))
#endif

View File

@ -0,0 +1,269 @@
/* ===========================================================================
PROJECT: FakeHandles
FILE: FakeHandles.c
PURPOSE: Simulate Handles on machines which only have ANSI-C to easily
port some of the more simple Macintosh code fragments to other
platforms.
(C) Copyright 1998 by Uli Kusterer, all rights reserved.
======================================================================== */
#pragma mark [Headers]
// -----------------------------------------------------------------------------
// Headers:
// -----------------------------------------------------------------------------
#include "FakeHandles.h"
// -----------------------------------------------------------------------------
// Globals:
// -----------------------------------------------------------------------------
/* The last entry in the master pointer array is mis-used to hold a pointer
to another master pointer array. Thus, we have a linked list of master
pointer arrays in RAM, and we don't run out of master pointers as easily. */
MasterPointer gMasterPointers[MASTERPOINTER_CHUNK_SIZE];
long gFakeHandleError = noErr;
/* -----------------------------------------------------------------------------
FakeInitHandles:
Call this to initialize the fake memory Manager at the start of your
program. Only call this once or you'll lose all your Handles and will have
stale memory lying around. Pass the global gMasterPointers in
masterPtrArray.
REVISIONS:
98-08-30 UK Created.
----------------------------------------------------------------------------- */
void FakeInitHandles( MasterPointer* masterPtrArray )
{
long x;
for( x = 0; x < MASTERPOINTER_CHUNK_SIZE; x++ )
{
masterPtrArray[x].actualPointer = NULL;
masterPtrArray[x].used = false;
masterPtrArray[x].memoryFlags = 0;
masterPtrArray[x].size = 0;
}
gFakeHandleError = noErr;
}
/* -----------------------------------------------------------------------------
FakeMoreMasters:
Call this if you need more master pointers Called internally by
FakeNewHandle() when it runs out of master pointers.
REVISIONS:
98-08-30 UK Created.
----------------------------------------------------------------------------- */
void FakeMoreMasters()
{
long x;
MasterPointer* vMPtrBlock;
MasterPointer* vCurrBlock;
// Make a new master pointer block:
vMPtrBlock = malloc( MASTERPOINTER_CHUNK_SIZE *sizeof(MasterPointer) );
if( vMPtrBlock == NULL )
{
gFakeHandleError = memFulErr;
return;
}
// Clear it:
for( x = 0; x < MASTERPOINTER_CHUNK_SIZE; x++ )
{
vMPtrBlock[x].actualPointer = NULL;
vMPtrBlock[x].used = false;
vMPtrBlock[x].memoryFlags = 0;
vMPtrBlock[x].size = 0;
}
// Find last master pointer in last master pointer block:
vCurrBlock = gMasterPointers;
while( vCurrBlock[MASTERPOINTER_CHUNK_SIZE -1].used == true )
vCurrBlock = (MasterPointer*) vCurrBlock[MASTERPOINTER_CHUNK_SIZE-1].actualPointer;
// Make this last master pointer point to our new block:
vCurrBlock[MASTERPOINTER_CHUNK_SIZE-1].actualPointer = (char*) vMPtrBlock;
vCurrBlock[MASTERPOINTER_CHUNK_SIZE-1].used = true;
vMPtrBlock[MASTERPOINTER_CHUNK_SIZE-1].size = MASTERPOINTER_CHUNK_SIZE *sizeof(MasterPointer);
gFakeHandleError = noErr;
}
Handle FakeNewEmptyHandle()
{
Handle theHandle = NULL;
long x;
MasterPointer* vCurrBlock = gMasterPointers;
bool notFound = true;
gFakeHandleError = noErr;
while( notFound )
{
for( x = 0; x < (MASTERPOINTER_CHUNK_SIZE-1); x++ )
{
if( !(vCurrBlock[x].used) )
{
vCurrBlock[x].used = true;
vCurrBlock[x].memoryFlags = 0;
vCurrBlock[x].size = 0;
theHandle = (Handle) &(vCurrBlock[x]);
notFound = false;
break;
}
}
if( !vCurrBlock[MASTERPOINTER_CHUNK_SIZE-1].used ) // Last is unused? We need a new master pointer block!
{
FakeMoreMasters();
if( !vCurrBlock[MASTERPOINTER_CHUNK_SIZE-1].used ) // No new block added?!
notFound = false; // Terminate, it's very likely an error occurred.
}
vCurrBlock = (MasterPointer*) vCurrBlock[MASTERPOINTER_CHUNK_SIZE-1].actualPointer; // Go next master pointer block.
}
return theHandle;
}
/* -----------------------------------------------------------------------------
NewHandle:
Create a new Handle. This creates a new entry in the Master Ptr array and
allocates memory of the specified size for it. Then it returns a Ptr to
this entry.
Returns NULL if not successful. If MemError() is noErr upon a NULL return
value, we are out of master pointers.
REVISIONS:
2001-02-16 UK Added support for error codes.
1998-08-30 UK Created.
----------------------------------------------------------------------------- */
Handle FakeNewHandle( long theSize )
{
MasterPointer * theHandle = (MasterPointer*) FakeNewEmptyHandle();
theHandle->actualPointer = malloc( theSize );
if( theHandle->actualPointer == NULL )
{
FakeDisposeHandle( (Handle) theHandle );
gFakeHandleError = memFulErr;
}
else
theHandle->size = theSize;
return (Handle)theHandle;
}
/* -----------------------------------------------------------------------------
DisposeHandle:
Dispose an existing Handle. Only call this once or you might kill valid
memory or worse.
This frees the memory we use and marks the entry for the specified Handle
as unused.
REVISIONS:
1998-08-30 UK Created.
----------------------------------------------------------------------------- */
void FakeDisposeHandle( Handle theHand )
{
MasterPointer* theEntry = (MasterPointer*) theHand;
if( theEntry->actualPointer )
free( theEntry->actualPointer );
theEntry->used = false;
theEntry->actualPointer = NULL;
theEntry->memoryFlags = 0;
theEntry->size = 0;
}
void FakeEmptyHandle( Handle theHand )
{
MasterPointer* theEntry = (MasterPointer*) theHand;
if( theEntry->actualPointer )
free( theEntry->actualPointer );
theEntry->actualPointer = NULL;
}
/* -----------------------------------------------------------------------------
GetHandleSize:
Return the size of an existing Handle. This simply examines the "size"
field of the Handle's entry.
REVISIONS:
1998-08-30 UK Created.
----------------------------------------------------------------------------- */
long FakeGetHandleSize( Handle theHand )
{
MasterPointer* theEntry = (MasterPointer*) theHand;
gFakeHandleError = noErr;
return( theEntry->size );
}
/* -----------------------------------------------------------------------------
SetHandleSize:
Change the size of an existing Handle. This reallocates the Handle (keeping
its data) and updates the size field of the Handle's entry accordingly.
REVISIONS:
1998-08-30 UK Created.
----------------------------------------------------------------------------- */
void FakeSetHandleSize( Handle theHand, long theSize )
{
MasterPointer* theEntry = (MasterPointer*) theHand;
char* thePtr;
thePtr = theEntry->actualPointer;
thePtr = realloc( thePtr, theSize );
if( thePtr )
{
theEntry->actualPointer = thePtr;
theEntry->size = theSize;
gFakeHandleError = noErr;
}
else
gFakeHandleError = memFulErr;
}

View File

@ -0,0 +1,114 @@
/* ===========================================================================
PROJECT: FakeHandles
FILE: FakeHandles.h
PURPOSE: Simulate Handles on machines which only have ANSI-C to easily
port some of the more simple Macintosh code fragments to other
platforms.
(C) Copyright 1998 by Uli Kusterer, all rights reserved.
DIRECTIONS:
A Handle is a memory block that remembers its size automatically.
To the user, a Handle is simply a pointer to a pointer to the actual
data. Dereference it twice to get at the actual data. Before you
pass a once-dereferenced Handle to any other functions, you need to
call HLock() on it to avoid that it moves. Call HUnlock() when you
are finished with that.
To create a Handle, use NewHandle(). To free a Handle, call
DisposeHandle(). To resize use SetHandleSize() (the Handle itself
will not change, but the pointer to the actual data may change),
GetHandleSize() returns the actual size of the Handle.
Before making any of these calls, you *must have* called
InitHandles().
======================================================================== */
#ifndef FAKEHANDLES_H
#define FAKEHANDLES_H
#pragma mark [Headers]
// -----------------------------------------------------------------------------
// Headers:
// -----------------------------------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
// -----------------------------------------------------------------------------
// Constants:
// -----------------------------------------------------------------------------
#ifndef NULL
#define NULL 0L
#endif
#define MASTERPOINTER_CHUNK_SIZE 1024 // Size of blocks of master pointers we allocate in one go.
// Error codes MemError() may return after Handle calls:
enum
{
#ifndef __MACTYPES__
noErr = 0, // No error, success.
#endif /* __MACTYPES__ */
memFulErr = -108 // Out of memory error.
};
// -----------------------------------------------------------------------------
// Data Types:
// -----------------------------------------------------------------------------
// Data types special to Mac:
typedef char** Handle;
#ifndef __MACTYPES__
typedef unsigned char Boolean;
#endif /* __MACTYPES__ */
// Private data structure used internally to keep track of Handles:
typedef struct MasterPointer
{
char* actualPointer; // The actual Pointer we're pointing to.
Boolean used; // Is this master Ptr being used?
long memoryFlags; // Some flags for this Handle.
long size; // The size of this Handle.
} MasterPointer;
// -----------------------------------------------------------------------------
// Globals:
// -----------------------------------------------------------------------------
extern MasterPointer gMasterPointers[MASTERPOINTER_CHUNK_SIZE];
extern long gFakeHandleError;
// -----------------------------------------------------------------------------
// Prototypes:
// -----------------------------------------------------------------------------
extern void FakeInitHandles( MasterPointer* masterPtrArray );
extern Handle FakeNewHandle( long theSize );
extern void FakeDisposeHandle( Handle theHand );
extern long FakeGetHandleSize( Handle theHand );
extern void FakeSetHandleSize( Handle theHand, long theSize );
extern void FakeMoreMasters( void );
extern Handle FakeNewEmptyHandle();
extern void FakeEmptyHandle( Handle theHand );
#endif /*FAKEHANDLES_H*/

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,84 @@
//
// FakeResources.h
// ReClassicfication
//
// Created by Uli Kusterer on 21.02.13.
// Copyright (c) 2013 Uli Kusterer. All rights reserved.
//
#ifndef ReClassicfication_FakeResources_h
#define ReClassicfication_FakeResources_h
#include "FakeHandles.h"
// Possible return values of FakeResError():
#ifndef __MACERRORS__
enum
{
resNotFound = -192,
resFNotFound = -193,
addResFailed = -194,
rmvResFailed = -196,
resAttrErr = -198,
eofErr = -39,
fnfErr = -43
};
#endif /* __MACERRORS__ */
#ifndef __RESOURCES__
// Resource attribute bit flags:
enum
{
resReserved = (1 << 0), // Apparently not yet used.
resChanged = (1 << 1),
resPreload = (1 << 2),
resProtected = (1 << 3),
resLocked = (1 << 4),
resPurgeable = (1 << 5),
resSysHeap = (1 << 6),
resReserved2 = (1 << 7) // Apparently not yet used.
};
#endif
typedef unsigned char FakeStr255[256];
int16_t FakeOpenResFile( const unsigned char* inPath );
void FakeCloseResFile( int16_t resRefNum );
Handle FakeGet1Resource( uint32_t resType, int16_t resID );
Handle FakeGetResource( uint32_t resType, int16_t resID );
int16_t FakeCurResFile();
void FakeUseResFile( int16_t resRefNum );
void FakeUpdateResFile( int16_t inFileRefNum );
int16_t FakeHomeResFile( Handle theResource );
int16_t FakeCount1Types();
int16_t FakeCount1Resources( uint32_t resType );
int16_t FakeCountTypes();
int16_t FakeCountResources( uint32_t resType );
void FakeGet1IndType( uint32_t * resType, int16_t index );
Handle FakeGet1IndResource( uint32_t resType, int16_t index );
void FakeGetResInfo( Handle theResource, int16_t * theID, uint32_t * theType, FakeStr255 * name );
void FakeSetResInfo( Handle theResource, int16_t theID, FakeStr255 name );
void FakeAddResource( Handle theData, uint32_t theType, int16_t theID, FakeStr255 name );
void FakeChangedResource( Handle theResource );
void FakeRemoveResource( Handle theResource );
void FakeWriteResource( Handle theResource );
void FakeLoadResource( Handle theResource );
void FakeReleaseResource( Handle theResource );
void FakeSetResLoad(bool load);
int16_t FakeResError();
// Private calls for internal use/tests:
void FakeRedirectResFileToPath( int16_t inFileRefNum, const char* cPath );
struct FakeResourceMap* FakeResFileOpen( const char* inPath, const char* inMode );
struct FakeResourceMap* FakeFindResourceMap( int16_t inFileRefNum, struct FakeResourceMap*** outPrevMapPtr );
int16_t FakeCount1ResourcesInMap( uint32_t resType, struct FakeResourceMap* inMap );
int16_t FakeCount1TypesInMap( struct FakeResourceMap* inMap );
#endif

View File

@ -0,0 +1,56 @@
/*****************************************************************************\
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
This file is licensed under the Snes9x License.
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
/***********************************************************************************
SNES9X for Mac OS (c) Copyright John Stiles
Snes9x for Mac OS X
(c) Copyright 2001 - 2011 zones
(c) Copyright 2002 - 2005 107
(c) Copyright 2002 PB1400c
(c) Copyright 2004 Alexander and Sander
(c) Copyright 2004 - 2005 Steven Seeger
(c) Copyright 2005 Ryan Vogt
(c) Copyright 2019 Michael Donald Buckley
***********************************************************************************/
#import <Cocoa/Cocoa.h>
#import <snes9x_framework/snes9x_framework.h>
#import "S9xPreferences/S9xPreferencesWindowController.h"
extern NSWindowFrameAutosaveName const kMainWindowIdentifier;
@interface AppDelegate : NSObject <NSApplicationDelegate, S9xInputDelegate>
@property (nonatomic, readonly, assign) BOOL isRunningEmulation;
@property (nonatomic, strong) S9xEngine *s9xEngine;
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSNumber *> *keys;
@property (nonatomic, strong) NSWindow *gameWindow;
@property (nonatomic, strong) S9xPreferencesWindowController *preferencesWindowController;
@property (nonatomic, readonly, assign) S9xDeviceSetting deviceSetting;
- (void)setButtonCode:(S9xButtonCode)buttonCode forKeyCode:(int16)keyCode player:(int8)player;
- (void)clearButton:(S9xButtonCode)button forPlayer:(int8)player;
- (NSArray<S9xJoypad *> *)listJoypads;
- (void)setPlayer:(int8)player forVendorID:(uint32)vendorID productID:(uint32)productID index:(uint32)index;
- (BOOL)setButton:(S9xButtonCode)button forVendorID:(uint32)vendorID productID:(uint32)productID index:(uint32)index cookie:(uint32)cookie value:(int32)value;
- (void)clearJoypadForVendorID:(uint32)vendorID productID:(uint32)productID index:(uint32)index buttonCode:(S9xButtonCode)buttonCode;
- (NSString *)labelForVendorID:(uint32)vendorID productID:(uint32)productID cookie:(uint32)cookie value:(int32)value;
- (NSString *)prefsKeyForVendorID:(uint32)vendorID productID:(uint32)productID index:(uint32)index;
- (BOOL)getValuesFromString:(NSString *)str vendorID:(uint32 *)vendorID productID:(uint32 *)productID index:(uint32 *)index;
- (NSString *)prefValueForCookie:(uint32)cookie value:(int32)value;
- (BOOL)getValuesFromString:(NSString *)str cookie:(uint32 *)cookie value:(int32 *)value;
- (void)setVideoMode:(int)videoMode;
- (void)setMacFrameSkip:(int)_macFrameSkip;
- (void)setShowFPS:(BOOL)showFPS;
@end

564
macosx/Snes9x/AppDelegate.m Normal file
View File

@ -0,0 +1,564 @@
/*****************************************************************************\
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
This file is licensed under the Snes9x License.
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
/***********************************************************************************
SNES9X for Mac OS (c) Copyright John Stiles
Snes9x for Mac OS X
(c) Copyright 2001 - 2011 zones
(c) Copyright 2002 - 2005 107
(c) Copyright 2002 PB1400c
(c) Copyright 2004 Alexander and Sander
(c) Copyright 2004 - 2005 Steven Seeger
(c) Copyright 2005 Ryan Vogt
(c) Copyright 2019 Michael Donald Buckley
***********************************************************************************/
#import <Carbon/Carbon.h>
#import "AppDelegate.h"
NSWindowFrameAutosaveName const kMainWindowIdentifier = @"s9xMainWindow";
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
self.s9xEngine = [S9xEngine new];
self.s9xEngine.inputDelegate = self;
[self setupDefaults];
[self importRecentItems];
NSWindow *gameWindow = [[NSWindow alloc] initWithContentRect:s9xView.frame styleMask:NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSWindowStyleMaskMiniaturizable|NSWindowStyleMaskResizable backing:NSBackingStoreBuffered defer:NO];
gameWindow.contentView.wantsLayer = YES;
gameWindow.contentView.layer.backgroundColor = NSColor.blackColor.CGColor;
gameWindow.title = @"Snes9x";
gameWindow.restorationClass = [self class];
gameWindow.frameAutosaveName = kMainWindowIdentifier;
gameWindow.releasedWhenClosed = NO;
gameWindow.backgroundColor = NSColor.clearColor;
if ( ![gameWindow setFrameUsingName:kMainWindowIdentifier] )
{
[gameWindow center];
}
self.gameWindow = gameWindow;
[NSNotificationCenter.defaultCenter addObserverForName:NSWindowWillCloseNotification object:gameWindow queue:NSOperationQueue.mainQueue usingBlock:^(NSNotification *notification)
{
[self.s9xEngine quit];
}];
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
[self.s9xEngine quit];
}
- (void)setupDefaults
{
NSUserDefaults *defaults = NSUserDefaults.standardUserDefaults;
NSDictionary *defaultSettings = @{
kKeyboardPrefs : @{
@(kUp).stringValue : @(kVK_UpArrow),
@(kDown).stringValue : @(kVK_DownArrow),
@(kLeft).stringValue : @(kVK_LeftArrow),
@(kRight).stringValue : @(kVK_RightArrow),
@(kY).stringValue : @(kVK_ANSI_X),
@(kB).stringValue : @(kVK_ANSI_C),
@(kX).stringValue : @(kVK_ANSI_D),
@(kA).stringValue : @(kVK_ANSI_V),
@(kL).stringValue : @(kVK_ANSI_A),
@(kR).stringValue : @(kVK_ANSI_S),
@(kStart).stringValue : @(kVK_Space),
@(kSelect).stringValue : @(kVK_Return),
@(kNumButtons + kUp).stringValue : @(kVK_ANSI_Keypad8),
@(kNumButtons + kDown).stringValue : @(kVK_ANSI_Keypad2),
@(kNumButtons + kLeft).stringValue : @(kVK_ANSI_Keypad4),
@(kNumButtons + kRight).stringValue : @(kVK_ANSI_Keypad6),
@(kNumButtons + kY).stringValue : @(kVK_PageDown),
@(kNumButtons + kB).stringValue : @(kVK_PageUp),
@(kNumButtons + kX).stringValue : @(kVK_End),
@(kNumButtons + kA).stringValue : @(kVK_Home),
@(kNumButtons + kL).stringValue : @(kVK_ANSI_Keypad0),
@(kNumButtons + kR).stringValue : @(kVK_ANSI_KeypadDecimal),
@(kNumButtons + kStart).stringValue : @(kVK_ANSI_KeypadEnter),
@(kNumButtons + kSelect).stringValue : @(kVK_ANSI_KeypadPlus),
@(kKeyFastForward).stringValue : @(kVK_ANSI_Backslash),
@(kKeyFreeze).stringValue : @(kVK_ANSI_1),
@(kKeyDefrost).stringValue : @(kVK_ANSI_0),
@(kKeyScreenshot).stringValue : @(kVK_ANSI_Grave),
@(kKeySPC).stringValue : @(kVK_ANSI_R),
@(kKeyScopeTurbo).stringValue : @(kVK_ANSI_B),
@(kKeyScopePause).stringValue : @(kVK_ANSI_N),
@(kKeyScopeCursor).stringValue : @(kVK_ANSI_M),
@(kKeyOffScreen).stringValue : @(kVK_Tab),
@(kKeyFunction).stringValue : @(kVK_ANSI_Slash),
@(kKeyAlt).stringValue : @(kVK_ANSI_Period),
@(kKeyFFDown).stringValue : @(kVK_ANSI_Q),
@(kKeyFFUp).stringValue : @(kVK_ANSI_W),
@(kKeyEsc).stringValue : @(kVK_Escape),
@(kKeyTC).stringValue : @(kVK_ANSI_Comma)
},
kShowFPSPref: @(NO),
kVideoModePref:@(VIDEOMODE_BLOCKY),
kMacFrameSkipPref:@(macFrameSkip)
};
[defaults registerDefaults:defaultSettings];
[defaults setBool:NO forKey:@"NSWindowAssertWhenDisplayCycleLimitReached"];
[defaults synchronize];
self.keys = [[defaults objectForKey:kKeyboardPrefs] mutableCopy];
for (NSString *control in [self.keys copy])
{
NSInteger key = control.integerValue;
NSInteger player = key / kNumButtons;
S9xButtonCode buttonCode = (S9xButtonCode)(key - (kNumButtons * player));
[self setButtonCode:buttonCode forKeyCode:self.keys[control].integerValue player:player];
}
NSDictionary *joypadPlayerPrefs = [defaults objectForKey:kJoypadPlayerPrefs];
for ( S9xJoypad *joypad in [self listJoypads])
{
NSMutableDictionary *joypadPrefs = [[defaults objectForKey:kJoypadInputPrefs] mutableCopy];
if (joypadPrefs == nil)
{
joypadPrefs = [NSMutableDictionary new];
[defaults synchronize];
}
NSString *key = [self prefsKeyForVendorID:joypad.vendorID productID:joypad.productID index:joypad.index];
for ( NSString *playerString in joypadPlayerPrefs )
{
if ( [key isEqualToString:joypadPlayerPrefs[playerString]] )
{
[self setPlayer:playerString.intValue forVendorID:joypad.vendorID productID:joypad.productID index:joypad.index];
}
}
NSMutableDictionary *devicePrefs = [joypadPrefs[key] mutableCopy];
if (devicePrefs == nil)
{
devicePrefs = [NSMutableDictionary new];
for (S9xJoypadInput *input in [self.s9xEngine getInputsForVendorID:joypad.vendorID productID:joypad.productID index:joypad.index])
{
devicePrefs[@(input.buttonCode).stringValue] = [self prefValueForCookie:input.cookie value:input.value];
}
joypadPrefs[key] = devicePrefs;
[defaults setObject:joypadPrefs forKey:kJoypadInputPrefs];
[defaults synchronize];
}
else
{
[self.s9xEngine clearJoypadForVendorID:joypad.vendorID productID:joypad.productID index:joypad.index];
for (NSString *buttonCodeString in devicePrefs)
{
S9xButtonCode buttonCode = (S9xButtonCode)buttonCodeString.intValue;
NSString *str = devicePrefs[buttonCodeString];
uint32 cookie = 0;
int32 value = -1;
if ([self getValuesFromString:str cookie:&cookie value:&value])
{
[self setButton:buttonCode forVendorID:joypad.vendorID productID:joypad.productID index:joypad.index cookie:cookie value:value];
}
}
}
}
self.deviceSetting = Gamepads;
[self importKeySettings];
[self importGraphicsSettings];
[defaults synchronize];
}
- (void)setButtonCode:(S9xButtonCode)buttonCode forKeyCode:(int16)keyCode player:(int8)player
{
if (keyCode < 0)
{
return;
}
self.keys[@(buttonCode + (kNumButtons * player)).stringValue] = @(keyCode);
S9xButtonCode oldButton = kNumButtons;
int8 oldPlayer = -1;
if ([self.s9xEngine setButton:buttonCode forKey:keyCode player:player oldButton:&oldButton oldPlayer:&oldPlayer oldKey:NULL])
{
if (oldButton >= 0 && oldButton < kNumButtons && oldPlayer >= 0 && oldPlayer < MAC_MAX_PLAYERS && (oldPlayer != player || oldButton != buttonCode))
{
[self.keys removeObjectForKey:@(oldButton + (kNumButtons * oldPlayer)).stringValue];
}
[NSUserDefaults.standardUserDefaults setObject:[self.keys copy] forKey:kKeyboardPrefs];
}
}
- (void)clearButton:(S9xButtonCode)button forPlayer:(int8)player
{
[self.s9xEngine clearButton:button forPlayer:player];
NSMutableDictionary *keyDict = [[NSUserDefaults.standardUserDefaults objectForKey:kKeyboardPrefs] mutableCopy];
[keyDict removeObjectForKey:@(button).stringValue];
[NSUserDefaults.standardUserDefaults setObject:[keyDict copy] forKey:kKeyboardPrefs];
[NSUserDefaults.standardUserDefaults synchronize];
}
- (NSArray<S9xJoypad *> *)listJoypads
{
return [self.s9xEngine listJoypads];
}
- (NSString *)prefsKeyForVendorID:(uint32)vendorID productID:(uint32)productID index:(uint32)index
{
return [NSString stringWithFormat:@"%@:%@:%@", @(vendorID).stringValue, @(productID).stringValue, @(index).stringValue];
}
- (BOOL)getValuesFromString:(NSString *)str vendorID:(uint32 *)vendorID productID:(uint32 *)productID index:(uint32 *)index
{
if (vendorID == NULL || productID == NULL || index == NULL)
{
return NO;
}
NSArray<NSString *> *components = [str componentsSeparatedByString:@":"];
if (components.count != 3)
{
return NO;
}
*vendorID = components[0].intValue;
*productID = components[1].intValue;
*index = components[2].intValue;
return YES;
}
- (NSString *)prefValueForCookie:(uint32)cookie value:(int32)value
{
return [NSString stringWithFormat:@"%@:%@", @(cookie).stringValue, @(value).stringValue];
}
- (BOOL)getValuesFromString:(NSString *)str cookie:(uint32 *)cookie value:(int32 *)value
{
if (cookie == NULL || value == NULL)
{
return NO;
}
NSArray<NSString *> *components = [str componentsSeparatedByString:@":"];
if (components.count != 2)
{
return NO;
}
*cookie = components.firstObject.intValue;
*value = components.lastObject.intValue;
return YES;
}
- (void)setPlayer:(int8)player forVendorID:(uint32)vendorID productID:(uint32)productID index:(uint32)index
{
int8 oldPlayer = -1;
[self.s9xEngine setPlayer:player forVendorID:vendorID productID:productID index:index oldPlayer:&oldPlayer];
NSMutableDictionary *playersDict = [[NSUserDefaults.standardUserDefaults objectForKey:kJoypadPlayerPrefs] mutableCopy];
if (playersDict == nil)
{
playersDict = [NSMutableDictionary new];
}
if (oldPlayer >= 0 && player != oldPlayer)
{
[playersDict removeObjectForKey:@(oldPlayer).stringValue];
}
playersDict[@(player).stringValue] = [self prefsKeyForVendorID:vendorID productID:productID index:index];
[NSUserDefaults.standardUserDefaults setObject:[playersDict copy] forKey:kJoypadPlayerPrefs];
}
- (BOOL)setButton:(S9xButtonCode)button forVendorID:(uint32)vendorID productID:(uint32)productID index:(uint32)index cookie:(uint32)cookie value:(int32)value
{
S9xButtonCode oldButton = (S9xButtonCode)-1;
BOOL result = [self.s9xEngine setButton:button forVendorID:vendorID productID:productID index:index cookie:cookie value:value oldButton:&oldButton];
NSMutableDictionary *prefsDict = [[NSUserDefaults.standardUserDefaults objectForKey:kJoypadInputPrefs] mutableCopy];
NSString *key = [self prefsKeyForVendorID:vendorID productID:productID index:index];
NSMutableDictionary *joypadDict = [prefsDict[key] mutableCopy];
if (result && button != oldButton)
{
[joypadDict removeObjectForKey:@(oldButton).stringValue];
}
joypadDict[@(button).stringValue] = [self prefValueForCookie:cookie value:value];
prefsDict[key] = [joypadDict copy];
[NSUserDefaults.standardUserDefaults setObject:[prefsDict copy] forKey:kJoypadInputPrefs];
return result;
}
- (void)clearJoypadForVendorID:(uint32)vendorID productID:(uint32)productID index:(uint32)index buttonCode:(S9xButtonCode)buttonCode
{
[self.s9xEngine clearJoypadForVendorID:vendorID productID:productID index:index buttonCode:buttonCode];
NSString *key = [self prefsKeyForVendorID:vendorID productID:productID index:index];
NSMutableDictionary *joypadsDict = [[NSUserDefaults.standardUserDefaults objectForKey:kJoypadInputPrefs] mutableCopy];
NSMutableDictionary *deviceDict = [joypadsDict[key] mutableCopy];
[deviceDict removeObjectForKey:@(buttonCode).stringValue];
joypadsDict[key] = deviceDict;
[NSUserDefaults.standardUserDefaults setObject:[joypadsDict copy] forKey:kJoypadInputPrefs];
[NSUserDefaults.standardUserDefaults synchronize];
}
- (NSString *)labelForVendorID:(uint32)vendorID productID:(uint32)productID cookie:(uint32)cookie value:(int32)value
{
return [self.s9xEngine labelForVendorID:vendorID productID:productID cookie:cookie value:value];
}
- (void)importRecentItems
{
const NSInteger maxRecents = 20;
for (NSInteger i = maxRecents - 1; i >= 0; --i)
{
NSString *key = [NSString stringWithFormat:@"RecentItem_%02tu", i];
NSString *recentItem = [NSUserDefaults.standardUserDefaults objectForKey:key];
if (recentItem != nil)
{
[NSDocumentController.sharedDocumentController noteNewRecentDocumentURL:[NSURL fileURLWithPath:recentItem]];
[NSUserDefaults.standardUserDefaults removeObjectForKey:key];
}
}
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)importKeySettings
{
NSData *data = [self objectForPrefOSCode:'keyb'];
NSUInteger length = data.length;
char *bytes = (char*)data.bytes;
for ( NSUInteger i = 0; i < length; ++i )
{
// The enum values for controls changed between the Carbon and Cocoa versions.
// The first 24 enum values are the same, but we have to adjust after that.
if ( i < 24 )
{
[self setButtonCode:(S9xButtonCode)(i - (i / 12)) forKeyCode:bytes[i] player:i / 12];
}
else
{
[self setButtonCode:(S9xButtonCode)(i - 24 + kKeyFastForward) forKeyCode:bytes[i] player:0];
}
}
}
- (void)importGraphicsSettings
{
NSData *data = [self objectForPrefOSCode:'dfps'];
if (data != nil)
{
[NSUserDefaults.standardUserDefaults setBool:(data.length > 0 && ((char *)data.bytes)[0]) forKey:kShowFPSPref];
}
[self setShowFPS:[NSUserDefaults.standardUserDefaults boolForKey:kShowFPSPref]];
data = [self objectForPrefOSCode:'Vmod'];
if ( data != nil)
{
[NSUserDefaults.standardUserDefaults setInteger:((data.length >= 0 && ((char *)data.bytes)[0]) ? VIDEOMODE_SMOOTH : VIDEOMODE_BLOCKY) forKey:kVideoModePref];
}
[self setVideoMode:(int)[NSUserDefaults.standardUserDefaults integerForKey:kVideoModePref]];
}
- (id)objectForPrefOSCode:(uint32_t)osCode
{
NSString *key = [@"Preferences_" stringByAppendingString:[[NSString alloc] initWithBytes:(char *)&osCode length:sizeof(uint32_t) encoding:NSASCIIStringEncoding]];
id obj = [NSUserDefaults.standardUserDefaults objectForKey:key];
if (obj == nil)
{
osCode =CFSwapInt32(osCode);
key = [@"Preferences_" stringByAppendingString:[[NSString alloc] initWithBytes:(char *)&osCode length:sizeof(uint32_t) encoding:NSASCIIStringEncoding]];
obj = [NSUserDefaults.standardUserDefaults objectForKey:key];
if (obj != nil)
{
[NSUserDefaults.standardUserDefaults removeObjectForKey:key];
}
}
else
{
[NSUserDefaults.standardUserDefaults removeObjectForKey:key];
}
return obj;
}
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename
{
return [self openURL:[NSURL fileURLWithPath:filename]];
}
- (IBAction)openDocument:(id)sender
{
NSOpenPanel* panel = [NSOpenPanel new];
NSModalResponse response = [panel runModal];
if ( response == NSModalResponseOK )
{
[self openURL:panel.URL];
}
}
- (BOOL)openURL:(NSURL *)url
{
if ([self.s9xEngine loadROM:url])
{
[self.s9xEngine recreateS9xView];
NSWindow *gameWindow = self.gameWindow;
[gameWindow.contentView addSubview:s9xView];
[s9xView.topAnchor constraintEqualToAnchor:gameWindow.contentView.topAnchor].active = YES;
[s9xView.bottomAnchor constraintEqualToAnchor:gameWindow.contentView.bottomAnchor].active = YES;
[s9xView.centerXAnchor constraintEqualToAnchor:gameWindow.contentView.centerXAnchor].active = YES;
[s9xView.leftAnchor constraintGreaterThanOrEqualToAnchor:gameWindow.contentView.leftAnchor].active = YES;
[s9xView.rightAnchor constraintLessThanOrEqualToAnchor:gameWindow.contentView.rightAnchor].active = YES;
[gameWindow makeKeyAndOrderFront:self];
[NSDocumentController.sharedDocumentController noteNewRecentDocumentURL:url];
return YES;
}
return NO;
}
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
{
SEL action = menuItem.action;
if (action == @selector(resume:) || action == @selector(softwareReset:) || action == @selector(hardwareReset:)) {
return [self.s9xEngine isRunning] && [self.s9xEngine isPaused];
}
else if (action == @selector(updateDeviceSetting:)) {
menuItem.state = (self.deviceSetting == (S9xDeviceSetting)menuItem.tag) ? NSOnState : NSOffState;
}
return !self.isRunningEmulation;
}
@dynamic isRunningEmulation;
- (BOOL)isRunningEmulation
{
return [self.s9xEngine isRunning] && ![self.s9xEngine isPaused];
}
- (IBAction)terminate:(id)sender
{
[self.s9xEngine stop];
[NSApp terminate:sender];
}
- (IBAction)openPreferencesWindow:(id)sender
{
if ( self.preferencesWindowController == nil )
{
self.preferencesWindowController = [[S9xPreferencesWindowController alloc] initWithWindowNibName:@"S9xPreferencesWindowController"];
}
[self.preferencesWindowController showWindow:nil];
[self.preferencesWindowController.window makeKeyAndOrderFront:nil];
[self.preferencesWindowController.window makeKeyWindow];
}
- (void)setVideoMode:(int)videoMode
{
[self.s9xEngine setVideoMode:videoMode];
[NSUserDefaults.standardUserDefaults setObject:@(videoMode) forKey:kVideoModePref];
[NSUserDefaults.standardUserDefaults synchronize];
}
- (void)setMacFrameSkip:(int)_macFrameSkip
{
[self.s9xEngine setMacFrameSkip:_macFrameSkip];
[NSUserDefaults.standardUserDefaults setObject:@(_macFrameSkip) forKey:kMacFrameSkipPref];
[NSUserDefaults.standardUserDefaults synchronize];
}
- (void)setShowFPS:(BOOL)showFPS
{
[self.s9xEngine setShowFPS:showFPS];
[NSUserDefaults.standardUserDefaults setObject:@(showFPS) forKey:kShowFPSPref];
[NSUserDefaults.standardUserDefaults synchronize];
}
- (IBAction)resume:(id)sender
{
[self.s9xEngine resume];
}
- (IBAction)softwareReset:(id)sender
{
[self.s9xEngine softwareReset];
}
- (IBAction)hardwareReset:(id)sender
{
[self.s9xEngine hardwareReset];
}
- (IBAction)updateDeviceSetting:(id)sender
{
self.deviceSetting = (S9xDeviceSetting)[sender tag];
}
- (void)setDeviceSetting:(S9xDeviceSetting)deviceSetting
{
_deviceSetting = deviceSetting;
[self.s9xEngine setDeviceSetting:deviceSetting];
}
- (BOOL)handleInput:(S9xJoypadInput *)input fromJoypad:(S9xJoypad *)joypad
{
if (NSApp.keyWindow != nil && NSApp.keyWindow == self.preferencesWindowController.window)
{
return [((S9xPreferencesWindowController *) self.preferencesWindowController.contentViewController) handleInput:input fromJoypad:joypad];
}
return NO;
}
- (void)deviceSettingChanged:(S9xDeviceSetting)deviceSetting
{
_deviceSetting = deviceSetting;
}
@end

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1,60 @@
{
"images" : [
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "16x16",
"scale" : "2x"
},
{
"size" : "32x32",
"idiom" : "mac",
"filename" : "APPL-32.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "32x32",
"scale" : "2x"
},
{
"size" : "128x128",
"idiom" : "mac",
"filename" : "APPL.png",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "128x128",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "256x256",
"scale" : "2x"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "1x"
},
{
"idiom" : "mac",
"size" : "512x512",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@ -0,0 +1,234 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="16097.3" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16097.3"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate"/>
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
<items>
<menuItem title="Snes9x" id="1Xt-HY-uBw">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Snes9x" systemMenu="apple" id="uQy-DD-JDr">
<items>
<menuItem title="About Snes9x" id="5kV-Vb-QxS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
<menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW">
<connections>
<action selector="openPreferencesWindow:" target="-1" id="MJd-bf-iNU"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/>
<menuItem title="Services" id="NMo-om-nkz">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/>
</menuItem>
<menuItem isSeparatorItem="YES" id="4je-JR-u6R"/>
<menuItem title="Hide Snes9x" keyEquivalent="h" id="Olw-nP-bQN">
<connections>
<action selector="hide:" target="-1" id="PnN-Uc-m68"/>
</connections>
</menuItem>
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/>
</connections>
</menuItem>
<menuItem title="Show All" id="Kd2-mp-pUS">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
<menuItem title="Quit Snes9x" keyEquivalent="q" id="4sb-4s-VLi">
<connections>
<action selector="terminate:" target="Voe-Tx-rLC" id="KcN-YT-dDk"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="File" id="dMs-cI-mzQ">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="File" id="bib-Uj-vzu">
<items>
<menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9">
<connections>
<action selector="openDocument:" target="-1" id="bVn-NM-KNZ"/>
</connections>
</menuItem>
<menuItem title="Open Recent" id="tXI-mr-wws">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ">
<items>
<menuItem title="Clear Menu" id="vNY-rz-j42">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="clearRecentDocuments:" target="-1" id="Daa-9d-B3U"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
<menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG">
<connections>
<action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Emulation" id="Kjk-eO-rPI">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Emulation" id="s2F-Pd-YT5">
<items>
<menuItem title="Resume" keyEquivalent="r" id="m8Y-5s-VGC">
<connections>
<action selector="resume:" target="-1" id="jxw-ZM-JXi"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="wRV-3p-Ovs"/>
<menuItem title="Software Reset" keyEquivalent="R" id="rpq-ak-IWU">
<connections>
<action selector="softwareReset:" target="-1" id="SCG-64-bMI"/>
</connections>
</menuItem>
<menuItem title="Hardware Reset" keyEquivalent="r" id="tbk-CC-2si">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="hardwareReset:" target="-1" id="dRy-5Q-N2I"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="YAv-y2-CdP"/>
<menuItem title="Controls" id="2xu-Kh-K2Q">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" id="Scs-jj-0pz">
<items>
<menuItem title="Gamepads" tag="1" id="ntk-uz-aiW">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="updateDeviceSetting:" target="-1" id="GxE-k5-uWL"/>
</connections>
</menuItem>
<menuItem title="Mouse (Port 1)" tag="2" id="5es-Zi-iof">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="updateDeviceSetting:" target="-1" id="jtg-E2-98q"/>
</connections>
</menuItem>
<menuItem title="Mouse (Port 2)" tag="3" id="vrV-Bh-KyE">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="updateDeviceSetting:" target="-1" id="LGe-fJ-vTb"/>
</connections>
</menuItem>
<menuItem title="Super Scope (Port 2)" tag="4" id="ZF8-Xw-08U">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="updateDeviceSetting:" target="-1" id="1qY-rM-anV"/>
</connections>
</menuItem>
<menuItem title="Multitap (Port 2)" tag="5" id="cdn-s1-eHL">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="updateDeviceSetting:" target="-1" id="qrs-Ih-u7R"/>
</connections>
</menuItem>
<menuItem title="Multitap (Both Ports)" tag="6" id="fQJ-1V-NpK">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="updateDeviceSetting:" target="-1" id="5d9-tW-Rfm"/>
</connections>
</menuItem>
<menuItem title="Justifier (Port 2)" tag="7" id="hUi-aI-ihE">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="updateDeviceSetting:" target="-1" id="QBV-bU-viB"/>
</connections>
</menuItem>
<menuItem title="Double Justifier (Port 2)" tag="8" id="wTw-mT-ha1">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="updateDeviceSetting:" target="-1" id="XZV-DZ-rX3"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="View" id="H8h-7b-M4v">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="View" id="HyV-fh-RgO">
<items>
<menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="toggleFullScreen:" target="-1" id="dU3-MA-1Rq"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Window" id="aUF-d1-5bR">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo">
<items>
<menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV">
<connections>
<action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/>
</connections>
</menuItem>
<menuItem title="Zoom" id="R4o-n2-Eq4">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="performZoom:" target="-1" id="DIl-cC-cCs"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/>
<menuItem title="Bring All to Front" id="LE2-aR-0XJ">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Help" id="wpr-3q-Mcd">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
<items>
<menuItem title="Snes9x Help" keyEquivalent="?" id="FKE-Sm-Kum">
<connections>
<action selector="showHelp:" target="-1" id="y7X-2Q-9no"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
<point key="canvasLocation" x="132" y="154"/>
</menu>
<menuItem title="Mouse (Port 2)" id="P6N-Mq-1PD">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
</objects>
</document>

View File

@ -3,7 +3,31 @@
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>CFBundleHelpBookFolder</key>
<string>Snes9x Help</string>
<key>CFBundleHelpBookName</key>
<string>Snes9x Help</string>
<key>NSPrincipalClass</key>
<string>S9xApplication</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
@ -159,31 +183,5 @@
<false/>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>Snes9x (ppc)</string>
<key>CFBundleGetInfoString</key>
<string>Snes9x 1.60, Copyright 1996-2019 Snes9x developers.</string>
<key>CFBundleHelpBookFolder</key>
<string>Snes9x Help</string>
<key>CFBundleHelpBookName</key>
<string>Snes9x Help</string>
<key>CFBundleIconFile</key>
<string>APPL.icns</string>
<key>CFBundleIdentifier</key>
<string>com.snes9x.macos.snes9x</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Snes9x</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.60</string>
<key>CFBundleSignature</key>
<string>~9X~</string>
<key>CFBundleVersion</key>
<string>1.60</string>
<key>CSResourcesFileMapped</key>
<true/>
</dict>
</plist>

14
macosx/mac-prefs.h → macosx/Snes9x/S9xApplication.h Executable file → Normal file
View File

@ -15,15 +15,15 @@
(c) Copyright 2004 Alexander and Sander
(c) Copyright 2004 - 2005 Steven Seeger
(c) Copyright 2005 Ryan Vogt
(c) Copyright 2019 Michael Donald Buckley
***********************************************************************************/
#import <Cocoa/Cocoa.h>
#ifndef _mac_prefs_h_
#define _mac_prefs_h_
NS_ASSUME_NONNULL_BEGIN
void LoadPrefs (void);
void SavePrefs (void);
void ConfigurePreferences (void);
void ConfigureExtraOptions (void);
@interface S9xApplication : NSApplication
#endif
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,38 @@
/*****************************************************************************\
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
This file is licensed under the Snes9x License.
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
/***********************************************************************************
SNES9X for Mac OS (c) Copyright John Stiles
Snes9x for Mac OS X
(c) Copyright 2001 - 2011 zones
(c) Copyright 2002 - 2005 107
(c) Copyright 2002 PB1400c
(c) Copyright 2004 Alexander and Sander
(c) Copyright 2004 - 2005 Steven Seeger
(c) Copyright 2005 Ryan Vogt
(c) Copyright 2019 Michael Donald Buckley
***********************************************************************************/
#import "S9xApplication.h"
#import "AppDelegate.h"
@implementation S9xApplication
- (void)sendEvent:(NSEvent *)event
{
if (event.modifierFlags * NSEventModifierFlagCommand && event.type == NSEventTypeKeyUp && ((AppDelegate *)self.delegate).isRunningEmulation)
{
[self.keyWindow sendEvent:event];
}
else
{
[super sendEvent:event];
}
}
@end

View File

@ -0,0 +1,35 @@
/*****************************************************************************\
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
This file is licensed under the Snes9x License.
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
/***********************************************************************************
SNES9X for Mac OS (c) Copyright John Stiles
Snes9x for Mac OS X
(c) Copyright 2001 - 2011 zones
(c) Copyright 2002 - 2005 107
(c) Copyright 2002 PB1400c
(c) Copyright 2004 Alexander and Sander
(c) Copyright 2004 - 2005 Steven Seeger
(c) Copyright 2005 Ryan Vogt
(c) Copyright 2019 Michael Donald Buckley
***********************************************************************************/
#import <Cocoa/Cocoa.h>
@class S9xJoypadInput;
NS_ASSUME_NONNULL_BEGIN
@interface S9xButtonConfigTextField : NSSearchField<NSSearchFieldDelegate>
@property (nonatomic, assign) CGKeyCode keyCode;
@property (nonatomic, strong, nullable) S9xJoypadInput *joypadInput;
@property (nonatomic, assign) BOOL disableKeyboardInput;
@end
NS_ASSUME_NONNULL_END

Some files were not shown because too many files have changed in this diff Show More