Compare commits

..
38 Commits
Author SHA1 Message Date
Themaister 8ea5ba171a Updates for 0.8.2. 2011-09-21 21:17:46 +02:00
Themaister fa876b10a3 Style nit. 2011-09-20 12:22:30 +02:00
Themaister 3c58d10eae Small fix. 2011-09-20 12:05:21 +02:00
Themaister a3ee8c8849 Defensive nit. 2011-09-20 11:58:21 +02:00
Themaister 5e14b302bc Replace a VLA with char[MAXPATHLEN]. 2011-09-20 12:50:13 +03:00
Themaister efe3f943d5 Only autosave when the data actually changed. 2011-09-17 10:57:55 +02:00
Themaister 38e7fc6659 Add support for blocking SRAM writes :) 2011-09-16 15:32:21 +02:00
Themaister a1ceb534de nit. 2011-09-13 23:24:06 +02:00
Themaister 0d897dd65d Check some additional WM messages. 2011-09-13 22:38:32 +02:00
Themaister 721d73f451 Fix stupid crash. 2011-09-13 22:16:34 +02:00
Themaister e8bd64e898 Allow SDL driver to work as well in 1.3. 2011-09-13 20:01:22 +02:00
Themaister 7da7ab2ce7 lalala ... 2011-09-13 19:36:15 +02:00
Themaister 3f6183ff15 Updates, fixes ... 2011-09-13 19:30:22 +02:00
Themaister 642316a1e2 Somewhat haphazard. Can't find some needed API calls :\ 2011-09-13 18:50:40 +02:00
Themaister 21c6b75839 Use SwapInterval with SDL 1.3. 2011-09-13 15:00:26 +02:00
Themaister 87d34deb0c Can build with SDL 1.3 on Win32. 2011-09-13 14:57:42 +02:00
Themaister 1b3408919c Can use SDL 1.3 just fine now. 2011-09-13 14:41:45 +02:00
Themaister 23516572b7 Use SK_* keysyms (pretty much SDL 1.2). 2011-09-13 14:40:33 +02:00
Themaister 924848fdad Start working towards SDL 1.2/1.3 compat. 2011-09-13 14:06:49 +02:00
Themaister 4c40e56060 Properly disable it :D 2011-09-11 15:41:46 +02:00
Themaister cf34444505 Disable resizing on OSX. 2011-09-11 15:33:28 +02:00
Themaister 9ca5e4e470 Updates for 0.8.1. 2011-09-10 19:15:05 +02:00
Themaister 32f2689b6a Add LIBXML_TEST_VERSION to XML cheats. 2011-09-09 09:48:46 +02:00
Themaister 13ae61031f Add ttf_font_color to ext driver struct.
Does not need to bump ABI version.
2011-09-09 09:47:32 +02:00
Themaister 1ced96c5e9 Make it non-public. 2011-09-07 18:59:51 +02:00
Themaister 0d905eb3f6 Actually load cheats on startup ... :') 2011-09-07 18:59:01 +02:00
Themaister 32a5460ea7 Small cleanup. 2011-09-06 19:53:22 +02:00
Themaister be5acff69c Update font rendering for SDL. 2011-09-06 18:32:40 +02:00
Themaister 1b0ef5793e Font colors for XVideo. Some cleanups. 2011-09-06 17:56:42 +02:00
Themaister 2bd0caae2e Do not set RESIZABLE on fullscreen (really? :v) 2011-09-06 15:38:32 +02:00
Themaister 3045f2c478 Move cheat initializing as late as possible. 2011-09-06 12:55:21 +03:00
Themaister 1282a142d6 Fix load/save semantics for cheats ... 2011-09-06 12:51:52 +03:00
Themaister ac1a539d22 Fix stupid typo. 2011-09-05 21:21:18 +02:00
Themaister 6f47775239 Add cheat config. 2011-09-05 17:57:30 +02:00
Themaister 0823d72dee Add coloring to fonts. 2011-09-05 17:00:28 +02:00
Themaister 407ad94f58 Style nit. 2011-09-04 21:11:26 +02:00
Themaister b2b103362d Warn if glX VSync call isn't found. 2011-09-04 13:01:54 +02:00
Themaister 231680944f Remove #ifdef for FFmpeg. 2011-09-04 11:37:59 +02:00
32 changed files with 1394 additions and 490 deletions

No files matched your search

+1 -1
View File
@@ -89,7 +89,7 @@ ifeq ($(HAVE_COREAUDIO), 1)
endif
ifeq ($(HAVE_SDL), 1)
OBJ += gfx/sdl.o gfx/gl.o input/sdl.o audio/sdl.o fifo_buffer.o
OBJ += gfx/sdl.o gfx/gl.o gfx/sdlwrap.o input/sdl.o audio/sdl.o fifo_buffer.o
DEFINES += $(SDL_CFLAGS) $(BSD_LOCAL_INC)
LIBS += $(SDL_LIBS)
ifeq ($(OSX),1)
+3 -3
View File
@@ -32,7 +32,7 @@ LDFLAGS = -L. -static-libgcc -s
LDCXXFLAGS = -static-libstdc++
ifeq ($(HAVE_SDL), 1)
OBJ += gfx/sdl.o gfx/gl.o input/sdl.o audio/sdl.o fifo_buffer.o
OBJ += gfx/sdl.o gfx/gl.o gfx/sdlwrap.o input/sdl.o audio/sdl.o fifo_buffer.o
LIBS += -lSDL -lopengl32
DEFINES += -ISDL -DHAVE_SDL
endif
@@ -160,10 +160,10 @@ clean:
rm -f tools/*.o
dist_x86: all
zip -r ssnes-win32-0.8.zip $(TARGET) $(JTARGET) ssnes.cfg snes.dll SDL.dll
zip -r ssnes-win32-0.8.2.zip $(TARGET) $(JTARGET) ssnes.cfg snes.dll SDL.dll
dist_x86_64: all
zip -r ssnes-win64-0.8.zip $(TARGET) $(JTARGET) ssnes.cfg snes.dll SDL.dll
zip -r ssnes-win64-0.8.2.zip $(TARGET) $(JTARGET) ssnes.cfg snes.dll SDL.dll
libs_x86:
wget https://github.com/downloads/Themaister/SSNES/SSNES-win32-libs.zip --no-check-certificate
+23 -15
View File
@@ -48,26 +48,33 @@ static int autosave_thread(void *data)
while (!save->quit)
{
autosave_lock(save);
memcpy(save->buffer, save->snes_buffer, save->bufsize);
bool differ = memcmp(save->buffer, save->snes_buffer, save->bufsize) != 0;
if (differ)
memcpy(save->buffer, save->snes_buffer, save->bufsize);
autosave_unlock(save);
// Should probably deal with this more elegantly.
FILE *file = fopen(save->path, "wb");
if (file)
if (differ)
{
// Avoid spamming down stderr ... :)
if (first_log)
// Should probably deal with this more elegantly.
FILE *file = fopen(save->path, "wb");
if (file)
{
SSNES_LOG("Autosaving SRAM to \"%s\", will continue to autosave every %u seconds ...\n", save->path, save->interval);
first_log = false;
}
// Avoid spamming down stderr ... :)
if (first_log)
{
SSNES_LOG("Autosaving SRAM to \"%s\", will continue to check every %u seconds ...\n", save->path, save->interval);
first_log = false;
}
else
SSNES_LOG("SRAM changed ... autosaving ...\n");
bool failed = false;
failed |= fwrite(save->buffer, 1, save->bufsize, file) != save->bufsize;
failed |= fflush(file) != 0;
failed |= fclose(file) != 0;
if (failed)
SSNES_WARN("Failed to autosave SRAM! Disk might be full.\n");
bool failed = false;
failed |= fwrite(save->buffer, 1, save->bufsize, file) != save->bufsize;
failed |= fflush(file) != 0;
failed |= fclose(file) != 0;
if (failed)
SSNES_WARN("Failed to autosave SRAM! Disk might be full.\n");
}
}
SDL_mutexP(save->cond_lock);
@@ -96,6 +103,7 @@ autosave_t *autosave_new(const char *path, const void *data, size_t size, unsign
free(handle);
return NULL;
}
memcpy(handle->buffer, handle->snes_buffer, handle->bufsize);
handle->lock = SDL_CreateMutex();
handle->cond_lock = SDL_CreateMutex();
+111 -10
View File
@@ -21,6 +21,14 @@
#include "general.h"
#include "strl.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_CONFIGFILE
#include "conf/config_file.h"
#endif
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
@@ -131,8 +139,105 @@ static bool xml_grab_cheats(cheat_manager_t *handle, xmlNodePtr ptr)
return true;
}
static void cheat_manager_apply_cheats(cheat_manager_t *handle)
{
unsigned index = 0;
psnes_cheat_reset();
for (unsigned i = 0; i < handle->size; i++)
{
if (handle->cheats[i].state)
psnes_cheat_set(index++, true, handle->cheats[i].code);
}
}
static void cheat_manager_load_config(cheat_manager_t *handle, const char *path, const char *sha256)
{
#ifdef HAVE_CONFIGFILE
if (!(*path))
return;
config_file_t *conf = config_file_new(path);
if (!conf)
return;
char *str;
if (!config_get_string(conf, sha256, &str))
{
config_file_free(conf);
return;
}
const char *num = strtok(str, ";");
while (num)
{
unsigned index = strtoul(num, NULL, 0);
if (index < handle->size)
handle->cheats[index].state = true;
num = strtok(NULL, ";");
}
free(str);
config_file_free(conf);
cheat_manager_apply_cheats(handle);
#else
(void)handle;
(void)path;
(void)sha256;
#endif
}
static void cheat_manager_save_config(cheat_manager_t *handle, const char *path, const char *sha256)
{
#ifdef HAVE_CONFIGFILE
if (!(*path))
return;
config_file_t *conf = config_file_new(path);
if (!conf)
conf = config_file_new(NULL);
if (!conf)
{
SSNES_ERR("Cannot save XML cheat settings!\n");
return;
}
char conf_str[512] = {0};
char tmp[32] = {0};
for (unsigned i = 0; i < handle->size; i++)
{
if (handle->cheats[i].state)
{
snprintf(tmp, sizeof(tmp), "%u;", i);
strlcat(conf_str, tmp, sizeof(conf_str));
}
}
if (*conf_str)
conf_str[strlen(conf_str) - 1] = '\0'; // Remove the trailing ';'
config_set_string(conf, sha256, conf_str);
if (!config_file_write(conf, path))
SSNES_ERR("Failed to write XML cheat settings to \"%s\"! Check permissions!\n", path);
config_file_free(conf);
#else
(void)handle;
(void)path;
(void)sha256;
#endif
}
cheat_manager_t* cheat_manager_new(const char *path)
{
LIBXML_TEST_VERSION;
psnes_cheat_reset();
xmlParserCtxtPtr ctx = NULL;
@@ -188,7 +293,7 @@ cheat_manager_t* cheat_manager_new(const char *path)
if (!sha256)
continue;
if (memcmp(sha256, g_extern.sha256, 64) == 0)
if (strcmp((const char*)sha256, g_extern.sha256) == 0)
{
xmlFree(sha256);
break;
@@ -213,6 +318,8 @@ cheat_manager_t* cheat_manager_new(const char *path)
goto error;
}
cheat_manager_load_config(handle, g_settings.cheat_settings_path, g_extern.sha256);
xmlFreeDoc(doc);
xmlFreeParserCtxt(ctx);
return handle;
@@ -233,6 +340,7 @@ void cheat_manager_free(cheat_manager_t *handle)
if (handle->cheats)
{
cheat_manager_save_config(handle, g_settings.cheat_settings_path, g_extern.sha256);
for (unsigned i = 0; i < handle->size; i++)
{
xmlFree(handle->cheats[i].desc);
@@ -254,18 +362,11 @@ static void cheat_manager_update(cheat_manager_t *handle)
SSNES_LOG("%s\n", msg);
}
void cheat_manager_toggle(cheat_manager_t *handle)
{
handle->cheats[handle->ptr].state ^= true;
unsigned index = 0;
psnes_cheat_reset();
for (unsigned i = 0; i < handle->size; i++)
{
if (handle->cheats[handle->ptr].state)
psnes_cheat_set(index++, true, handle->cheats[handle->ptr].code);
}
cheat_manager_apply_cheats(handle);
cheat_manager_update(handle);
}
+19 -4
View File
@@ -21,6 +21,7 @@
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include "strl.h"
struct entry_list
@@ -216,8 +217,15 @@ bool config_get_int(config_file_t *conf, const char *key, int *in)
{
if (strcmp(key, list->key) == 0)
{
*in = strtol(list->value, NULL, 0);
return true;
errno = 0;
int val = strtol(list->value, NULL, 0);
if (errno == 0)
{
*in = val;
return true;
}
return
false;
}
list = list->next;
}
@@ -232,8 +240,15 @@ bool config_get_hex(config_file_t *conf, const char *key, unsigned *in)
{
if (strcmp(key, list->key) == 0)
{
*in = strtol(list->value, NULL, 16);
return true;
errno = 0;
unsigned val = strtoul(list->value, NULL, 16);
if (errno == 0)
{
*in = val;
return true;
}
else
return false;
}
list = list->next;
}
+54 -53
View File
@@ -30,17 +30,12 @@
#include "config.h"
#endif
#ifdef HAVE_SDL
#include "SDL.h"
#else
#error "HAVE_SDL is not defined!"
#endif
#include "input/keysym.h"
#ifdef HAVE_SRC
#include <samplerate.h>
#endif
///////////////// Drivers
#define VIDEO_GL 0
#define VIDEO_XVIDEO 11
@@ -150,6 +145,8 @@ static const unsigned font_size = 48;
// Offset for where messages will be placed on-screen. Values are in range [0.0, 1.0].
static const float message_pos_offset_x = 0.05;
static const float message_pos_offset_y = 0.05;
// Color of the message.
static const uint32_t message_color = 0xffffff; // RGB hex value.
// Render-to-texture before rendering to screen (multi-pass shaders)
static const bool render_to_texture = false;
@@ -215,6 +212,10 @@ static const unsigned autosave_interval = 0;
// When being client over netplay, use keybinds for player 1 rather than player 2.
static const bool netplay_client_swap_input = true;
// On save state load, block SRAM from being overwritten.
// This could potentially lead to buggy games.
static const bool block_sram_overwrite = false;
////////////////////
// Keybinds, Joypad
@@ -222,64 +223,64 @@ static const bool netplay_client_swap_input = true;
// Axis threshold (between 0.0 and 1.0)
// How far an axis must be tilted to result in a button press
#define AXIS_THRESHOLD 0.5
static const float axis_threshold = 0.5;
// To figure out which joypad buttons to use, check jstest or similar.
// SDL sometimes reverses the axes for some odd reason, but hey. :D
// Player 1
static const struct snes_keybind snes_keybinds_1[] = {
// SNES button | keyboard key | js btn | js axis |
{ SNES_DEVICE_ID_JOYPAD_A, SDLK_x, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_B, SDLK_z, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_X, SDLK_s, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_Y, SDLK_a, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_L, SDLK_q, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_R, SDLK_w, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_LEFT, SDLK_LEFT, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_RIGHT, SDLK_RIGHT, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_UP, SDLK_UP, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_DOWN, SDLK_DOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_START, SDLK_RETURN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_SELECT, SDLK_RSHIFT, NO_BTN, AXIS_NONE },
{ SSNES_FAST_FORWARD_KEY, SDLK_SPACE, NO_BTN, AXIS_NONE },
{ SSNES_FAST_FORWARD_HOLD_KEY, SDLK_l, NO_BTN, AXIS_NONE },
{ SSNES_SAVE_STATE_KEY, SDLK_F2, NO_BTN, AXIS_NONE },
{ SSNES_LOAD_STATE_KEY, SDLK_F4, NO_BTN, AXIS_NONE },
{ SSNES_FULLSCREEN_TOGGLE_KEY, SDLK_f, NO_BTN, AXIS_NONE },
{ SSNES_QUIT_KEY, SDLK_ESCAPE, NO_BTN, AXIS_NONE },
{ SSNES_STATE_SLOT_MINUS, SDLK_F6, NO_BTN, AXIS_NONE },
{ SSNES_STATE_SLOT_PLUS, SDLK_F7, NO_BTN, AXIS_NONE },
{ SSNES_AUDIO_INPUT_RATE_PLUS, SDLK_KP_PLUS, NO_BTN, AXIS_NONE },
{ SSNES_AUDIO_INPUT_RATE_MINUS, SDLK_KP_MINUS, NO_BTN, AXIS_NONE },
{ SSNES_REWIND, SDLK_r, NO_BTN, AXIS_NONE },
{ SSNES_MOVIE_RECORD_TOGGLE, SDLK_o, NO_BTN, AXIS_NONE },
{ SSNES_PAUSE_TOGGLE, SDLK_p, NO_BTN, AXIS_NONE },
{ SSNES_RESET, SDLK_h, NO_BTN, AXIS_NONE },
{ SSNES_SHADER_NEXT, SDLK_m, NO_BTN, AXIS_NONE },
{ SSNES_SHADER_PREV, SDLK_n, NO_BTN, AXIS_NONE },
{ SSNES_CHEAT_INDEX_PLUS, SDLK_y, NO_BTN, AXIS_NONE },
{ SSNES_CHEAT_INDEX_MINUS, SDLK_t, NO_BTN, AXIS_NONE },
{ SSNES_CHEAT_TOGGLE, SDLK_u, NO_BTN, AXIS_NONE },
{ SSNES_SCREENSHOT, SDLK_PRINT, NO_BTN, AXIS_NONE },
{ SSNES_DSP_CONFIG, SDLK_c, NO_BTN, AXIS_NONE },
// SNES button | keyboard key | js btn | js axis |
{ SNES_DEVICE_ID_JOYPAD_A, SK_x, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_B, SK_z, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_X, SK_s, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_Y, SK_a, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_L, SK_q, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_R, SK_w, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_LEFT, SK_LEFT, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_RIGHT, SK_RIGHT, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_UP, SK_UP, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_DOWN, SK_DOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_START, SK_RETURN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_SELECT, SK_RSHIFT, NO_BTN, AXIS_NONE },
{ SSNES_FAST_FORWARD_KEY, SK_SPACE, NO_BTN, AXIS_NONE },
{ SSNES_FAST_FORWARD_HOLD_KEY, SK_l, NO_BTN, AXIS_NONE },
{ SSNES_SAVE_STATE_KEY, SK_F2, NO_BTN, AXIS_NONE },
{ SSNES_LOAD_STATE_KEY, SK_F4, NO_BTN, AXIS_NONE },
{ SSNES_FULLSCREEN_TOGGLE_KEY, SK_f, NO_BTN, AXIS_NONE },
{ SSNES_QUIT_KEY, SK_ESCAPE, NO_BTN, AXIS_NONE },
{ SSNES_STATE_SLOT_MINUS, SK_F6, NO_BTN, AXIS_NONE },
{ SSNES_STATE_SLOT_PLUS, SK_F7, NO_BTN, AXIS_NONE },
{ SSNES_AUDIO_INPUT_RATE_PLUS, SK_KP_PLUS, NO_BTN, AXIS_NONE },
{ SSNES_AUDIO_INPUT_RATE_MINUS, SK_KP_MINUS, NO_BTN, AXIS_NONE },
{ SSNES_REWIND, SK_r, NO_BTN, AXIS_NONE },
{ SSNES_MOVIE_RECORD_TOGGLE, SK_o, NO_BTN, AXIS_NONE },
{ SSNES_PAUSE_TOGGLE, SK_p, NO_BTN, AXIS_NONE },
{ SSNES_RESET, SK_h, NO_BTN, AXIS_NONE },
{ SSNES_SHADER_NEXT, SK_m, NO_BTN, AXIS_NONE },
{ SSNES_SHADER_PREV, SK_n, NO_BTN, AXIS_NONE },
{ SSNES_CHEAT_INDEX_PLUS, SK_y, NO_BTN, AXIS_NONE },
{ SSNES_CHEAT_INDEX_MINUS, SK_t, NO_BTN, AXIS_NONE },
{ SSNES_CHEAT_TOGGLE, SK_u, NO_BTN, AXIS_NONE },
{ SSNES_SCREENSHOT, SK_PRINT, NO_BTN, AXIS_NONE },
{ SSNES_DSP_CONFIG, SK_c, NO_BTN, AXIS_NONE },
{ -1 }
};
// Player 2-5
static const struct snes_keybind snes_keybinds_rest[] = {
{ SNES_DEVICE_ID_JOYPAD_A, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_B, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_X, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_Y, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_L, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_R, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_LEFT, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_RIGHT, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_UP, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_DOWN, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_START, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_SELECT, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_A, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_B, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_X, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_Y, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_L, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_R, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_LEFT, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_RIGHT, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_UP, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_DOWN, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_START, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_SELECT, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ -1 }
};
+7 -4
View File
@@ -399,6 +399,9 @@ static void deinit_shader_dir(void)
{
// It handles NULL, no worries :D
dir_list_free(g_extern.shader_dir.elems);
g_extern.shader_dir.elems = NULL;
g_extern.shader_dir.size = 0;
g_extern.shader_dir.ptr = 0;
}
#endif
@@ -456,7 +459,7 @@ void init_video_input(void)
const input_driver_t *tmp = driver.input;
driver.video_data = driver.video->init(&video, &driver.input, &driver.input_data);
if ( driver.video_data == NULL )
if (driver.video_data == NULL)
{
SSNES_ERR("Cannot open video driver ... Exiting ...\n");
exit(1);
@@ -469,7 +472,7 @@ void init_video_input(void)
if (driver.input != NULL)
{
driver.input_data = driver.input->init();
if ( driver.input_data == NULL )
if (driver.input_data == NULL)
{
SSNES_ERR("Cannot init input driver. Exiting ...\n");
exit(1);
@@ -485,10 +488,10 @@ void init_video_input(void)
void uninit_video_input(void)
{
if ( driver.input_data != driver.video_data && driver.input )
if (driver.input_data != driver.video_data && driver.input)
driver.input->free(driver.input_data);
if ( driver.video_data && driver.video )
if (driver.video_data && driver.video)
driver.video->free(driver.video_data);
deinit_filter();
+6 -3
View File
@@ -24,10 +24,11 @@
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include "input/keysym.h"
enum
{
SSNES_FAST_FORWARD_KEY = 0x666, // Hurr, durr
SSNES_FAST_FORWARD_KEY = 12, // SNES has 12 buttons from 0-11 (libsnes.hpp)
SSNES_FAST_FORWARD_HOLD_KEY,
SSNES_LOAD_STATE_KEY,
SSNES_SAVE_STATE_KEY,
@@ -47,14 +48,16 @@ enum
SSNES_CHEAT_INDEX_MINUS,
SSNES_CHEAT_TOGGLE,
SSNES_SCREENSHOT,
SSNES_DSP_CONFIG
SSNES_DSP_CONFIG,
SSNES_BIND_LIST_END
};
struct snes_keybind
{
int id;
uint16_t key;
enum ssnes_key key;
uint16_t joykey;
uint32_t joyaxis;
};
+70 -3
View File
@@ -425,7 +425,74 @@ bool load_state(const char *path)
else
{
SSNES_LOG("State size: %d bytes.\n", (int)size);
uint8_t *block_buf[2] = {NULL, NULL};
int block_type[2] = {-1, -1};
unsigned block_size[2] = {0};
if (g_settings.block_sram_overwrite)
{
SSNES_LOG("Blocking SRAM overwrite!\n");
switch (g_extern.game_type)
{
case SSNES_CART_NORMAL:
block_type[0] = SNES_MEMORY_CARTRIDGE_RAM;
block_type[1] = SNES_MEMORY_CARTRIDGE_RTC;
break;
case SSNES_CART_BSX:
case SSNES_CART_BSX_SLOTTED:
block_type[0] = SNES_MEMORY_BSX_RAM;
block_type[1] = SNES_MEMORY_BSX_PRAM;
break;
case SSNES_CART_SUFAMI:
block_type[0] = SNES_MEMORY_SUFAMI_TURBO_A_RAM;
block_type[1] = SNES_MEMORY_SUFAMI_TURBO_B_RAM;
break;
case SSNES_CART_SGB:
block_type[0] = SNES_MEMORY_GAME_BOY_RAM;
block_type[1] = SNES_MEMORY_GAME_BOY_RTC;
break;
}
}
for (unsigned i = 0; i < 2; i++)
if (block_type[i] != -1)
block_size[i] = psnes_get_memory_size(block_type[i]);
for (unsigned i = 0; i < 2; i++)
if (block_size[i])
block_buf[i] = malloc(block_size[i]);
// Backup current SRAM which is overwritten by unserialize.
for (unsigned i = 0; i < 2; i++)
{
if (block_buf[i])
{
const uint8_t *ptr = psnes_get_memory_data(block_type[i]);
if (ptr)
memcpy(block_buf[i], ptr, block_size[i]);
}
}
psnes_unserialize(buf, size);
// Flush back :D
for (unsigned i = 0; i < 2; i++)
{
if (block_buf[i])
{
uint8_t *ptr = psnes_get_memory_data(block_type[i]);
if (ptr)
memcpy(ptr, block_buf[i], block_size[i]);
}
}
for (unsigned i = 0; i < 2; i++)
if (block_buf[i])
free(block_buf[i]);
}
free(buf);
@@ -783,7 +850,7 @@ char** dir_list_new(const char *dir, const char *ext)
#ifdef _WIN32
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
continue;
if (WideCharToMultiByte(CP_UTF8, 0, ffd.cFileName, -1, utf8_buf, MAX_PATH, NULL, NULL) == 0)
if (WideCharToMultiByte(CP_UTF8, 0, ffd.cFileName, -1, utf8_buf, MAXPATHLEN, NULL, NULL) == 0)
continue;
if (ext && !strstr(utf8_buf, ext))
continue;
@@ -880,8 +947,8 @@ bool path_file_exists(const char *path)
void fill_pathname(char *out_path, const char *in_path, const char *replace, size_t size)
{
char tmp_path[strlen(in_path) + 1];
strlcpy(tmp_path, in_path, sizeof(tmp_path));
char tmp_path[MAXPATHLEN];
assert(strlcpy(tmp_path, in_path, sizeof(tmp_path)) < sizeof(tmp_path));
char *tok = strrchr(tmp_path, '.');
if (tok != NULL)
*tok = '\0';
+7 -1
View File
@@ -55,7 +55,7 @@
#endif
#define MAX_PLAYERS 5
#define MAX_BINDS 34 // Needs to be increased every time there are new binds added.
#define MAX_BINDS (SSNES_BIND_LIST_END + 1)
#define SSNES_NO_JOYPAD 0xFFFF
enum ssnes_shader_type
@@ -98,6 +98,9 @@ struct settings
unsigned font_size;
float msg_pos_x;
float msg_pos_y;
float msg_color_r;
float msg_color_g;
float msg_color_b;
bool force_16bit;
bool disable_composition;
@@ -135,6 +138,7 @@ struct settings
char libsnes[MAXPATHLEN];
char cheat_database[MAXPATHLEN];
char cheat_settings_path[MAXPATHLEN];
char screenshot_directory[MAXPATHLEN];
@@ -144,6 +148,8 @@ struct settings
bool pause_nonactive;
unsigned autosave_interval;
bool block_sram_overwrite;
};
enum ssnes_game_type
+9 -1
View File
@@ -24,6 +24,7 @@
#include <stdint.h>
#include "dynamic.h"
#include "general.h"
#include "sdlwrap.h"
static bool g_input_dead = true;
static bool g_video_dead = true;
@@ -232,6 +233,12 @@ static bool setup_video(ext_t *ext, const video_info_t *video, const input_drive
else if ((type == SSNES_SHADER_BSNES || type == SSNES_SHADER_AUTO) && *g_settings.video.bsnes_shader_path)
xml_shader = g_settings.video.bsnes_shader_path;
int font_color_r = g_settings.video.msg_color_r * 255;
int font_color_g = g_settings.video.msg_color_g * 255;
int font_color_b = g_settings.video.msg_color_b * 255;
font_color_r = font_color_r > 255 ? 255 : (font_color_r < 0 ? 0 : font_color_r);
font_color_g = font_color_g > 255 ? 255 : (font_color_g < 0 ? 0 : font_color_g);
font_color_b = font_color_b > 255 ? 255 : (font_color_b < 0 ? 0 : font_color_b);
ssnes_video_info_t info = {
.width = video->width,
@@ -246,7 +253,8 @@ static bool setup_video(ext_t *ext, const video_info_t *video, const input_drive
.xml_shader = xml_shader,
.cg_shader = cg_shader,
.ttf_font = *g_settings.video.font_path ? g_settings.video.font_path : NULL,
.ttf_font_size = g_settings.video.font_size
.ttf_font_size = g_settings.video.font_size,
.ttf_font_color = (font_color_r << 16) | (font_color_g << 8) | (font_color_b << 0),
};
const ssnes_input_driver_t *input_driver = NULL;
+3 -2
View File
@@ -108,7 +108,7 @@ typedef struct ssnes_video_info
// Can be disregarded.
const char *ttf_font;
unsigned ttf_font_size;
unsigned ttf_font_color; // Font color, in format RGB888.
} ssnes_video_info_t;
// Some convenience macros.
@@ -155,8 +155,9 @@ struct ssnes_keybind
// last frame and current frame in the Y-axis.
int analog_y;
// Keyboard key. The key values use the SDL keysyms,
// Keyboard key. The key values use the SDL 1.2 keysyms,
// which probably need to be transformed to the native format.
// The actual keysyms SSNES uses are found in input/keysym.h.
unsigned short key;
// Joypad key. Joypad POV (hats) are embedded into this key as well.
-20
View File
@@ -112,23 +112,3 @@ void gfx_set_dwm(void)
}
#endif
#include "SDL_syswm.h"
#include "SDL.h"
#if !defined(__APPLE__) && !defined(_WIN32)
void gfx_get_window_size(unsigned *width, unsigned *height)
{
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
SDL_GetWMInfo(&info);
XWindowAttributes target;
info.info.x11.lock_func();
XGetWindowAttributes(info.info.x11.display, info.info.x11.window,
&target);
info.info.x11.unlock_func();
*width = target.width;
*height = target.height;
}
#endif
-4
View File
@@ -28,8 +28,4 @@ void gfx_window_title_reset(void);
void gfx_set_dwm(void);
#endif
#if !defined(__APPLE__) && !defined(_WIN32)
void gfx_get_window_size(unsigned *width, unsigned *height);
#endif
#endif
+43 -96
View File
@@ -33,6 +33,7 @@
#include "gl_common.h"
#include "gfx_common.h"
#include "sdlwrap.h"
#define NO_SDL_GLEXT
#include "SDL.h"
@@ -622,6 +623,7 @@ static void gl_render_msg(gl_t *gl, const char *msg)
// Need blending.
// Using fixed function pipeline here since we cannot guarantee presence of shaders (would be kinda overkill anyways).
glEnable(GL_BLEND);
glColor4f(g_settings.video.msg_color_r, g_settings.video.msg_color_g, g_settings.video.msg_color_b, 1);
struct font_output_list out;
font_renderer_msg(gl->font, msg, &out);
@@ -654,10 +656,13 @@ static void gl_render_msg(gl_t *gl, const char *msg)
}
font_renderer_free_output(&out);
glColor4f(1, 1, 1, 1);
// Go back to old rendering path.
glTexCoordPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), gl->tex_coords);
glVertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), vertexes_flipped);
glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]);
glDisable(GL_BLEND);
#endif
}
@@ -685,43 +690,20 @@ static inline void set_texture_coords(GLfloat *coords, GLfloat xamt, GLfloat yam
static void check_window(gl_t *gl)
{
SDL_Event event;
bool quit, resize;
// Search for events we care about ...
while (SDL_PollEvent(&event))
sdlwrap_check_window(&quit,
&resize, &gl->win_width, &gl->win_height,
gl->frame_count);
if (quit)
{
switch (event.type)
{
case SDL_QUIT:
gl->quitting = true;
break;
case SDL_VIDEORESIZE:
gl->should_resize = true;
gl->win_width = event.resize.w;
gl->win_height = event.resize.h;
break;
default:
break;
}
gl->quitting = true;
}
#if !defined(__APPLE__) && !defined(_WIN32)
// Hack to workaround limitations in tiling WMs ...
if (!gl->should_resize && !gl->fullscreen)
else if (resize)
{
unsigned new_width, new_height;
gfx_get_window_size(&new_width, &new_height);
if ((new_width != gl->win_width || new_height != gl->win_height) || (gl->frame_count == 10)) // Ugly hack :D
{
gl->should_resize = true;
gl->win_width = new_width;
gl->win_height = new_height;
SSNES_LOG("GL: Verified window size: %u x %u\n", gl->win_width, gl->win_height);
}
gl->should_resize = true;
}
#endif
}
static bool gl_frame(void *data, const void* frame, unsigned width, unsigned height, unsigned pitch, const char *msg)
@@ -801,7 +783,8 @@ static bool gl_frame(void *data, const void* frame, unsigned width, unsigned hei
if (gl->should_resize)
{
gl->should_resize = false;
SDL_SetVideoMode(gl->win_width, gl->win_height, 0, SDL_OPENGL | SDL_RESIZABLE | (g_settings.video.fullscreen ? SDL_FULLSCREEN : 0));
sdlwrap_set_video_mode(gl->win_width, gl->win_height, 0, g_settings.video.fullscreen);
#ifdef HAVE_FBO
if (!gl->render_to_tex)
@@ -873,7 +856,7 @@ static bool gl_frame(void *data, const void* frame, unsigned width, unsigned hei
#endif
#ifdef HAVE_FBO
// Need to preserve the "flipped" state when in FBO too to have
// Need to preserve the "flipped" state when in FBO as well to have
// consistent texture coordinates.
if (gl->render_to_tex)
glVertexPointer(2, GL_FLOAT, 2 * sizeof(GLfloat), vertexes);
@@ -985,8 +968,9 @@ static bool gl_frame(void *data, const void* frame, unsigned width, unsigned hei
char buf[128];
if (gfx_window_title(buf, sizeof(buf)))
SDL_WM_SetCaption(buf, NULL);
SDL_GL_SwapBuffers();
sdlwrap_wm_set_caption(buf);
sdlwrap_swap_buffers();
return true;
}
@@ -1008,7 +992,7 @@ static void gl_free(void *data)
pglDeleteFramebuffers(gl->fbo_pass, gl->fbo);
}
#endif
SDL_QuitSubSystem(SDL_INIT_VIDEO);
sdlwrap_destroy();
if (gl->empty_buf)
free(gl->empty_buf);
@@ -1016,38 +1000,13 @@ static void gl_free(void *data)
free(gl);
}
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#endif
static void gl_set_nonblock_state(void *data, bool state)
{
gl_t *gl = data;
if (gl->vsync)
{
SSNES_LOG("GL VSync => %s\n", state ? "off" : "on");
#if defined(_WIN32)
static BOOL (APIENTRY *wgl_swap_interval)(int) = NULL;
if (!wgl_swap_interval)
{
SDL_SYM_WRAP(wgl_swap_interval, "wglSwapIntervalEXT");
}
if (wgl_swap_interval) wgl_swap_interval(state ? 0 : 1);
#elif defined(__APPLE__)
GLint val = state ? 0 : 1;
CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &val);
#else
static int (*glx_swap_interval)(int) = NULL;
if (!glx_swap_interval)
{
SDL_SYM_WRAP(glx_swap_interval, "glXSwapIntervalSGI");
}
if (!glx_swap_interval)
{
SDL_SYM_WRAP(glx_swap_interval, "glXSwapIntervalMESA");
}
if (glx_swap_interval) glx_swap_interval(state ? 0 : 1);
#endif
sdlwrap_set_swap_interval(state ? 0 : 1, true);
}
}
@@ -1057,7 +1016,7 @@ static void* gl_init(const video_info_t *video, const input_driver_t **input, vo
gfx_set_dwm();
#endif
if (SDL_Init(SDL_INIT_VIDEO) < 0)
if (!sdlwrap_init())
return NULL;
const SDL_VideoInfo *video_info = SDL_GetVideoInfo();
@@ -1066,16 +1025,24 @@ static void* gl_init(const video_info_t *video, const input_driver_t **input, vo
unsigned full_y = video_info->current_h;
SSNES_LOG("Detecting desktop resolution %ux%u.\n", full_x, full_y);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, video->vsync ? 1 : 0);
sdlwrap_set_swap_interval(video->vsync ? 1 : 0, false);
if (!SDL_SetVideoMode(video->width, video->height, g_settings.video.force_16bit ? 16 : 0, SDL_OPENGL | SDL_RESIZABLE | (video->fullscreen ? SDL_FULLSCREEN : 0)))
unsigned win_width = video->width;
unsigned win_height = video->height;
if (video->fullscreen && (win_width == 0) && (win_height == 0))
{
win_width = full_x;
win_height = full_y;
}
if (!sdlwrap_set_video_mode(win_width, win_height,
g_settings.video.force_16bit ? 15 : 0, video->fullscreen))
return NULL;
gfx_window_title_reset();
char buf[128];
if (gfx_window_title(buf, sizeof(buf)))
SDL_WM_SetCaption(buf, NULL);
sdlwrap_wm_set_caption(buf);
// Remove that ugly mouse :D
SDL_ShowCursor(SDL_DISABLE);
@@ -1086,7 +1053,7 @@ static void* gl_init(const video_info_t *video, const input_driver_t **input, vo
// Need to load dynamically :(
if (!load_gl_proc())
{
SDL_QuitSubSystem(SDL_INIT_VIDEO);
sdlwrap_destroy();
return NULL;
}
#endif
@@ -1094,44 +1061,24 @@ static void* gl_init(const video_info_t *video, const input_driver_t **input, vo
gl_t *gl = calloc(1, sizeof(gl_t));
if (!gl)
{
SDL_QuitSubSystem(SDL_INIT_VIDEO);
sdlwrap_destroy();
return NULL;
}
gl->vsync = video->vsync;
gl->fullscreen = video->fullscreen;
int attr = 0;
SDL_GL_GetAttribute(SDL_GL_SWAP_CONTROL, &attr);
if (attr <= 0 && video->vsync)
{
SSNES_WARN("SDL failed to setup VSync, attempting to recover using native calls!\n");
gl_set_nonblock_state(gl, false);
}
attr = 0;
SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &attr);
if (attr <= 0)
SSNES_WARN("GL double buffer has not been enabled!\n");
gl->full_x = full_x;
gl->full_y = full_y;
if (video->fullscreen)
{
gl->win_width = video->width ? video->width : gl->full_x;
gl->win_height = video->height ? video->height : gl->full_y;
}
else
{
gl->win_width = video->width;
gl->win_height = video->height;
}
gl->win_width = win_width;
gl->win_height = win_height;
SSNES_LOG("GL: Using resolution %ux%u\n", gl->win_width, gl->win_height);
if (!gl_shader_init())
{
SSNES_ERR("Shader init failed.\n");
SDL_QuitSubSystem(SDL_INIT_VIDEO);
sdlwrap_destroy();
free(gl);
return NULL;
}
@@ -1233,7 +1180,7 @@ static void* gl_init(const video_info_t *video, const input_driver_t **input, vo
if (!gl_check_error())
{
SDL_QuitSubSystem(SDL_INIT_VIDEO);
sdlwrap_destroy();
free(gl);
return NULL;
}
@@ -1250,7 +1197,7 @@ static bool gl_alive(void *data)
static bool gl_focus(void *data)
{
(void)data;
return (SDL_GetAppState() & (SDL_APPINPUTFOCUS | SDL_APPACTIVE)) == (SDL_APPINPUTFOCUS | SDL_APPACTIVE);
return sdlwrap_window_has_focus();
}
#ifdef HAVE_XML
-7
View File
@@ -106,13 +106,6 @@ struct gl_tex_info
GLfloat coord[8];
};
// Not legal to cast void* to fn-pointer. Need dirty hack to be compilant.
// sizeof(void*) == sizeof(void (*)(void)) is asserted earlier.
#define SDL_SYM_WRAP(sym, symbol) { \
void *sym__ = SDL_GL_GetProcAddress(symbol); \
memcpy(&(sym), &sym__, sizeof(void*)); \
}
// Windows ... <_<
#if (defined(HAVE_XML) || defined(HAVE_CG)) && defined(_WIN32)
extern PFNGLCLIENTACTIVETEXTUREPROC pglClientActiveTexture;
+49 -20
View File
@@ -45,11 +45,16 @@ struct sdl_video
bool rgb32;
bool upsample;
bool render32;
void (*convert_15_func)(uint16_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned, const SDL_PixelFormat*);
void (*convert_32_func)(uint32_t*, unsigned, const uint32_t*, unsigned, unsigned, unsigned, const SDL_PixelFormat*);
#ifdef HAVE_FREETYPE
font_renderer_t *font;
uint8_t font_r;
uint8_t font_g;
uint8_t font_b;
#endif
};
@@ -78,7 +83,29 @@ static void sdl_init_font(sdl_video_t *vid, const char *font_path, unsigned font
if (*font_path)
{
vid->font = font_renderer_new(font_path, font_size);
if (!vid->font)
if (vid->font)
{
int r = g_settings.video.msg_color_r * 255;
int g = g_settings.video.msg_color_g * 255;
int b = g_settings.video.msg_color_b * 255;
r = r < 0 ? 0 : (r > 255 ? 255 : r);
g = g < 0 ? 0 : (g > 255 ? 255 : g);
b = b < 0 ? 0 : (b > 255 ? 255 : b);
// RGB888 -> RGB555
if (!vid->render32)
{
r >>= 3;
g >>= 3;
b >>= 3;
}
vid->font_r = r;
vid->font_g = g;
vid->font_b = b;
}
else
SSNES_WARN("Failed to init font.\n");
}
#else
@@ -128,9 +155,9 @@ static void sdl_render_msg_15(sdl_video_t *vid, SDL_Surface *buffer, const char
unsigned g = (out_pix >> gshift) & 0x1f;
unsigned b = (out_pix >> bshift) & 0x1f;
unsigned out_r = (r * (256 - blend) + 0x1f * blend) >> 8;
unsigned out_g = (g * (256 - blend) + 0x1f * blend) >> 8;
unsigned out_b = (b * (256 - blend) + 0x1f * blend) >> 8;
unsigned out_r = (r * (256 - blend) + vid->font_r * blend) >> 8;
unsigned out_g = (g * (256 - blend) + vid->font_g * blend) >> 8;
unsigned out_b = (b * (256 - blend) + vid->font_b * blend) >> 8;
out[x] = (out_r << rshift) | (out_g << gshift) | (out_b << bshift);
}
}
@@ -189,9 +216,9 @@ static void sdl_render_msg_32(sdl_video_t *vid, SDL_Surface *buffer, const char
unsigned g = (out_pix >> gshift) & 0xff;
unsigned b = (out_pix >> bshift) & 0xff;
unsigned out_r = (r * (256 - blend) + 0xff * blend) >> 8;
unsigned out_g = (g * (256 - blend) + 0xff * blend) >> 8;
unsigned out_b = (b * (256 - blend) + 0xff * blend) >> 8;
unsigned out_r = (r * (256 - blend) + vid->font_r * blend) >> 8;
unsigned out_g = (g * (256 - blend) + vid->font_g * blend) >> 8;
unsigned out_b = (b * (256 - blend) + vid->font_b * blend) >> 8;
out[x] = (out_r << rshift) | (out_g << gshift) | (out_b << bshift);
}
}
@@ -232,13 +259,15 @@ static void* sdl_gfx_init(const video_info_t *video, const input_driver_t **inpu
if (!video->fullscreen)
SSNES_LOG("Creating window @ %ux%u\n", video->width, video->height);
vid->screen = SDL_SetVideoMode(video->width, video->height, (g_settings.video.force_16bit || !video->rgb32) ? 15 : 32, SDL_HWSURFACE | SDL_HWACCEL | SDL_DOUBLEBUF | (video->fullscreen ? SDL_FULLSCREEN : 0));
vid->render32 = video->rgb32 && !g_settings.video.force_16bit;
vid->screen = SDL_SetVideoMode(video->width, video->height, vid->render32 ? 32 : 15, SDL_HWSURFACE | SDL_HWACCEL | SDL_DOUBLEBUF | (video->fullscreen ? SDL_FULLSCREEN : 0));
if (!vid->screen && !g_settings.video.force_16bit && !video->rgb32)
{
vid->upsample = true;
vid->screen = SDL_SetVideoMode(video->width, video->height, 32, SDL_HWSURFACE | SDL_HWACCEL | SDL_DOUBLEBUF | (video->fullscreen ? SDL_FULLSCREEN : 0));
SSNES_WARN("SDL: 15-bit colors failed, attempting 32-bit colors.\n");
vid->render32 = true;
}
if (!vid->screen)
@@ -250,7 +279,7 @@ static void* sdl_gfx_init(const video_info_t *video, const input_driver_t **inpu
SDL_ShowCursor(SDL_DISABLE);
const SDL_PixelFormat *fmt = vid->screen->format;
if (!g_settings.video.force_16bit && (video->rgb32 || vid->upsample))
if (vid->render32)
{
SSNES_LOG("SDL: Creating 32-bit buffer.\n");
vid->buffer = SDL_CreateRGBSurface(SDL_SWSURFACE, 256 * video->input_scale, 256 * video->input_scale, 32,
@@ -285,7 +314,7 @@ static void* sdl_gfx_init(const video_info_t *video, const input_driver_t **inpu
sdl_init_font(vid, g_settings.video.font_path, g_settings.video.font_size);
if (fmt->Rshift == 10 && fmt->Gshift == 5 && fmt->Bshift == 0)
if (fmt->Rshift == 10 && fmt->Gshift == 5 && fmt->Bshift == 0) // XRGB1555
{
SSNES_LOG("SDL: 15-bit format matches. Fast blit.\n");
vid->convert_15_func = convert_15bit_15bit_direct;
@@ -296,7 +325,7 @@ static void* sdl_gfx_init(const video_info_t *video, const input_driver_t **inpu
vid->convert_15_func = convert_15bit_15bit_shift;
}
if (fmt->Rshift == 16 && fmt->Gshift == 8 && fmt->Bshift == 0)
if (fmt->Rshift == 16 && fmt->Gshift == 8 && fmt->Bshift == 0) // ARGB8888
{
SSNES_LOG("SDL: 32-bit format matches. Fast blit.\n");
vid->convert_32_func = convert_32bit_32bit_direct;
@@ -456,15 +485,7 @@ static bool sdl_gfx_frame(void *data, const void* frame, unsigned width, unsigne
{
vid->convert_32_func(vid->buffer->pixels, vid->buffer->pitch, frame, width, height, pitch, vid->screen->format);
}
if (msg)
{
if ((!vid->rgb32 || g_settings.video.force_16bit) && !vid->upsample)
sdl_render_msg_15(vid, vid->buffer, msg, width, height, vid->screen->format);
else
sdl_render_msg_32(vid, vid->buffer, msg, width, height, vid->screen->format);
}
if (SDL_MUSTLOCK(vid->buffer))
SDL_UnlockSurface(vid->buffer);
@@ -484,6 +505,14 @@ static bool sdl_gfx_frame(void *data, const void* frame, unsigned width, unsigne
SDL_SoftStretch(vid->buffer, &src, vid->screen, &dest);
if (msg)
{
if ((!vid->rgb32 || g_settings.video.force_16bit) && !vid->upsample)
sdl_render_msg_15(vid, vid->screen, msg, vid->screen->w, vid->screen->h, vid->screen->format);
else
sdl_render_msg_32(vid, vid->screen, msg, vid->screen->w, vid->screen->h, vid->screen->format);
}
char buf[128];
if (gfx_window_title(buf, sizeof(buf)))
SDL_WM_SetCaption(buf, NULL);
+330
View File
@@ -0,0 +1,330 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "sdlwrap.h"
#include "SDL_syswm.h"
#include "general.h"
#include <assert.h>
#ifdef __APPLE__
#include <OpenGL/OpenGL.h>
#endif
// SDL 1.2 is portable, sure, but you still need some platform specific workarounds ;)
// Hopefully SDL 1.3 will solve this more cleanly :D
// Welcome to #ifdef HELL! :D
//
#if SDL_MODERN
static SDL_Window* g_window;
static SDL_GLContext g_ctx;
#endif
static bool g_fullscreen;
static unsigned g_interval;
void sdlwrap_set_swap_interval(unsigned interval, bool inited)
{
g_interval = interval;
#if SDL_MODERN
if (g_window)
SDL_GL_SetSwapInterval(g_interval);
#else
if (inited)
{
#if defined(_WIN32)
static BOOL (APIENTRY *wgl_swap_interval)(int) = NULL;
if (!wgl_swap_interval)
{
SDL_SYM_WRAP(wgl_swap_interval, "wglSwapIntervalEXT");
}
if (wgl_swap_interval) wgl_swap_interval(g_interval);
#elif defined(__APPLE__)
GLint val = g_interval;
CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &val);
#else
static int (*glx_swap_interval)(int) = NULL;
if (!glx_swap_interval)
{
SDL_SYM_WRAP(glx_swap_interval, "glXSwapIntervalSGI");
}
if (!glx_swap_interval)
{
SDL_SYM_WRAP(glx_swap_interval, "glXSwapIntervalMESA");
}
if (glx_swap_interval)
glx_swap_interval(g_interval);
else
SSNES_WARN("Could not find GLX VSync call. :(\n");
#endif
}
#endif
}
bool sdlwrap_init(void)
{
#if SDL_MODERN
return SDL_VideoInit(NULL) == 0;
#else
return SDL_Init(SDL_INIT_VIDEO) == 0;
#endif
}
#if SDL_MODERN
void sdlwrap_destroy(void)
{
if (g_ctx)
SDL_GL_DeleteContext(g_ctx);
if (g_window)
SDL_DestroyWindow(g_window);
g_ctx = NULL;
g_window = NULL;
SDL_VideoQuit();
}
#else
void sdlwrap_destroy(void)
{
SDL_QuitSubSystem(SDL_INIT_VIDEO);
}
#endif
bool sdlwrap_set_video_mode(
unsigned width, unsigned height,
unsigned bits, bool fullscreen)
{
#if SDL_MODERN
if (g_window)
return true;
#endif
#if SDL_MODERN
static const int resizable = SDL_WINDOW_RESIZABLE;
#else
#ifndef __APPLE__ // Resizing on OSX is broken in 1.2 it seems :)
static const int resizable = SDL_RESIZABLE;
#else
static const int resizable = 0;
#endif
#endif
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
#if !SDL_MODERN
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, g_interval);
#endif
#if SDL_MODERN
if (bits == 15)
{
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
}
g_window = SDL_CreateWindow("SSNES", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | (fullscreen ? SDL_WINDOW_FULLSCREEN : resizable));
if (!g_window)
return false;
g_ctx = SDL_GL_CreateContext(g_window);
#else
if (!SDL_SetVideoMode(width, height, bits,
SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : resizable)))
return false;
#endif
int attr = 0;
#if SDL_MODERN
SDL_GL_SetSwapInterval(g_interval);
#else
SDL_GL_GetAttribute(SDL_GL_SWAP_CONTROL, &attr);
if (attr <= 0 && g_interval)
{
SSNES_WARN("SDL failed to setup VSync, attempting to recover using native calls!\n");
sdlwrap_set_swap_interval(g_interval, true);
}
#endif
g_fullscreen = fullscreen;
attr = 0;
SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &attr);
if (attr <= 0)
SSNES_WARN("GL double buffer has not been enabled!\n");
return true;
}
void sdlwrap_wm_set_caption(const char *str)
{
#if SDL_MODERN
SDL_SetWindowTitle(g_window, str);
#else
SDL_WM_SetCaption(str, NULL);
#endif
}
void sdlwrap_swap_buffers(void)
{
#if SDL_MODERN
SDL_GL_SwapWindow(g_window);
#else
SDL_GL_SwapBuffers();
#endif
}
bool sdlwrap_key_pressed(int key)
{
int num_keys;
#if SDL_MODERN
Uint8 *keymap = SDL_GetKeyboardState(&num_keys);
key = SDL_GetScancodeFromKey(key);
if (key >= num_keys)
return false;
return keymap[key];
#else
Uint8 *keymap = SDL_GetKeyState(&num_keys);
if (key >= num_keys)
return false;
return keymap[key];
#endif
}
// 1.2 specific workaround for tiling WMs. In 1.3 we call GetSize directly, so we don't need to rely on
// proper event handling (I hope).
#if !defined(__APPLE__) && !defined(_WIN32) && !SDL_MODERN
static void sdlwrap_get_window_size(unsigned *width, unsigned *height)
{
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
SDL_GetWMInfo(&info);
XWindowAttributes target;
info.info.x11.lock_func();
XGetWindowAttributes(info.info.x11.display, info.info.x11.window,
&target);
info.info.x11.unlock_func();
*width = target.width;
*height = target.height;
}
#endif
void sdlwrap_check_window(bool *quit,
bool *resize, unsigned *width, unsigned *height, unsigned frame_count)
{
*quit = false;
*resize = false;
SDL_Event event;
#if SDL_MODERN
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
*quit = true;
return;
case SDL_WINDOWEVENT:
switch (event.window.event)
{
case SDL_WINDOWEVENT_CLOSE:
*quit = true;
return;
case SDL_WINDOWEVENT_RESIZED:
*resize = true;
*width = event.window.data1;
*height = event.window.data2;
break;
}
break;
}
}
if (!*resize)
{
int w, h;
SDL_GetWindowSize(g_window, &w, &h);
if (*width != (unsigned)w || *height != (unsigned)h)
{
*resize = true;
*width = w;
*height = h;
}
}
#else
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
*quit = true;
break;
case SDL_VIDEORESIZE:
*resize = true;
*width = event.resize.w;
*height = event.resize.h;
break;
}
}
#if !defined(__APPLE__) && !defined(_WIN32)
// Hack to workaround limitations in tiling WMs ...
if (!*resize && !g_fullscreen)
{
unsigned new_width, new_height;
sdlwrap_get_window_size(&new_width, &new_height);
if ((new_width != *width || new_height != *height) || (frame_count == 10)) // Ugly hack :D
{
*resize = true;
*width = new_width;
*height = new_height;
SSNES_LOG("GL: Verified window size: %u x %u\n", *width, *height);
}
}
#endif
#endif
}
bool sdlwrap_get_wm_info(SDL_SysWMinfo *info)
{
#if SDL_MODERN
if (g_window)
return SDL_GetWindowWMInfo(g_window, info);
else
return SDL_GetWMInfo(info) == 1;
#else
return SDL_GetWMInfo(info) == 1;
#endif
}
bool sdlwrap_window_has_focus(void)
{
#if SDL_MODERN
Uint32 flags = SDL_GetWindowFlags(g_window);
flags &= SDL_WINDOW_INPUT_FOCUS;
return flags == SDL_WINDOW_INPUT_FOCUS;
#else
return (SDL_GetAppState() & (SDL_APPINPUTFOCUS | SDL_APPACTIVE)) == (SDL_APPINPUTFOCUS | SDL_APPACTIVE);
#endif
}
+66
View File
@@ -0,0 +1,66 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
// Compatibility wrapper between SDL 1.2/1.3 for OpenGL.
// Wraps functions which differ in 1.2 and 1.3.
#ifndef __SDLWRAP_H
#define __SDLWRAP_H
#include <stdbool.h>
#include "SDL.h"
#include "SDL_version.h"
#include "SDL_syswm.h"
#if SDL_VERSION_ATLEAST(1, 3, 0)
#define SDL_MODERN 1
#else
#define SDL_MODERN 0
#endif
// Not legal to cast void* to fn-pointer. Need workaround to be compliant.
#define SDL_SYM_WRAP(sym, symbol) { \
assert(sizeof(void*) == sizeof(void (*)(void))); \
void *sym__ = SDL_GL_GetProcAddress(symbol); \
memcpy(&(sym), &sym__, sizeof(void*)); \
}
void sdlwrap_set_swap_interval(unsigned interval, bool inited);
bool sdlwrap_set_video_mode(
unsigned width, unsigned height,
unsigned bits, bool fullscreen);
bool sdlwrap_init(void);
void sdlwrap_destroy(void);
void sdlwrap_wm_set_caption(const char *str);
void sdlwrap_swap_buffers(void);
bool sdlwrap_key_pressed(int key);
void sdlwrap_check_window(bool *quit,
bool *resize, unsigned *width, unsigned *height, unsigned frame_count);
bool sdlwrap_get_wm_info(SDL_SysWMinfo *info);
bool sdlwrap_window_has_focus(void);
#endif
+6 -3
View File
@@ -37,20 +37,23 @@ static const char* stock_cg_program =
"("
" float4 position : POSITION,"
" float2 texCoord : TEXCOORD0,"
" float4 color : COLOR,"
""
" uniform float4x4 modelViewProj,"
""
" out float4 oPosition : POSITION,"
" out float2 otexCoord : TEXCOORD0"
" out float2 otexCoord : TEXCOORD0,"
" out float4 oColor : COLOR"
")"
"{"
" oPosition = mul(modelViewProj, position);"
" otexCoord = texCoord;"
" oColor = color;"
"}"
""
"float4 main_fragment(float2 tex : TEXCOORD0, uniform sampler2D s0 : TEXUNIT0) : COLOR"
"float4 main_fragment(in float4 color : COLOR, float2 tex : TEXCOORD0, uniform sampler2D s0 : TEXUNIT0) : COLOR"
"{"
" return tex2D(s0, tex);"
" return color * tex2D(s0, tex);"
"}";
#ifdef SSNES_CG_DEBUG
+1 -1
View File
@@ -33,7 +33,7 @@
#define NO_SDL_GLEXT
#include "SDL.h"
#include "sdlwrap.h"
#include "SDL_opengl.h"
#include <stdlib.h>
#include <libxml/parser.h>
+104 -49
View File
@@ -63,11 +63,17 @@ struct xv
uint8_t *ytable;
uint8_t *utable;
uint8_t *vtable;
unsigned luma_i;
unsigned chroma_i;
#ifdef HAVE_FREETYPE
font_renderer_t *font;
unsigned luma_index[2];
unsigned chroma_u_index;
unsigned chroma_v_index;
uint8_t font_y;
uint8_t font_u;
uint8_t font_v;
#endif
void (*render_func)(xv_t*, const void *frame, unsigned width, unsigned height, unsigned pitch);
@@ -89,6 +95,17 @@ static void sighandler(int sig)
g_quit = 1;
}
static inline void calculate_yuv(uint8_t *y, uint8_t *u, uint8_t *v, unsigned r, unsigned g, unsigned b)
{
int y_ = (int)(+((double)r * 0.257) + ((double)g * 0.504) + ((double)b * 0.098) + 16.0);
int u_ = (int)(-((double)r * 0.148) - ((double)g * 0.291) + ((double)b * 0.439) + 128.0);
int v_ = (int)(+((double)r * 0.439) - ((double)g * 0.368) - ((double)b * 0.071) + 128.0);
*y = y_ < 0 ? 0 : (y_ > 255 ? 255 : y_);
*u = y_ < 0 ? 0 : (u_ > 255 ? 255 : u_);
*v = v_ < 0 ? 0 : (v_ > 255 ? 255 : v_);
}
static void init_yuv_tables(xv_t *xv)
{
xv->ytable = malloc(0x8000);
@@ -98,18 +115,12 @@ static void init_yuv_tables(xv_t *xv)
for (unsigned i = 0; i < 0x8000; i++)
{
// Extract RGB555 color data from i
uint8_t r = (i >> 10) & 0x1F, g = (i >> 5) & 0x1F, b = (i) & 0x1F;
r = (r << 3) | (r >> 2); //R5->R8
g = (g << 3) | (g >> 2); //G5->G8
b = (b << 3) | (b >> 2); //B5->B8
unsigned r = (i >> 10) & 0x1F, g = (i >> 5) & 0x1F, b = (i) & 0x1F;
r = (r << 3) | (r >> 2); // R5->R8
g = (g << 3) | (g >> 2); // G5->G8
b = (b << 3) | (b >> 2); // B5->B8
int y = (int)(+((double)r * 0.257) + ((double)g * 0.504) + ((double)b * 0.098) + 16.0);
int u = (int)(-((double)r * 0.148) - ((double)g * 0.291) + ((double)b * 0.439) + 128.0);
int v = (int)(+((double)r * 0.439) - ((double)g * 0.368) - ((double)b * 0.071) + 128.0);
xv->ytable[i] = y < 0 ? 0 : y > 255 ? 255 : y;
xv->utable[i] = u < 0 ? 0 : u > 255 ? 255 : u;
xv->vtable[i] = v < 0 ? 0 : v > 255 ? 255 : v;
calculate_yuv(&xv->ytable[i], &xv->utable[i], &xv->vtable[i], r, g, b);
}
}
@@ -176,7 +187,19 @@ static void xv_init_font(xv_t *xv, const char *font_path, unsigned font_size)
if (*font_path)
{
xv->font = font_renderer_new(font_path, font_size);
if (!xv->font)
if (xv->font)
{
int r = g_settings.video.msg_color_r * 255;
r = (r < 0 ? 0 : (r > 255 ? 255 : r));
int g = g_settings.video.msg_color_g * 255;
g = (g < 0 ? 0 : (g > 255 ? 255 : g));
int b = g_settings.video.msg_color_b * 255;
b = (b < 0 ? 0 : (b > 255 ? 255 : b));
calculate_yuv(&xv->font_y, &xv->font_u, &xv->font_v,
r, g, b);
}
else
SSNES_WARN("Failed to init font.\n");
}
#endif
@@ -297,7 +320,6 @@ static void render32_uyvy(xv_t *xv, const void *input_, unsigned width, unsigned
}
}
static void* xv_init(const video_info_t *video, const input_driver_t **input, void **input_data)
{
xv_t *xv = calloc(1, sizeof(*xv));
@@ -383,7 +405,7 @@ static void* xv_init(const video_info_t *video, const input_driver_t **input, vo
// Set colorkey to auto paint, so that Xv video output is always visible
Atom atom = XInternAtom(xv->display, "XV_AUTOPAINT_COLORKEY", true);
if(atom != None) XvSetPortAttribute(xv->display, xv->port, atom, 1);
if (atom != None) XvSetPortAttribute(xv->display, xv->port, atom, 1);
int format_count;
XvImageFormatValues *format = XvListImageFormats(xv->display, xv->port, &format_count);
@@ -399,29 +421,43 @@ static void* xv_init(const video_info_t *video, const input_driver_t **input, vo
has_format = true;
xv->fourcc = format[i].id;
xv->render_func = video->rgb32 ? render32_yuy2 : render16_yuy2;
xv->luma_i = 0; xv->chroma_i = 1;
#ifdef HAVE_FREETYPE
xv->luma_index[0] = 0;
xv->luma_index[1] = 2;
xv->chroma_u_index = 1;
xv->chroma_v_index = 3;
#endif
break;
}
}
}
if (!has_format) for (int i = 0; i < format_count; i++)
if (!has_format)
{
if (format[i].type == XvYUV && format[i].bits_per_pixel == 16 && format[i].format == XvPacked)
for (int i = 0; i < format_count; i++)
{
if (format[i].component_order[0] == 'U' && format[i].component_order[1] == 'Y'
&& format[i].component_order[2] == 'V' && format[i].component_order[3] == 'Y')
if (format[i].type == XvYUV && format[i].bits_per_pixel == 16 && format[i].format == XvPacked)
{
has_format = true;
xv->fourcc = format[i].id;
xv->render_func = video->rgb32 ? render32_uyvy : render16_uyvy;
xv->chroma_i = 0; xv->luma_i = 1;
break;
if (format[i].component_order[0] == 'U' && format[i].component_order[1] == 'Y'
&& format[i].component_order[2] == 'V' && format[i].component_order[3] == 'Y')
{
has_format = true;
xv->fourcc = format[i].id;
xv->render_func = video->rgb32 ? render32_uyvy : render16_uyvy;
#ifdef HAVE_FREETYPE
xv->luma_index[0] = 1;
xv->luma_index[1] = 3;
xv->chroma_u_index = 0;
xv->chroma_v_index = 2;
#endif
break;
}
}
}
}
free(format);
if (!has_format)
{
@@ -466,8 +502,6 @@ static void* xv_init(const video_info_t *video, const input_driver_t **input, vo
xv_set_nonblock_state(xv, !video->vsync);
xv->focus = true;
xv_init_font(xv, g_settings.video.font_path, g_settings.video.font_size);
void *xinput = input_x.init();
if (xinput)
{
@@ -478,6 +512,8 @@ static void* xv_init(const video_info_t *video, const input_driver_t **input, vo
*input = NULL;
init_yuv_tables(xv);
xv_init_font(xv, g_settings.video.font_path, g_settings.video.font_size);
return xv;
error:
@@ -561,6 +597,7 @@ static void calc_out_rect(bool keep_aspect, unsigned *x, unsigned *y, unsigned *
}
// TODO: Is there some way to render directly like GL? :(
// Hacky C code is hacky :D Yay.
static void xv_render_msg(xv_t *xv, const char *msg, unsigned width, unsigned height)
{
#ifdef HAVE_FREETYPE
@@ -574,12 +611,17 @@ static void xv_render_msg(xv_t *xv, const char *msg, unsigned width, unsigned he
int _base_x = g_settings.video.msg_pos_x * width;
int _base_y = height - g_settings.video.msg_pos_y * height;
unsigned luma_i = xv->luma_i;
unsigned chroma_i = xv->chroma_i;
unsigned luma_index[2] = { xv->luma_index[0], xv->luma_index[1] };
unsigned chroma_u_index = xv->chroma_u_index;
unsigned chroma_v_index = xv->chroma_v_index;
unsigned pitch = width << 1; // YUV formats used are 16 bpp.
while (head)
{
int base_x = _base_x + head->off_x;
int base_x = (_base_x + head->off_x) << 1;
base_x &= ~3; // Make sure we always start on the correct boundary so the indices are correct.
int base_y = _base_y - head->off_y;
if (base_y >= 0)
{
@@ -588,21 +630,33 @@ static void xv_render_msg(xv_t *xv, const char *msg, unsigned width, unsigned he
if (base_x < 0)
continue;
const uint8_t *a = head->output + head->pitch * y;
uint8_t *out = (uint8_t*)xv->image->data + (base_y - head->height + y) * (width << 1) + (base_x << 1);
const uint8_t * restrict a = head->output + head->pitch * y;
uint8_t * restrict out = (uint8_t*)xv->image->data + (base_y - head->height + y) * pitch + base_x;
for (int x = 0; x < (head->width << 1) && (base_x + x) < width; x += 2)
for (int x = 0; x < (head->width << 1) && (base_x + x) < pitch; x += 4)
{
// Blend luma
uint8_t blend = a[x >> 1];
unsigned blended = blend + (((256 - blend) * (unsigned)out[x + luma_i]) >> 8);
blended = blended > 255 ? 255 : blended;
out[x + luma_i] = blended;
unsigned alpha[2];
alpha[0] = a[(x >> 1) + 0];
// Blend chroma
blended = (128 * blend + ((256 - blend) * (unsigned)out[x + chroma_i])) >> 8;
blended = blended > 255 ? 255 : blended;
out[x + chroma_i] = blended;
if (((x >> 1) + 1) == head->width) // We reached the end, uhoh! Branching like a BOSS! :D
alpha[1] = 0;
else
alpha[1] = a[(x >> 1) + 1];
unsigned alpha_sub = (alpha[0] + alpha[1]) >> 1; // Blended alpha for the sub-samples U/V channels.
for (unsigned i = 0; i < 2; i++)
{
unsigned blended = (xv->font_y * alpha[i] + ((256 - alpha[i]) * out[x + luma_index[i]])) >> 8;
out[x + luma_index[i]] = blended;
}
// Blend chroma channels
unsigned blended = (xv->font_u * alpha_sub + ((256 - alpha_sub) * out[x + chroma_u_index])) >> 8;
out[x + chroma_u_index] = blended;
blended = (xv->font_v * alpha_sub + ((256 - alpha_sub) * out[x + chroma_v_index])) >> 8;
out[x + chroma_v_index] = blended;
}
}
}
@@ -630,11 +684,12 @@ static bool xv_frame(void *data, const void* frame, unsigned width, unsigned hei
XGetWindowAttributes(xv->display, xv->window, &target);
xv->render_func(xv, frame, width, height, pitch);
if (msg)
xv_render_msg(xv, msg, xv->width, xv->height);
unsigned x, y, owidth, oheight;
calc_out_rect(xv->keep_aspect, &x, &y, &owidth, &oheight, target.width, target.height);
if (msg)
xv_render_msg(xv, msg, width << 1, height << 1);
XvShmPutImage(xv->display, xv->port, xv->window, xv->gc, xv->image,
0, 0, width << 1, height << 1,
x, y, owidth, oheight,
@@ -693,9 +748,9 @@ static void xv_free(void *data)
shmctl(xv->shminfo.shmid, IPC_RMID, NULL);
XFree(xv->image);
if(xv->window)
if (xv->window)
XUnmapWindow(xv->display, xv->window);
if(xv->colormap)
if (xv->colormap)
XFreeColormap(xv->display, xv->colormap);
XCloseDisplay(xv->display);
+9 -1
View File
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include "../gfx/sdlwrap.h"
void sdl_dinput_free(sdl_dinput_t *di)
{
@@ -103,12 +104,19 @@ sdl_dinput_t* sdl_dinput_init(void)
CoInitialize(NULL);
SDL_SysWMinfo info;
if (!SDL_GetWMInfo(&info))
SDL_VERSION(&info.version);
if (!sdlwrap_get_wm_info(&info))
{
SSNES_ERR("Failed to get SysWM info.\n");
goto error;
}
#if SDL_MODERN
di->hWnd = info.info.win.window;
#else
di->hWnd = info.window;
#endif
if (FAILED(DirectInput8Create(
GetModuleHandle(NULL), DIRECTINPUT_VERSION, &IID_IDirectInput8,
+173
View File
@@ -0,0 +1,173 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __SSNES_KEYSYM_H
#define __SSNES_KEYSYM_H
// Global keysym table for SSNES.
// As you may have noticed, it's the same as SDL 1.2 since I'm lazy.
enum ssnes_key
{
SK_UNKNOWN = 0,
SK_FIRST = 0,
SK_BACKSPACE = 8,
SK_TAB = 9,
SK_CLEAR = 12,
SK_RETURN = 13,
SK_PAUSE = 19,
SK_ESCAPE = 27,
SK_SPACE = 32,
SK_EXCLAIM = 33,
SK_QUOTEDBL = 34,
SK_HASH = 35,
SK_DOLLAR = 36,
SK_AMPERSAND = 38,
SK_QUOTE = 39,
SK_LEFTPAREN = 40,
SK_RIGHTPAREN = 41,
SK_ASTERISK = 42,
SK_PLUS = 43,
SK_COMMA = 44,
SK_MINUS = 45,
SK_PERIOD = 46,
SK_SLASH = 47,
SK_0 = 48,
SK_1 = 49,
SK_2 = 50,
SK_3 = 51,
SK_4 = 52,
SK_5 = 53,
SK_6 = 54,
SK_7 = 55,
SK_8 = 56,
SK_9 = 57,
SK_COLON = 58,
SK_SEMICOLON = 59,
SK_LESS = 60,
SK_EQUALS = 61,
SK_GREATER = 62,
SK_QUESTION = 63,
SK_AT = 64,
SK_LEFTBRACKET = 91,
SK_BACKSLASH = 92,
SK_RIGHTBRACKET = 93,
SK_CARET = 94,
SK_UNDERSCORE = 95,
SK_BACKQUOTE = 96,
SK_a = 97,
SK_b = 98,
SK_c = 99,
SK_d = 100,
SK_e = 101,
SK_f = 102,
SK_g = 103,
SK_h = 104,
SK_i = 105,
SK_j = 106,
SK_k = 107,
SK_l = 108,
SK_m = 109,
SK_n = 110,
SK_o = 111,
SK_p = 112,
SK_q = 113,
SK_r = 114,
SK_s = 115,
SK_t = 116,
SK_u = 117,
SK_v = 118,
SK_w = 119,
SK_x = 120,
SK_y = 121,
SK_z = 122,
SK_DELETE = 127,
SK_KP0 = 256,
SK_KP1 = 257,
SK_KP2 = 258,
SK_KP3 = 259,
SK_KP4 = 260,
SK_KP5 = 261,
SK_KP6 = 262,
SK_KP7 = 263,
SK_KP8 = 264,
SK_KP9 = 265,
SK_KP_PERIOD = 266,
SK_KP_DIVIDE = 267,
SK_KP_MULTIPLY = 268,
SK_KP_MINUS = 269,
SK_KP_PLUS = 270,
SK_KP_ENTER = 271,
SK_KP_EQUALS = 272,
SK_UP = 273,
SK_DOWN = 274,
SK_RIGHT = 275,
SK_LEFT = 276,
SK_INSERT = 277,
SK_HOME = 278,
SK_END = 279,
SK_PAGEUP = 280,
SK_PAGEDOWN = 281,
SK_F1 = 282,
SK_F2 = 283,
SK_F3 = 284,
SK_F4 = 285,
SK_F5 = 286,
SK_F6 = 287,
SK_F7 = 288,
SK_F8 = 289,
SK_F9 = 290,
SK_F10 = 291,
SK_F11 = 292,
SK_F12 = 293,
SK_F13 = 294,
SK_F14 = 295,
SK_F15 = 296,
SK_NUMLOCK = 300,
SK_CAPSLOCK = 301,
SK_SCROLLOCK = 302,
SK_RSHIFT = 303,
SK_LSHIFT = 304,
SK_RCTRL = 305,
SK_LCTRL = 306,
SK_RALT = 307,
SK_LALT = 308,
SK_RMETA = 309,
SK_LMETA = 310,
SK_LSUPER = 311,
SK_RSUPER = 312,
SK_MODE = 313,
SK_COMPOSE = 314,
SK_HELP = 315,
SK_PRINT = 316,
SK_SYSREQ = 317,
SK_BREAK = 318,
SK_MENU = 319,
SK_POWER = 320,
SK_EURO = 321,
SK_UNDO = 322,
SK_LAST
};
#endif
+99 -9
View File
@@ -17,17 +17,114 @@
#include "driver.h"
#include "SDL.h"
#include "../gfx/sdlwrap.h"
#include <stdbool.h>
#include "general.h"
#include <stdint.h>
#include <stdlib.h>
#include <libsnes.hpp>
#include "ssnes_sdl_input.h"
#include "keysym.h"
struct key_bind
{
unsigned sdl;
enum ssnes_key sk;
};
static unsigned keysym_lut[SK_LAST];
static const struct key_bind lut_binds[] = {
{ SDLK_LEFT, SK_LEFT },
{ SDLK_RIGHT, SK_RIGHT },
{ SDLK_UP, SK_UP },
{ SDLK_DOWN, SK_DOWN },
{ SDLK_RETURN, SK_RETURN },
{ SDLK_TAB, SK_TAB },
{ SDLK_INSERT, SK_INSERT },
{ SDLK_DELETE, SK_DELETE },
{ SDLK_RSHIFT, SK_RSHIFT },
{ SDLK_LSHIFT, SK_LSHIFT },
{ SDLK_LCTRL, SK_LCTRL },
{ SDLK_LALT, SK_LALT },
{ SDLK_SPACE, SK_SPACE },
{ SDLK_ESCAPE, SK_ESCAPE },
{ SDLK_BACKSPACE, SK_BACKSPACE },
{ SDLK_KP_ENTER, SK_KP_ENTER },
{ SDLK_KP_PLUS, SK_KP_PLUS },
{ SDLK_KP_MINUS, SK_KP_MINUS },
{ SDLK_KP_MULTIPLY, SK_KP_MULTIPLY },
{ SDLK_KP_DIVIDE, SK_KP_DIVIDE },
{ SDLK_BACKQUOTE, SK_BACKQUOTE },
{ SDLK_KP0, SK_KP0 },
{ SDLK_KP1, SK_KP1 },
{ SDLK_KP2, SK_KP2 },
{ SDLK_KP3, SK_KP3 },
{ SDLK_KP4, SK_KP4 },
{ SDLK_KP5, SK_KP5 },
{ SDLK_KP6, SK_KP6 },
{ SDLK_KP7, SK_KP7 },
{ SDLK_KP8, SK_KP8 },
{ SDLK_KP9, SK_KP9 },
{ SDLK_0, SK_0 },
{ SDLK_1, SK_1 },
{ SDLK_2, SK_2 },
{ SDLK_3, SK_3 },
{ SDLK_4, SK_4 },
{ SDLK_5, SK_5 },
{ SDLK_6, SK_6 },
{ SDLK_7, SK_7 },
{ SDLK_8, SK_8 },
{ SDLK_9, SK_9 },
{ SDLK_F1, SK_F1 },
{ SDLK_F2, SK_F2 },
{ SDLK_F3, SK_F3 },
{ SDLK_F4, SK_F4 },
{ SDLK_F5, SK_F5 },
{ SDLK_F6, SK_F6 },
{ SDLK_F7, SK_F7 },
{ SDLK_F8, SK_F8 },
{ SDLK_F9, SK_F9 },
{ SDLK_F10, SK_F10 },
{ SDLK_F11, SK_F11 },
{ SDLK_F12, SK_F12 },
{ SDLK_a, SK_a },
{ SDLK_b, SK_b },
{ SDLK_c, SK_c },
{ SDLK_d, SK_d },
{ SDLK_e, SK_e },
{ SDLK_f, SK_f },
{ SDLK_g, SK_g },
{ SDLK_h, SK_h },
{ SDLK_i, SK_i },
{ SDLK_j, SK_j },
{ SDLK_k, SK_k },
{ SDLK_l, SK_l },
{ SDLK_m, SK_m },
{ SDLK_n, SK_n },
{ SDLK_o, SK_o },
{ SDLK_p, SK_p },
{ SDLK_q, SK_q },
{ SDLK_r, SK_r },
{ SDLK_s, SK_s },
{ SDLK_t, SK_t },
{ SDLK_u, SK_u },
{ SDLK_v, SK_v },
{ SDLK_w, SK_w },
{ SDLK_x, SK_x },
{ SDLK_y, SK_y },
{ SDLK_z, SK_z },
};
static void init_lut(void)
{
memset(keysym_lut, 0, sizeof(keysym_lut));
for (unsigned i = 0; i < sizeof(lut_binds) / sizeof(lut_binds[0]); i++)
keysym_lut[lut_binds[i].sk] = lut_binds[i].sdl;
}
static void* sdl_input_init(void)
{
init_lut();
sdl_input_t *sdl = calloc(1, sizeof(*sdl));
if (!sdl)
return NULL;
@@ -76,16 +173,9 @@ static void* sdl_input_init(void)
return sdl;
}
static bool sdl_key_pressed(int key)
{
int num_keys;
Uint8 *keymap = SDL_GetKeyState(&num_keys);
if (key >= num_keys)
return false;
return keymap[key];
return sdlwrap_key_pressed(keysym_lut[key]);
}
#ifndef HAVE_DINPUT
+84 -85
View File
@@ -23,6 +23,7 @@
#include <stdint.h>
#include <stdlib.h>
#include "ssnes_sdl_input.h"
#include "keysym.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -37,100 +38,98 @@ typedef struct x11_input
struct key_bind
{
int x;
int sdl;
unsigned x;
enum ssnes_key sk;
};
static int keysym_lut[SDLK_LAST];
static unsigned keysym_lut[SK_LAST];
static const struct key_bind lut_binds[] = {
{ XK_Left, SDLK_LEFT },
{ XK_Right, SDLK_RIGHT },
{ XK_Up, SDLK_UP },
{ XK_Down, SDLK_DOWN },
{ XK_Return, SDLK_RETURN },
{ XK_Tab, SDLK_TAB },
{ XK_Insert, SDLK_INSERT },
{ XK_Delete, SDLK_DELETE },
{ XK_Shift_R, SDLK_RSHIFT },
{ XK_Shift_L, SDLK_LSHIFT },
{ XK_Control_L, SDLK_LCTRL },
{ XK_Alt_L, SDLK_LALT },
{ XK_space, SDLK_SPACE },
{ XK_Escape, SDLK_ESCAPE },
{ XK_KP_Add, SDLK_KP_PLUS },
{ XK_KP_Subtract, SDLK_KP_MINUS },
{ XK_BackSpace, SDLK_BACKSPACE },
{ XK_KP_Enter, SDLK_KP_ENTER },
{ XK_KP_Add, SDLK_KP_PLUS },
{ XK_KP_Subtract, SDLK_KP_MINUS },
{ XK_KP_Multiply, SDLK_KP_MULTIPLY },
{ XK_KP_Divide, SDLK_KP_DIVIDE },
{ XK_grave, SDLK_BACKQUOTE },
{ XK_KP_0, SDLK_KP0 },
{ XK_KP_1, SDLK_KP1 },
{ XK_KP_2, SDLK_KP2 },
{ XK_KP_3, SDLK_KP3 },
{ XK_KP_4, SDLK_KP4 },
{ XK_KP_5, SDLK_KP5 },
{ XK_KP_6, SDLK_KP6 },
{ XK_KP_7, SDLK_KP7 },
{ XK_KP_8, SDLK_KP8 },
{ XK_KP_9, SDLK_KP9 },
{ XK_0, SDLK_0 },
{ XK_1, SDLK_1 },
{ XK_2, SDLK_2 },
{ XK_3, SDLK_3 },
{ XK_4, SDLK_4 },
{ XK_5, SDLK_5 },
{ XK_6, SDLK_6 },
{ XK_7, SDLK_7 },
{ XK_8, SDLK_8 },
{ XK_9, SDLK_9 },
{ XK_F1, SDLK_F1 },
{ XK_F2, SDLK_F2 },
{ XK_F3, SDLK_F3 },
{ XK_F4, SDLK_F4 },
{ XK_F5, SDLK_F5 },
{ XK_F6, SDLK_F6 },
{ XK_F7, SDLK_F7 },
{ XK_F8, SDLK_F8 },
{ XK_F9, SDLK_F9 },
{ XK_F10, SDLK_F10 },
{ XK_F11, SDLK_F11 },
{ XK_F12, SDLK_F12 },
{ XK_a, SDLK_a },
{ XK_b, SDLK_b },
{ XK_c, SDLK_c },
{ XK_d, SDLK_d },
{ XK_e, SDLK_e },
{ XK_f, SDLK_f },
{ XK_g, SDLK_g },
{ XK_h, SDLK_h },
{ XK_i, SDLK_i },
{ XK_j, SDLK_j },
{ XK_k, SDLK_k },
{ XK_l, SDLK_l },
{ XK_m, SDLK_m },
{ XK_n, SDLK_n },
{ XK_o, SDLK_o },
{ XK_p, SDLK_p },
{ XK_q, SDLK_q },
{ XK_r, SDLK_r },
{ XK_s, SDLK_s },
{ XK_t, SDLK_t },
{ XK_u, SDLK_u },
{ XK_v, SDLK_v },
{ XK_w, SDLK_w },
{ XK_x, SDLK_x },
{ XK_y, SDLK_y },
{ XK_z, SDLK_z },
{ XK_Left, SK_LEFT },
{ XK_Right, SK_RIGHT },
{ XK_Up, SK_UP },
{ XK_Down, SK_DOWN },
{ XK_Return, SK_RETURN },
{ XK_Tab, SK_TAB },
{ XK_Insert, SK_INSERT },
{ XK_Delete, SK_DELETE },
{ XK_Shift_R, SK_RSHIFT },
{ XK_Shift_L, SK_LSHIFT },
{ XK_Control_L, SK_LCTRL },
{ XK_Alt_L, SK_LALT },
{ XK_space, SK_SPACE },
{ XK_Escape, SK_ESCAPE },
{ XK_BackSpace, SK_BACKSPACE },
{ XK_KP_Enter, SK_KP_ENTER },
{ XK_KP_Add, SK_KP_PLUS },
{ XK_KP_Subtract, SK_KP_MINUS },
{ XK_KP_Multiply, SK_KP_MULTIPLY },
{ XK_KP_Divide, SK_KP_DIVIDE },
{ XK_grave, SK_BACKQUOTE },
{ XK_KP_0, SK_KP0 },
{ XK_KP_1, SK_KP1 },
{ XK_KP_2, SK_KP2 },
{ XK_KP_3, SK_KP3 },
{ XK_KP_4, SK_KP4 },
{ XK_KP_5, SK_KP5 },
{ XK_KP_6, SK_KP6 },
{ XK_KP_7, SK_KP7 },
{ XK_KP_8, SK_KP8 },
{ XK_KP_9, SK_KP9 },
{ XK_0, SK_0 },
{ XK_1, SK_1 },
{ XK_2, SK_2 },
{ XK_3, SK_3 },
{ XK_4, SK_4 },
{ XK_5, SK_5 },
{ XK_6, SK_6 },
{ XK_7, SK_7 },
{ XK_8, SK_8 },
{ XK_9, SK_9 },
{ XK_F1, SK_F1 },
{ XK_F2, SK_F2 },
{ XK_F3, SK_F3 },
{ XK_F4, SK_F4 },
{ XK_F5, SK_F5 },
{ XK_F6, SK_F6 },
{ XK_F7, SK_F7 },
{ XK_F8, SK_F8 },
{ XK_F9, SK_F9 },
{ XK_F10, SK_F10 },
{ XK_F11, SK_F11 },
{ XK_F12, SK_F12 },
{ XK_a, SK_a },
{ XK_b, SK_b },
{ XK_c, SK_c },
{ XK_d, SK_d },
{ XK_e, SK_e },
{ XK_f, SK_f },
{ XK_g, SK_g },
{ XK_h, SK_h },
{ XK_i, SK_i },
{ XK_j, SK_j },
{ XK_k, SK_k },
{ XK_l, SK_l },
{ XK_m, SK_m },
{ XK_n, SK_n },
{ XK_o, SK_o },
{ XK_p, SK_p },
{ XK_q, SK_q },
{ XK_r, SK_r },
{ XK_s, SK_s },
{ XK_t, SK_t },
{ XK_u, SK_u },
{ XK_v, SK_v },
{ XK_w, SK_w },
{ XK_x, SK_x },
{ XK_y, SK_y },
{ XK_z, SK_z },
};
static void init_lut(void)
{
memset(keysym_lut, 0, sizeof(keysym_lut));
for (unsigned i = 0; i < sizeof(lut_binds) / sizeof(lut_binds[0]); i++)
keysym_lut[lut_binds[i].sdl] = lut_binds[i].x;
keysym_lut[lut_binds[i].sk] = lut_binds[i].x;
}
static void* x_input_init(void)
+1 -6
View File
@@ -58,12 +58,7 @@ check_pkgconf PULSE libpulse
check_lib COREAUDIO "-framework AudioUnit" AudioUnitInitialize
check_pkgconf SDL sdl 1.2.10
check_critical SDL "Cannot find SDL 1.2 library."
check_pkgconf SDL_NEW sdl 1.3
if [ $HAVE_SDL_NEW = yes ]; then
echo "SSNES is not compatible with SDL 1.3 API, please use a recent 1.2 release."
exit 1
fi
check_critical SDL "Cannot find SDL library."
# On some distros, -lCg doesn't link against -lstdc++ it seems ...
check_lib_cxx CG -lCg cgCreateContext
+1 -1
View File
@@ -1,7 +1,7 @@
. qb/qb.params.sh
PACKAGE_NAME=ssnes
PACKAGE_VERSION=0.8
PACKAGE_VERSION=0.8.2
# Adds a command line opt to ./configure --help
# $1: Variable (HAVE_ALSA, HAVE_OSS, etc)
-4
View File
@@ -147,11 +147,7 @@ static bool init_muxer(ffemu_t *handle)
AVFormatContext *ctx = avformat_alloc_context();
av_strlcpy(ctx->filename, handle->params.filename, sizeof(ctx->filename));
ctx->oformat = av_guess_format(NULL, ctx->filename, NULL);
#ifdef AVIO_FLAG_WRITE
if (avio_open(&ctx->pb, ctx->filename, AVIO_FLAG_WRITE) < 0)
#else
if (url_fopen(&ctx->pb, ctx->filename, URL_WRONLY) < 0)
#endif
{
av_free(ctx);
return false;
+92 -74
View File
@@ -17,6 +17,7 @@
#include "general.h"
#include "conf/config_file.h"
#include "input/keysym.h"
#include <assert.h>
#include "strl.h"
#include "config.def.h"
@@ -135,6 +136,10 @@ static void set_defaults(void)
g_settings.video.font_size = font_size;
g_settings.video.msg_pos_x = message_pos_offset_x;
g_settings.video.msg_pos_y = message_pos_offset_y;
g_settings.video.msg_color_r = ((message_color >> 16) & 0xff) / 255.0f;
g_settings.video.msg_color_g = ((message_color >> 8) & 0xff) / 255.0f;
g_settings.video.msg_color_b = ((message_color >> 0) & 0xff) / 255.0f;
#endif
#if defined(HAVE_CG) || defined(HAVE_XML)
@@ -166,13 +171,15 @@ static void set_defaults(void)
g_settings.pause_nonactive = pause_nonactive;
g_settings.autosave_interval = autosave_interval;
g_settings.block_sram_overwrite = block_sram_overwrite;
assert(sizeof(g_settings.input.binds[0]) >= sizeof(snes_keybinds_1));
assert(sizeof(g_settings.input.binds[1]) >= sizeof(snes_keybinds_rest));
memcpy(g_settings.input.binds[0], snes_keybinds_1, sizeof(snes_keybinds_1));
for (unsigned i = 1; i < 5; i++)
memcpy(g_settings.input.binds[i], snes_keybinds_rest, sizeof(snes_keybinds_rest));
g_settings.input.axis_threshold = AXIS_THRESHOLD;
g_settings.input.axis_threshold = axis_threshold;
g_settings.input.netplay_client_swap_input = netplay_client_swap_input;
for (int i = 0; i < MAX_PLAYERS; i++)
g_settings.input.joypad_map[i] = i;
@@ -322,6 +329,14 @@ static void parse_config_file(void)
CONFIG_GET_INT(video.font_size, "video_font_size");
CONFIG_GET_DOUBLE(video.msg_pos_x, "video_message_pos_x");
CONFIG_GET_DOUBLE(video.msg_pos_y, "video_message_pos_y");
unsigned msg_color;
if (config_get_hex(conf, "video_message_color", &msg_color))
{
g_settings.video.msg_color_r = ((msg_color >> 16) & 0xff) / 255.0f;
g_settings.video.msg_color_g = ((msg_color >> 8) & 0xff) / 255.0f;
g_settings.video.msg_color_b = ((msg_color >> 0) & 0xff) / 255.0f;
}
#endif
CONFIG_GET_BOOL(video.hires_record, "video_hires_record");
@@ -403,6 +418,9 @@ static void parse_config_file(void)
CONFIG_GET_INT(autosave_interval, "autosave_interval");
CONFIG_GET_STRING(cheat_database, "cheat_database_path");
CONFIG_GET_STRING(cheat_settings_path, "cheat_settings_path");
CONFIG_GET_BOOL(block_sram_overwrite, "block_sram_overwrite");
if (!g_extern.has_set_save_path && config_get_array(conf, "savefile_directory", tmp_str, sizeof(tmp_str)))
{
@@ -627,71 +645,71 @@ struct key_map
// Edit: Not portable to different input systems atm. Might move this map into the driver itself or something.
// However, this should map nicely over to other systems aswell since the definition are mostly the same anyways.
static const struct key_map sdlk_map[] = {
{ "left", SDLK_LEFT },
{ "right", SDLK_RIGHT },
{ "up", SDLK_UP },
{ "down", SDLK_DOWN },
{ "enter", SDLK_RETURN },
{ "kp_enter", SDLK_KP_ENTER },
{ "tab", SDLK_TAB },
{ "insert", SDLK_INSERT },
{ "del", SDLK_DELETE },
{ "end", SDLK_END },
{ "home", SDLK_HOME },
{ "rshift", SDLK_RSHIFT },
{ "shift", SDLK_LSHIFT },
{ "ctrl", SDLK_LCTRL },
{ "alt", SDLK_LALT },
{ "space", SDLK_SPACE },
{ "escape", SDLK_ESCAPE },
{ "add", SDLK_KP_PLUS },
{ "subtract", SDLK_KP_MINUS },
{ "f1", SDLK_F1 },
{ "f2", SDLK_F2 },
{ "f3", SDLK_F3 },
{ "f4", SDLK_F4 },
{ "f5", SDLK_F5 },
{ "f6", SDLK_F6 },
{ "f7", SDLK_F7 },
{ "f8", SDLK_F8 },
{ "f9", SDLK_F9 },
{ "f10", SDLK_F10 },
{ "f11", SDLK_F11 },
{ "f12", SDLK_F12 },
{ "num0", SDLK_0 },
{ "num1", SDLK_1 },
{ "num2", SDLK_2 },
{ "num3", SDLK_3 },
{ "num4", SDLK_4 },
{ "num5", SDLK_5 },
{ "num6", SDLK_6 },
{ "num7", SDLK_7 },
{ "num8", SDLK_8 },
{ "num9", SDLK_9 },
{ "pageup", SDLK_PAGEUP },
{ "pagedown", SDLK_PAGEDOWN },
{ "keypad0", SDLK_KP0 },
{ "keypad1", SDLK_KP1 },
{ "keypad2", SDLK_KP2 },
{ "keypad3", SDLK_KP3 },
{ "keypad4", SDLK_KP4 },
{ "keypad5", SDLK_KP5 },
{ "keypad6", SDLK_KP6 },
{ "keypad7", SDLK_KP7 },
{ "keypad8", SDLK_KP8 },
{ "keypad9", SDLK_KP9 },
{ "period", SDLK_PERIOD },
{ "capslock", SDLK_CAPSLOCK },
{ "numlock", SDLK_NUMLOCK },
{ "backspace", SDLK_BACKSPACE },
{ "multiply", SDLK_KP_MULTIPLY },
{ "divide", SDLK_KP_DIVIDE },
{ "print_screen", SDLK_PRINT },
{ "scroll_lock", SDLK_SCROLLOCK },
{ "tilde", SDLK_BACKQUOTE },
{ "backquote", SDLK_BACKQUOTE },
{ "nul", SDLK_UNKNOWN },
static const struct key_map sk_map[] = {
{ "left", SK_LEFT },
{ "right", SK_RIGHT },
{ "up", SK_UP },
{ "down", SK_DOWN },
{ "enter", SK_RETURN },
{ "kp_enter", SK_KP_ENTER },
{ "tab", SK_TAB },
{ "insert", SK_INSERT },
{ "del", SK_DELETE },
{ "end", SK_END },
{ "home", SK_HOME },
{ "rshift", SK_RSHIFT },
{ "shift", SK_LSHIFT },
{ "ctrl", SK_LCTRL },
{ "alt", SK_LALT },
{ "space", SK_SPACE },
{ "escape", SK_ESCAPE },
{ "add", SK_KP_PLUS },
{ "subtract", SK_KP_MINUS },
{ "f1", SK_F1 },
{ "f2", SK_F2 },
{ "f3", SK_F3 },
{ "f4", SK_F4 },
{ "f5", SK_F5 },
{ "f6", SK_F6 },
{ "f7", SK_F7 },
{ "f8", SK_F8 },
{ "f9", SK_F9 },
{ "f10", SK_F10 },
{ "f11", SK_F11 },
{ "f12", SK_F12 },
{ "num0", SK_0 },
{ "num1", SK_1 },
{ "num2", SK_2 },
{ "num3", SK_3 },
{ "num4", SK_4 },
{ "num5", SK_5 },
{ "num6", SK_6 },
{ "num7", SK_7 },
{ "num8", SK_8 },
{ "num9", SK_9 },
{ "pageup", SK_PAGEUP },
{ "pagedown", SK_PAGEDOWN },
{ "keypad0", SK_KP0 },
{ "keypad1", SK_KP1 },
{ "keypad2", SK_KP2 },
{ "keypad3", SK_KP3 },
{ "keypad4", SK_KP4 },
{ "keypad5", SK_KP5 },
{ "keypad6", SK_KP6 },
{ "keypad7", SK_KP7 },
{ "keypad8", SK_KP8 },
{ "keypad9", SK_KP9 },
{ "period", SK_PERIOD },
{ "capslock", SK_CAPSLOCK },
{ "numlock", SK_NUMLOCK },
{ "backspace", SK_BACKSPACE },
{ "multiply", SK_KP_MULTIPLY },
{ "divide", SK_KP_DIVIDE },
{ "print_screen", SK_PRINT },
{ "scroll_lock", SK_SCROLLOCK },
{ "tilde", SK_BACKQUOTE },
{ "backquote", SK_BACKQUOTE },
{ "nul", SK_UNKNOWN },
};
static struct snes_keybind *find_snes_bind(unsigned port, int id)
@@ -706,23 +724,23 @@ static struct snes_keybind *find_snes_bind(unsigned port, int id)
return NULL;
}
static int find_sdlk_bind(const char *str)
static int find_sk_bind(const char *str)
{
for (int i = 0; i < sizeof(sdlk_map)/sizeof(struct key_map); i++)
for (int i = 0; i < sizeof(sk_map)/sizeof(struct key_map); i++)
{
if (strcasecmp(sdlk_map[i].str, str) == 0)
return sdlk_map[i].key;
if (strcasecmp(sk_map[i].str, str) == 0)
return sk_map[i].key;
}
return -1;
}
static int find_sdlk_key(const char *str)
static int find_sk_key(const char *str)
{
// If the bind is a normal key-press ...
if (strlen(str) == 1 && isalpha(*str))
return (int)SDLK_a + (tolower(*str) - (int)'a');
return (int)SK_a + (tolower(*str) - (int)'a');
else // Check if we have a special mapping for it.
return find_sdlk_bind(str);
return find_sk_bind(str);
}
// Yes, this function needs a good refactor :)
@@ -743,7 +761,7 @@ static void read_keybinds(config_file_t *conf)
// Check keybind
if (bind_maps[j][i].key && config_get_string(conf, bind_maps[j][i].key, &tmp_key))
{
int key = find_sdlk_key(tmp_key);
int key = find_sk_key(tmp_key);
if (key >= 0)
bind->key = key;
+9 -9
View File
@@ -332,7 +332,7 @@ static int16_t input_state(bool port, unsigned device, unsigned index, unsigned
#endif
#ifdef _WIN32
#define PACKAGE_VERSION "0.8"
#define PACKAGE_VERSION "0.8.2"
#endif
#include "config.features.h"
@@ -1443,7 +1443,6 @@ static void check_shader_dir(void)
old_pressed_next = pressed_next;
old_pressed_prev = pressed_prev;
}
static void check_cheats(void)
@@ -1569,7 +1568,7 @@ int main(int argc, char *argv[])
fill_title_buf();
psnes_init();
if (strlen(g_extern.basename) > 0)
if (*g_extern.basename)
psnes_set_cartridge_basename(g_extern.basename);
SSNES_LOG("Version of libsnes API: %u.%u\n", psnes_library_revision_major(), psnes_library_revision_minor());
@@ -1579,10 +1578,6 @@ int main(int argc, char *argv[])
if (!init_rom_file(g_extern.game_type))
goto error;
#ifdef HAVE_XML
init_cheats();
#endif
init_msg_queue();
init_movie();
@@ -1596,7 +1591,7 @@ int main(int argc, char *argv[])
if (!g_extern.netplay)
init_rewind();
#ifdef HAVE_NETPLAY
psnes_set_video_refresh(g_extern.netplay ? video_frame_net : video_frame);
psnes_set_audio_sample(g_extern.netplay ? audio_sample_net : audio_sample);
@@ -1616,9 +1611,14 @@ int main(int argc, char *argv[])
if (!g_extern.bsv_movie_playback && !g_extern.netplay_is_client)
init_autosave();
#ifdef HAVE_XML
if (!g_extern.netplay && !g_extern.bsv_movie)
init_cheats();
#endif
// Main loop
for(;;)
for (;;)
{
// DSP plugin GUI events.
if (g_extern.audio_data.dsp_handle && g_extern.audio_data.dsp_plugin->events)
+14 -1
View File
@@ -91,7 +91,11 @@
# Offset for where messages will be placed on screen. Values are in range 0.0 to 1.0 for both x and y values.
# [0.0, 0.0] maps to the lower left corner of the screen.
# video_message_pos_x = 0.05
# video_message_pox_y = 0.05
# video_message_pos_y = 0.05
# Color for message. The value is treated as a hexadecimal value.
# It is a regular RGB hex number, i.e. red is "ff0000".
# video_message_color = ffffff
#### Audio
@@ -291,6 +295,11 @@
# Path to XML cheat database (as used by bSNES).
# cheat_database_path =
# Path to XML cheat config, a file which keeps track of which
# cheat settings are used for individual games.
# If the file does not exist, it will be created.
# cheat_settings_path =
# Cheats.
# input_cheat_index_plus = y
# input_cheat_index_minus = t
@@ -307,3 +316,7 @@
# Records video after CPU video filter.
# video_post_filter_record = false
# Block SRAM from being overwritten when loading save states.
# Might potentially lead to buggy games.
# block_sram_overwrite = false