mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-09 11:41:35 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
331f46fb24 | ||
|
|
e88662cab0 | ||
|
|
395f6d1d3c | ||
|
|
94bd78b3e1 | ||
|
|
dc373fb7d0 | ||
|
|
140812d64a | ||
|
|
a91c4e556f | ||
|
|
372c622166 | ||
|
|
d961d68e9c | ||
|
|
33a325a730 | ||
|
|
909b25c7ac | ||
|
|
77f110c23e | ||
|
|
9dc9416ef9 | ||
|
|
0b20f11617 | ||
|
|
c9594776f8 | ||
|
|
8f55b9904d | ||
|
|
093ba1c33d | ||
|
|
67a434d563 | ||
|
|
ff0c3f047a | ||
|
|
2934ba301b | ||
|
|
f3627aaf59 | ||
|
|
dc8a2dea72 | ||
|
|
329969eb05 | ||
|
|
71923af675 | ||
|
|
18e58ca5f4 | ||
|
|
8c3aebbbc8 | ||
|
|
7f40c11eb7 | ||
|
|
0ed668d1b5 | ||
|
|
1c8632cac9 | ||
|
|
e7324989fc | ||
|
|
a7fc3807b9 | ||
|
|
99ad7bcc51 | ||
|
|
5b88e338df | ||
|
|
425af71450 | ||
|
|
19c5eab07a | ||
|
|
e5286cbe39 | ||
|
|
02d40aa212 | ||
|
|
8a5c537e15 | ||
|
|
c6c4f2f4d1 | ||
|
|
5bc7ea4045 | ||
|
|
077acf7894 | ||
|
|
c5f86f12c0 | ||
|
|
243e941d81 | ||
|
|
d67e6b7c15 | ||
|
|
f76bf59fed | ||
|
|
1c4d88eb04 | ||
|
|
ad04db8365 | ||
|
|
a63ccbbdab | ||
|
|
278f314c03 | ||
|
|
a3abda7e7b | ||
|
|
c0a9db111d | ||
|
|
676ce10119 | ||
|
|
c18dce4783 | ||
|
|
088b01b52e | ||
|
|
c0f436b8ab | ||
|
|
3377020242 | ||
|
|
6db58fe1dd | ||
|
|
67c7cd8de9 | ||
|
|
457a3d458a | ||
|
|
6538312d86 | ||
|
|
7f1a5075b1 | ||
|
|
e412ecdefe | ||
|
|
67b89d6f42 | ||
|
|
c8d3278dbc | ||
|
|
3556445660 | ||
|
|
f28fc0cabb | ||
|
|
e0bc548400 | ||
|
|
011a4c8a89 | ||
|
|
87bc5220eb | ||
|
|
673d0ed1a2 | ||
|
|
a5079bdda1 | ||
|
|
fc43e7155e | ||
|
|
4935333b63 | ||
|
|
5a3232adff | ||
|
|
d03f351f33 | ||
|
|
8d5bf997a9 | ||
|
|
0738480439 | ||
|
|
9a5e1a31ad | ||
|
|
5ab7664f49 | ||
|
|
1cb2c60ccc | ||
|
|
1356d0ab4c | ||
|
|
b4c4a65f2d | ||
|
|
ab3cf8daca | ||
|
|
2b6c252747 | ||
|
|
ec9a6ac90a | ||
|
|
a207549f18 | ||
|
|
efbf9354f9 | ||
|
|
216ddc9fd6 | ||
|
|
3b668cccd3 | ||
|
|
30a86a2845 | ||
|
|
a7870aa888 | ||
|
|
271b99981c | ||
|
|
08ef01bb13 | ||
|
|
e778af462a | ||
|
|
9d124b2380 | ||
|
|
f24e7cd665 | ||
|
|
e7f1526942 | ||
|
|
647b1ba53c | ||
|
|
eac8d9f191 | ||
|
|
50babe8432 | ||
|
|
8171977ed7 | ||
|
|
f8aaf1df1e | ||
|
|
04d0d84d01 | ||
|
|
f4aa9fa865 | ||
|
|
40ef7d6f00 | ||
|
|
66b7b1691c | ||
|
|
43972d4c35 | ||
|
|
632545c409 | ||
|
|
3a47e2cd63 | ||
|
|
a221e3e4cd | ||
|
|
b87f50dc9d | ||
|
|
a5b3f421d1 | ||
|
|
182525afa9 | ||
|
|
419afbcb83 | ||
|
|
12ca70a308 | ||
|
|
1fa7663d3b | ||
|
|
2e34c6fc5c | ||
|
|
cb7002559d | ||
|
|
36ec92793f | ||
|
|
4187d70b30 | ||
|
|
5969655c3c | ||
|
|
09d2ec7d3a | ||
|
|
27b975d0fc | ||
|
|
6da64013fa | ||
|
|
d8eb5de380 | ||
|
|
23aa8bbe7a | ||
|
|
3b5472dbac | ||
|
|
3b4e60aada | ||
|
|
8d8fb44c18 | ||
|
|
b46fb60a6e | ||
|
|
f7399bbc8b | ||
|
|
7f7d47b120 | ||
|
|
e7aa3ed0cc | ||
|
|
0ece8b1319 | ||
|
|
557e05dd12 | ||
|
|
08a1496501 | ||
|
|
5a24037c61 | ||
|
|
5dbd1ea35c |
No files matched your search
@@ -6,3 +6,7 @@ Devin J. Pohly - <[email protected]>
|
||||
|
||||
Chris Moeller - <[email protected]>
|
||||
- CoreAudio audio driver
|
||||
|
||||
Daniel De Matteis - <[email protected]>
|
||||
- PlayStation 3 port
|
||||
|
||||
@@ -2,11 +2,11 @@ include config.mk
|
||||
|
||||
TARGET = ssnes tools/ssnes-joyconfig
|
||||
|
||||
OBJ = ssnes.o file.o driver.o settings.o dynamic.o message.o rewind.o movie.o autosave.o gfx/gfx_common.o ups.o bps.o strl.o screenshot.o thread.o audio/hermite.o
|
||||
OBJ = ssnes.o file.o driver.o settings.o dynamic.o message.o rewind.o movie.o gfx/gfx_common.o ups.o bps.o strl.o getopt.o screenshot.o audio/hermite.o audio/utils.o
|
||||
JOYCONFIG_OBJ = tools/ssnes-joyconfig.o conf/config_file.o strl.o
|
||||
HEADERS = $(wildcard */*.h) $(wildcard *.h)
|
||||
|
||||
LIBS = -lm -lpthread
|
||||
LIBS = -lm
|
||||
DEFINES = -DHAVE_CONFIG_H
|
||||
|
||||
ifneq ($(findstring Darwin,$(OS)),)
|
||||
@@ -27,6 +27,11 @@ ifneq ($(findstring Linux,$(OS)),)
|
||||
LIBS += -lrt
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_THREADS), 1)
|
||||
OBJ += autosave.o thread.o
|
||||
LIBS += -lpthread
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_CONFIGFILE), 1)
|
||||
OBJ += conf/config_file.o
|
||||
endif
|
||||
@@ -155,10 +160,6 @@ else
|
||||
LIBS += $(libsnes)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_STRL), 1)
|
||||
DEFINES += -DHAVE_STRL
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_PYTHON), 1)
|
||||
DEFINES += $(PYTHON_CFLAGS) -Wno-unused-parameter
|
||||
LIBS += $(PYTHON_LIBS)
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
###
|
||||
##
|
||||
# Makefile for SSNES PS3. Somewhat generic and avoids using the odd SDK examples.
|
||||
##
|
||||
###
|
||||
##
|
||||
DEBUG = 0
|
||||
CELL_BUILD_TOOLS = GCC
|
||||
|
||||
## Platform detection from nall/Makefile. Only two applicable hosts for PS3 SDK.
|
||||
ifeq ($(platform),)
|
||||
uname := $(shell uname -a)
|
||||
ifeq ($(uname),)
|
||||
platform := win
|
||||
else
|
||||
platform := linux
|
||||
endif
|
||||
endif
|
||||
|
||||
CELL_SDK := /usr/local/cell
|
||||
ifeq ($(platform),win)
|
||||
HOST_DIR := host-win32
|
||||
else
|
||||
HOST_DIR := host-linux
|
||||
endif
|
||||
|
||||
ifeq ($(CELL_BUILD_TOOLS),SNC)
|
||||
CC = $(CELL_SDK)/sn/ps3ppusnc
|
||||
CXX = $(CC)
|
||||
LD = $(CELL_SDK)/sn/ps3ppuld
|
||||
else
|
||||
CC = $(CELL_SDK)/$(HOST_DIR)/ppu/bin/ppu-lv2-gcc
|
||||
CXX = $(CELL_SDK)/$(HOST_DIR)/ppu/bin/ppu-lv2-g++
|
||||
LD = $(CELL_SDK)/$(HOST_DIR)/ppu/bin/ppu-lv2-g++
|
||||
endif
|
||||
STRIP = $(CELL_SDK)/$(HOST_DIR)/ppu/bin/ppu-lv2-strip
|
||||
|
||||
PPU_TARGET := ssnes.elf
|
||||
|
||||
LDDIRS = -L. -L$(CELL_SDK)/target/ppu/lib/PSGL/RSX/ultra-opt
|
||||
INCDIRS = -I. -Icommon
|
||||
|
||||
MAKE_FSELF_NPDRM = $(CELL_SDK)/$(HOST_DIR)/bin/make_fself_npdrm
|
||||
MAKE_PACKAGE_NPDRM = $(CELL_SDK)/$(HOST_DIR)/bin/make_package_npdrm
|
||||
|
||||
OBJ = fifo_buffer.o ps3/ps3_audio.o ps3/ps3_input.o ps3/pad_input.o getopt.o ssnes.o driver.o file.o settings.o message.o rewind.o movie.o gfx/gfx_common.o ps3/ps3_video_psgl.o gfx/shader_cg.o gfx/snes_state.o ups.o bps.o strl.o screenshot.o audio/hermite.o dynamic.o ps3/main.o audio/utils.o conf/config_file.o gfx/image.o
|
||||
|
||||
LIBS = -ldbgfont -lPSGL -lPSGLcgc -lcgc -lgcm_cmd -lgcm_sys_stub -lsnes -lresc_stub -lm -lio_stub -lfs_stub -lsysutil_stub -lsysmodule_stub -laudio_stub -lnet_stub -lpthread
|
||||
|
||||
DEFINES = -DHAVE_OPENGL=1 -DHAVE_CG=1 -DHAVE_FBO=1 -D__CELLOS_LV2__ -DHAVE_CONFIGFILE=1 -DPACKAGE_VERSION=\"0.9.3\" -Dmain=ssnes_main
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
PPU_OPTIMIZE_LV := -O0 -g
|
||||
else
|
||||
PPU_OPTIMIZE_LV := -O3
|
||||
endif
|
||||
|
||||
## Use this for new SDK!
|
||||
CFLAGS = $(PPU_OPTIMIZE_LV) $(DEFINES)
|
||||
CXXFLAGS = $(PPU_OPTIMIZE_LV) $(DEFINES)
|
||||
|
||||
all: pkg
|
||||
|
||||
$(PPU_TARGET): $(OBJ)
|
||||
$(LD) -o $@ $(OBJ) $(LDFLAGS) $(LDDIRS) $(LIBS)
|
||||
$(STRIP) $(PPU_TARGET)
|
||||
|
||||
%.o: %.c config.h
|
||||
$(CC) $(INCDIRS) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
%.o: %.cpp config.h
|
||||
$(CXX) $(INCDIRS) $(CXXFLAGS) -c -o $@ $<
|
||||
|
||||
pkg: $(PPU_TARGET)
|
||||
$(MAKE_FSELF_NPDRM) $(PPU_TARGET) ps3/pkg/USRDIR/EBOOT.BIN
|
||||
$(MAKE_PACKAGE_NPDRM) ps3/pkg/package.conf ps3/pkg
|
||||
|
||||
clean:
|
||||
rm -f $(PPU_TARGET)
|
||||
rm -f $(OBJ)
|
||||
rm -f *.pkg
|
||||
|
||||
.PHONY: all clean pkg
|
||||
|
||||
+10
-4
@@ -1,6 +1,6 @@
|
||||
TARGET = ssnes.exe
|
||||
JTARGET = ssnes-joyconfig.exe
|
||||
OBJ = ssnes.o file.o driver.o conf/config_file.o settings.o dynamic.o message.o rewind.o movie.o autosave.o gfx/gfx_common.o bps.o ups.o strl.o screenshot.o audio/hermite.o thread.o
|
||||
OBJ = ssnes.o file.o driver.o conf/config_file.o settings.o dynamic.o message.o rewind.o movie.o gfx/gfx_common.o bps.o ups.o strl.o screenshot.o audio/hermite.o getopt.o audio/utils.o
|
||||
JOBJ = conf/config_file.o tools/main-stub.o tools/ssnes-joyconfig.o strl.o
|
||||
|
||||
CC = gcc
|
||||
@@ -13,6 +13,7 @@ HAVE_SDL = 1
|
||||
HAVE_OPENGL = 1
|
||||
HAVE_DYLIB = 1
|
||||
HAVE_NETPLAY = 1
|
||||
HAVE_THREADS = 1
|
||||
DYNAMIC = 1
|
||||
|
||||
ifeq ($(SLIM),)
|
||||
@@ -29,7 +30,7 @@ endif
|
||||
libsnes ?= -lsnes
|
||||
|
||||
LIBS = -lm -lshlwapi
|
||||
DEFINES = -I. -DHAVE_CONFIGFILE
|
||||
DEFINES = -I. -DHAVE_CONFIGFILE -DPACKAGE_VERSION=\"0.9.3\"
|
||||
LDFLAGS = -L. -static-libgcc
|
||||
LDCXXFLAGS = -static-libstdc++ -s
|
||||
|
||||
@@ -39,6 +40,11 @@ ifeq ($(HAVE_SDL), 1)
|
||||
DEFINES += -ISDL -DHAVE_SDL
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_THREADS), 1)
|
||||
OBJ += autosave.o thread.o
|
||||
DEFINES += -DHAVE_THREADS
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_OPENGL), 1)
|
||||
DEFINES += -DHAVE_OPENGL
|
||||
LIBS += -lopengl32
|
||||
@@ -173,10 +179,10 @@ clean:
|
||||
rm -f tools/*.o
|
||||
|
||||
dist_x86: all
|
||||
zip -r ssnes-win32-0.9.2.zip $(TARGET) $(JTARGET) ssnes.cfg snes.dll SDL.dll
|
||||
zip -r ssnes-win32-0.9.3.zip $(TARGET) $(JTARGET) ssnes.cfg snes.dll SDL.dll
|
||||
|
||||
dist_x86_64: all
|
||||
zip -r ssnes-win64-0.9.2.zip $(TARGET) $(JTARGET) ssnes.cfg snes.dll SDL.dll
|
||||
zip -r ssnes-win64-0.9.3.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
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
###
|
||||
##
|
||||
# Makefile for SSNES libxenon.
|
||||
##
|
||||
###
|
||||
##
|
||||
|
||||
DEBUG = 0
|
||||
|
||||
CC = xenon-gcc
|
||||
CXX = xenon-g++
|
||||
OBJCOPY = xenon-objcopy
|
||||
STRIP = xenon-strip
|
||||
|
||||
PPU_TARGET := ssnes-libxenon.elf
|
||||
PPU_TARGET_ADJUSTED := ssnes-libxenon.elf32
|
||||
|
||||
LDDIRS = -L. -L$(DEVKITXENON)/usr/lib -L$(DEVKITXENON)/xenon/lib/32
|
||||
INCDIRS = -I. -I$(DEVKITXENON)/usr/include -I$(DEVKITXENON)/usr/include/SDL
|
||||
|
||||
OBJ = fifo_buffer.o ssnes.o driver.o file.o settings.o message.o rewind.o movie.o input/sdl.o audio/sdl.o gfx/sdl.o gfx/sdlwrap.o gfx/gfx_common.o ups.o bps.o strl.o screenshot.o audio/hermite.o dynamic.o audio/utils.o conf/config_file.o
|
||||
|
||||
LIBS = -lsnes -lSDL -lxenon -lm -lc
|
||||
DEFINES = -std=gnu99 -DHAVE_CONFIGFILE=1 -DHAVE_SDL=1 -DPACKAGE_VERSION=\"0.9.3\" -DHAVE_GETOPT_LONG=1
|
||||
DEFINES += -maltivec -mhard-float -m32 -mpowerpc64 -mcpu=cell -mtune=cell -fno-pic -g -Wall -DSDL -DXENON $(INCDIRS)
|
||||
DEFINES += -u read -u _start -u exc_base
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
OPTIMIZE_LV := -O0 -g
|
||||
else
|
||||
OPTIMIZE_LV := -O3
|
||||
endif
|
||||
|
||||
all: $(PPU_TARGET_ADJUSTED)
|
||||
|
||||
CFLAGS := $(OPTIMIZE_LV) $(DEFINES)
|
||||
|
||||
LDFLAGS := -m32 -n -T $(DEVKITXENON)/app.lds
|
||||
|
||||
$(PPU_TARGET_ADJUSTED): $(PPU_TARGET)
|
||||
$(OBJCOPY) -O elf32-powerpc --adjust-vma 0x80000000 $< $@
|
||||
$(STRIP) $@
|
||||
|
||||
$(PPU_TARGET): $(OBJ)
|
||||
$(CXX) -o $@ $(OBJ) $(LDFLAGS) $(LDDIRS) $(LIBS)
|
||||
|
||||
%.o: %.c config.h
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f $(PPU_TARGET)
|
||||
rm -f $(OBJ)
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
#include "utils.h"
|
||||
|
||||
#if __SSE2__
|
||||
#include <emmintrin.h>
|
||||
#elif __ALTIVEC__
|
||||
#include <altivec.h>
|
||||
#endif
|
||||
|
||||
void audio_convert_s16_to_float_C(float *out,
|
||||
const int16_t *in, size_t samples)
|
||||
{
|
||||
for (size_t i = 0; i < samples; i++)
|
||||
out[i] = (float)in[i] / 0x8000;
|
||||
}
|
||||
|
||||
void audio_convert_float_to_s16_C(int16_t *out,
|
||||
const float *in, size_t samples)
|
||||
{
|
||||
for (size_t i = 0; i < samples; i++)
|
||||
{
|
||||
int32_t val = in[i] * 0x8000;
|
||||
out[i] = (val > 0x7FFF) ? 0x7FFF : (val < -0x8000 ? -0x8000 : (int16_t)val);
|
||||
}
|
||||
}
|
||||
|
||||
#if __SSE2__
|
||||
void audio_convert_s16_to_float_SSE2(float *out,
|
||||
const int16_t *in, size_t samples)
|
||||
{
|
||||
__m128 factor = _mm_set1_ps(1.0f / (0x7fff * 0x10000));
|
||||
size_t i;
|
||||
for (i = 0; i + 8 <= samples; i += 8, in += 8, out += 8)
|
||||
{
|
||||
__m128i input = _mm_loadu_si128((const __m128i *)in);
|
||||
__m128i regs[2] = {
|
||||
_mm_unpacklo_epi16(_mm_setzero_si128(), input),
|
||||
_mm_unpackhi_epi16(_mm_setzero_si128(), input),
|
||||
};
|
||||
|
||||
__m128 output[2] = {
|
||||
_mm_mul_ps(_mm_cvtepi32_ps(regs[0]), factor),
|
||||
_mm_mul_ps(_mm_cvtepi32_ps(regs[1]), factor),
|
||||
};
|
||||
|
||||
_mm_storeu_ps(out + 0, output[0]);
|
||||
_mm_storeu_ps(out + 4, output[1]);
|
||||
}
|
||||
|
||||
audio_convert_s16_to_float_C(out, in, samples - i);
|
||||
}
|
||||
|
||||
void audio_convert_float_to_s16_SSE2(int16_t *out,
|
||||
const float *in, size_t samples)
|
||||
{
|
||||
__m128 factor = _mm_set1_ps((float)0x7fff);
|
||||
size_t i;
|
||||
for (i = 0; i + 8 <= samples; i += 8, in += 8, out += 8)
|
||||
{
|
||||
__m128 input[2] = { _mm_loadu_ps(in + 0), _mm_loadu_ps(in + 4) };
|
||||
__m128 res[2] = { _mm_mul_ps(input[0], factor), _mm_mul_ps(input[1], factor) };
|
||||
|
||||
__m128i ints[2] = { _mm_cvtps_epi32(res[0]), _mm_cvtps_epi32(res[1]) };
|
||||
__m128i packed = _mm_packs_epi32(ints[0], ints[1]);
|
||||
|
||||
_mm_storeu_si128((__m128i *)out, packed);
|
||||
}
|
||||
|
||||
audio_convert_float_to_s16_C(out, in, samples - i);
|
||||
}
|
||||
#elif __ALTIVEC__
|
||||
void audio_convert_s16_to_float_altivec(float *out,
|
||||
const int16_t *in, size_t samples)
|
||||
{
|
||||
// Unaligned loads/store is a bit expensive, so we optimize for the good path (very likely).
|
||||
if (((uintptr_t)out & 15) + ((uintptr_t)in & 15) == 0)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i + 8 <= samples; i += 8, in += 8, out += 8)
|
||||
{
|
||||
vector signed short input = vec_ld(0, in);
|
||||
vector signed int hi = vec_unpackh(input);
|
||||
vector signed int lo = vec_unpackl(input);
|
||||
vector float out_hi = vec_ctf(hi, 15);
|
||||
vector float out_lo = vec_ctf(lo, 15);
|
||||
|
||||
vec_st(out_hi, 0, out);
|
||||
vec_st(out_lo, 16, out);
|
||||
}
|
||||
|
||||
audio_convert_s16_to_float_C(out, in, samples - i);
|
||||
}
|
||||
else
|
||||
audio_convert_s16_to_float_C(out, in, samples);
|
||||
}
|
||||
|
||||
void audio_convert_float_to_s16_altivec(int16_t *out,
|
||||
const float *in, size_t samples)
|
||||
{
|
||||
// Unaligned loads/store is a bit expensive, so we optimize for the good path (very likely).
|
||||
if (((uintptr_t)out & 15) + ((uintptr_t)in & 15) == 0)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i + 8 <= samples; i += 8, in += 8, out += 8)
|
||||
{
|
||||
vector float input0 = vec_ld( 0, in);
|
||||
vector float input1 = vec_ld(16, in);
|
||||
vector signed int result0 = vec_cts(input0, 15);
|
||||
vector signed int result1 = vec_cts(input1, 15);
|
||||
vec_st(vec_packs(result0, result1), 0, out);
|
||||
}
|
||||
|
||||
audio_convert_float_to_s16_C(out, in, samples - i);
|
||||
}
|
||||
else
|
||||
audio_convert_float_to_s16_C(out, in, samples);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+22
-66
@@ -2,81 +2,37 @@
|
||||
#define AUDIO_UTILS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#if __SSE2__
|
||||
#include <mmintrin.h>
|
||||
#include <emmintrin.h>
|
||||
#define audio_convert_s16_to_float audio_convert_s16_to_float_SSE2
|
||||
#define audio_convert_float_to_s16 audio_convert_float_to_s16_SSE2
|
||||
|
||||
void audio_convert_s16_to_float_SSE2(float *out,
|
||||
const int16_t *in, size_t samples);
|
||||
|
||||
void audio_convert_float_to_s16_SSE2(int16_t *out,
|
||||
const float *in, size_t samples);
|
||||
|
||||
#elif __ALTIVEC__
|
||||
#define audio_convert_s16_to_float audio_convert_s16_to_float_altivec
|
||||
#define audio_convert_float_to_s16 audio_convert_float_to_s16_altivec
|
||||
|
||||
void audio_convert_s16_to_float_altivec(float *out,
|
||||
const int16_t *in, size_t samples);
|
||||
|
||||
void audio_convert_float_to_s16_altivec(int16_t *out,
|
||||
const float *in, size_t samples);
|
||||
|
||||
#else
|
||||
#define audio_convert_s16_to_float audio_convert_s16_to_float_C
|
||||
#define audio_convert_float_to_s16 audio_convert_float_to_s16_C
|
||||
#endif
|
||||
|
||||
static inline void audio_convert_s16_to_float_C(float *out,
|
||||
const int16_t *in, unsigned samples)
|
||||
{
|
||||
for (unsigned i = 0; i < samples; i++)
|
||||
out[i] = (float)in[i] / 0x8000;
|
||||
}
|
||||
|
||||
static inline void audio_convert_float_to_s16_C(int16_t *out,
|
||||
const float *in, unsigned samples)
|
||||
{
|
||||
for (unsigned i = 0; i < samples; i++)
|
||||
{
|
||||
int32_t val = in[i] * 0x8000;
|
||||
out[i] = (val > 0x7FFF) ? 0x7FFF : (val < -0x8000 ? -0x8000 : (int16_t)val);
|
||||
}
|
||||
}
|
||||
|
||||
#if __SSE2__
|
||||
static inline void audio_convert_s16_to_float_SSE2(float *out,
|
||||
const int16_t *in, unsigned samples)
|
||||
{
|
||||
__m128 factor = _mm_set1_ps(1.0f / (0x7fff * 0x10000));
|
||||
unsigned i;
|
||||
for (i = 0; i + 8 <= samples; i += 8, in += 8, out += 8)
|
||||
{
|
||||
__m128i input = _mm_loadu_si128((const __m128i *)in);
|
||||
__m128i regs[2] = {
|
||||
_mm_unpacklo_epi16(_mm_setzero_si128(), input),
|
||||
_mm_unpackhi_epi16(_mm_setzero_si128(), input),
|
||||
};
|
||||
|
||||
__m128 output[2] = {
|
||||
_mm_mul_ps(_mm_cvtepi32_ps(regs[0]), factor),
|
||||
_mm_mul_ps(_mm_cvtepi32_ps(regs[1]), factor),
|
||||
};
|
||||
|
||||
_mm_storeu_ps(out + 0, output[0]);
|
||||
_mm_storeu_ps(out + 4, output[1]);
|
||||
}
|
||||
|
||||
audio_convert_s16_to_float_C(out, in, samples - i);
|
||||
}
|
||||
|
||||
static inline void audio_convert_float_to_s16_SSE2(int16_t *out,
|
||||
const float *in, unsigned samples)
|
||||
{
|
||||
__m128 factor = _mm_set1_ps((float)0x7fff);
|
||||
unsigned i;
|
||||
for (i = 0; i + 8 <= samples; i += 8, in += 8, out += 8)
|
||||
{
|
||||
__m128 input[2] = { _mm_loadu_ps(in + 0), _mm_loadu_ps(in + 4) };
|
||||
__m128 res[2] = { _mm_mul_ps(input[0], factor), _mm_mul_ps(input[1], factor) };
|
||||
|
||||
__m128i ints[2] = { _mm_cvtps_epi32(res[0]), _mm_cvtps_epi32(res[1]) };
|
||||
__m128i packed = _mm_packs_epi32(ints[0], ints[1]);
|
||||
|
||||
_mm_storeu_si128((__m128i *)out, packed);
|
||||
}
|
||||
|
||||
audio_convert_float_to_s16_C(out, in, samples - i);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
void audio_convert_s16_to_float_C(float *out,
|
||||
const int16_t *in, size_t samples);
|
||||
void audio_convert_float_to_s16_C(int16_t *out,
|
||||
const float *in, size_t samples);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
Simple C interface for XAudio2
|
||||
Author: Hans-Kristian Arntzen
|
||||
License: Public Domain
|
||||
*/
|
||||
|
||||
#include "xaudio-c.h"
|
||||
#include "xaudio.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define MAX_BUFFERS 16
|
||||
#define MAX_BUFFERS_MASK (MAX_BUFFERS - 1)
|
||||
|
||||
struct xaudio2
|
||||
{
|
||||
const IXAudio2VoiceCallbackVtbl *lpVtbl;
|
||||
|
||||
uint8_t *buf;
|
||||
IXAudio2 *pXAudio2;
|
||||
IXAudio2MasteringVoice *pMasterVoice;
|
||||
IXAudio2SourceVoice *pSourceVoice;
|
||||
HANDLE hEvent;
|
||||
|
||||
volatile long buffers;
|
||||
unsigned bufsize;
|
||||
unsigned bufptr;
|
||||
unsigned write_buffer;
|
||||
};
|
||||
|
||||
static void WINAPI voice_on_buffer_end(void *handle_, void *data)
|
||||
{
|
||||
(void)data;
|
||||
xaudio2_t *handle = handle_;
|
||||
InterlockedDecrement(&handle->buffers);
|
||||
SetEvent(handle->hEvent);
|
||||
}
|
||||
|
||||
static void WINAPI dummy_voidp(void *handle, void *data) { (void)handle; (void)data; }
|
||||
static void WINAPI dummy_nil(void *handle) { (void)handle; }
|
||||
static void WINAPI dummy_uint32(void *handle, UINT32 dummy) { (void)handle; (void)dummy; }
|
||||
static void WINAPI dummy_voidp_hresult(void *handle, void *data, HRESULT dummy) { (void)handle; (void)data; (void)dummy; }
|
||||
|
||||
const struct IXAudio2VoiceCallbackVtbl voice_vtable = {
|
||||
.OnBufferStart = dummy_voidp,
|
||||
.OnBufferEnd = voice_on_buffer_end,
|
||||
.OnLoopEnd = dummy_voidp,
|
||||
.OnVoiceProcessingPassEnd = dummy_nil,
|
||||
.OnVoiceProcessingPassStart = dummy_uint32,
|
||||
.OnVoiceError = dummy_voidp_hresult,
|
||||
.OnStreamEnd = dummy_nil,
|
||||
};
|
||||
|
||||
xaudio2_t *xaudio2_new(unsigned samplerate, unsigned channels, size_t size)
|
||||
{
|
||||
xaudio2_t *handle = calloc(1, sizeof(*handle));
|
||||
if (!handle)
|
||||
return NULL;
|
||||
|
||||
handle->lpVtbl = &voice_vtable;
|
||||
CoInitializeEx(0, COINIT_MULTITHREADED);
|
||||
if (FAILED(XAudio2Create(&handle->pXAudio2)))
|
||||
goto error;
|
||||
if (FAILED(IXAudio2_CreateMasteringVoice(handle->pXAudio2,
|
||||
&handle->pMasterVoice, channels, samplerate, 0, 0, 0)))
|
||||
goto error;
|
||||
|
||||
WAVEFORMATEX wfx;
|
||||
wfx.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
|
||||
wfx.nChannels = channels;
|
||||
wfx.nSamplesPerSec = samplerate;
|
||||
wfx.nBlockAlign = channels * sizeof(float);
|
||||
wfx.wBitsPerSample = sizeof(float) * 8;
|
||||
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
|
||||
wfx.cbSize = 0;
|
||||
if (FAILED(IXAudio2_CreateSourceVoice(handle->pXAudio2,
|
||||
&handle->pSourceVoice, &wfx,
|
||||
XAUDIO2_VOICE_NOSRC, XAUDIO2_DEFAULT_FREQ_RATIO,
|
||||
(IXAudio2VoiceCallback*)handle, 0, 0)))
|
||||
goto error;
|
||||
|
||||
handle->hEvent = CreateEvent(0, FALSE, FALSE, 0);
|
||||
if (!handle->hEvent)
|
||||
goto error;
|
||||
|
||||
IXAudio2SourceVoice_Start(handle->pSourceVoice, 0, XAUDIO2_COMMIT_NOW);
|
||||
|
||||
handle->bufsize = size / MAX_BUFFERS;
|
||||
handle->buf = calloc(1, handle->bufsize * MAX_BUFFERS);
|
||||
if (!handle->buf)
|
||||
goto error;
|
||||
|
||||
return handle;
|
||||
|
||||
error:
|
||||
xaudio2_free(handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t xaudio2_write_avail(xaudio2_t *handle)
|
||||
{
|
||||
return handle->bufsize * (MAX_BUFFERS - handle->buffers - 1);
|
||||
}
|
||||
|
||||
size_t xaudio2_write(xaudio2_t *handle, const void *buf, size_t bytes_)
|
||||
{
|
||||
unsigned bytes = bytes_;
|
||||
const uint8_t *buffer = buf;
|
||||
while (bytes)
|
||||
{
|
||||
unsigned need = min(bytes, handle->bufsize - handle->bufptr);
|
||||
memcpy(handle->buf + handle->write_buffer * handle->bufsize + handle->bufptr,
|
||||
buffer, need);
|
||||
|
||||
handle->bufptr += need;
|
||||
buffer += need;
|
||||
bytes -= need;
|
||||
|
||||
if (handle->bufptr == handle->bufsize)
|
||||
{
|
||||
while (handle->buffers == MAX_BUFFERS - 1)
|
||||
WaitForSingleObject(handle->hEvent, INFINITE);
|
||||
|
||||
XAUDIO2_BUFFER xa2buffer = {
|
||||
.AudioBytes = handle->bufsize,
|
||||
.pAudioData = handle->buf + handle->write_buffer * handle->bufsize,
|
||||
};
|
||||
if (FAILED(IXAudio2SourceVoice_SubmitSourceBuffer(handle->pSourceVoice, &xa2buffer, NULL)))
|
||||
return 0;
|
||||
|
||||
InterlockedIncrement(&handle->buffers);
|
||||
handle->bufptr = 0;
|
||||
handle->write_buffer = (handle->write_buffer + 1) & MAX_BUFFERS_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
return bytes_;
|
||||
}
|
||||
|
||||
void xaudio2_free(xaudio2_t *handle)
|
||||
{
|
||||
if (handle)
|
||||
{
|
||||
if (handle->pSourceVoice)
|
||||
{
|
||||
IXAudio2SourceVoice_Stop(handle->pSourceVoice, 0, XAUDIO2_COMMIT_NOW);
|
||||
IXAudio2SourceVoice_DestroyVoice(handle->pSourceVoice);
|
||||
}
|
||||
|
||||
if (handle->pMasterVoice)
|
||||
IXAudio2MasteringVoice_DestroyVoice(handle->pMasterVoice);
|
||||
|
||||
if (handle->pXAudio2)
|
||||
IXAudio2_Release(handle->pXAudio2);
|
||||
|
||||
if (handle->hEvent)
|
||||
CloseHandle(handle->hEvent);
|
||||
|
||||
free(handle->buf);
|
||||
free(handle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
Simple C interface for XAudio2
|
||||
Author: Hans-Kristian Arntzen
|
||||
License: Public Domain
|
||||
*/
|
||||
|
||||
#include "xaudio-c.h"
|
||||
#include "xaudio2.hpp"
|
||||
#include <stdint.h>
|
||||
#include <algorithm>
|
||||
|
||||
struct xaudio2 : public IXAudio2VoiceCallback
|
||||
{
|
||||
xaudio2(unsigned samplerate, unsigned channels, unsigned size) :
|
||||
buf(0), pXAudio2(0), pMasterVoice(0), pSourceVoice(0),
|
||||
buffers(0), bufptr(0)
|
||||
{
|
||||
CoInitializeEx(0, COINIT_MULTITHREADED);
|
||||
if (FAILED(XAudio2Create(&pXAudio2, 0)))
|
||||
throw -1;
|
||||
if (FAILED(pXAudio2->CreateMasteringVoice(
|
||||
&pMasterVoice, channels, samplerate, 0, 0, 0)))
|
||||
throw -1;
|
||||
|
||||
WAVEFORMATEX wfx;
|
||||
wfx.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
|
||||
wfx.nChannels = channels;
|
||||
wfx.nSamplesPerSec = samplerate;
|
||||
wfx.nBlockAlign = channels * sizeof(float);
|
||||
wfx.wBitsPerSample = sizeof(float) * 8;
|
||||
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
|
||||
wfx.cbSize = 0;
|
||||
if (FAILED(pXAudio2->CreateSourceVoice(
|
||||
&pSourceVoice, &wfx, XAUDIO2_VOICE_NOSRC, XAUDIO2_DEFAULT_FREQ_RATIO, this, 0, 0)))
|
||||
throw -1;
|
||||
|
||||
hEvent = CreateEvent(0, FALSE, FALSE, 0);
|
||||
if (!hEvent)
|
||||
throw -1;
|
||||
|
||||
pSourceVoice->Start(0);
|
||||
|
||||
bufsize = size / max_buffers;
|
||||
buf = new uint8_t[bufsize * max_buffers];
|
||||
write_buffer = 0;
|
||||
}
|
||||
|
||||
virtual ~xaudio2()
|
||||
{
|
||||
if (pSourceVoice)
|
||||
{
|
||||
pSourceVoice->Stop(0);
|
||||
pSourceVoice->DestroyVoice();
|
||||
}
|
||||
|
||||
if (pMasterVoice)
|
||||
pMasterVoice->DestroyVoice();
|
||||
|
||||
if (pXAudio2)
|
||||
pXAudio2->Release();
|
||||
|
||||
if (hEvent)
|
||||
CloseHandle(hEvent);
|
||||
|
||||
if (buf)
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
size_t write_avail() const
|
||||
{
|
||||
return bufsize * (max_buffers - buffers - 1);
|
||||
}
|
||||
|
||||
size_t write(const void *buffer_, size_t bytes_)
|
||||
{
|
||||
unsigned bytes = bytes_;
|
||||
const uint8_t *buffer = reinterpret_cast<const uint8_t*>(buffer_);
|
||||
while (bytes > 0)
|
||||
{
|
||||
unsigned need = std::min(bytes, bufsize - bufptr);
|
||||
memcpy(buf + write_buffer * bufsize + bufptr,
|
||||
buffer, need);
|
||||
|
||||
bufptr += need;
|
||||
buffer += need;
|
||||
bytes -= need;
|
||||
|
||||
if (bufptr == bufsize)
|
||||
{
|
||||
WaitForSingleObject(hEvent, 0); // Clear out ready state.
|
||||
while (buffers == max_buffers - 1)
|
||||
WaitForSingleObject(hEvent, INFINITE);
|
||||
|
||||
XAUDIO2_BUFFER xa2buffer = {0};
|
||||
xa2buffer.AudioBytes = bufsize;
|
||||
xa2buffer.pAudioData = buf + write_buffer * bufsize;
|
||||
xa2buffer.pContext = 0;
|
||||
if (FAILED(pSourceVoice->SubmitSourceBuffer(&xa2buffer)))
|
||||
return 0;
|
||||
|
||||
InterlockedIncrement(&buffers);
|
||||
bufptr = 0;
|
||||
write_buffer = (write_buffer + 1) & (max_buffers_mask);
|
||||
}
|
||||
}
|
||||
|
||||
return bytes_;
|
||||
}
|
||||
|
||||
enum { max_buffers = 16, max_buffers_mask = max_buffers - 1 };
|
||||
|
||||
STDMETHOD_(void, OnBufferStart) (void *) {}
|
||||
STDMETHOD_(void, OnBufferEnd) (void *)
|
||||
{
|
||||
InterlockedDecrement(&buffers);
|
||||
SetEvent(hEvent);
|
||||
}
|
||||
STDMETHOD_(void, OnLoopEnd) (void *) {}
|
||||
STDMETHOD_(void, OnStreamEnd) () {}
|
||||
STDMETHOD_(void, OnVoiceError) (void *, HRESULT) {}
|
||||
STDMETHOD_(void, OnVoiceProcessingPassEnd) () {}
|
||||
STDMETHOD_(void, OnVoiceProcessingPassStart) (UINT32) {}
|
||||
|
||||
uint8_t *buf;
|
||||
IXAudio2 *pXAudio2;
|
||||
IXAudio2MasteringVoice *pMasterVoice;
|
||||
IXAudio2SourceVoice *pSourceVoice;
|
||||
HANDLE hEvent;
|
||||
|
||||
volatile long buffers;
|
||||
unsigned bufsize;
|
||||
unsigned bufptr;
|
||||
unsigned write_buffer;
|
||||
};
|
||||
|
||||
xaudio2_t *xaudio2_new(unsigned samplerate, unsigned channels, size_t size)
|
||||
{
|
||||
xaudio2 *handle = 0;
|
||||
try {
|
||||
handle = new xaudio2(samplerate, channels, size);
|
||||
} catch(...) { delete handle; return 0; }
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
size_t xaudio2_write_avail(xaudio2_t *handle)
|
||||
{
|
||||
try {
|
||||
return handle->write_avail();
|
||||
} catch(...) { return 0; }
|
||||
}
|
||||
|
||||
size_t xaudio2_write(xaudio2_t *handle, const void *buf, size_t bytes)
|
||||
{
|
||||
try {
|
||||
return handle->write(buf, bytes);
|
||||
} catch(...) { return 0; }
|
||||
}
|
||||
|
||||
void xaudio2_free(xaudio2_t *handle)
|
||||
{
|
||||
delete handle;
|
||||
}
|
||||
|
||||
Executable → Regular
+44
-151
@@ -1,35 +1,33 @@
|
||||
/*
|
||||
xaudio2.hpp (2010-08-14)
|
||||
author: OV2
|
||||
xaudio.h (2010-08-14) / (2011-12-04)
|
||||
authors: OV2, Themaister
|
||||
*/
|
||||
|
||||
// Kinda stripped down. Only contains the bare essentials used in SSNES.
|
||||
|
||||
#ifndef XAUDIO2_MINGW_H
|
||||
#define XAUDIO2_MINGW_H
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#undef min
|
||||
#undef max
|
||||
#include <basetyps.h>
|
||||
#include <objbase.h>
|
||||
#include <mmreg.h>
|
||||
|
||||
// 64-bit GCC fix
|
||||
#define GUID_EXT EXTERN_C
|
||||
#define GUID_SECT
|
||||
|
||||
#define DEFINE_GUID_X(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) GUID_EXT const GUID n GUID_SECT = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
|
||||
#define DEFINE_GUID_X(n, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||
static const GUID n = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
|
||||
#define DEFINE_CLSID_X(className, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||
DEFINE_GUID_X(CLSID_##className, 0x##l, 0x##w1, 0x##w2, 0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8)
|
||||
#define DEFINE_IID_X(interfaceName, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
|
||||
DEFINE_GUID_X(IID_##interfaceName, 0x##l, 0x##w1, 0x##w2, 0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8)
|
||||
#define X2DEFAULT(x) =x
|
||||
#define X2DEFAULT(x)
|
||||
|
||||
DEFINE_CLSID_X(XAudio2, e21a7345, eb21, 468e, be, 50, 80, 4d, b9, 7c, f7, 08);
|
||||
DEFINE_CLSID_X(XAudio2_Debug, f7a76c21, 53d4, 46bb, ac, 53, 8b, 45, 9c, ae, 46, bd);
|
||||
DEFINE_IID_X(IXAudio2, 8bcf1f58, 9fe7, 4583, 8a, c6, e2, ad, c4, 65, c8, bb);
|
||||
|
||||
DECLARE_INTERFACE(IXAudio2Voice);
|
||||
#ifndef INTERFACE
|
||||
#define INTERFACE void
|
||||
#endif
|
||||
|
||||
#define XAUDIO2_COMMIT_NOW 0
|
||||
#define XAUDIO2_DEFAULT_CHANNELS 0
|
||||
@@ -46,95 +44,33 @@ typedef enum XAUDIO2_DEVICE_ROLE
|
||||
DefaultCommunicationsDevice = 0x4,
|
||||
DefaultGameDevice = 0x8,
|
||||
GlobalDefaultDevice = 0xf,
|
||||
InvalidDeviceRole = ~GlobalDefaultDevice
|
||||
InvalidDeviceRole = ~GlobalDefaultDevice
|
||||
} XAUDIO2_DEVICE_ROLE;
|
||||
|
||||
typedef struct XAUDIO2_DEVICE_DETAILS
|
||||
{
|
||||
WCHAR DeviceID[256];
|
||||
WCHAR DisplayName[256];
|
||||
XAUDIO2_DEVICE_ROLE Role;
|
||||
WAVEFORMATEXTENSIBLE OutputFormat;
|
||||
} XAUDIO2_DEVICE_DETAILS;
|
||||
|
||||
typedef struct XAUDIO2_VOICE_DETAILS
|
||||
{
|
||||
UINT32 CreationFlags;
|
||||
UINT32 InputChannels;
|
||||
UINT32 InputSampleRate;
|
||||
} XAUDIO2_VOICE_DETAILS;
|
||||
|
||||
typedef enum XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER
|
||||
{
|
||||
Processor1 = 0x00000001,
|
||||
Processor2 = 0x00000002,
|
||||
Processor3 = 0x00000004,
|
||||
Processor4 = 0x00000008,
|
||||
Processor5 = 0x00000010,
|
||||
Processor6 = 0x00000020,
|
||||
Processor7 = 0x00000040,
|
||||
Processor8 = 0x00000080,
|
||||
Processor9 = 0x00000100,
|
||||
Processor10 = 0x00000200,
|
||||
Processor11 = 0x00000400,
|
||||
Processor12 = 0x00000800,
|
||||
Processor13 = 0x00001000,
|
||||
Processor14 = 0x00002000,
|
||||
Processor15 = 0x00004000,
|
||||
Processor16 = 0x00008000,
|
||||
Processor17 = 0x00010000,
|
||||
Processor18 = 0x00020000,
|
||||
Processor19 = 0x00040000,
|
||||
Processor20 = 0x00080000,
|
||||
Processor21 = 0x00100000,
|
||||
Processor22 = 0x00200000,
|
||||
Processor23 = 0x00400000,
|
||||
Processor24 = 0x00800000,
|
||||
Processor25 = 0x01000000,
|
||||
Processor26 = 0x02000000,
|
||||
Processor27 = 0x04000000,
|
||||
Processor28 = 0x08000000,
|
||||
Processor29 = 0x10000000,
|
||||
Processor30 = 0x20000000,
|
||||
Processor31 = 0x40000000,
|
||||
Processor32 = 0x80000000,
|
||||
XAUDIO2_ANY_PROCESSOR = 0xffffffff,
|
||||
XAUDIO2_DEFAULT_PROCESSOR = XAUDIO2_ANY_PROCESSOR
|
||||
XAUDIO2_ANY_PROCESSOR = 0xffffffff,
|
||||
XAUDIO2_DEFAULT_PROCESSOR = XAUDIO2_ANY_PROCESSOR
|
||||
} XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER, XAUDIO2_PROCESSOR;
|
||||
|
||||
typedef struct XAUDIO2_VOICE_SENDS
|
||||
{
|
||||
UINT32 OutputCount;
|
||||
IXAudio2Voice** pOutputVoices;
|
||||
} XAUDIO2_VOICE_SENDS;
|
||||
|
||||
typedef struct XAUDIO2_EFFECT_DESCRIPTOR
|
||||
{
|
||||
IUnknown* pEffect;
|
||||
BOOL InitialState;
|
||||
UINT32 OutputChannels;
|
||||
} XAUDIO2_EFFECT_DESCRIPTOR;
|
||||
|
||||
typedef struct XAUDIO2_EFFECT_CHAIN
|
||||
{
|
||||
UINT32 EffectCount;
|
||||
const XAUDIO2_EFFECT_DESCRIPTOR* pEffectDescriptors;
|
||||
} XAUDIO2_EFFECT_CHAIN;
|
||||
|
||||
typedef enum XAUDIO2_FILTER_TYPE
|
||||
{
|
||||
typedef enum XAUDIO2_FILTER_TYPE {
|
||||
LowPassFilter,
|
||||
BandPassFilter,
|
||||
HighPassFilter
|
||||
HighPassFilter
|
||||
} XAUDIO2_FILTER_TYPE;
|
||||
|
||||
typedef struct XAUDIO2_FILTER_PARAMETERS
|
||||
{
|
||||
XAUDIO2_FILTER_TYPE Type;
|
||||
float Frequency;
|
||||
float OneOverQ;
|
||||
|
||||
} XAUDIO2_FILTER_PARAMETERS;
|
||||
typedef struct XAUDIO2_DEVICE_DETAILS XAUDIO2_DEVICE_DETAILS;
|
||||
typedef struct XAUDIO2_VOICE_DETAILS XAUDIO2_VOICE_DETAILS;
|
||||
typedef struct XAUDIO2_VOICE_SENDS XAUDIO2_VOICE_SENDS;
|
||||
typedef struct XAUDIO2_EFFECT_DESCRIPTOR XAUDIO2_EFFECT_DESCRIPTOR;
|
||||
typedef struct XAUDIO2_EFFECT_CHAIN XAUDIO2_EFFECT_CHAIN;
|
||||
typedef struct XAUDIO2_FILTER_PARAMETERS XAUDIO2_FILTER_PARAMETERS;
|
||||
typedef struct XAUDIO2_BUFFER_WMA XAUDIO2_BUFFER_WMA;
|
||||
typedef struct XAUDIO2_VOICE_STATE XAUDIO2_VOICE_STATE;
|
||||
typedef struct XAUDIO2_PERFORMANCE_DATA XAUDIO2_PERFORMANCE_DATA;
|
||||
typedef struct XAUDIO2_DEBUG_CONFIGURATION XAUDIO2_DEBUG_CONFIGURATION;
|
||||
typedef struct IXAudio2EngineCallback IXAudio2EngineCallback;
|
||||
typedef struct IXAudio2SubmixVoice IXAudio2SubmixVoice;
|
||||
|
||||
typedef struct XAUDIO2_BUFFER
|
||||
{
|
||||
@@ -149,53 +85,6 @@ typedef struct XAUDIO2_BUFFER
|
||||
void *pContext;
|
||||
} XAUDIO2_BUFFER;
|
||||
|
||||
typedef struct XAUDIO2_BUFFER_WMA
|
||||
{
|
||||
const UINT32* pDecodedPacketCumulativeBytes;
|
||||
UINT32 PacketCount;
|
||||
} XAUDIO2_BUFFER_WMA;
|
||||
|
||||
typedef struct XAUDIO2_VOICE_STATE
|
||||
{
|
||||
void *pCurrentBufferContext;
|
||||
UINT32 BuffersQueued;
|
||||
UINT64 SamplesPlayed;
|
||||
} XAUDIO2_VOICE_STATE;
|
||||
|
||||
typedef struct XAUDIO2_PERFORMANCE_DATA
|
||||
{
|
||||
UINT64 AudioCyclesSinceLastQuery;
|
||||
UINT64 TotalCyclesSinceLastQuery;
|
||||
UINT32 MinimumCyclesPerQuantum;
|
||||
UINT32 MaximumCyclesPerQuantum;
|
||||
UINT32 MemoryUsageInBytes;
|
||||
UINT32 CurrentLatencyInSamples;
|
||||
UINT32 GlitchesSinceEngineStarted;
|
||||
UINT32 ActiveSourceVoiceCount;
|
||||
UINT32 TotalSourceVoiceCount;
|
||||
UINT32 ActiveSubmixVoiceCount;
|
||||
UINT32 TotalSubmixVoiceCount;
|
||||
UINT32 ActiveXmaSourceVoices;
|
||||
UINT32 ActiveXmaStreams;
|
||||
} XAUDIO2_PERFORMANCE_DATA;
|
||||
|
||||
typedef struct XAUDIO2_DEBUG_CONFIGURATION
|
||||
{
|
||||
UINT32 TraceMask;
|
||||
UINT32 BreakMask;
|
||||
BOOL LogThreadID;
|
||||
BOOL LogFileline;
|
||||
BOOL LogFunctionName;
|
||||
BOOL LogTiming;
|
||||
} XAUDIO2_DEBUG_CONFIGURATION;
|
||||
|
||||
DECLARE_INTERFACE(IXAudio2EngineCallback)
|
||||
{
|
||||
STDMETHOD_(void, OnProcessingPassStart) (THIS) PURE;
|
||||
STDMETHOD_(void, OnProcessingPassEnd) (THIS) PURE;
|
||||
STDMETHOD_(void, OnCriticalError) (THIS_ HRESULT Error) PURE;
|
||||
};
|
||||
|
||||
DECLARE_INTERFACE(IXAudio2VoiceCallback)
|
||||
{
|
||||
STDMETHOD_(void, OnVoiceProcessingPassStart) (THIS_ UINT32 BytesRequired) PURE;
|
||||
@@ -245,17 +134,11 @@ DECLARE_INTERFACE(IXAudio2Voice)
|
||||
Declare_IXAudio2Voice_Methods();
|
||||
};
|
||||
|
||||
|
||||
DECLARE_INTERFACE_(IXAudio2MasteringVoice, IXAudio2Voice)
|
||||
{
|
||||
Declare_IXAudio2Voice_Methods();
|
||||
};
|
||||
|
||||
DECLARE_INTERFACE_(IXAudio2SubmixVoice, IXAudio2Voice)
|
||||
{
|
||||
Declare_IXAudio2Voice_Methods();
|
||||
};
|
||||
|
||||
DECLARE_INTERFACE_(IXAudio2SourceVoice, IXAudio2Voice)
|
||||
{
|
||||
Declare_IXAudio2Voice_Methods();
|
||||
@@ -307,20 +190,30 @@ DECLARE_INTERFACE_(IXAudio2, IUnknown)
|
||||
void *pReserved X2DEFAULT(NULL)) PURE;
|
||||
};
|
||||
|
||||
static inline HRESULT XAudio2Create(IXAudio2** ppXAudio2, UINT32 Flags X2DEFAULT(0),
|
||||
XAUDIO2_PROCESSOR XAudio2Processor X2DEFAULT(XAUDIO2_DEFAULT_PROCESSOR))
|
||||
// C hooks.
|
||||
#define IXAudio2_Initialize(THIS, a, b) (THIS)->lpVtbl->Initialize(THIS, a, b)
|
||||
#define IXAudio2_Release(THIS) (THIS)->lpVtbl->Release(THIS)
|
||||
#define IXAudio2_CreateSourceVoice(THIS, a, b, c, d, e, f, g) (THIS)->lpVtbl->CreateSourceVoice(THIS, a, b, c, d, e, f, g)
|
||||
#define IXAudio2_CreateMasteringVoice(THIS, a, b, c, d, e, f) (THIS)->lpVtbl->CreateMasteringVoice(THIS, a, b, c, d, e, f)
|
||||
|
||||
#define IXAudio2SourceVoice_Start(THIS, a, b) (THIS)->lpVtbl->Start(THIS, a, b)
|
||||
#define IXAudio2SourceVoice_Stop(THIS, a, b) (THIS)->lpVtbl->Stop(THIS, a, b)
|
||||
#define IXAudio2SourceVoice_SubmitSourceBuffer(THIS, a, b) (THIS)->lpVtbl->SubmitSourceBuffer(THIS, a, b)
|
||||
#define IXAudio2SourceVoice_DestroyVoice(THIS) (THIS)->lpVtbl->DestroyVoice(THIS)
|
||||
#define IXAudio2MasteringVoice_DestroyVoice(THIS) (THIS)->lpVtbl->DestroyVoice(THIS)
|
||||
|
||||
static inline HRESULT XAudio2Create(IXAudio2 **ppXAudio2)
|
||||
{
|
||||
IXAudio2* pXAudio2;
|
||||
HRESULT hr = CoCreateInstance((Flags & XAUDIO2_DEBUG_ENGINE) ? CLSID_XAudio2_Debug : CLSID_XAudio2,
|
||||
NULL, CLSCTX_INPROC_SERVER, IID_IXAudio2, reinterpret_cast<void**>(&pXAudio2));
|
||||
IXAudio2 *pXAudio2;
|
||||
HRESULT hr = CoCreateInstance(&CLSID_XAudio2, NULL, CLSCTX_INPROC_SERVER, &IID_IXAudio2, (void**)&pXAudio2);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pXAudio2->Initialize(Flags, XAudio2Processor);
|
||||
hr = IXAudio2_Initialize(pXAudio2, 0, XAUDIO2_DEFAULT_PROCESSOR);
|
||||
if (SUCCEEDED(hr))
|
||||
*ppXAudio2 = pXAudio2;
|
||||
else
|
||||
pXAudio2->Release();
|
||||
IXAudio2_Release(pXAudio2);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
+29
-27
@@ -22,11 +22,11 @@
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include "strl.h"
|
||||
#include "../strl.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#if !defined(_WIN32) && !defined(__CELLOS_LV2__)
|
||||
#include <sys/param.h> // MAXPATHLEN
|
||||
#else
|
||||
#elif defined(_WIN32)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
@@ -195,30 +195,7 @@ static void add_sub_conf(config_file_t *conf, char *line)
|
||||
|
||||
char real_path[MAXPATHLEN];
|
||||
|
||||
#ifndef _WIN32
|
||||
if (*path == '/')
|
||||
{
|
||||
strlcpy(real_path, path, sizeof(real_path));
|
||||
}
|
||||
else if (*path == '~')
|
||||
{
|
||||
const char *home = getenv("HOME");
|
||||
strlcpy(real_path, home ? home : "/", sizeof(real_path));
|
||||
strlcat(real_path, path + 1, sizeof(real_path));
|
||||
}
|
||||
else
|
||||
{
|
||||
strlcpy(real_path, conf->path, sizeof(real_path));
|
||||
char *split = strrchr(real_path, '/');
|
||||
if (split)
|
||||
{
|
||||
split[1] = '\0';
|
||||
strlcat(real_path, path, sizeof(real_path));
|
||||
}
|
||||
else
|
||||
strlcpy(real_path, path, sizeof(real_path));
|
||||
}
|
||||
#else
|
||||
#ifdef _WIN32
|
||||
// Accomodate POSIX systems on Win32.
|
||||
bool is_full_path = *path == '/';
|
||||
|
||||
@@ -237,6 +214,31 @@ static void add_sub_conf(config_file_t *conf, char *line)
|
||||
split[1] = '\0';
|
||||
strlcat(real_path, path, sizeof(real_path));
|
||||
}
|
||||
#else
|
||||
if (*path == '/')
|
||||
{
|
||||
strlcpy(real_path, path, sizeof(real_path));
|
||||
}
|
||||
#ifndef __CELLOS_LV2__
|
||||
else if (*path == '~')
|
||||
{
|
||||
const char *home = getenv("HOME");
|
||||
strlcpy(real_path, home ? home : "/", sizeof(real_path));
|
||||
strlcat(real_path, path + 1, sizeof(real_path));
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
strlcpy(real_path, conf->path, sizeof(real_path));
|
||||
char *split = strrchr(real_path, '/');
|
||||
if (split)
|
||||
{
|
||||
split[1] = '\0';
|
||||
strlcat(real_path, path, sizeof(real_path));
|
||||
}
|
||||
else
|
||||
strlcpy(real_path, path, sizeof(real_path));
|
||||
}
|
||||
#endif
|
||||
|
||||
config_file_t *sub_conf = config_file_new_internal(real_path, conf->include_depth + 1);
|
||||
|
||||
+13
-2
@@ -50,12 +50,14 @@
|
||||
#define AUDIO_EXT 15
|
||||
#define AUDIO_DSOUND 16
|
||||
#define AUDIO_COREAUDIO 17
|
||||
#define AUDIO_PS3 18
|
||||
////////////////////////
|
||||
#define INPUT_SDL 7
|
||||
#define INPUT_X 12
|
||||
#define INPUT_PS3 19
|
||||
////////////////////////
|
||||
|
||||
#if defined(HAVE_OPENGL)
|
||||
#if defined(HAVE_OPENGL) || defined(__CELLOS_LV2__)
|
||||
#define VIDEO_DEFAULT_DRIVER VIDEO_GL
|
||||
#elif defined(HAVE_XVIDEO)
|
||||
#define VIDEO_DEFAULT_DRIVER VIDEO_XVIDEO
|
||||
@@ -67,7 +69,9 @@
|
||||
#error "Need at least one video driver!"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_ALSA)
|
||||
#if defined(__CELLOS_LV2__)
|
||||
#define AUDIO_DEFAULT_DRIVER AUDIO_PS3
|
||||
#elif defined(HAVE_ALSA)
|
||||
#define AUDIO_DEFAULT_DRIVER AUDIO_ALSA
|
||||
#elif defined(HAVE_PULSE)
|
||||
#define AUDIO_DEFAULT_DRIVER AUDIO_PULSE
|
||||
@@ -97,6 +101,8 @@
|
||||
|
||||
#if defined(HAVE_SDL)
|
||||
#define INPUT_DEFAULT_DRIVER INPUT_SDL
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
#define INPUT_DEFAULT_DRIVER INPUT_PS3
|
||||
#elif defined(HAVE_XVIDEO)
|
||||
#define INPUT_DEFAULT_DRIVER INPUT_X
|
||||
#else
|
||||
@@ -167,7 +173,11 @@ static const bool font_enable = true;
|
||||
// This value should stay close to 60Hz to avoid large pitch changes.
|
||||
// If your monitor does not run at 60Hz, or something close to it, disable VSync,
|
||||
// and leave this at its default.
|
||||
#ifdef __CELLOS_LV2__
|
||||
static const float refresh_rate = 59.92;
|
||||
#else
|
||||
static const float refresh_rate = 59.95;
|
||||
#endif
|
||||
|
||||
////////////////
|
||||
// Audio
|
||||
@@ -267,6 +277,7 @@ static const struct snes_keybind snes_keybinds_1[] = {
|
||||
{ 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 },
|
||||
{ SSNES_MUTE, SK_F9, NO_BTN, AXIS_NONE },
|
||||
{ -1 }
|
||||
};
|
||||
|
||||
|
||||
@@ -14,6 +14,12 @@ static const bool _sdl_supp = true;
|
||||
static const bool _sdl_supp = false;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
static const bool _thread_supp = true;
|
||||
#else
|
||||
static const bool _thread_supp = false;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENGL
|
||||
static const bool _opengl_supp = true;
|
||||
#else
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ Connects a four-way multitap into port 2 of the SNES. This allows for up to 5 pl
|
||||
.TP
|
||||
\fB--record PATH, -r PATH\fR
|
||||
Activates video recording of gameplay into PATH. Using .mkv extension is recommended.
|
||||
Codecs used are FFV1/FLAC, suitable for processing the material further.
|
||||
Codecs used are (FFV1 or H264 RGB lossless (x264))/FLAC, suitable for processing the material further.
|
||||
|
||||
.TP
|
||||
\fB--size WIDTHxHEIGHT\fR
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
#endif
|
||||
|
||||
static const audio_driver_t *audio_drivers[] = {
|
||||
#ifdef __CELLOS_LV2__
|
||||
&audio_ps3,
|
||||
#endif
|
||||
#ifdef HAVE_ALSA
|
||||
&audio_alsa,
|
||||
#endif
|
||||
@@ -83,6 +86,9 @@ static const video_driver_t *video_drivers[] = {
|
||||
};
|
||||
|
||||
static const input_driver_t *input_drivers[] = {
|
||||
#ifdef __CELLOS_LV2__
|
||||
&input_ps3,
|
||||
#endif
|
||||
#ifdef HAVE_SDL
|
||||
&input_sdl,
|
||||
#endif
|
||||
@@ -157,6 +163,7 @@ void uninit_drivers(void)
|
||||
uninit_audio();
|
||||
}
|
||||
|
||||
#ifdef HAVE_DYLIB
|
||||
static void init_dsp_plugin(void)
|
||||
{
|
||||
if (!(*g_settings.audio.dsp_plugin))
|
||||
@@ -221,6 +228,7 @@ static void deinit_dsp_plugin(void)
|
||||
dylib_close(g_extern.audio_data.dsp_lib);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void adjust_audio_input_rate(void)
|
||||
{
|
||||
@@ -311,7 +319,9 @@ void init_audio(void)
|
||||
g_extern.audio_data.src_ratio =
|
||||
(double)g_settings.audio.out_rate / g_settings.audio.in_rate;
|
||||
|
||||
#ifdef HAVE_DYLIB
|
||||
init_dsp_plugin();
|
||||
#endif
|
||||
}
|
||||
|
||||
void uninit_audio(void)
|
||||
@@ -338,7 +348,9 @@ void uninit_audio(void)
|
||||
free(g_extern.audio_data.outsamples);
|
||||
g_extern.audio_data.outsamples = NULL;
|
||||
|
||||
#ifdef HAVE_DYLIB
|
||||
deinit_dsp_plugin();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_DYLIB
|
||||
@@ -402,7 +414,6 @@ static void init_filter(void)
|
||||
g_extern.filter.colormap[i] = (r << 16) | (g << 8) | (b << 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void deinit_filter(void)
|
||||
{
|
||||
@@ -415,6 +426,7 @@ static void deinit_filter(void)
|
||||
free(g_extern.filter.colormap);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XML
|
||||
static void init_shader_dir(void)
|
||||
@@ -543,7 +555,9 @@ void uninit_video_input(void)
|
||||
if (driver.video_data && driver.video)
|
||||
driver.video->free(driver.video_data);
|
||||
|
||||
#ifdef HAVE_DYLIB
|
||||
deinit_filter();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XML
|
||||
deinit_shader_dir();
|
||||
|
||||
@@ -52,6 +52,7 @@ enum
|
||||
SSNES_CHEAT_TOGGLE,
|
||||
SSNES_SCREENSHOT,
|
||||
SSNES_DSP_CONFIG,
|
||||
SSNES_MUTE,
|
||||
|
||||
SSNES_BIND_LIST_END
|
||||
};
|
||||
@@ -166,12 +167,14 @@ extern const audio_driver_t audio_pulse;
|
||||
extern const audio_driver_t audio_ext;
|
||||
extern const audio_driver_t audio_dsound;
|
||||
extern const audio_driver_t audio_coreaudio;
|
||||
extern const audio_driver_t audio_ps3;
|
||||
extern const video_driver_t video_gl;
|
||||
extern const video_driver_t video_xvideo;
|
||||
extern const video_driver_t video_sdl;
|
||||
extern const video_driver_t video_ext;
|
||||
extern const input_driver_t input_sdl;
|
||||
extern const input_driver_t input_x;
|
||||
extern const input_driver_t input_ps3;
|
||||
////////////////////////////////////////////////
|
||||
|
||||
#endif
|
||||
@@ -25,15 +25,18 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <libsnes.hpp>
|
||||
#include <stdbool.h>
|
||||
#include "libsnes.hpp"
|
||||
|
||||
#ifdef NEED_DYNAMIC
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DYNAMIC
|
||||
#ifdef NEED_DYNAMIC
|
||||
#define DLSYM(lib, x) dylib_proc(lib, #x)
|
||||
|
||||
#define SYM(type, x) do { \
|
||||
@@ -45,6 +48,9 @@
|
||||
p##x = (type)DLSYM(lib_handle, x); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DYNAMIC
|
||||
static dylib_t lib_handle = NULL;
|
||||
#endif
|
||||
|
||||
@@ -96,9 +102,10 @@ unsigned (*psnes_get_memory_size)(unsigned);
|
||||
void (*psnes_unload_cartridge)(void);
|
||||
void (*psnes_term)(void);
|
||||
|
||||
#ifdef HAVE_DYLIB
|
||||
#ifdef NEED_DYNAMIC
|
||||
static void set_environment(void);
|
||||
#endif
|
||||
static void set_environment_defaults(void);
|
||||
|
||||
#ifdef HAVE_DYNAMIC
|
||||
static void load_dynamic(void)
|
||||
@@ -144,13 +151,11 @@ static void load_dynamic(void)
|
||||
SYM(void (*)(void), snes_unload_cartridge);
|
||||
SYM(void (*)(void), snes_term);
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define SSYM(x) do { \
|
||||
p##x = x; \
|
||||
} while (0)
|
||||
|
||||
#ifndef HAVE_DYNAMIC
|
||||
static void set_statics(void)
|
||||
{
|
||||
SSYM(snes_init);
|
||||
@@ -183,14 +188,13 @@ static void set_statics(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
void init_dlsym(void)
|
||||
void init_libsnes_sym(void)
|
||||
{
|
||||
// Guarantee that we can do "dirty" casting.
|
||||
// Every OS that this program supports should pass this ...
|
||||
assert(sizeof(void*) == sizeof(void (*)(void)));
|
||||
|
||||
#ifdef HAVE_DYNAMIC
|
||||
|
||||
// Try to verify that -lsnes was not linked in from other modules
|
||||
// since loading it dynamically and with -l will fail hard.
|
||||
function_t sym = dylib_proc(NULL, "snes_init");
|
||||
@@ -218,12 +222,13 @@ void init_dlsym(void)
|
||||
set_statics();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DYLIB
|
||||
set_environment_defaults();
|
||||
#ifdef NEED_DYNAMIC
|
||||
set_environment();
|
||||
#endif
|
||||
}
|
||||
|
||||
void uninit_dlsym(void)
|
||||
void uninit_libsnes_sym(void)
|
||||
{
|
||||
#ifdef HAVE_DYNAMIC
|
||||
if (lib_handle)
|
||||
@@ -231,6 +236,7 @@ void uninit_dlsym(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef NEED_DYNAMIC
|
||||
// Platform independent dylib loading.
|
||||
dylib_t dylib_load(const char *path)
|
||||
{
|
||||
@@ -282,14 +288,14 @@ static bool environment_cb(unsigned cmd, void *data)
|
||||
{
|
||||
case SNES_ENVIRONMENT_GET_FULLPATH:
|
||||
*(const char**)data = g_extern.system.fullpath;
|
||||
SSNES_LOG("FULLPATH: \"%s\"\n", g_extern.system.fullpath);
|
||||
SSNES_LOG("Environ FULLPATH: \"%s\"\n", g_extern.system.fullpath);
|
||||
break;
|
||||
|
||||
case SNES_ENVIRONMENT_SET_GEOMETRY:
|
||||
g_extern.system.geom = *(const struct snes_geometry*)data;
|
||||
g_extern.system.geom.max_width = next_pow2(g_extern.system.geom.max_width);
|
||||
g_extern.system.geom.max_height = next_pow2(g_extern.system.geom.max_height);
|
||||
SSNES_LOG("SET_GEOMETRY: (%ux%u) / (%ux%u)\n",
|
||||
SSNES_LOG("Environ SET_GEOMETRY: (%ux%u) / (%ux%u)\n",
|
||||
g_extern.system.geom.base_width,
|
||||
g_extern.system.geom.base_height,
|
||||
g_extern.system.geom.max_width,
|
||||
@@ -298,43 +304,43 @@ static bool environment_cb(unsigned cmd, void *data)
|
||||
|
||||
case SNES_ENVIRONMENT_SET_PITCH:
|
||||
g_extern.system.pitch = *(const unsigned*)data;
|
||||
SSNES_LOG("SET_PITCH: %u\n", g_extern.system.pitch);
|
||||
SSNES_LOG("Environ SET_PITCH: %u\n", g_extern.system.pitch);
|
||||
break;
|
||||
|
||||
case SNES_ENVIRONMENT_GET_OVERSCAN:
|
||||
*(bool*)data = !g_settings.video.crop_overscan;
|
||||
SSNES_LOG("GET_OVERSCAN: %u\n", (unsigned)!g_settings.video.crop_overscan);
|
||||
SSNES_LOG("Environ GET_OVERSCAN: %u\n", (unsigned)!g_settings.video.crop_overscan);
|
||||
break;
|
||||
|
||||
case SNES_ENVIRONMENT_SET_TIMING:
|
||||
g_extern.system.timing = *(const struct snes_system_timing*)data;
|
||||
g_extern.system.timing_set = true;
|
||||
SSNES_LOG("Environ SET_TIMING: %.3lf Hz/ %.3lf Hz\n", g_extern.system.timing.fps, g_extern.system.timing.sample_rate);
|
||||
break;
|
||||
|
||||
case SNES_ENVIRONMENT_GET_CAN_DUPE:
|
||||
*(bool*)data = true;
|
||||
SSNES_LOG("Environ GET_CAN_DUPE: true\n");
|
||||
break;
|
||||
|
||||
case SNES_ENVIRONMENT_SET_NEED_FULLPATH:
|
||||
g_extern.system.need_fullpath = *(const bool*)data;
|
||||
SSNES_LOG("Environ SET_NEED_FULLPATH: %s\n", g_extern.system.need_fullpath ? "true" : "false");
|
||||
break;
|
||||
|
||||
case SNES_ENVIRONMENT_GET_CAN_REWIND:
|
||||
*(bool*)data = g_settings.rewind_enable;
|
||||
SSNES_LOG("Environ GET_CAN_REWIND: %s\n", g_settings.rewind_enable ? "true" : "false");
|
||||
break;
|
||||
|
||||
default:
|
||||
SSNES_LOG("Environ UNSUPPORTED (#%u)!\n", cmd);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DYLIB
|
||||
// Assume SNES as defaults.
|
||||
static void set_environment_defaults(void)
|
||||
{
|
||||
g_extern.system.pitch = 0; // 0 is classic libsnes semantics.
|
||||
g_extern.system.geom = (struct snes_geometry) {
|
||||
.base_width = 256,
|
||||
.base_height = 224,
|
||||
.max_width = 512,
|
||||
.max_height = 512,
|
||||
};
|
||||
}
|
||||
|
||||
// SSNES extension hooks. Totally optional 'n shizz :)
|
||||
static void set_environment(void)
|
||||
{
|
||||
@@ -349,9 +355,19 @@ static void set_environment(void)
|
||||
|
||||
if (psnes_set_environment)
|
||||
psnes_set_environment(environment_cb);
|
||||
|
||||
set_environment_defaults();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Assume SNES as defaults.
|
||||
static void set_environment_defaults(void)
|
||||
{
|
||||
SSNES_LOG("Setting environment defaults (SNES)\n");
|
||||
g_extern.system.pitch = 0; // 0 is classic libsnes semantics.
|
||||
g_extern.system.geom = (struct snes_geometry) {
|
||||
.base_width = 256,
|
||||
.base_height = 224,
|
||||
.max_width = 512,
|
||||
.max_height = 512,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -19,17 +19,29 @@
|
||||
#define __DYNAMIC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <libsnes.hpp>
|
||||
#include "libsnes.hpp"
|
||||
|
||||
void init_dlsym(void);
|
||||
void uninit_dlsym(void);
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB)
|
||||
#define NEED_DYNAMIC
|
||||
#else
|
||||
#undef NEED_DYNAMIC
|
||||
#endif
|
||||
|
||||
void init_libsnes_sym(void);
|
||||
void uninit_libsnes_sym(void);
|
||||
|
||||
typedef void *dylib_t;
|
||||
#ifdef NEED_DYNAMIC
|
||||
typedef void (*function_t)(void);
|
||||
|
||||
dylib_t dylib_load(const char *path);
|
||||
void dylib_close(dylib_t lib);
|
||||
function_t dylib_proc(dylib_t lib, const char *proc);
|
||||
#endif
|
||||
|
||||
extern void (*psnes_init)(void);
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "general.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <libsnes.hpp>
|
||||
#include "libsnes.hpp"
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
@@ -361,6 +361,8 @@ static void dump_to_file_desperate(const void *data, size_t size, int type)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const char *base = getenv("APPDATA");
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
const char *base = NULL;
|
||||
#else
|
||||
const char *base = getenv("HOME");
|
||||
#endif
|
||||
@@ -735,29 +737,43 @@ static bool load_normal_rom(void)
|
||||
void *rom_buf = NULL;
|
||||
ssize_t rom_len = 0;
|
||||
|
||||
if ((rom_len = read_rom_file(g_extern.rom_file, &rom_buf)) == -1)
|
||||
if (!g_extern.system.need_fullpath)
|
||||
{
|
||||
SSNES_ERR("Could not read ROM file.\n");
|
||||
return false;
|
||||
if ((rom_len = read_rom_file(g_extern.rom_file, &rom_buf)) == -1)
|
||||
{
|
||||
SSNES_ERR("Could not read ROM file.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_extern.rom_file)
|
||||
fclose(g_extern.rom_file);
|
||||
|
||||
SSNES_LOG("ROM size: %d bytes\n", (int)rom_len);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!g_extern.rom_file)
|
||||
{
|
||||
SSNES_ERR("Implementation requires a full path to be set, cannot load ROM from stdin. Aborting ...\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_extern.rom_file != NULL)
|
||||
fclose(g_extern.rom_file);
|
||||
|
||||
SSNES_LOG("ROM size: %d bytes\n", (int)rom_len);
|
||||
|
||||
char *xml_buf = load_xml_map(g_extern.xml_name);
|
||||
SSNES_LOG("ROM loading skipped. Implementation will load it on its own.\n");
|
||||
}
|
||||
|
||||
char *xml_buf = load_xml_map(g_extern.xml_name);
|
||||
|
||||
if (!psnes_load_cartridge_normal(xml_buf, rom_buf, rom_len))
|
||||
{
|
||||
SSNES_ERR("ROM file is not valid!\n");
|
||||
free(rom_buf);
|
||||
free(xml_buf);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (xml_buf)
|
||||
free(xml_buf);
|
||||
|
||||
free(xml_buf);
|
||||
free(rom_buf);
|
||||
return true;
|
||||
}
|
||||
@@ -929,6 +945,12 @@ bool path_is_directory(const char *path)
|
||||
if (MultiByteToWideChar(CP_UTF8, 0, path, -1, buf, MAXPATHLEN) == 0)
|
||||
return false;
|
||||
return PathIsDirectoryW(buf) == FILE_ATTRIBUTE_DIRECTORY;
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
return false; // STUB
|
||||
#elif defined(XENON)
|
||||
// Dummy
|
||||
(void)path;
|
||||
return false;
|
||||
#else
|
||||
struct stat buf;
|
||||
if (stat(path, &buf) < 0)
|
||||
|
||||
@@ -28,20 +28,27 @@
|
||||
#include "rewind.h"
|
||||
#include "movie.h"
|
||||
#include "autosave.h"
|
||||
#include "netplay.h"
|
||||
#include "dynamic.h"
|
||||
#include "cheats.h"
|
||||
#include "audio/ext/ssnes_dsp.h"
|
||||
|
||||
#ifdef __CELLOS_LV2__
|
||||
#include <sys/timer.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETPLAY
|
||||
#include "netplay.h"
|
||||
#endif
|
||||
|
||||
#include "audio/hermite.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#if !defined(_WIN32) && !defined(__CELLOS_LV2__)
|
||||
#include <sys/param.h> // MAXPATHLEN
|
||||
#else
|
||||
#elif defined(_WIN32)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
@@ -216,6 +223,7 @@ struct global
|
||||
char fullpath[MAXPATHLEN];
|
||||
struct snes_system_timing timing;
|
||||
bool timing_set;
|
||||
bool need_fullpath;
|
||||
} system;
|
||||
|
||||
struct
|
||||
@@ -231,6 +239,7 @@ struct global
|
||||
double src_ratio;
|
||||
|
||||
bool use_float;
|
||||
bool mute;
|
||||
|
||||
float *outsamples;
|
||||
int16_t *conv_outsamples;
|
||||
@@ -290,12 +299,14 @@ struct global
|
||||
autosave_t *autosave[2];
|
||||
|
||||
// Netplay.
|
||||
#ifdef HAVE_NETPLAY
|
||||
netplay_t *netplay;
|
||||
char netplay_server[MAXPATHLEN];
|
||||
bool netplay_enable;
|
||||
bool netplay_is_client;
|
||||
unsigned netplay_sync_frames;
|
||||
uint16_t netplay_port;
|
||||
#endif
|
||||
|
||||
// FFmpeg record.
|
||||
#ifdef HAVE_FFMPEG
|
||||
@@ -384,14 +395,19 @@ static inline uint8_t is_little_endian(void)
|
||||
return u.y[0];
|
||||
}
|
||||
|
||||
static inline void ssnes_sleep(unsigned usec)
|
||||
static inline void ssnes_sleep(unsigned msec)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
Sleep(10);
|
||||
#ifdef __CELLOS_LV2__
|
||||
sys_timer_usleep(1000 * msec);
|
||||
#elif defined(_WIN32)
|
||||
Sleep(msec);
|
||||
#elif defined(XENON)
|
||||
// Dummy
|
||||
(void)msec;
|
||||
#else
|
||||
struct timespec tv = {
|
||||
.tv_sec = 0,
|
||||
.tv_nsec = 10000000
|
||||
.tv_sec = msec / 1000,
|
||||
.tv_nsec = (msec % 1000) * 1000000,
|
||||
};
|
||||
nanosleep(&tv, NULL);
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
/* 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 "getopt_ssnes.h"
|
||||
|
||||
#ifndef HAVE_GETOPT_LONG
|
||||
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
|
||||
char *optarg;
|
||||
int optind, opterr, optopt;
|
||||
|
||||
static bool is_short_option(const char *str)
|
||||
{
|
||||
return str[0] == '-' && str[1] != '-';
|
||||
}
|
||||
|
||||
static bool is_long_option(const char *str)
|
||||
{
|
||||
return str[0] == '-' && str[1] == '-';
|
||||
}
|
||||
|
||||
static int find_short_index(char * const *argv)
|
||||
{
|
||||
for (int index = 0; argv[index]; index++)
|
||||
{
|
||||
if (is_short_option(argv[index]))
|
||||
return index;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int find_long_index(char * const *argv)
|
||||
{
|
||||
for (int index = 0; argv[index]; index++)
|
||||
{
|
||||
if (is_long_option(argv[index]))
|
||||
return index;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int parse_short(const char *optstring, char * const *argv)
|
||||
{
|
||||
char arg = argv[0][1];
|
||||
if (arg == ':')
|
||||
return '?';
|
||||
|
||||
const char *opt = strchr(optstring, arg);
|
||||
if (!opt)
|
||||
return '?';
|
||||
|
||||
bool multiple_opt = argv[0][2];
|
||||
bool takes_arg = opt[1] == ':';
|
||||
if (multiple_opt && takes_arg) // Makes little sense to allow.
|
||||
return '?';
|
||||
|
||||
if (takes_arg)
|
||||
{
|
||||
optarg = argv[1];
|
||||
optind += 2;
|
||||
return optarg ? opt[0] : '?';
|
||||
}
|
||||
else if (multiple_opt)
|
||||
{
|
||||
memmove(&argv[0][1], &argv[0][2], strlen(&argv[0][2]) + 1);
|
||||
return opt[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
optind++;
|
||||
return opt[0];
|
||||
}
|
||||
}
|
||||
|
||||
static int parse_long(const struct option *longopts, char * const *argv)
|
||||
{
|
||||
const struct option *opt = NULL;
|
||||
for (size_t indice = 0; longopts[indice].name; indice++)
|
||||
{
|
||||
if (strcmp(longopts[indice].name, &argv[0][2]) == 0)
|
||||
{
|
||||
opt = &longopts[indice];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!opt)
|
||||
return '?';
|
||||
|
||||
// getopt_long has an "optional" arg, but we don't bother with that.
|
||||
if (opt->has_arg && !argv[1])
|
||||
return '?';
|
||||
|
||||
if (opt->has_arg)
|
||||
{
|
||||
optarg = argv[1];
|
||||
optind += 2;
|
||||
}
|
||||
else
|
||||
optind++;
|
||||
|
||||
if (opt->flag)
|
||||
{
|
||||
*opt->flag = opt->val;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return opt->val;
|
||||
}
|
||||
|
||||
static void shuffle_block(char **begin, char **last, char **end)
|
||||
{
|
||||
ptrdiff_t len = last - begin;
|
||||
const char *tmp[len];
|
||||
memcpy(tmp, begin, sizeof(tmp));
|
||||
memmove(begin, last, (end - last) * sizeof(char*));
|
||||
memcpy(end - len, tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
int getopt_long(int argc, char *argv[],
|
||||
const char *optstring, const struct option *longopts, int *longindex)
|
||||
{
|
||||
(void)longindex;
|
||||
if (argc == 1)
|
||||
return -1;
|
||||
|
||||
if (optind == 0)
|
||||
optind = 1;
|
||||
|
||||
int short_index = find_short_index(&argv[optind]);
|
||||
int long_index = find_long_index(&argv[optind]);
|
||||
|
||||
// We're done here.
|
||||
if (short_index == -1 && long_index == -1)
|
||||
return -1;
|
||||
|
||||
// Reorder argv so that non-options come last.
|
||||
// Non-POSIXy, but that's what getopt does by default.
|
||||
if ((short_index > 0) && ((short_index < long_index) || (long_index == -1)))
|
||||
{
|
||||
shuffle_block(&argv[optind], &argv[optind + short_index], &argv[argc]);
|
||||
short_index = 0;
|
||||
}
|
||||
else if ((long_index > 0) && ((long_index < short_index) || (short_index == -1)))
|
||||
{
|
||||
shuffle_block(&argv[optind], &argv[optind + long_index], &argv[argc]);
|
||||
long_index = 0;
|
||||
}
|
||||
|
||||
assert(short_index == 0 || long_index == 0);
|
||||
|
||||
if (short_index == 0)
|
||||
return parse_short(optstring, &argv[optind]);
|
||||
else if (long_index == 0)
|
||||
return parse_long(longopts, &argv[optind]);
|
||||
else
|
||||
return '?';
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/* 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_GETOPT_H
|
||||
#define __SSNES_GETOPT_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
// Custom implementation of the GNU getopt_long for portability.
|
||||
// Not designed to be fully compatible,
|
||||
// but compatible with the features SSNES uses.
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
#include <getopt.h>
|
||||
#else
|
||||
// Avoid possible naming collitions during link since we prefer to use the actual name.
|
||||
#define getopt_long(argc, argv, optstring, longopts, longindex) __getopt_long_ssnes(argc, argv, optstring, longopts, longindex)
|
||||
|
||||
struct option
|
||||
{
|
||||
const char *name;
|
||||
int has_arg;
|
||||
int *flag;
|
||||
int val;
|
||||
};
|
||||
|
||||
// argv[] is declared with char * const argv[] in GNU,
|
||||
// but this makes no sense, as non-POSIX getopt_long mutates argv (non-opts are moved to the end).
|
||||
int getopt_long(int argc, char *argv[],
|
||||
const char *optstring, const struct option *longopts, int *longindex);
|
||||
extern char *optarg;
|
||||
extern int optind, opterr, optopt;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+12
-1
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "gfx_common.h"
|
||||
#include "general.h"
|
||||
#include "../general.h"
|
||||
#include <sys/time.h>
|
||||
|
||||
static float tv_to_fps(const struct timeval *tv, const struct timeval *new_tv, int frames)
|
||||
@@ -32,6 +32,17 @@ void gfx_window_title_reset(void)
|
||||
gl_frames = 0;
|
||||
}
|
||||
|
||||
#ifdef __CELLOS_LV2__
|
||||
#include <sys/sys_time.h>
|
||||
static void gettimeofday(struct timeval *val, void *dummy)
|
||||
{
|
||||
(void)dummy;
|
||||
uint64_t usec = sys_time_get_system_time();
|
||||
val->tv_sec = usec / 1000000;
|
||||
val->tv_usec = usec % 1000000;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool gfx_window_title(char *buf, size_t size)
|
||||
{
|
||||
static struct timeval tv;
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "driver.h"
|
||||
#include "../driver.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include "libsnes.hpp"
|
||||
#include "../libsnes.hpp"
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <string.h>
|
||||
#include "general.h"
|
||||
#include "../general.h"
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include "gl_common.h"
|
||||
#include "gfx_common.h"
|
||||
#include "sdlwrap.h"
|
||||
#include "strl.h"
|
||||
#include "../strl.h"
|
||||
|
||||
#define NO_SDL_GLEXT
|
||||
#include "SDL.h"
|
||||
@@ -192,6 +192,7 @@ typedef struct gl
|
||||
char font_last_msg[256];
|
||||
int font_last_width, font_last_height;
|
||||
GLfloat font_color[16];
|
||||
GLfloat font_color_dark[16];
|
||||
#endif
|
||||
|
||||
} gl_t;
|
||||
@@ -386,6 +387,13 @@ static inline void gl_init_font(gl_t *gl, const char *font_path, unsigned font_s
|
||||
gl->font_color[4 * i + 3] = 1.0;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
{
|
||||
for (unsigned j = 0; j < 3; j++)
|
||||
gl->font_color_dark[4 * i + j] = 0.3 * gl->font_color[4 * i + j];
|
||||
gl->font_color_dark[4 * i + 3] = 1.0;
|
||||
}
|
||||
|
||||
#else
|
||||
(void)gl;
|
||||
(void)font_path;
|
||||
@@ -748,7 +756,7 @@ static void blit_fonts(gl_t *gl, const struct font_output *head, const struct fo
|
||||
}
|
||||
|
||||
static void calculate_font_coords(gl_t *gl,
|
||||
GLfloat font_vertex[8], GLfloat font_tex_coords[8])
|
||||
GLfloat font_vertex[8], GLfloat font_vertex_dark[8], GLfloat font_tex_coords[8])
|
||||
{
|
||||
GLfloat lx = g_settings.video.msg_pos_x;
|
||||
GLfloat hx = (GLfloat)gl->font_last_width / gl->vp_width + lx;
|
||||
@@ -764,6 +772,14 @@ static void calculate_font_coords(gl_t *gl,
|
||||
font_vertex[6] = hx;
|
||||
font_vertex[7] = ly;
|
||||
|
||||
GLfloat shift_x = 2.0f / gl->vp_width;
|
||||
GLfloat shift_y = 2.0f / gl->vp_height;
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
{
|
||||
font_vertex_dark[2 * i + 0] = font_vertex[2 * i + 0] - shift_x;
|
||||
font_vertex_dark[2 * i + 1] = font_vertex[2 * i + 1] - shift_y;
|
||||
}
|
||||
|
||||
lx = 0.0f;
|
||||
hx = (GLfloat)gl->font_last_width / gl->font_tex_w;
|
||||
ly = 1.0f - (GLfloat)gl->font_last_height / gl->font_tex_h;
|
||||
@@ -785,15 +801,14 @@ static void gl_render_msg(gl_t *gl, const char *msg)
|
||||
return;
|
||||
|
||||
GLfloat font_vertex[8];
|
||||
GLfloat font_vertex_dark[8];
|
||||
GLfloat font_tex_coords[8];
|
||||
|
||||
// Deactivate custom shaders. Enable the font texture.
|
||||
gl_shader_use(0);
|
||||
set_viewport(gl, gl->win_width, gl->win_height, false);
|
||||
glBindTexture(GL_TEXTURE_2D, gl->font_tex);
|
||||
glVertexPointer(2, GL_FLOAT, 0, font_vertex);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, font_tex_coords);
|
||||
glColorPointer(4, GL_FLOAT, 0, gl->font_color);
|
||||
|
||||
// Need blending.
|
||||
// Using fixed function pipeline here since we cannot guarantee presence of shaders (would be kinda overkill anyways).
|
||||
@@ -818,8 +833,13 @@ static void gl_render_msg(gl_t *gl, const char *msg)
|
||||
gl->font_last_width = geom.width;
|
||||
gl->font_last_height = geom.height;
|
||||
}
|
||||
calculate_font_coords(gl, font_vertex, font_tex_coords);
|
||||
calculate_font_coords(gl, font_vertex, font_vertex_dark, font_tex_coords);
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, 0, font_vertex_dark);
|
||||
glColorPointer(4, GL_FLOAT, 0, gl->font_color_dark);
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
glVertexPointer(2, GL_FLOAT, 0, font_vertex);
|
||||
glColorPointer(4, GL_FLOAT, 0, gl->font_color);
|
||||
glDrawArrays(GL_QUADS, 0, 4);
|
||||
|
||||
// Go back to old rendering path.
|
||||
|
||||
+7
-6
@@ -18,16 +18,20 @@
|
||||
#ifndef __GL_COMMON_H
|
||||
#define __GL_COMMON_H
|
||||
|
||||
#include "general.h"
|
||||
#include "../general.h"
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#if defined(__APPLE__)
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/glext.h>
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
#include <PSGL/psgl.h>
|
||||
#include <PSGL/psglu.h>
|
||||
#include <GLES/glext.h>
|
||||
#else
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GL/gl.h>
|
||||
@@ -57,9 +61,6 @@ static inline bool gl_check_error(void)
|
||||
case GL_OUT_OF_MEMORY:
|
||||
SSNES_ERR("GL: Out of memory. Harhar.\n");
|
||||
break;
|
||||
case GL_TABLE_TOO_LARGE:
|
||||
SSNES_ERR("GL: Table too large. Big tables scare you! :(\n");
|
||||
break;
|
||||
case GL_NO_ERROR:
|
||||
return true;
|
||||
break;
|
||||
|
||||
+3
-3
@@ -16,16 +16,16 @@
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include "image.h"
|
||||
#include "file.h"
|
||||
#include "../file.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include "general.h"
|
||||
#include "../general.h"
|
||||
|
||||
#ifdef HAVE_SDL_IMAGE
|
||||
|
||||
|
||||
+1
-1
@@ -30,5 +30,5 @@ struct texture_image
|
||||
|
||||
bool texture_image_load(const char *path, struct texture_image* img);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -161,6 +161,7 @@ static void py_set_attrs(PyObject *mod)
|
||||
DECL_ATTR_SSNES(CHEAT_TOGGLE);
|
||||
DECL_ATTR_SSNES(SCREENSHOT);
|
||||
DECL_ATTR_SSNES(DSP_CONFIG);
|
||||
DECL_ATTR_SSNES(MUTE);
|
||||
}
|
||||
|
||||
static PyModuleDef SNESModule = {
|
||||
|
||||
+6
-3
@@ -230,7 +230,7 @@ bool sdlwrap_key_pressed(int key)
|
||||
|
||||
// 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
|
||||
#if !defined(__APPLE__) && !defined(_WIN32) && !SDL_MODERN && !defined(XENON)
|
||||
static void sdlwrap_get_window_size(unsigned *width, unsigned *height)
|
||||
{
|
||||
SDL_SysWMinfo info;
|
||||
@@ -308,7 +308,7 @@ void sdlwrap_check_window(bool *quit,
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(__APPLE__) && !defined(_WIN32)
|
||||
#if !defined(__APPLE__) && !defined(_WIN32) && !defined(XENON)
|
||||
// Hack to workaround limitations in tiling WMs ...
|
||||
if (!*resize && !g_fullscreen)
|
||||
{
|
||||
@@ -328,7 +328,10 @@ void sdlwrap_check_window(bool *quit,
|
||||
|
||||
bool sdlwrap_get_wm_info(SDL_SysWMinfo *info)
|
||||
{
|
||||
#if SDL_MODERN
|
||||
#ifdef XENON
|
||||
(void)info;
|
||||
return false;
|
||||
#elif SDL_MODERN
|
||||
if (g_window)
|
||||
return SDL_GetWindowWMInfo(g_window, info);
|
||||
else
|
||||
|
||||
+11
-4
@@ -18,12 +18,12 @@
|
||||
#include "shader_cg.h"
|
||||
#include <Cg/cg.h>
|
||||
#include <Cg/cgGL.h>
|
||||
#include "general.h"
|
||||
#include "../general.h"
|
||||
#include <string.h>
|
||||
#include "strl.h"
|
||||
#include "conf/config_file.h"
|
||||
#include "../strl.h"
|
||||
#include "../conf/config_file.h"
|
||||
#include "image.h"
|
||||
#include "dynamic.h"
|
||||
#include "../dynamic.h"
|
||||
|
||||
#ifdef HAVE_CONFIGFILE
|
||||
#include "snes_state.h"
|
||||
@@ -312,7 +312,9 @@ void gl_cg_deinit(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef __CELLOS_LV2__
|
||||
cgDestroyContext(cgCtx);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define SET_LISTING_INDEX(type, index) \
|
||||
@@ -444,8 +446,10 @@ static bool load_textures(const char *dir_path, config_file_t *conf)
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, smooth ? GL_LINEAR : GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, smooth ? GL_LINEAR : GL_NEAREST);
|
||||
|
||||
#ifndef __CELLOS_LV2__
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, img.width);
|
||||
#endif
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
0, GL_RGBA, img.width, img.height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, img.pixels);
|
||||
|
||||
@@ -940,6 +944,9 @@ error:
|
||||
|
||||
bool gl_cg_init(const char *path)
|
||||
{
|
||||
#ifdef __CELLOS_LV2__
|
||||
cgRTCgcInit();
|
||||
#endif
|
||||
cgCtx = cgCreateContext();
|
||||
if (cgCtx == NULL)
|
||||
{
|
||||
|
||||
+3
-3
@@ -17,11 +17,11 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "general.h"
|
||||
#include "../general.h"
|
||||
#include "shader_glsl.h"
|
||||
#include "strl.h"
|
||||
#include "../strl.h"
|
||||
#include "snes_state.h"
|
||||
#include "dynamic.h"
|
||||
#include "../dynamic.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <OpenGL/gl.h>
|
||||
|
||||
+3
-3
@@ -18,9 +18,9 @@
|
||||
#include "snes_state.h"
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "strl.h"
|
||||
#include "general.h"
|
||||
#include <libsnes.hpp>
|
||||
#include "../strl.h"
|
||||
#include "../general.h"
|
||||
#include "../libsnes.hpp"
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
#include "py_state/py_state.h"
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@
|
||||
#include "general.h"
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <libsnes.hpp>
|
||||
#include "../libsnes.hpp"
|
||||
#include "ssnes_sdl_input.h"
|
||||
#include "keysym.h"
|
||||
|
||||
|
||||
+32
-8
@@ -67,14 +67,38 @@ extern "C" {
|
||||
#define SNES_MEMORY_CGRAM 104
|
||||
|
||||
// SSNES extension. Not required to be implemented for a working implementation.
|
||||
#define SNES_ENVIRONMENT_GET_FULLPATH 0 // const char ** -- Full path of game loaded.
|
||||
#define SNES_ENVIRONMENT_SET_GEOMETRY 1 // const struct snes_geometry * -- Window geometry information for the system/game.
|
||||
#define SNES_ENVIRONMENT_SET_PITCH 2 // const unsigned * -- Pitch of game image.
|
||||
#define SNES_ENVIRONMENT_GET_OVERSCAN 3 // bool * -- Boolean value whether or not the implementation should use overscan.
|
||||
#define SNES_ENVIRONMENT_SET_TIMING 4 // const struct snes_system_timing * -- Set exact timings of the system.
|
||||
// Used primarily for video recording.
|
||||
#define SNES_ENVIRONMENT_GET_CAN_DUPE 5 // bool * -- Boolean value whether or not SSNES supports frame duping,
|
||||
// passing NULL to video frame callback.
|
||||
#define SNES_ENVIRONMENT_GET_FULLPATH 0 // const char ** --
|
||||
// Full path of game loaded.
|
||||
//
|
||||
#define SNES_ENVIRONMENT_SET_GEOMETRY 1 // const struct snes_geometry * --
|
||||
// Window geometry information for the system/game.
|
||||
//
|
||||
#define SNES_ENVIRONMENT_SET_PITCH 2 // const unsigned * --
|
||||
// Pitch of game image.
|
||||
//
|
||||
#define SNES_ENVIRONMENT_GET_OVERSCAN 3 // bool * --
|
||||
// Boolean value whether or not the implementation should use overscan.
|
||||
//
|
||||
#define SNES_ENVIRONMENT_SET_TIMING 4 // const struct snes_system_timing * --
|
||||
// Set exact timings of the system. Used primarily for video recording.
|
||||
//
|
||||
#define SNES_ENVIRONMENT_GET_CAN_DUPE 5 // bool * --
|
||||
// Boolean value whether or not SSNES supports frame duping,
|
||||
// passing NULL to video frame callback.
|
||||
//
|
||||
//
|
||||
#define SNES_ENVIRONMENT_SET_NEED_FULLPATH 6 // const bool * --
|
||||
// Boolean value telling if implementation needs a valid fullpath to be able to run.
|
||||
// If this is the case, SSNES will not open the rom directly,
|
||||
// and pass NULL to rom data.
|
||||
// Implementation must then use SNES_ENVIRONMENT_GET_FULLPATH.
|
||||
// This is useful for implementations with very large roms,
|
||||
// which are impractical to load fully into RAM.
|
||||
//
|
||||
#define SNES_ENVIRONMENT_GET_CAN_REWIND 7 // bool * --
|
||||
// Boolean value telling if SSNES is able to rewind.
|
||||
// Some implementations might need to take extra precautions
|
||||
// to allow this as smoothly as possible.
|
||||
|
||||
struct snes_geometry
|
||||
{
|
||||
|
||||
@@ -115,6 +115,14 @@ static inline uint32_t swap_if_big32(uint32_t val)
|
||||
return (val >> 24) | ((val >> 8) & 0xFF00) | ((val << 8) & 0xFF0000) | (val << 24);
|
||||
}
|
||||
|
||||
static inline uint32_t swap_if_little32(uint32_t val)
|
||||
{
|
||||
if (!is_little_endian()) // Big-endian
|
||||
return val;
|
||||
else
|
||||
return (val >> 24) | ((val >> 8) & 0xFF00) | ((val << 8) & 0xFF0000) | (val << 24);
|
||||
}
|
||||
|
||||
static inline uint16_t swap_if_big16(uint16_t val)
|
||||
{
|
||||
if (is_little_endian())
|
||||
@@ -140,7 +148,8 @@ static bool init_playback(bsv_movie_t *handle, const char *path)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (swap_if_big32(header[MAGIC_INDEX]) != BSV_MAGIC)
|
||||
// Compatibility with old implementation that used incorrect documentation.
|
||||
if (swap_if_little32(header[MAGIC_INDEX]) != BSV_MAGIC && swap_if_big32(header[MAGIC_INDEX]) != BSV_MAGIC)
|
||||
{
|
||||
SSNES_ERR("Movie file is not a valid BSV1 file!\n");
|
||||
return false;
|
||||
@@ -192,7 +201,10 @@ static bool init_record(bsv_movie_t *handle, const char *path)
|
||||
}
|
||||
|
||||
uint32_t header[4] = {0};
|
||||
header[MAGIC_INDEX] = swap_if_big32(BSV_MAGIC);
|
||||
|
||||
// This value is supposed to show up as BSV1 in a HEX editor.
|
||||
header[MAGIC_INDEX] = swap_if_little32(BSV_MAGIC);
|
||||
|
||||
header[CRC_INDEX] = swap_if_big32(g_extern.cart_crc);
|
||||
|
||||
uint32_t state_size = psnes_serialize_size();
|
||||
|
||||
@@ -735,9 +735,13 @@ void netplay_post_frame(netplay_t *handle)
|
||||
while (first || (handle->tmp_ptr != handle->self_ptr))
|
||||
{
|
||||
psnes_serialize(handle->buffer[handle->tmp_ptr].state, handle->state_size);
|
||||
#ifdef HAVE_THREADS
|
||||
lock_autosave();
|
||||
#endif
|
||||
psnes_run();
|
||||
#ifdef HAVE_THREADS
|
||||
unlock_autosave();
|
||||
#endif
|
||||
handle->tmp_ptr = NEXT_PTR(handle->tmp_ptr);
|
||||
first = false;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <libsnes.hpp>
|
||||
#include "libsnes.hpp"
|
||||
|
||||
void input_poll_net(void);
|
||||
int16_t input_state_net(bool port, unsigned device, unsigned index, unsigned id);
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
|
||||
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011 - Daniel De Matteis
|
||||
*
|
||||
* 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 <sys/process.h>
|
||||
#include <sysutil/sysutil_common.h>
|
||||
#include <sys/spu_initialize.h>
|
||||
#include <stddef.h>
|
||||
|
||||
int ssnes_main(int argc, char *argv[]);
|
||||
|
||||
SYS_PROCESS_PARAM(1001, 0x100000)
|
||||
|
||||
#undef main
|
||||
// Temporary, a more sane implementation should go here.
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
sys_spu_initialize(4, 3);
|
||||
char arg1[] = "ssnes";
|
||||
char arg2[] = "/dev_hdd0/game/SNES90000/USRDIR/main.sfc";
|
||||
char arg3[] = "-v";
|
||||
char arg4[] = "-c";
|
||||
char arg5[] = "/dev_hdd0/game/SSNE10000/USRDIR/ssnes.cfg";
|
||||
char *argv_[] = { arg1, arg2, arg3, arg4, arg5, NULL };
|
||||
return ssnes_main(sizeof(argv_) / sizeof(argv_[0]) - 1, argv_);
|
||||
}
|
||||
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
|
||||
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011 - Daniel De Matteis
|
||||
*
|
||||
* 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 <cell/pad.h>
|
||||
#include <sdk_version.h>
|
||||
#include "pad_input.h"
|
||||
|
||||
#define LOWER_BUTTONS 2
|
||||
#define HIGHER_BUTTONS 3
|
||||
#define RSTICK_X 4
|
||||
#define RSTICK_Y 5
|
||||
#define LSTICK_X 6
|
||||
#define LSTICK_Y 7
|
||||
|
||||
#define DEADZONE_LOW 55
|
||||
#define DEADZONE_HIGH 210
|
||||
|
||||
#define PRESSED_LEFT_LSTICK(state) (CTRL_AXIS_LSTICK_X(state) <= DEADZONE_LOW)
|
||||
#define PRESSED_RIGHT_LSTICK(state) (CTRL_AXIS_LSTICK_X(state) >= DEADZONE_HIGH)
|
||||
#define PRESSED_UP_LSTICK(state) (CTRL_AXIS_LSTICK_Y(state) <= DEADZONE_LOW)
|
||||
#define PRESSED_DOWN_LSTICK(state) (CTRL_AXIS_LSTICK_Y(state) >= DEADZONE_HIGH)
|
||||
#define PRESSED_LEFT_RSTICK(state) (CTRL_AXIS_RSTICK_X(state) <= DEADZONE_LOW)
|
||||
#define PRESSED_RIGHT_RSTICK(state) (CTRL_AXIS_RSTICK_X(state) >= DEADZONE_HIGH)
|
||||
#define PRESSED_UP_RSTICK(state) (CTRL_AXIS_RSTICK_Y(state) <= DEADZONE_LOW)
|
||||
#define PRESSED_DOWN_RSTICK(state) (CTRL_AXIS_RSTICK_Y(state) >= DEADZONE_HIGH)
|
||||
|
||||
#define LSTICK_LEFT_SHIFT 48
|
||||
#define LSTICK_RIGHT_SHIFT 49
|
||||
#define LSTICK_UP_SHIFT 50
|
||||
#define LSTICK_DOWN_SHIFT 51
|
||||
|
||||
#define RSTICK_LEFT_SHIFT 52
|
||||
#define RSTICK_RIGHT_SHIFT 53
|
||||
#define RSTICK_UP_SHIFT 54
|
||||
#define RSTICK_DOWN_SHIFT 55
|
||||
|
||||
int cell_pad_input_init(void)
|
||||
{
|
||||
return cellPadInit(MAX_PADS);
|
||||
}
|
||||
|
||||
void cell_pad_input_deinit(void)
|
||||
{
|
||||
cellPadEnd();
|
||||
}
|
||||
|
||||
uint32_t cell_pad_input_pads_connected(void)
|
||||
{
|
||||
#if(CELL_SDK_VERSION > 0x340000)
|
||||
CellPadInfo2 pad_info;
|
||||
cellPadGetInfo2(&pad_info);
|
||||
#else
|
||||
CellPadInfo pad_info;
|
||||
cellPadGetInfo(&pad_info);
|
||||
#endif
|
||||
return pad_info.now_connect;
|
||||
}
|
||||
|
||||
#define M(x) (x & 0xFF)
|
||||
|
||||
uint64_t cell_pad_input_poll_device(uint32_t id)
|
||||
{
|
||||
CellPadData pad_data;
|
||||
static uint64_t ret[MAX_PADS];
|
||||
|
||||
// Get new pad data
|
||||
cellPadGetData(id, &pad_data);
|
||||
|
||||
if (pad_data.len == 0)
|
||||
return ret[id];
|
||||
else
|
||||
{
|
||||
ret[id] = 0;
|
||||
|
||||
// Build the return value.
|
||||
ret[id] |= (uint64_t)M(pad_data.button[LOWER_BUTTONS]);
|
||||
ret[id] |= (uint64_t)M(pad_data.button[HIGHER_BUTTONS]) << 8;
|
||||
ret[id] |= (uint64_t)M(pad_data.button[RSTICK_X]) << 32;
|
||||
ret[id] |= (uint64_t)M(pad_data.button[RSTICK_Y]) << 40;
|
||||
ret[id] |= (uint64_t)M(pad_data.button[LSTICK_X]) << 16;
|
||||
ret[id] |= (uint64_t)M(pad_data.button[LSTICK_Y]) << 24;
|
||||
|
||||
ret[id] |= (uint64_t)(PRESSED_LEFT_LSTICK(ret[id]) ? 1 : 0) << LSTICK_LEFT_SHIFT;
|
||||
ret[id] |= (uint64_t)(PRESSED_RIGHT_LSTICK(ret[id]) ? 1 : 0) << LSTICK_RIGHT_SHIFT;
|
||||
ret[id] |= (uint64_t)(PRESSED_UP_LSTICK(ret[id]) ? 1 : 0) << LSTICK_UP_SHIFT;
|
||||
ret[id] |= (uint64_t)(PRESSED_DOWN_LSTICK(ret[id]) ? 1 : 0) << LSTICK_DOWN_SHIFT;
|
||||
|
||||
ret[id] |= (uint64_t)(PRESSED_LEFT_RSTICK(ret[id]) ? 1 : 0) << RSTICK_LEFT_SHIFT;
|
||||
ret[id] |= (uint64_t)(PRESSED_RIGHT_RSTICK(ret[id]) ? 1 : 0) << RSTICK_RIGHT_SHIFT;
|
||||
ret[id] |= (uint64_t)(PRESSED_UP_RSTICK(ret[id]) ? 1 : 0) << RSTICK_UP_SHIFT;
|
||||
ret[id] |= (uint64_t)(PRESSED_DOWN_RSTICK(ret[id]) ? 1 : 0) << RSTICK_DOWN_SHIFT;
|
||||
return ret[id];
|
||||
}
|
||||
}
|
||||
#undef M
|
||||
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
|
||||
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011 - Daniel De Matteis
|
||||
*
|
||||
* 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 __CELL_PAD_INPUT_H
|
||||
#define __CELL_PAD_INPUT_H
|
||||
|
||||
#define MAX_PADS 7
|
||||
|
||||
#define CTRL_SELECT_MASK 0x01
|
||||
#define CTRL_L3_MASK 0x2
|
||||
#define CTRL_R3_MASK 0x4
|
||||
#define CTRL_START_MASK 0x8
|
||||
#define CTRL_UP_MASK 0x10
|
||||
#define CTRL_RIGHT_MASK 0x20
|
||||
#define CTRL_DOWN_MASK 0x40
|
||||
#define CTRL_LEFT_MASK 0x80
|
||||
|
||||
#define CTRL_L2_MASK 0x100
|
||||
#define CTRL_R2_MASK 0x200
|
||||
#define CTRL_L1_MASK 0x400
|
||||
#define CTRL_R1_MASK 0x800
|
||||
#define CTRL_TRIANGLE_MASK 0x1000
|
||||
#define CTRL_CIRCLE_MASK 0x2000
|
||||
#define CTRL_CROSS_MASK 0x4000
|
||||
#define CTRL_SQUARE_MASK 0x8000
|
||||
|
||||
// Big numbers, harhar.
|
||||
#define CTRL_LSTICK_LEFT_MASK 0x1000000000000LLU
|
||||
#define CTRL_LSTICK_RIGHT_MASK 0x2000000000000LLU
|
||||
#define CTRL_LSTICK_UP_MASK 0x4000000000000LLU
|
||||
#define CTRL_LSTICK_DOWN_MASK 0x8000000000000LLU
|
||||
#define CTRL_RSTICK_LEFT_MASK 0x10000000000000LLU
|
||||
#define CTRL_RSTICK_RIGHT_MASK 0x20000000000000LLU
|
||||
#define CTRL_RSTICK_UP_MASK 0x40000000000000LLU
|
||||
#define CTRL_RSTICK_DOWN_MASK 0x80000000000000LLU
|
||||
|
||||
|
||||
#define CTRL_SELECT(state) (CTRL_SELECT_MASK & state)
|
||||
#define CTRL_L3(state) (CTRL_L3_MASK & state)
|
||||
#define CTRL_R3(state) (CTRL_R3_MASK & state)
|
||||
#define CTRL_START(state) (CTRL_START_MASK & state)
|
||||
#define CTRL_UP(state) (CTRL_UP_MASK & state)
|
||||
#define CTRL_RIGHT(state) (CTRL_RIGHT_MASK & state)
|
||||
#define CTRL_DOWN(state) (CTRL_DOWN_MASK & state)
|
||||
#define CTRL_LEFT(state) (CTRL_LEFT_MASK & state)
|
||||
|
||||
#define CTRL_L2(state) (CTRL_L2_MASK & state)
|
||||
#define CTRL_R2(state) (CTRL_R2_MASK & state)
|
||||
#define CTRL_L1(state) (CTRL_L1_MASK & state)
|
||||
#define CTRL_R1(state) (CTRL_R1_MASK & state)
|
||||
#define CTRL_TRIANGLE(state) (CTRL_TRIANGLE_MASK & state)
|
||||
#define CTRL_CIRCLE(state) (CTRL_CIRCLE_MASK & state)
|
||||
#define CTRL_CROSS(state) (CTRL_CROSS_MASK & state)
|
||||
#define CTRL_SQUARE(state) (CTRL_SQUARE_MASK & state)
|
||||
|
||||
#define CTRL_LSTICK_LEFT(state) (CTRL_LSTICK_LEFT_MASK & state)
|
||||
#define CTRL_LSTICK_RIGHT(state) (CTRL_LSTICK_RIGHT_MASK & state)
|
||||
#define CTRL_LSTICK_UP(state) (CTRL_LSTICK_UP_MASK & state)
|
||||
#define CTRL_LSTICK_DOWN(state) (CTRL_LSTICK_DOWN_MASK & state)
|
||||
#define CTRL_RSTICK_LEFT(state) (CTRL_RSTICK_LEFT_MASK & state)
|
||||
#define CTRL_RSTICK_RIGHT(state) (CTRL_RSTICK_RIGHT_MASK & state)
|
||||
#define CTRL_RSTICK_UP(state) (CTRL_RSTICK_UP_MASK & state)
|
||||
#define CTRL_RSTICK_DOWN(state) (CTRL_RSTICK_DOWN_MASK & state)
|
||||
|
||||
#define CTRL_MASK(state, mask) (state & mask)
|
||||
|
||||
#define CTRL_AXIS_LSTICK_X(state) ((uint8_t)(((0xFF0000LLU & state) >> 16) & 0xFF))
|
||||
#define CTRL_AXIS_LSTICK_Y(state) ((uint8_t)(((0xFF000000LLU & state) >> 24) & 0xFF))
|
||||
#define CTRL_AXIS_RSTICK_X(state) ((uint8_t)(((0xFF00000000LLU & state) >> 32) & 0xFF))
|
||||
#define CTRL_AXIS_RSTICK_Y(state) ((uint8_t)(((0xFF0000000000LLU & state) >> 40) & 0xFF))
|
||||
|
||||
typedef uint64_t cell_input_state_t;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Init and destruction of device.
|
||||
int cell_pad_input_init(void);
|
||||
void cell_pad_input_deinit(void);
|
||||
|
||||
// Get number of pads connected
|
||||
uint32_t cell_pad_input_pads_connected(void);
|
||||
|
||||
cell_input_state_t cell_pad_input_poll_device(uint32_t id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
Binary file not shown.
Whitespace-only changes.
@@ -0,0 +1,335 @@
|
||||
##### Config file for SSNES
|
||||
|
||||
# Save all save files (*.srm) to this directory. This includes related files like .bsv, .rtc, .psrm, etc ...
|
||||
# This will be overridden by explicit command line options.
|
||||
# savefile_directory =
|
||||
|
||||
# Save all save states (*.state) to this directory.
|
||||
# This will be overridden by explicit command line options.
|
||||
# savestate_directory =
|
||||
|
||||
## If enabled, load libsnes from a dynamic location.
|
||||
# libsnes_path = "/path/to/libsnes.so"
|
||||
|
||||
#### Video
|
||||
|
||||
# Video driver to use. "gl", "xvideo", "sdl" or "ext" (external API driver)
|
||||
# video_driver = "gl"
|
||||
|
||||
# Path to external video driver using the SSNES driver API.
|
||||
# video_external_driver =
|
||||
|
||||
# Windowed xscale and yscale
|
||||
# (Real x res: base_size * xscale * aspect_ratio, real y res: base_size * yscale)
|
||||
# video_xscale = 3.0
|
||||
# video_yscale = 3.0
|
||||
|
||||
# Fullscreen resolution. Resolution of 0 uses the resolution of the desktop.
|
||||
# video_fullscreen_x = 0
|
||||
# video_fullscreen_y = 0
|
||||
|
||||
# Start in fullscreen. Can be changed at runtime.
|
||||
# video_fullscreen = false
|
||||
|
||||
# Force 16-bit colors. Apparently some video cards in use today have troubles with 32-bit ...
|
||||
# video_force_16bit = false
|
||||
|
||||
# Forcibly disable composition. Only works in Windows Vista/7 for now.
|
||||
# video_disable_composition = false
|
||||
|
||||
# Video vsync.
|
||||
# video_vsync = true
|
||||
|
||||
# Smoothens picture with bilinear filtering. Should be disabled if using pixel shaders.
|
||||
# video_smooth = true
|
||||
|
||||
# Forces rendering area to stay equal to SNES aspect ratio 4:3 or as defined in video_aspect_ratio.
|
||||
# video_force_aspect = true
|
||||
|
||||
# A floating point value for video aspect ratio (width / height)
|
||||
# video_aspect_ratio = 1.333
|
||||
|
||||
# Forces cropping of overscanned frames. Crops away top 7 scanlines and 8 bottom scanlines. (15/15 for interlaced frames).
|
||||
# video_crop_overscan = false
|
||||
|
||||
# Path to Cg shader.
|
||||
# video_cg_shader = "/path/to/cg/shader.cg"
|
||||
|
||||
# Path to bSNES XML shader (GLSL only). If both Cg shader path and XML shader path are defined,
|
||||
# Cg shader will take priority unless overridden in video_shader_type.
|
||||
# video_bsnes_shader = "/path/to/bsnes/xml/shader.shader"
|
||||
|
||||
# Which shader type to use. Valid values are "cg", "bsnes", "none" and "auto"
|
||||
# video_shader_type = auto
|
||||
|
||||
# Defines a directory where XML shaders are kept.
|
||||
# video_shader_dir =
|
||||
|
||||
# Render to texture first. Useful when doing multi-pass shaders or control the output of shaders better.
|
||||
# video_render_to_texture = false
|
||||
|
||||
# Defines the video scale of render-to-texture.
|
||||
# The output FBO size is scaled by these amounts against the input size (typically 256 * 224 for SNES).
|
||||
# video_fbo_scale_x = 2.0
|
||||
# video_fbo_scale_y = 2.0
|
||||
|
||||
# Define shader to use for second pass (needs render-to-texture).
|
||||
# video_second_pass_shader = "/path/to/second/shader.{cg,shader}"
|
||||
|
||||
# Defines if bilinear filtering is used during second pass (needs render-to-texture).
|
||||
# video_second_pass_smooth = true
|
||||
|
||||
# CPU-based filter. Path to a bSNES CPU filter (*.filter)
|
||||
# video_filter =
|
||||
|
||||
# Path to a TTF font used for rendering messages. This path must be defined to enable fonts.
|
||||
# Do note that the _full_ path of the font is necessary!
|
||||
# video_font_path =
|
||||
|
||||
# Size of the TTF font rendered.
|
||||
# video_font_size = 48
|
||||
|
||||
# Enable usage of OSD messages.
|
||||
# video_font_enable = true
|
||||
|
||||
# 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_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
|
||||
|
||||
# Video refresh rate of your monitor.
|
||||
# Used to calculate a suitable audio input rate.
|
||||
# video_refresh_rate = 59.95
|
||||
|
||||
#### Audio
|
||||
|
||||
# Enable audio.
|
||||
# audio_enable = true
|
||||
|
||||
# Audio output samplerate.
|
||||
# audio_out_rate = 48000
|
||||
|
||||
# When altering audio_in_rate on-the-fly, define by how much each time.
|
||||
# audio_rate_step = 0.25
|
||||
|
||||
# Audio driver backend. Depending on configuration possible candidates are: alsa, pulse, oss, jack, rsound, roar, openal, sdl, xaudio and ext (external driver).
|
||||
# audio_driver =
|
||||
|
||||
# Path to external audio driver using the SSNES audio driver API.
|
||||
# audio_external_driver =
|
||||
|
||||
# Override the default audio device the audio_driver uses. This is driver dependant. E.g. ALSA wants a PCM device, OSS wants a path (e.g. /dev/dsp), Jack wants portnames (e.g. system:playback1,system:playback_2), and so on ...
|
||||
# audio_device =
|
||||
|
||||
# External DSP plugin that processes audio before it's sent to the driver.
|
||||
# audio_dsp_plugin =
|
||||
|
||||
# Will sync (block) on audio. Recommended.
|
||||
# audio_sync = true
|
||||
|
||||
# Desired audio latency in milliseconds. Might not be honored if driver can't provide given latency.
|
||||
# audio_latency = 64
|
||||
|
||||
|
||||
### Input
|
||||
|
||||
# Input driver. Depending on video driver, it might force a different input driver.
|
||||
# input_driver = sdl
|
||||
|
||||
# Defines axis threshold. Possible values are [0.0, 1.0]
|
||||
# input_axis_threshold = 0.5
|
||||
|
||||
# Keyboard input. Will recognize normal keypresses and special keys like "left", "right", and so on.
|
||||
# Keyboard input, Joypad and Joyaxis will all obey the "nul" bind, which disables the bind completely,
|
||||
# rather than relying on a default.
|
||||
# input_player1_a = x
|
||||
# input_player1_b = z
|
||||
# input_player1_y = a
|
||||
# input_player1_x = s
|
||||
# input_player1_start = enter
|
||||
# input_player1_select = rshift
|
||||
# input_player1_l = q
|
||||
# input_player1_r = w
|
||||
# input_player1_left = left
|
||||
# input_player1_right = right
|
||||
# input_player1_up = up
|
||||
# input_player1_down = down
|
||||
|
||||
# If desired, it is possible to override which joypads are being used for player 1 through 5. First joypad available is 0.
|
||||
# input_player1_joypad_index = 0
|
||||
# input_player2_joypad_index = 1
|
||||
# input_player3_joypad_index = 2
|
||||
# input_player4_joypad_index = 3
|
||||
# input_player5_joypad_index = 4
|
||||
|
||||
# Joypad buttons. Figure these out by looking at jstest /dev/input/js0 output, or use ssnes-joyconfig.
|
||||
# You can use joypad hats with hnxx, where n is the hat, and xx is a string representing direction.
|
||||
# E.g. "h0up"
|
||||
# input_player1_a_btn = 1
|
||||
# input_player1_b_btn = 0
|
||||
# input_player1_y_btn = 2
|
||||
# input_player1_x_btn = 3
|
||||
# input_player1_start_btn = 7
|
||||
# input_player1_select_btn = 6
|
||||
# input_player1_l_btn = 4
|
||||
# input_player1_r_btn = 5
|
||||
# input_player1_left_btn = 11
|
||||
# input_player1_right_btn = 12
|
||||
# input_player1_up_btn = 13
|
||||
# input_player1_down_btn = 14
|
||||
|
||||
# Axis for SNES DPAD.
|
||||
# Needs to be either '+' or '-' in the first character signaling either positive or negative direction of the axis, then the axis number.
|
||||
# Do note that every other input option has the corresponding _btn and _axis binds as well; they are omitted here for clarity.
|
||||
# input_player1_left_axis = -0
|
||||
# input_player1_right_axis = +0
|
||||
# input_player1_up_axis = +1
|
||||
# input_player1_down_axis = -1
|
||||
|
||||
# Same stuff, just for player two.
|
||||
# input_player2_a =
|
||||
# input_player2_b =
|
||||
# input_player2_y =
|
||||
# input_player2_x =
|
||||
# input_player2_start =
|
||||
# input_player2_select =
|
||||
# input_player2_l =
|
||||
# input_player2_r =
|
||||
# input_player2_left =
|
||||
# input_player2_right =
|
||||
# input_player2_up =
|
||||
# input_player2_down =
|
||||
|
||||
# input_player2_a_btn = 1
|
||||
# input_player2_b_btn = 0
|
||||
# input_player2_y_btn = 2
|
||||
# input_player2_x_btn = 3
|
||||
# input_player2_start_btn = 7
|
||||
# input_player2_select_btn = 6
|
||||
# input_player2_l_btn = 4
|
||||
# input_player2_r_btn = 5
|
||||
# input_player2_left_btn = 11
|
||||
# input_player2_right_btn = 12
|
||||
# input_player2_up_btn = 13
|
||||
# input_player2_down_btn = 14
|
||||
|
||||
|
||||
# input_player2_left_axis = -0
|
||||
# input_player2_right_axis = +0
|
||||
# input_player2_up_axis = -1
|
||||
# input_player2_down_axis = +1
|
||||
|
||||
# This goes all the way to player 5, but again omitted for clarity.
|
||||
|
||||
# Toggles fullscreen.
|
||||
# input_toggle_fullscreen = f
|
||||
# Saves state.
|
||||
# input_save_state = f2
|
||||
# Loads state.
|
||||
# input_load_state = f4
|
||||
|
||||
# State slots. With slot set to 0, save state name is *.state (or whatever defined on commandline).
|
||||
# When slot is != 0, path will be $path%d, where %d is slot number.
|
||||
# input_state_slot_increase = f7
|
||||
# input_state_slot_decrease = f6
|
||||
|
||||
# Toggles between fast-forwarding and normal speed.
|
||||
# input_toggle_fast_forward = space
|
||||
|
||||
# Hold for fast-forward. Releasing button disables fast-forward.
|
||||
# input_hold_fast_forward = l
|
||||
|
||||
# Key to exit emulator cleanly.
|
||||
# Killing it in any hard way (SIGTERM, SIGKILL, etc, will terminate emulator without saving RAM, etc.)
|
||||
# input_exit_emulator = escape
|
||||
|
||||
# Decrease/increase input sample rate on the fly. Amount to decrease/increase is defined by audio_rate_step.
|
||||
# input_rate_step_up = kp_plus
|
||||
# input_rate_step_down = kp_minus
|
||||
|
||||
# Applies next and previous XML shader in directory.
|
||||
# input_shader_next = m
|
||||
# input_shader_prev = n
|
||||
|
||||
# Enable rewinding. This will take a performance hit when playing, so it is disabled by default.
|
||||
# Do note that rewinding will only work properly when using bSNES libsnes core atm.
|
||||
# rewind_enable = true
|
||||
|
||||
# Rewinding buffer size in megabytes. Bigger rewinding buffer means you can rewind longer.
|
||||
# The buffer should be approx. 20MB per minute of buffer time.
|
||||
# rewind_buffer_size = 20
|
||||
|
||||
# Rewind granularity. When rewinding defined number of frames, you can rewind several frames at a time, increasing the rewinding speed.
|
||||
# rewind_granularity = 1
|
||||
|
||||
# Hold button down to rewind. Rewinding must be enabled.
|
||||
# input_rewind = r
|
||||
|
||||
# Toggle between recording and not.
|
||||
# input_movie_record_toggle = o
|
||||
|
||||
# Toggle between paused and non-paused state
|
||||
# input_pause_toggle = p
|
||||
|
||||
# Frame advance when game is paused
|
||||
# input_frame_advance = k
|
||||
|
||||
# Reset the emulated SNES.
|
||||
# input_reset = h
|
||||
|
||||
# Configures DSP plugin
|
||||
# input_dsp_config = c
|
||||
|
||||
# Pause gameplay when window focus is lost.
|
||||
# pause_nonactive = true
|
||||
|
||||
# Autosaves the non-volatile SRAM at a regular interval. This is disabled by default unless set otherwise.
|
||||
# The interval is measured in seconds. A value of 0 disables autosave.
|
||||
# autosave_interval =
|
||||
|
||||
# When being client over netplay, use keybinds for player 1.
|
||||
# netplay_client_swap_input = false
|
||||
|
||||
|
||||
# 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
|
||||
# input_cheat_toggle = u
|
||||
|
||||
# Mute/unmute audio
|
||||
# input_audio_mute = f9
|
||||
|
||||
# Take screenshot
|
||||
# input_screenshot = print_screen
|
||||
|
||||
# Directory to dump screenshots to.
|
||||
# screenshot_directory =
|
||||
|
||||
# Records video assuming video is hi-res.
|
||||
# video_hires_record = false
|
||||
|
||||
# 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
|
||||
|
||||
# When saving a savestate, save state index is automatically increased before
|
||||
# it is saved.
|
||||
# Also, when loading a ROM, the index will be set to the highest existing index.
|
||||
# There is no upper bound on the index.
|
||||
# savestate_auto_index = false
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
Content-ID = UP0001-SSNE10000_00-0000000000000001
|
||||
k_licensee = 0x00000000000000000000000000000000
|
||||
DRM_Type = Local
|
||||
Content_Type = Game_Exec
|
||||
PackageVersion = 00.01
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
/* SSNES - A Super Ninteno Entertainment System (SNES) Emulator frontend for libsnes.
|
||||
* Copyright (C) 2010 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011 - Daniel De Matteis
|
||||
*
|
||||
* 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 "../driver.h"
|
||||
#include "../general.h"
|
||||
#include <stdlib.h>
|
||||
#include <cell/audio.h>
|
||||
#include <sys/timer.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/synchronization.h>
|
||||
#include "../fifo_buffer.h"
|
||||
#include <sys/event.h>
|
||||
|
||||
#define AUDIO_BLOCKS 8 // 8 or 16. Guess what we choose? :)
|
||||
#define AUDIO_CHANNELS 2 // All hail glorious stereo!
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t audio_port;
|
||||
bool nonblocking;
|
||||
volatile bool quit_thread;
|
||||
fifo_buffer_t *buffer;
|
||||
|
||||
pthread_t thread;
|
||||
sys_lwmutex_t lock;
|
||||
sys_lwmutex_t cond_lock;
|
||||
sys_lwcond_t cond;
|
||||
} ps3_audio_t;
|
||||
|
||||
static void *event_loop(void *data)
|
||||
{
|
||||
ps3_audio_t *aud = data;
|
||||
sys_event_queue_t id;
|
||||
sys_ipc_key_t key;
|
||||
sys_event_t event;
|
||||
|
||||
cellAudioCreateNotifyEventQueue(&id, &key);
|
||||
cellAudioSetNotifyEventQueue(key);
|
||||
|
||||
float out_tmp[CELL_AUDIO_BLOCK_SAMPLES * AUDIO_CHANNELS] __attribute__((aligned(16)));
|
||||
|
||||
while (!aud->quit_thread)
|
||||
{
|
||||
sys_event_queue_receive(id, &event, SYS_NO_TIMEOUT);
|
||||
|
||||
sys_lwmutex_lock(&aud->lock, SYS_NO_TIMEOUT);
|
||||
if (fifo_read_avail(aud->buffer) >= sizeof(out_tmp))
|
||||
fifo_read(aud->buffer, out_tmp, sizeof(out_tmp));
|
||||
else
|
||||
memset(out_tmp, 0, sizeof(out_tmp));
|
||||
sys_lwmutex_unlock(&aud->lock);
|
||||
sys_lwcond_signal(&aud->cond);
|
||||
|
||||
cellAudioAddData(aud->audio_port, out_tmp, CELL_AUDIO_BLOCK_SAMPLES, 1.0);
|
||||
}
|
||||
|
||||
cellAudioRemoveNotifyEventQueue(key);
|
||||
pthread_exit(NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *ps3_audio_init(const char *device, unsigned rate, unsigned latency)
|
||||
{
|
||||
(void)latency;
|
||||
(void)device;
|
||||
(void)rate; // Always use 48kHz.
|
||||
g_settings.audio.out_rate = 48000.0;
|
||||
|
||||
ps3_audio_t *data = calloc(1, sizeof(*data));
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
CellAudioPortParam params;
|
||||
cellAudioInit();
|
||||
params.nChannel = AUDIO_CHANNELS;
|
||||
params.nBlock = AUDIO_BLOCKS;
|
||||
params.attr = 0;
|
||||
|
||||
if (cellAudioPortOpen(¶ms, &data->audio_port) != CELL_OK)
|
||||
{
|
||||
cellAudioQuit();
|
||||
free(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data->buffer = fifo_new(CELL_AUDIO_BLOCK_SAMPLES * AUDIO_CHANNELS * AUDIO_BLOCKS * sizeof(float));
|
||||
|
||||
sys_lwmutex_attribute_t lock_attr, cond_lock_attr;
|
||||
sys_lwcond_attribute_t cond_attr;
|
||||
|
||||
sys_lwmutex_attribute_initialize(lock_attr);
|
||||
sys_lwmutex_attribute_initialize(cond_lock_attr);
|
||||
sys_lwcond_attribute_initialize(cond_attr);
|
||||
|
||||
sys_lwmutex_create(&data->lock, &lock_attr);
|
||||
sys_lwmutex_create(&data->cond_lock, &cond_lock_attr);
|
||||
sys_lwcond_create(&data->cond, &data->cond_lock, &cond_attr);
|
||||
|
||||
cellAudioPortStart(data->audio_port);
|
||||
pthread_create(&data->thread, NULL, event_loop, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
static ssize_t ps3_audio_write(void *data, const void *buf, size_t size)
|
||||
{
|
||||
ps3_audio_t *aud = data;
|
||||
|
||||
if (aud->nonblocking)
|
||||
{
|
||||
if (fifo_write_avail(aud->buffer) < size)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (fifo_write_avail(aud->buffer) < size)
|
||||
sys_lwcond_wait(&aud->cond, 0);
|
||||
}
|
||||
|
||||
sys_lwmutex_lock(&aud->lock, SYS_NO_TIMEOUT);
|
||||
fifo_write(aud->buffer, buf, size);
|
||||
sys_lwmutex_unlock(&aud->lock);
|
||||
return size;
|
||||
}
|
||||
|
||||
static bool ps3_audio_stop(void *data)
|
||||
{
|
||||
ps3_audio_t *aud = data;
|
||||
cellAudioPortStop(aud->audio_port);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ps3_audio_start(void *data)
|
||||
{
|
||||
ps3_audio_t *aud = data;
|
||||
cellAudioPortStart(aud->audio_port);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ps3_audio_set_nonblock_state(void *data, bool state)
|
||||
{
|
||||
ps3_audio_t *aud = data;
|
||||
aud->nonblocking = state;
|
||||
}
|
||||
|
||||
static void ps3_audio_free(void *data)
|
||||
{
|
||||
ps3_audio_t *aud = data;
|
||||
|
||||
aud->quit_thread = true;
|
||||
cellAudioPortStart(aud->audio_port);
|
||||
pthread_join(aud->thread, NULL);
|
||||
|
||||
cellAudioPortStop(aud->audio_port);
|
||||
cellAudioPortClose(aud->audio_port);
|
||||
cellAudioQuit();
|
||||
fifo_free(aud->buffer);
|
||||
|
||||
sys_lwmutex_destroy(&aud->lock);
|
||||
sys_lwmutex_destroy(&aud->cond_lock);
|
||||
sys_lwcond_destroy(&aud->cond);
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
static bool ps3_audio_use_float(void *data)
|
||||
{
|
||||
(void)data;
|
||||
return true;
|
||||
}
|
||||
|
||||
const audio_driver_t audio_ps3 = {
|
||||
.init = ps3_audio_init,
|
||||
.write = ps3_audio_write,
|
||||
.stop = ps3_audio_stop,
|
||||
.start = ps3_audio_start,
|
||||
.set_nonblock_state = ps3_audio_set_nonblock_state,
|
||||
.use_float = ps3_audio_use_float,
|
||||
.free = ps3_audio_free,
|
||||
.ident = "ps3"
|
||||
};
|
||||
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
/* SSNES - A Super Ninteno Entertainment System (SNES) Emulator frontend for libsnes.
|
||||
* Copyright (C) 2010 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011 - Daniel De Matteis
|
||||
*
|
||||
* 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 "../driver.h"
|
||||
#include "pad_input.h"
|
||||
#include <stdint.h>
|
||||
#include "../libsnes.hpp"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static uint64_t state[5];
|
||||
static void ps3_input_poll(void *data)
|
||||
{
|
||||
(void)data;
|
||||
for (unsigned i = 0; i < 5; i++)
|
||||
state[i] = cell_pad_input_poll_device(i);
|
||||
}
|
||||
|
||||
static int16_t ps3_input_state(void *data, const struct snes_keybind **binds,
|
||||
bool port, unsigned device,
|
||||
unsigned index, unsigned id)
|
||||
{
|
||||
(void)data;
|
||||
(void)binds;
|
||||
(void)index;
|
||||
|
||||
if (device != SNES_DEVICE_JOYPAD)
|
||||
return 0;
|
||||
|
||||
unsigned player = 0;
|
||||
if (port == SNES_PORT_2 && device == SNES_DEVICE_MULTITAP)
|
||||
player = index + 1;
|
||||
else if (port == SNES_PORT_2)
|
||||
player = 1;
|
||||
|
||||
// Hardcoded binds.
|
||||
uint64_t button;
|
||||
switch (id)
|
||||
{
|
||||
case SNES_DEVICE_ID_JOYPAD_A:
|
||||
button = CTRL_CIRCLE_MASK;
|
||||
break;
|
||||
case SNES_DEVICE_ID_JOYPAD_B:
|
||||
button = CTRL_CROSS_MASK;
|
||||
break;
|
||||
case SNES_DEVICE_ID_JOYPAD_X:
|
||||
button = CTRL_TRIANGLE_MASK;
|
||||
break;
|
||||
case SNES_DEVICE_ID_JOYPAD_Y:
|
||||
button = CTRL_SQUARE_MASK;
|
||||
break;
|
||||
case SNES_DEVICE_ID_JOYPAD_LEFT:
|
||||
button = CTRL_LEFT_MASK;
|
||||
break;
|
||||
case SNES_DEVICE_ID_JOYPAD_RIGHT:
|
||||
button = CTRL_RIGHT_MASK;
|
||||
break;
|
||||
case SNES_DEVICE_ID_JOYPAD_UP:
|
||||
button = CTRL_UP_MASK;
|
||||
break;
|
||||
case SNES_DEVICE_ID_JOYPAD_DOWN:
|
||||
button = CTRL_DOWN_MASK;
|
||||
break;
|
||||
case SNES_DEVICE_ID_JOYPAD_START:
|
||||
button = CTRL_START_MASK;
|
||||
break;
|
||||
case SNES_DEVICE_ID_JOYPAD_SELECT:
|
||||
button = CTRL_SELECT_MASK;
|
||||
break;
|
||||
case SNES_DEVICE_ID_JOYPAD_L:
|
||||
button = CTRL_L1_MASK;
|
||||
break;
|
||||
case SNES_DEVICE_ID_JOYPAD_R:
|
||||
button = CTRL_R1_MASK;
|
||||
break;
|
||||
default:
|
||||
button = 0;
|
||||
}
|
||||
|
||||
return CTRL_MASK(state[player], button) ? 1 : 0;
|
||||
}
|
||||
|
||||
static void ps3_free_input(void *data)
|
||||
{
|
||||
(void)data;
|
||||
cell_pad_input_deinit();
|
||||
}
|
||||
|
||||
static void* ps3_input_init(void)
|
||||
{
|
||||
cell_pad_input_init();
|
||||
return (void*)-1;
|
||||
}
|
||||
|
||||
static bool ps3_key_pressed(void *data, int key)
|
||||
{
|
||||
(void)data;
|
||||
switch(key)
|
||||
{
|
||||
case SSNES_FAST_FORWARD_HOLD_KEY:
|
||||
return CTRL_RSTICK_UP(state[0]) && CTRL_R2(~state[0]);
|
||||
case SSNES_LOAD_STATE_KEY:
|
||||
return (CTRL_RSTICK_UP(state[0]) && CTRL_R2(state[0]));
|
||||
case SSNES_SAVE_STATE_KEY:
|
||||
return (CTRL_RSTICK_DOWN(state[0]) && CTRL_R2(state[0]));
|
||||
case SSNES_STATE_SLOT_PLUS:
|
||||
return (CTRL_RSTICK_RIGHT(state[0]) && CTRL_R2(state[0]));
|
||||
case SSNES_STATE_SLOT_MINUS:
|
||||
return (CTRL_RSTICK_LEFT(state[0]) && CTRL_R2(state[0]));
|
||||
case SSNES_REWIND:
|
||||
return CTRL_RSTICK_DOWN(state[0]) && CTRL_R2(~state[0]);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const input_driver_t input_ps3 = {
|
||||
.init = ps3_input_init,
|
||||
.poll = ps3_input_poll,
|
||||
.input_state = ps3_input_state,
|
||||
.key_pressed = ps3_key_pressed,
|
||||
.free = ps3_free_input,
|
||||
.ident = "ps3",
|
||||
};
|
||||
File diff suppressed because it is too large.
Load diff
+24
-17
@@ -31,8 +31,10 @@ if [ $HAVE_DYNAMIC != yes ]; then
|
||||
add_define_make libsnes $LIBSNES
|
||||
fi
|
||||
|
||||
check_lib THREADS -lpthread pthread_create
|
||||
check_lib DYLIB $DYLIB dlopen
|
||||
check_lib NETPLAY -lc socket
|
||||
check_lib GETOPT_LONG -lc getopt_long
|
||||
|
||||
if [ $HAVE_DYLIB = no ] && [ $HAVE_DYNAMIC = yes ]; then
|
||||
echo "Dynamic loading of libsnes is enabled, but your platform does not appear to have dlopen(), use --disable-dynamic or --with-libsnes=\"-lsnes\"".
|
||||
@@ -77,25 +79,30 @@ fi
|
||||
check_pkgconf XML libxml-2.0
|
||||
check_pkgconf SDL_IMAGE SDL_image
|
||||
|
||||
if [ $HAVE_FFMPEG != no ]; then
|
||||
check_pkgconf AVCODEC libavcodec
|
||||
check_pkgconf AVFORMAT libavformat
|
||||
check_pkgconf AVUTIL libavutil
|
||||
check_pkgconf SWSCALE libswscale
|
||||
if [ $HAVE_THREADS != no ]; then
|
||||
if [ $HAVE_FFMPEG != no ]; then
|
||||
check_pkgconf AVCODEC libavcodec
|
||||
check_pkgconf AVFORMAT libavformat
|
||||
check_pkgconf AVUTIL libavutil
|
||||
check_pkgconf SWSCALE libswscale
|
||||
|
||||
( [ $HAVE_FFMPEG = auto ] && ( [ $HAVE_AVCODEC = no ] || [ $HAVE_AVFORMAT = no ] || [ $HAVE_AVUTIL = no ] || [ $HAVE_SWSCALE = no ] ) && HAVE_FFMPEG=no ) || HAVE_FFMPEG=yes
|
||||
fi
|
||||
( [ $HAVE_FFMPEG = auto ] && ( [ $HAVE_AVCODEC = no ] || [ $HAVE_AVFORMAT = no ] || [ $HAVE_AVUTIL = no ] || [ $HAVE_SWSCALE = no ] ) && HAVE_FFMPEG=no ) || HAVE_FFMPEG=yes
|
||||
fi
|
||||
|
||||
if [ $HAVE_FFMPEG = yes ]; then
|
||||
check_lib FFMPEG_ALLOC_CONTEXT3 "$AVCODEC_LIBS" avcodec_alloc_context3
|
||||
check_lib FFMPEG_AVCODEC_OPEN2 "$AVCODEC_LIBS" avcodec_open2
|
||||
check_lib FFMPEG_AVIO_OPEN "$AVFORMAT_LIBS" avio_open
|
||||
check_lib FFMPEG_AVFORMAT_WRITE_HEADER "$AVFORMAT_LIBS" avformat_write_header
|
||||
check_lib FFMPEG_AVFORMAT_NEW_STREAM "$AVFORMAT_LIBS" avformat_new_stream
|
||||
fi
|
||||
if [ $HAVE_FFMPEG = yes ]; then
|
||||
check_lib FFMPEG_ALLOC_CONTEXT3 "$AVCODEC_LIBS" avcodec_alloc_context3
|
||||
check_lib FFMPEG_AVCODEC_OPEN2 "$AVCODEC_LIBS" avcodec_open2
|
||||
check_lib FFMPEG_AVIO_OPEN "$AVFORMAT_LIBS" avio_open
|
||||
check_lib FFMPEG_AVFORMAT_WRITE_HEADER "$AVFORMAT_LIBS" avformat_write_header
|
||||
check_lib FFMPEG_AVFORMAT_NEW_STREAM "$AVFORMAT_LIBS" avformat_new_stream
|
||||
fi
|
||||
|
||||
if [ $HAVE_FFMPEG = no ] && [ $HAVE_X264RGB = yes ]; then
|
||||
echo "x264 RGB recording is enabled, but FFmpeg is not. --enable-x264rgb will not have any effect."
|
||||
if [ $HAVE_FFMPEG = no ] && [ $HAVE_X264RGB = yes ]; then
|
||||
echo "x264 RGB recording is enabled, but FFmpeg is not. --enable-x264rgb will not have any effect."
|
||||
fi
|
||||
else
|
||||
echo "Not building with threading support. Will skip FFmpeg."
|
||||
HAVE_FFMPEG=no
|
||||
fi
|
||||
|
||||
check_lib DYNAMIC $DYLIB dlopen
|
||||
@@ -117,7 +124,7 @@ check_pkgconf PYTHON python3
|
||||
add_define_make OS $OS
|
||||
|
||||
# Creates config.mk and config.h.
|
||||
VARS="ALSA OSS OSS_BSD OSS_LIB AL RSOUND ROAR JACK COREAUDIO PULSE SDL OPENGL DYLIB CG XML SDL_IMAGE DYNAMIC FFMPEG AVCODEC AVFORMAT AVUTIL SWSCALE CONFIGFILE FREETYPE XVIDEO X11 XEXT NETPLAY FBO STRL PYTHON FFMPEG_ALLOC_CONTEXT3 FFMPEG_AVCODEC_OPEN2 FFMPEG_AVIO_OPEN FFMPEG_AVFORMAT_WRITE_HEADER FFMPEG_AVFORMAT_NEW_STREAM X264RGB"
|
||||
VARS="ALSA OSS OSS_BSD OSS_LIB AL RSOUND ROAR JACK COREAUDIO PULSE SDL OPENGL DYLIB GETOPT_LONG THREADS CG XML SDL_IMAGE DYNAMIC FFMPEG AVCODEC AVFORMAT AVUTIL SWSCALE CONFIGFILE FREETYPE XVIDEO X11 XEXT NETPLAY FBO STRL PYTHON FFMPEG_ALLOC_CONTEXT3 FFMPEG_AVCODEC_OPEN2 FFMPEG_AVIO_OPEN FFMPEG_AVFORMAT_WRITE_HEADER FFMPEG_AVFORMAT_NEW_STREAM X264RGB"
|
||||
create_config_make config.mk $VARS
|
||||
create_config_header config.h $VARS
|
||||
|
||||
+2
-1
@@ -1,7 +1,7 @@
|
||||
. qb/qb.params.sh
|
||||
|
||||
PACKAGE_NAME=ssnes
|
||||
PACKAGE_VERSION=0.9.2
|
||||
PACKAGE_VERSION=0.9.3
|
||||
|
||||
# Adds a command line opt to ./configure --help
|
||||
# $1: Variable (HAVE_ALSA, HAVE_OSS, etc)
|
||||
@@ -9,6 +9,7 @@ PACKAGE_VERSION=0.9.2
|
||||
# $3: Default arg. auto implies that HAVE_ALSA will be set according to library checks later on.
|
||||
add_command_line_enable DYNAMIC "Disable dynamic loading of libsnes library" yes
|
||||
add_command_line_string LIBSNES "libsnes library used" ""
|
||||
add_command_line_enable THREADS "Threading support" auto
|
||||
add_command_line_enable FFMPEG "Enable FFmpeg recording support" auto
|
||||
add_command_line_enable X264RGB "Enable lossless X264 RGB recording" no
|
||||
add_command_line_enable DYLIB "Enable dynamic loading support" auto
|
||||
|
||||
+71
-183
@@ -62,6 +62,9 @@ static void set_defaults(void)
|
||||
|
||||
switch (AUDIO_DEFAULT_DRIVER)
|
||||
{
|
||||
case AUDIO_PS3:
|
||||
def_audio = "ps3";
|
||||
break;
|
||||
case AUDIO_RSOUND:
|
||||
def_audio = "rsound";
|
||||
break;
|
||||
@@ -101,6 +104,9 @@ static void set_defaults(void)
|
||||
|
||||
switch (INPUT_DEFAULT_DRIVER)
|
||||
{
|
||||
case INPUT_PS3:
|
||||
def_input = "ps3";
|
||||
break;
|
||||
case INPUT_SDL:
|
||||
def_input = "sdl";
|
||||
break;
|
||||
@@ -226,6 +232,8 @@ static config_file_t *open_default_config_file(void)
|
||||
}
|
||||
if (!conf)
|
||||
conf = config_file_new("/etc/ssnes.cfg");
|
||||
#elif defined(__CELLOS_LV2__)
|
||||
return NULL;
|
||||
#else
|
||||
const char *xdg = getenv("XDG_CONFIG_HOME");
|
||||
if (!xdg)
|
||||
@@ -273,7 +281,7 @@ static void parse_config_file(void)
|
||||
{
|
||||
config_file_t *conf = NULL;
|
||||
|
||||
if (strlen(g_extern.config_path) > 0)
|
||||
if (*g_extern.config_path)
|
||||
{
|
||||
conf = config_file_new(g_extern.config_path);
|
||||
if (!conf)
|
||||
@@ -453,190 +461,70 @@ struct bind_map
|
||||
int snes_key;
|
||||
};
|
||||
|
||||
#define DECLARE_BIND(x, bind) { "input_" #x, "input_" #x "_btn", "input_" #x "_axis", bind }
|
||||
#define DECLARE_BIND_END() { NULL, NULL, NULL, SSNES_BIND_LIST_END }
|
||||
#define DECL_PLAYER(P) \
|
||||
{ \
|
||||
DECLARE_BIND(player##P##_a, SNES_DEVICE_ID_JOYPAD_A), \
|
||||
DECLARE_BIND(player##P##_b, SNES_DEVICE_ID_JOYPAD_B), \
|
||||
DECLARE_BIND(player##P##_y, SNES_DEVICE_ID_JOYPAD_Y), \
|
||||
DECLARE_BIND(player##P##_x, SNES_DEVICE_ID_JOYPAD_X), \
|
||||
DECLARE_BIND(player##P##_start, SNES_DEVICE_ID_JOYPAD_START), \
|
||||
DECLARE_BIND(player##P##_select, SNES_DEVICE_ID_JOYPAD_SELECT), \
|
||||
DECLARE_BIND(player##P##_l, SNES_DEVICE_ID_JOYPAD_L), \
|
||||
DECLARE_BIND(player##P##_r, SNES_DEVICE_ID_JOYPAD_R), \
|
||||
DECLARE_BIND(player##P##_left, SNES_DEVICE_ID_JOYPAD_LEFT), \
|
||||
DECLARE_BIND(player##P##_right, SNES_DEVICE_ID_JOYPAD_RIGHT), \
|
||||
DECLARE_BIND(player##P##_up, SNES_DEVICE_ID_JOYPAD_UP), \
|
||||
DECLARE_BIND(player##P##_down, SNES_DEVICE_ID_JOYPAD_DOWN), \
|
||||
DECLARE_BIND_END(), \
|
||||
}
|
||||
|
||||
#define DECLARE_BIND(x, bind) { "input_" #x, "input_" #x "_btn", "input_" #x "_axis", bind },
|
||||
// Big and nasty bind map... :)
|
||||
static const struct bind_map bind_maps[MAX_PLAYERS][MAX_BINDS - 1] = {
|
||||
static const struct bind_map bind_maps[MAX_PLAYERS][MAX_BINDS] = {
|
||||
{
|
||||
DECLARE_BIND(player1_a, SNES_DEVICE_ID_JOYPAD_A)
|
||||
DECLARE_BIND(player1_b, SNES_DEVICE_ID_JOYPAD_B)
|
||||
DECLARE_BIND(player1_y, SNES_DEVICE_ID_JOYPAD_Y)
|
||||
DECLARE_BIND(player1_x, SNES_DEVICE_ID_JOYPAD_X)
|
||||
DECLARE_BIND(player1_start, SNES_DEVICE_ID_JOYPAD_START)
|
||||
DECLARE_BIND(player1_select, SNES_DEVICE_ID_JOYPAD_SELECT)
|
||||
DECLARE_BIND(player1_l, SNES_DEVICE_ID_JOYPAD_L)
|
||||
DECLARE_BIND(player1_r, SNES_DEVICE_ID_JOYPAD_R)
|
||||
DECLARE_BIND(player1_left, SNES_DEVICE_ID_JOYPAD_LEFT)
|
||||
DECLARE_BIND(player1_right, SNES_DEVICE_ID_JOYPAD_RIGHT)
|
||||
DECLARE_BIND(player1_up, SNES_DEVICE_ID_JOYPAD_UP)
|
||||
DECLARE_BIND(player1_down, SNES_DEVICE_ID_JOYPAD_DOWN)
|
||||
DECLARE_BIND(toggle_fast_forward, SSNES_FAST_FORWARD_KEY)
|
||||
DECLARE_BIND(hold_fast_forward, SSNES_FAST_FORWARD_HOLD_KEY)
|
||||
DECLARE_BIND(save_state, SSNES_SAVE_STATE_KEY)
|
||||
DECLARE_BIND(load_state, SSNES_LOAD_STATE_KEY)
|
||||
DECLARE_BIND(state_slot_increase, SSNES_STATE_SLOT_PLUS)
|
||||
DECLARE_BIND(state_slot_decrease, SSNES_STATE_SLOT_MINUS)
|
||||
DECLARE_BIND(exit_emulator, SSNES_QUIT_KEY)
|
||||
DECLARE_BIND(toggle_fullscreen, SSNES_FULLSCREEN_TOGGLE_KEY)
|
||||
DECLARE_BIND(rate_step_up, SSNES_AUDIO_INPUT_RATE_PLUS)
|
||||
DECLARE_BIND(rate_step_down, SSNES_AUDIO_INPUT_RATE_MINUS)
|
||||
DECLARE_BIND(rewind, SSNES_REWIND)
|
||||
DECLARE_BIND(movie_record_toggle, SSNES_MOVIE_RECORD_TOGGLE)
|
||||
DECLARE_BIND(pause_toggle, SSNES_PAUSE_TOGGLE)
|
||||
DECLARE_BIND(frame_advance, SSNES_FRAMEADVANCE)
|
||||
DECLARE_BIND(reset, SSNES_RESET)
|
||||
DECLARE_BIND(shader_next, SSNES_SHADER_NEXT)
|
||||
DECLARE_BIND(shader_prev, SSNES_SHADER_PREV)
|
||||
DECLARE_BIND(cheat_index_plus, SSNES_CHEAT_INDEX_PLUS)
|
||||
DECLARE_BIND(cheat_index_minus, SSNES_CHEAT_INDEX_MINUS)
|
||||
DECLARE_BIND(cheat_toggle, SSNES_CHEAT_TOGGLE)
|
||||
DECLARE_BIND(screenshot, SSNES_SCREENSHOT)
|
||||
DECLARE_BIND(dsp_config, SSNES_DSP_CONFIG)
|
||||
},
|
||||
{
|
||||
DECLARE_BIND(player2_a, SNES_DEVICE_ID_JOYPAD_A)
|
||||
DECLARE_BIND(player2_b, SNES_DEVICE_ID_JOYPAD_B)
|
||||
DECLARE_BIND(player2_y, SNES_DEVICE_ID_JOYPAD_Y)
|
||||
DECLARE_BIND(player2_x, SNES_DEVICE_ID_JOYPAD_X)
|
||||
DECLARE_BIND(player2_start, SNES_DEVICE_ID_JOYPAD_START)
|
||||
DECLARE_BIND(player2_select, SNES_DEVICE_ID_JOYPAD_SELECT)
|
||||
DECLARE_BIND(player2_l, SNES_DEVICE_ID_JOYPAD_L)
|
||||
DECLARE_BIND(player2_r, SNES_DEVICE_ID_JOYPAD_R)
|
||||
DECLARE_BIND(player2_left, SNES_DEVICE_ID_JOYPAD_LEFT)
|
||||
DECLARE_BIND(player2_right, SNES_DEVICE_ID_JOYPAD_RIGHT)
|
||||
DECLARE_BIND(player2_up, SNES_DEVICE_ID_JOYPAD_UP)
|
||||
DECLARE_BIND(player2_down, SNES_DEVICE_ID_JOYPAD_DOWN)
|
||||
DECLARE_BIND(toggle_fast_forward, SSNES_FAST_FORWARD_KEY)
|
||||
DECLARE_BIND(hold_fast_forward, SSNES_FAST_FORWARD_HOLD_KEY)
|
||||
DECLARE_BIND(save_state, SSNES_SAVE_STATE_KEY)
|
||||
DECLARE_BIND(load_state, SSNES_LOAD_STATE_KEY)
|
||||
DECLARE_BIND(state_slot_increase, SSNES_STATE_SLOT_PLUS)
|
||||
DECLARE_BIND(state_slot_decrease, SSNES_STATE_SLOT_MINUS)
|
||||
DECLARE_BIND(exit_emulator, SSNES_QUIT_KEY)
|
||||
DECLARE_BIND(toggle_fullscreen, SSNES_FULLSCREEN_TOGGLE_KEY)
|
||||
DECLARE_BIND(rate_step_up, SSNES_AUDIO_INPUT_RATE_PLUS)
|
||||
DECLARE_BIND(rate_step_down, SSNES_AUDIO_INPUT_RATE_MINUS)
|
||||
DECLARE_BIND(rewind, SSNES_REWIND)
|
||||
DECLARE_BIND(movie_record_toggle, SSNES_MOVIE_RECORD_TOGGLE)
|
||||
DECLARE_BIND(pause_toggle, SSNES_PAUSE_TOGGLE)
|
||||
DECLARE_BIND(frame_advance, SSNES_FRAMEADVANCE)
|
||||
DECLARE_BIND(reset, SSNES_RESET)
|
||||
DECLARE_BIND(shader_next, SSNES_SHADER_NEXT)
|
||||
DECLARE_BIND(shader_prev, SSNES_SHADER_PREV)
|
||||
DECLARE_BIND(cheat_index_plus, SSNES_CHEAT_INDEX_PLUS)
|
||||
DECLARE_BIND(cheat_index_minus, SSNES_CHEAT_INDEX_MINUS)
|
||||
DECLARE_BIND(cheat_toggle, SSNES_CHEAT_TOGGLE)
|
||||
DECLARE_BIND(screenshot, SSNES_SCREENSHOT)
|
||||
DECLARE_BIND(dsp_config, SSNES_DSP_CONFIG)
|
||||
},
|
||||
{
|
||||
DECLARE_BIND(player3_a, SNES_DEVICE_ID_JOYPAD_A)
|
||||
DECLARE_BIND(player3_b, SNES_DEVICE_ID_JOYPAD_B)
|
||||
DECLARE_BIND(player3_y, SNES_DEVICE_ID_JOYPAD_Y)
|
||||
DECLARE_BIND(player3_x, SNES_DEVICE_ID_JOYPAD_X)
|
||||
DECLARE_BIND(player3_start, SNES_DEVICE_ID_JOYPAD_START)
|
||||
DECLARE_BIND(player3_select, SNES_DEVICE_ID_JOYPAD_SELECT)
|
||||
DECLARE_BIND(player3_l, SNES_DEVICE_ID_JOYPAD_L)
|
||||
DECLARE_BIND(player3_r, SNES_DEVICE_ID_JOYPAD_R)
|
||||
DECLARE_BIND(player3_left, SNES_DEVICE_ID_JOYPAD_LEFT)
|
||||
DECLARE_BIND(player3_right, SNES_DEVICE_ID_JOYPAD_RIGHT)
|
||||
DECLARE_BIND(player3_up, SNES_DEVICE_ID_JOYPAD_UP)
|
||||
DECLARE_BIND(player3_down, SNES_DEVICE_ID_JOYPAD_DOWN)
|
||||
DECLARE_BIND(toggle_fast_forward, SSNES_FAST_FORWARD_KEY)
|
||||
DECLARE_BIND(hold_fast_forward, SSNES_FAST_FORWARD_HOLD_KEY)
|
||||
DECLARE_BIND(save_state, SSNES_SAVE_STATE_KEY)
|
||||
DECLARE_BIND(load_state, SSNES_LOAD_STATE_KEY)
|
||||
DECLARE_BIND(state_slot_increase, SSNES_STATE_SLOT_PLUS)
|
||||
DECLARE_BIND(state_slot_decrease, SSNES_STATE_SLOT_MINUS)
|
||||
DECLARE_BIND(exit_emulator, SSNES_QUIT_KEY)
|
||||
DECLARE_BIND(toggle_fullscreen, SSNES_FULLSCREEN_TOGGLE_KEY)
|
||||
DECLARE_BIND(rate_step_up, SSNES_AUDIO_INPUT_RATE_PLUS)
|
||||
DECLARE_BIND(rate_step_down, SSNES_AUDIO_INPUT_RATE_MINUS)
|
||||
DECLARE_BIND(rewind, SSNES_REWIND)
|
||||
DECLARE_BIND(movie_record_toggle, SSNES_MOVIE_RECORD_TOGGLE)
|
||||
DECLARE_BIND(pause_toggle, SSNES_PAUSE_TOGGLE)
|
||||
DECLARE_BIND(frame_advance, SSNES_FRAMEADVANCE)
|
||||
DECLARE_BIND(reset, SSNES_RESET)
|
||||
DECLARE_BIND(shader_next, SSNES_SHADER_NEXT)
|
||||
DECLARE_BIND(shader_prev, SSNES_SHADER_PREV)
|
||||
DECLARE_BIND(cheat_index_plus, SSNES_CHEAT_INDEX_PLUS)
|
||||
DECLARE_BIND(cheat_index_minus, SSNES_CHEAT_INDEX_MINUS)
|
||||
DECLARE_BIND(cheat_toggle, SSNES_CHEAT_TOGGLE)
|
||||
DECLARE_BIND(screenshot, SSNES_SCREENSHOT)
|
||||
DECLARE_BIND(dsp_config, SSNES_DSP_CONFIG)
|
||||
},
|
||||
{
|
||||
DECLARE_BIND(player4_a, SNES_DEVICE_ID_JOYPAD_A)
|
||||
DECLARE_BIND(player4_b, SNES_DEVICE_ID_JOYPAD_B)
|
||||
DECLARE_BIND(player4_y, SNES_DEVICE_ID_JOYPAD_Y)
|
||||
DECLARE_BIND(player4_x, SNES_DEVICE_ID_JOYPAD_X)
|
||||
DECLARE_BIND(player4_start, SNES_DEVICE_ID_JOYPAD_START)
|
||||
DECLARE_BIND(player4_select, SNES_DEVICE_ID_JOYPAD_SELECT)
|
||||
DECLARE_BIND(player4_l, SNES_DEVICE_ID_JOYPAD_L)
|
||||
DECLARE_BIND(player4_r, SNES_DEVICE_ID_JOYPAD_R)
|
||||
DECLARE_BIND(player4_left, SNES_DEVICE_ID_JOYPAD_LEFT)
|
||||
DECLARE_BIND(player4_right, SNES_DEVICE_ID_JOYPAD_RIGHT)
|
||||
DECLARE_BIND(player4_up, SNES_DEVICE_ID_JOYPAD_UP)
|
||||
DECLARE_BIND(player4_down, SNES_DEVICE_ID_JOYPAD_DOWN)
|
||||
DECLARE_BIND(toggle_fast_forward, SSNES_FAST_FORWARD_KEY)
|
||||
DECLARE_BIND(hold_fast_forward, SSNES_FAST_FORWARD_HOLD_KEY)
|
||||
DECLARE_BIND(save_state, SSNES_SAVE_STATE_KEY)
|
||||
DECLARE_BIND(load_state, SSNES_LOAD_STATE_KEY)
|
||||
DECLARE_BIND(state_slot_increase, SSNES_STATE_SLOT_PLUS)
|
||||
DECLARE_BIND(state_slot_decrease, SSNES_STATE_SLOT_MINUS)
|
||||
DECLARE_BIND(exit_emulator, SSNES_QUIT_KEY)
|
||||
DECLARE_BIND(toggle_fullscreen, SSNES_FULLSCREEN_TOGGLE_KEY)
|
||||
DECLARE_BIND(rate_step_up, SSNES_AUDIO_INPUT_RATE_PLUS)
|
||||
DECLARE_BIND(rate_step_down, SSNES_AUDIO_INPUT_RATE_MINUS)
|
||||
DECLARE_BIND(rewind, SSNES_REWIND)
|
||||
DECLARE_BIND(movie_record_toggle, SSNES_MOVIE_RECORD_TOGGLE)
|
||||
DECLARE_BIND(pause_toggle, SSNES_PAUSE_TOGGLE)
|
||||
DECLARE_BIND(frame_advance, SSNES_FRAMEADVANCE)
|
||||
DECLARE_BIND(reset, SSNES_RESET)
|
||||
DECLARE_BIND(shader_next, SSNES_SHADER_NEXT)
|
||||
DECLARE_BIND(shader_prev, SSNES_SHADER_PREV)
|
||||
DECLARE_BIND(cheat_index_plus, SSNES_CHEAT_INDEX_PLUS)
|
||||
DECLARE_BIND(cheat_index_minus, SSNES_CHEAT_INDEX_MINUS)
|
||||
DECLARE_BIND(cheat_toggle, SSNES_CHEAT_TOGGLE)
|
||||
DECLARE_BIND(screenshot, SSNES_SCREENSHOT)
|
||||
DECLARE_BIND(dsp_config, SSNES_DSP_CONFIG)
|
||||
},
|
||||
{
|
||||
DECLARE_BIND(player5_a, SNES_DEVICE_ID_JOYPAD_A)
|
||||
DECLARE_BIND(player5_b, SNES_DEVICE_ID_JOYPAD_B)
|
||||
DECLARE_BIND(player5_y, SNES_DEVICE_ID_JOYPAD_Y)
|
||||
DECLARE_BIND(player5_x, SNES_DEVICE_ID_JOYPAD_X)
|
||||
DECLARE_BIND(player5_start, SNES_DEVICE_ID_JOYPAD_START)
|
||||
DECLARE_BIND(player5_select, SNES_DEVICE_ID_JOYPAD_SELECT)
|
||||
DECLARE_BIND(player5_l, SNES_DEVICE_ID_JOYPAD_L)
|
||||
DECLARE_BIND(player5_r, SNES_DEVICE_ID_JOYPAD_R)
|
||||
DECLARE_BIND(player5_left, SNES_DEVICE_ID_JOYPAD_LEFT)
|
||||
DECLARE_BIND(player5_right, SNES_DEVICE_ID_JOYPAD_RIGHT)
|
||||
DECLARE_BIND(player5_up, SNES_DEVICE_ID_JOYPAD_UP)
|
||||
DECLARE_BIND(player5_down, SNES_DEVICE_ID_JOYPAD_DOWN)
|
||||
DECLARE_BIND(toggle_fast_forward, SSNES_FAST_FORWARD_KEY)
|
||||
DECLARE_BIND(hold_fast_forward, SSNES_FAST_FORWARD_HOLD_KEY)
|
||||
DECLARE_BIND(save_state, SSNES_SAVE_STATE_KEY)
|
||||
DECLARE_BIND(load_state, SSNES_LOAD_STATE_KEY)
|
||||
DECLARE_BIND(state_slot_increase, SSNES_STATE_SLOT_PLUS)
|
||||
DECLARE_BIND(state_slot_decrease, SSNES_STATE_SLOT_MINUS)
|
||||
DECLARE_BIND(exit_emulator, SSNES_QUIT_KEY)
|
||||
DECLARE_BIND(toggle_fullscreen, SSNES_FULLSCREEN_TOGGLE_KEY)
|
||||
DECLARE_BIND(rate_step_up, SSNES_AUDIO_INPUT_RATE_PLUS)
|
||||
DECLARE_BIND(rate_step_down, SSNES_AUDIO_INPUT_RATE_MINUS)
|
||||
DECLARE_BIND(rewind, SSNES_REWIND)
|
||||
DECLARE_BIND(movie_record_toggle, SSNES_MOVIE_RECORD_TOGGLE)
|
||||
DECLARE_BIND(pause_toggle, SSNES_PAUSE_TOGGLE)
|
||||
DECLARE_BIND(frame_advance, SSNES_FRAMEADVANCE)
|
||||
DECLARE_BIND(reset, SSNES_RESET)
|
||||
DECLARE_BIND(shader_next, SSNES_SHADER_NEXT)
|
||||
DECLARE_BIND(shader_prev, SSNES_SHADER_PREV)
|
||||
DECLARE_BIND(cheat_index_plus, SSNES_CHEAT_INDEX_PLUS)
|
||||
DECLARE_BIND(cheat_index_minus, SSNES_CHEAT_INDEX_MINUS)
|
||||
DECLARE_BIND(cheat_toggle, SSNES_CHEAT_TOGGLE)
|
||||
DECLARE_BIND(screenshot, SSNES_SCREENSHOT)
|
||||
DECLARE_BIND(dsp_config, SSNES_DSP_CONFIG)
|
||||
DECLARE_BIND(player1_a, SNES_DEVICE_ID_JOYPAD_A),
|
||||
DECLARE_BIND(player1_b, SNES_DEVICE_ID_JOYPAD_B),
|
||||
DECLARE_BIND(player1_y, SNES_DEVICE_ID_JOYPAD_Y),
|
||||
DECLARE_BIND(player1_x, SNES_DEVICE_ID_JOYPAD_X),
|
||||
DECLARE_BIND(player1_start, SNES_DEVICE_ID_JOYPAD_START),
|
||||
DECLARE_BIND(player1_select, SNES_DEVICE_ID_JOYPAD_SELECT),
|
||||
DECLARE_BIND(player1_l, SNES_DEVICE_ID_JOYPAD_L),
|
||||
DECLARE_BIND(player1_r, SNES_DEVICE_ID_JOYPAD_R),
|
||||
DECLARE_BIND(player1_left, SNES_DEVICE_ID_JOYPAD_LEFT),
|
||||
DECLARE_BIND(player1_right, SNES_DEVICE_ID_JOYPAD_RIGHT),
|
||||
DECLARE_BIND(player1_up, SNES_DEVICE_ID_JOYPAD_UP),
|
||||
DECLARE_BIND(player1_down, SNES_DEVICE_ID_JOYPAD_DOWN),
|
||||
DECLARE_BIND(toggle_fast_forward, SSNES_FAST_FORWARD_KEY),
|
||||
DECLARE_BIND(hold_fast_forward, SSNES_FAST_FORWARD_HOLD_KEY),
|
||||
DECLARE_BIND(save_state, SSNES_SAVE_STATE_KEY),
|
||||
DECLARE_BIND(load_state, SSNES_LOAD_STATE_KEY),
|
||||
DECLARE_BIND(state_slot_increase, SSNES_STATE_SLOT_PLUS),
|
||||
DECLARE_BIND(state_slot_decrease, SSNES_STATE_SLOT_MINUS),
|
||||
DECLARE_BIND(exit_emulator, SSNES_QUIT_KEY),
|
||||
DECLARE_BIND(toggle_fullscreen, SSNES_FULLSCREEN_TOGGLE_KEY),
|
||||
DECLARE_BIND(rate_step_up, SSNES_AUDIO_INPUT_RATE_PLUS),
|
||||
DECLARE_BIND(rate_step_down, SSNES_AUDIO_INPUT_RATE_MINUS),
|
||||
DECLARE_BIND(rewind, SSNES_REWIND),
|
||||
DECLARE_BIND(movie_record_toggle, SSNES_MOVIE_RECORD_TOGGLE),
|
||||
DECLARE_BIND(pause_toggle, SSNES_PAUSE_TOGGLE),
|
||||
DECLARE_BIND(frame_advance, SSNES_FRAMEADVANCE),
|
||||
DECLARE_BIND(reset, SSNES_RESET),
|
||||
DECLARE_BIND(shader_next, SSNES_SHADER_NEXT),
|
||||
DECLARE_BIND(shader_prev, SSNES_SHADER_PREV),
|
||||
DECLARE_BIND(cheat_index_plus, SSNES_CHEAT_INDEX_PLUS),
|
||||
DECLARE_BIND(cheat_index_minus, SSNES_CHEAT_INDEX_MINUS),
|
||||
DECLARE_BIND(cheat_toggle, SSNES_CHEAT_TOGGLE),
|
||||
DECLARE_BIND(screenshot, SSNES_SCREENSHOT),
|
||||
DECLARE_BIND(dsp_config, SSNES_DSP_CONFIG),
|
||||
DECLARE_BIND(audio_mute, SSNES_MUTE),
|
||||
DECLARE_BIND_END(),
|
||||
},
|
||||
|
||||
DECL_PLAYER(2),
|
||||
DECL_PLAYER(3),
|
||||
DECL_PLAYER(4),
|
||||
DECL_PLAYER(5),
|
||||
};
|
||||
|
||||
struct key_map
|
||||
@@ -729,7 +617,7 @@ static struct snes_keybind *find_snes_bind(unsigned port, int id)
|
||||
|
||||
static int find_sk_bind(const char *str)
|
||||
{
|
||||
for (int i = 0; i < sizeof(sk_map)/sizeof(struct key_map); i++)
|
||||
for (int i = 0; i < sizeof(sk_map) / sizeof(struct key_map); i++)
|
||||
{
|
||||
if (strcasecmp(sk_map[i].str, str) == 0)
|
||||
return sk_map[i].key;
|
||||
@@ -755,7 +643,7 @@ static void read_keybinds(config_file_t *conf)
|
||||
|
||||
for (int j = 0; j < MAX_PLAYERS; j++)
|
||||
{
|
||||
for (int i = 0; i < sizeof(bind_maps[0])/sizeof(struct bind_map); i++)
|
||||
for (int i = 0; bind_maps[j][i].snes_key != SSNES_BIND_LIST_END; i++)
|
||||
{
|
||||
struct snes_keybind *bind = find_snes_bind(j, bind_maps[j][i].snes_key);
|
||||
if (!bind)
|
||||
|
||||
@@ -16,25 +16,24 @@
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <libsnes.hpp>
|
||||
#include "libsnes.hpp"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include "driver.h"
|
||||
#include "file.h"
|
||||
#include "general.h"
|
||||
#include "dynamic.h"
|
||||
#include "audio/utils.h"
|
||||
#include "record/ffemu.h"
|
||||
#include "rewind.h"
|
||||
#include "movie.h"
|
||||
#include "netplay.h"
|
||||
#include "strl.h"
|
||||
#include "screenshot.h"
|
||||
#include "cheats.h"
|
||||
#include "audio/utils.h"
|
||||
#include "getopt_ssnes.h"
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -247,7 +246,7 @@ static void video_cached_frame(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool audio_flush(const int16_t *data, unsigned samples)
|
||||
static bool audio_flush(const int16_t *data, size_t samples)
|
||||
{
|
||||
#ifdef HAVE_FFMPEG
|
||||
if (g_extern.recording)
|
||||
@@ -302,9 +301,16 @@ static bool audio_flush(const int16_t *data, unsigned samples)
|
||||
output_frames = dsp_output.frames;
|
||||
}
|
||||
|
||||
union
|
||||
{
|
||||
float f[0x10000];
|
||||
int16_t i[0x10000 * sizeof(float) / sizeof(int16_t)];
|
||||
} static const empty_buf;
|
||||
|
||||
if (g_extern.audio_data.use_float)
|
||||
{
|
||||
if (driver.audio->write(driver.audio_data, output_data, output_frames * sizeof(float) * 2) < 0)
|
||||
if (driver.audio->write(driver.audio_data,
|
||||
g_extern.audio_data.mute ? empty_buf.f : output_data, output_frames * sizeof(float) * 2) < 0)
|
||||
{
|
||||
fprintf(stderr, "SSNES [ERROR]: Audio backend failed to write. Will continue without sound.\n");
|
||||
return false;
|
||||
@@ -312,10 +318,14 @@ static bool audio_flush(const int16_t *data, unsigned samples)
|
||||
}
|
||||
else
|
||||
{
|
||||
audio_convert_float_to_s16(g_extern.audio_data.conv_outsamples,
|
||||
output_data, output_frames * 2);
|
||||
if (!g_extern.audio_data.mute)
|
||||
{
|
||||
audio_convert_float_to_s16(g_extern.audio_data.conv_outsamples,
|
||||
output_data, output_frames * 2);
|
||||
}
|
||||
|
||||
if (driver.audio->write(driver.audio_data, g_extern.audio_data.conv_outsamples,
|
||||
if (driver.audio->write(driver.audio_data,
|
||||
g_extern.audio_data.mute ? empty_buf.i : g_extern.audio_data.conv_outsamples,
|
||||
output_frames * sizeof(int16_t) * 2) < 0)
|
||||
{
|
||||
fprintf(stderr, "SSNES [ERROR]: Audio backend failed to write. Will continue without sound.\n");
|
||||
@@ -388,10 +398,6 @@ static int16_t input_state(bool port, unsigned device, unsigned index, unsigned
|
||||
#define SSNES_DEFAULT_CONF_PATH_STR " Defaults to $XDG_CONFIG_HOME/ssnes/ssnes.cfg,\n\t\tor $HOME/.ssnes.cfg, if $XDG_CONFIG_HOME is not defined."
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define PACKAGE_VERSION "0.9.2"
|
||||
#endif
|
||||
|
||||
#include "config.features.h"
|
||||
|
||||
#define _PSUPP(var, name, desc) printf("\t%s:\n\t\t%s: %s\n", name, desc, _##var##_supp ? "yes" : "no")
|
||||
@@ -400,6 +406,7 @@ static void print_features(void)
|
||||
puts("");
|
||||
puts("Features:");
|
||||
_PSUPP(sdl, "SDL", "SDL drivers");
|
||||
_PSUPP(thread, "Threads", "Threading support");
|
||||
_PSUPP(opengl, "OpenGL", "OpenGL driver");
|
||||
_PSUPP(xvideo, "XVideo", "XVideo output");
|
||||
_PSUPP(alsa, "ALSA", "audio driver");
|
||||
@@ -608,10 +615,12 @@ static void parse_input(int argc, char *argv[])
|
||||
{ "bsvplay", 1, NULL, 'P' },
|
||||
{ "bsvrecord", 1, NULL, 'R' },
|
||||
{ "sram-mode", 1, NULL, 'M' },
|
||||
#ifdef HAVE_NETPLAY
|
||||
{ "host", 0, NULL, 'H' },
|
||||
{ "connect", 1, NULL, 'C' },
|
||||
{ "frames", 1, NULL, 'F' },
|
||||
{ "port", 1, &val, 'p' },
|
||||
#endif
|
||||
{ "ups", 1, NULL, 'U' },
|
||||
{ "bps", 1, &val, 'B' },
|
||||
{ "xml", 1, NULL, 'X' },
|
||||
@@ -620,8 +629,6 @@ static void parse_input(int argc, char *argv[])
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
int option_index = 0;
|
||||
|
||||
#ifdef HAVE_FFMPEG
|
||||
#define FFMPEG_RECORD_ARG "r:"
|
||||
#else
|
||||
@@ -640,11 +647,17 @@ static void parse_input(int argc, char *argv[])
|
||||
#define DYNAMIC_ARG
|
||||
#endif
|
||||
|
||||
char optstring[] = "hs:fvS:m:p4jJg:b:B:Y:Z:P:R:M:HC:F:U:DN:X:" DYNAMIC_ARG FFMPEG_RECORD_ARG CONFIG_FILE_ARG;
|
||||
#ifdef HAVE_NETPLAY
|
||||
#define NETPLAY_ARG "HC:F:"
|
||||
#else
|
||||
#define NETPLAY_ARG
|
||||
#endif
|
||||
|
||||
char optstring[] = "hs:fvS:m:p4jJg:b:B:Y:Z:P:R:M:U:DN:X:" NETPLAY_ARG DYNAMIC_ARG FFMPEG_RECORD_ARG CONFIG_FILE_ARG;
|
||||
for (;;)
|
||||
{
|
||||
val = 0;
|
||||
int c = getopt_long(argc, argv, optstring, opts, &option_index);
|
||||
int c = getopt_long(argc, argv, optstring, opts, NULL);
|
||||
int port;
|
||||
|
||||
if (c == -1)
|
||||
@@ -782,6 +795,7 @@ static void parse_input(int argc, char *argv[])
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef HAVE_NETPLAY
|
||||
case 'H':
|
||||
g_extern.netplay_enable = true;
|
||||
break;
|
||||
@@ -796,6 +810,7 @@ static void parse_input(int argc, char *argv[])
|
||||
if (g_extern.netplay_sync_frames > 16)
|
||||
g_extern.netplay_sync_frames = 16;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'U':
|
||||
strlcpy(g_extern.ups_name, optarg, sizeof(g_extern.ups_name));
|
||||
@@ -815,9 +830,11 @@ static void parse_input(int argc, char *argv[])
|
||||
case 0:
|
||||
switch (val)
|
||||
{
|
||||
#ifdef HAVE_NETPLAY
|
||||
case 'p':
|
||||
g_extern.netplay_port = strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 'B':
|
||||
strlcpy(g_extern.bps_name, optarg, sizeof(g_extern.bps_name));
|
||||
@@ -1196,6 +1213,7 @@ static void deinit_netplay(void)
|
||||
|
||||
static void init_autosave(void)
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
int ram_types[2] = {-1, -1};
|
||||
const char *ram_paths[2] = {NULL, NULL};
|
||||
|
||||
@@ -1245,15 +1263,18 @@ static void init_autosave(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void deinit_autosave(void)
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
for (unsigned i = 0; i < sizeof(g_extern.autosave)/sizeof(g_extern.autosave[0]); i++)
|
||||
{
|
||||
if (g_extern.autosave[i])
|
||||
autosave_free(g_extern.autosave[i]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void set_savestate_auto_index(void)
|
||||
@@ -1824,11 +1845,36 @@ static void check_dsp_config(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void check_mute(void)
|
||||
{
|
||||
if (!g_extern.audio_active)
|
||||
return;
|
||||
|
||||
static bool old_pressed = false;
|
||||
bool pressed = driver.input->key_pressed(driver.input_data, SSNES_MUTE);
|
||||
if (pressed && !old_pressed)
|
||||
{
|
||||
g_extern.audio_data.mute = !g_extern.audio_data.mute;
|
||||
|
||||
const char *msg = g_extern.audio_data.mute ? "Audio muted!" : "Audio unmuted!";
|
||||
msg_queue_clear(g_extern.msg_queue);
|
||||
msg_queue_push(g_extern.msg_queue, msg, 1, 180);
|
||||
|
||||
SSNES_LOG("%s\n", msg);
|
||||
}
|
||||
|
||||
old_pressed = pressed;
|
||||
}
|
||||
|
||||
static void do_state_checks(void)
|
||||
{
|
||||
check_screenshot();
|
||||
check_mute();
|
||||
|
||||
#ifdef HAVE_NETPLAY
|
||||
if (!g_extern.netplay)
|
||||
{
|
||||
#endif
|
||||
check_pause();
|
||||
check_oneshot();
|
||||
|
||||
@@ -1864,9 +1910,11 @@ static void do_state_checks(void)
|
||||
check_dsp_config();
|
||||
#endif
|
||||
check_reset();
|
||||
#ifdef HAVE_NETPLAY
|
||||
}
|
||||
else
|
||||
check_fullscreen();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DYLIB
|
||||
// DSP plugin doesn't use variable input rate.
|
||||
@@ -1896,7 +1944,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
parse_input(argc, argv);
|
||||
parse_config();
|
||||
init_dlsym();
|
||||
init_libsnes_sym();
|
||||
fill_title_buf();
|
||||
|
||||
psnes_init();
|
||||
@@ -1925,7 +1973,9 @@ int main(int argc, char *argv[])
|
||||
#endif
|
||||
init_drivers();
|
||||
|
||||
#ifdef HAVE_NETPLAY
|
||||
if (!g_extern.netplay)
|
||||
#endif
|
||||
init_rewind();
|
||||
|
||||
#ifdef HAVE_NETPLAY
|
||||
@@ -1948,8 +1998,11 @@ int main(int argc, char *argv[])
|
||||
init_recording();
|
||||
#endif
|
||||
|
||||
bool use_sram = !g_extern.netplay_is_client &&
|
||||
!g_extern.sram_save_disable;
|
||||
#ifdef HAVE_NETPLAY
|
||||
bool use_sram = !g_extern.sram_save_disable && !g_extern.netplay_is_client;
|
||||
#else
|
||||
bool use_sram = !g_extern.sram_save_disable;
|
||||
#endif
|
||||
|
||||
if (!use_sram)
|
||||
SSNES_LOG("SRAM will not be saved!\n");
|
||||
@@ -1958,7 +2011,11 @@ int main(int argc, char *argv[])
|
||||
init_autosave();
|
||||
|
||||
#ifdef HAVE_XML
|
||||
if (!g_extern.netplay && !g_extern.bsv.movie)
|
||||
#ifdef HAVE_NETPLAY
|
||||
if (!g_extern.bsv.movie && !g_extern.netplay)
|
||||
#else
|
||||
if (!g_extern.bsv.movie)
|
||||
#endif
|
||||
init_cheats();
|
||||
#endif
|
||||
|
||||
@@ -1980,7 +2037,9 @@ int main(int argc, char *argv[])
|
||||
// Run libsnes for one frame.
|
||||
if (!g_extern.is_paused || g_extern.is_oneshot)
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
lock_autosave();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETPLAY
|
||||
if (g_extern.netplay)
|
||||
@@ -1998,7 +2057,9 @@ int main(int argc, char *argv[])
|
||||
netplay_post_frame(g_extern.netplay);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_THREADS
|
||||
unlock_autosave();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2021,7 +2082,9 @@ int main(int argc, char *argv[])
|
||||
if (use_sram)
|
||||
save_files();
|
||||
|
||||
#ifdef HAVE_NETPLAY
|
||||
if (!g_extern.netplay)
|
||||
#endif
|
||||
deinit_rewind();
|
||||
|
||||
#ifdef HAVE_XML
|
||||
@@ -2034,7 +2097,7 @@ int main(int argc, char *argv[])
|
||||
psnes_unload_cartridge();
|
||||
psnes_term();
|
||||
uninit_drivers();
|
||||
uninit_dlsym();
|
||||
uninit_libsnes_sym();
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -2042,7 +2105,7 @@ error:
|
||||
psnes_unload_cartridge();
|
||||
psnes_term();
|
||||
uninit_drivers();
|
||||
uninit_dlsym();
|
||||
uninit_libsnes_sym();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -308,6 +308,9 @@
|
||||
# input_cheat_index_minus = t
|
||||
# input_cheat_toggle = u
|
||||
|
||||
# Mute/unmute audio
|
||||
# input_audio_mute = f9
|
||||
|
||||
# Take screenshot
|
||||
# input_screenshot = print_screen
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef HAVE_CONFIG
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@ static struct bind binds[] = {
|
||||
MISC_BIND("Cheat index minus", cheat_index_minus)
|
||||
MISC_BIND("Screenshot", screenshot)
|
||||
MISC_BIND("DSP config", dsp_config)
|
||||
MISC_BIND("Audio mute/unmute", audio_mute)
|
||||
};
|
||||
|
||||
static void get_binds(config_file_t *conf, int player, int joypad)
|
||||
|
||||
Reference in new issue
Block a user