mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-25 08:59:58 +00:00
Merge branch 'master' of https://github.com/Themaister/RetroArch into ios
This commit is contained in:
commit
5d139b185b
2
Makefile
2
Makefile
@ -310,7 +310,7 @@ ifneq ($(V),1)
|
||||
Q := @
|
||||
endif
|
||||
|
||||
OPTIMIZE_FLAG = -O3
|
||||
OPTIMIZE_FLAG = -O3 -ffast-math
|
||||
ifeq ($(DEBUG), 1)
|
||||
OPTIMIZE_FLAG = -O0
|
||||
endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
RARCH_VERSION = "0.9.8.3"
|
||||
RARCH_VERSION = "0.9.8.4"
|
||||
|
||||
DEBUG = 0
|
||||
HAVE_LOGGER = 1
|
||||
@ -53,7 +53,7 @@ CFLAGS += -DHAVE_FILE_LOGGER
|
||||
CFLAGS += -Iconsole/logger
|
||||
endif
|
||||
|
||||
CFLAGS += -std=gnu99 -DHAVE_DEFAULT_RETROPAD_INPUT -DHAVE_RMENU -DHAVE_RGUI -DHAVE_THREAD -DRARCH_CONSOLE -DHAVE_LIBRETRO_MANAGEMENT -DHAVE_RARCH_EXEC -DGEKKO -DHAVE_ZLIB -DWANT_RZLIB -DHAVE_RARCH_MAIN_WRAP -DHAVE_GRIFFIN=1 -DHAVE_SCREENSHOTS -DPACKAGE_VERSION=\"$(RARCH_VERSION)\" -Dmain=rarch_main -Wno-char-subscripts
|
||||
CFLAGS += -std=gnu99 -DHAVE_DEFAULT_RETROPAD_INPUT -DHAVE_RMENU -DHAVE_RGUI -DHAVE_THREAD -DRARCH_CONSOLE -DGEKKO -DHAVE_ZLIB -DWANT_RZLIB -DHAVE_RARCH_MAIN_WRAP -DHAVE_GRIFFIN=1 -DHAVE_SCREENSHOTS -DPACKAGE_VERSION=\"$(RARCH_VERSION)\" -Dmain=rarch_main -Wno-char-subscripts
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -O0 -g
|
||||
|
@ -1,83 +0,0 @@
|
||||
|
||||
##
|
||||
# Makefile for RetroArch GameCube.
|
||||
##
|
||||
|
||||
DEBUG = 0
|
||||
HAVE_LOGGER = 0
|
||||
HAVE_FILE_LOGGER = 0
|
||||
|
||||
# system platform
|
||||
system_platform = unix
|
||||
ifeq ($(shell uname -a),)
|
||||
EXE_EXT = .exe
|
||||
system_platform = win
|
||||
else ifneq ($(findstring Darwin,$(shell uname -a)),)
|
||||
system_platform = osx
|
||||
else ifneq ($(findstring MINGW,$(shell uname -a)),)
|
||||
system_platform = win
|
||||
endif
|
||||
|
||||
PC_DEVELOPMENT_IP_ADDRESS = "192.168.1.7"
|
||||
PC_DEVELOPMENT_UDP_PORT = 3490
|
||||
|
||||
CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT)
|
||||
CXX = $(DEVKITPPC)/bin/powerpc-eabi-g++$(EXE_EXT)
|
||||
LD = $(DEVKITPPC)/bin/powerpc-eabi-ld$(EXE_EXT)
|
||||
ELF2DOL = $(DEVKITPPC)/bin/elf2dol$(EXE_EXT)
|
||||
|
||||
DOL_TARGET := retroarch-salamander_ngc.dol
|
||||
ELF_TARGET := retroarch-salamander_ngc.elf
|
||||
|
||||
INCLUDE := -I. -I$(DEVKITPRO)/libogc/include
|
||||
LIBDIRS := -L$(DEVKITPRO)/libogc/lib/cube -L.
|
||||
|
||||
MACHDEP := -DGEKKO -DHW_DOL -mogc -mcpu=750 -meabi -mhard-float
|
||||
CFLAGS += -Wall -std=gnu99 $(MACHDEP) $(INCLUDE)
|
||||
LDFLAGS := $(MACHDEP) -Wl,-Map,$(notdir $(ELF_TARGET)).map
|
||||
LIBS := -lfat -logc
|
||||
|
||||
OBJ = frontend/frontend_console.o file_path.o compat/compat.o conf/config_file.o ngc/ssaram.o ngc/sidestep.o
|
||||
|
||||
ifeq ($(HAVE_LOGGER), 1)
|
||||
CFLAGS += -DHAVE_LOGGER
|
||||
CFLAGS += -DPC_DEVELOPMENT_IP_ADDRESS=\"$(PC_DEVELOPMENT_IP_ADDRESS)\" -DPC_DEVELOPMENT_UDP_PORT=$(PC_DEVELOPMENT_UDP_PORT)
|
||||
CFLAGS += -Iconsole/logger
|
||||
OBJ += console/logger/logger.o
|
||||
LIBS += -lbba
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_FILE_LOGGER), 1)
|
||||
CFLAGS += -DHAVE_FILE_LOGGER
|
||||
CFLAGS += -Iconsole/logger
|
||||
endif
|
||||
|
||||
CFLAGS += -std=gnu99 -DHAVE_DEFAULT_RETROPAD_INPUT -DIS_SALAMANDER -DRARCH_CONSOLE -DHAVE_RARCH_EXEC -DGEKKO -DPACKAGE_VERSION=\"0.9.8\" -Wno-char-subscripts
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -O0 -g
|
||||
else
|
||||
CFLAGS += -O3
|
||||
endif
|
||||
|
||||
all: $(DOL_TARGET)
|
||||
|
||||
%.dol: %.elf
|
||||
$(ELF2DOL) $< $@
|
||||
|
||||
$(ELF_TARGET): $(OBJ)
|
||||
$(CXX) -o $@ $(LDFLAGS) $(LIBDIRS) $(OBJ) $(LIBS)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
pkg: all
|
||||
cp -r $(DOL_TARGET) ngc/pkg/boot.dol
|
||||
|
||||
clean:
|
||||
rm -f $(DOL_TARGET)
|
||||
rm -f $(ELF_TARGET)
|
||||
rm -f $(OBJ)
|
||||
|
||||
.PHONY: clean
|
||||
|
@ -1,4 +1,4 @@
|
||||
RARCH_VERSION = "0.9.8.3"
|
||||
RARCH_VERSION = "0.9.8.4"
|
||||
|
||||
#which compiler to build with - GCC or SNC
|
||||
#set to GCC for debug builds for use with debugger
|
||||
|
@ -1,10 +1,9 @@
|
||||
RARCH_VERSION = "0.9.8.3"
|
||||
RARCH_VERSION = "0.9.8.4"
|
||||
|
||||
DEBUG = 0
|
||||
HAVE_LOGGER = 0
|
||||
HAVE_FILE_LOGGER = 0
|
||||
PERF_TEST = 0
|
||||
HAVE_WIIUSE_MOD = 0
|
||||
WHOLE_ARCHIVE_LINK = 0
|
||||
|
||||
PC_DEVELOPMENT_IP_ADDRESS = "192.168.1.100"
|
||||
@ -21,11 +20,7 @@ else ifneq ($(findstring MINGW,$(shell uname -a)),)
|
||||
system_platform = win
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_WIIUSE_MOD), 1)
|
||||
CFLAGS += -DHAVE_WIIUSE
|
||||
else
|
||||
LDFLAGS_WIIUSE := -lwiiuse
|
||||
endif
|
||||
|
||||
CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT)
|
||||
CXX = $(DEVKITPPC)/bin/powerpc-eabi-g++$(EXE_EXT)
|
||||
|
@ -221,8 +221,8 @@ ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -O0 -g
|
||||
CXXFLAGS += -O0 -g
|
||||
else
|
||||
CFLAGS += -O3
|
||||
CXXFLAGS += -O3
|
||||
CFLAGS += -O3 -ffast-math
|
||||
CXXFLAGS += -O3 -ffast-math
|
||||
LDCXXFLAGS += -s
|
||||
endif
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
RARCH_VERSION = "0.9.8.3"
|
||||
RARCH_VERSION = "0.9.8.4"
|
||||
|
||||
DEBUG = 0
|
||||
|
||||
|
@ -132,14 +132,24 @@ static void android_input_poll(void *data)
|
||||
long_msg_enable = true;
|
||||
}
|
||||
|
||||
if (keycode == AKEYCODE_BACK )
|
||||
if (keycode == AKEYCODE_BACK)
|
||||
{
|
||||
int meta = AKeyEvent_getMetaState(event);
|
||||
if (!(meta & AMETA_ALT_ON))
|
||||
uint8_t unpacked = (keycode_lut[AKEYCODE_BACK] >> ((state_id+1) << 3)) - 1;
|
||||
uint64_t input_state = (1ULL << unpacked);
|
||||
|
||||
if (type_event == AINPUT_EVENT_TYPE_KEY && input_state < (1ULL << RARCH_FIRST_META_KEY)
|
||||
&& input_state > 0)
|
||||
{
|
||||
*lifecycle_state |= (1ULL << RARCH_QUIT_KEY);
|
||||
AInputQueue_finishEvent(android_app->inputQueue, event, handled);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
int meta = AKeyEvent_getMetaState(event);
|
||||
if (!(meta & AMETA_ALT_ON))
|
||||
{
|
||||
*lifecycle_state |= (1ULL << RARCH_QUIT_KEY);
|
||||
AInputQueue_finishEvent(android_app->inputQueue, event, handled);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,6 +175,7 @@ void input_autodetect_setup (void *data, char *msg, size_t sizeof_msg, unsigned
|
||||
keycode_lut[AKEYCODE_BUTTON_THUMBL] |= ((RETRO_DEVICE_ID_JOYPAD_L3+1) << shift);
|
||||
keycode_lut[AKEYCODE_BUTTON_THUMBR] |= ((RETRO_DEVICE_ID_JOYPAD_R3+1) << shift);
|
||||
keycode_lut[AKEYCODE_BUTTON_SELECT] |= ((RETRO_DEVICE_ID_JOYPAD_SELECT+1) << shift);
|
||||
keycode_lut[AKEYCODE_BACK] |= ((RETRO_DEVICE_ID_JOYPAD_SELECT+1) << shift);
|
||||
keycode_lut[AKEYCODE_BUTTON_START] |= ((RETRO_DEVICE_ID_JOYPAD_START+1) << shift);
|
||||
}
|
||||
}
|
||||
@ -206,7 +207,7 @@ void input_autodetect_setup (void *data, char *msg, size_t sizeof_msg, unsigned
|
||||
keycode_lut[AKEYCODE_BUTTON_C] |= ((RETRO_DEVICE_ID_JOYPAD_SELECT+1) << shift);
|
||||
keycode_lut[AKEYCODE_BUTTON_X] |= ((RETRO_DEVICE_ID_JOYPAD_START+1) << shift);
|
||||
}
|
||||
else if (strstr(name_buf, "Madcatz"))
|
||||
else if (strstr(name_buf, "MadCatz"))
|
||||
{
|
||||
if (strstr(name_buf, "PC USB Wired Stick"))
|
||||
{
|
||||
@ -216,9 +217,12 @@ void input_autodetect_setup (void *data, char *msg, size_t sizeof_msg, unsigned
|
||||
keycode_lut[AKEYCODE_BUTTON_X] |= ((RETRO_DEVICE_ID_JOYPAD_X+1) << shift);
|
||||
|
||||
keycode_lut[AKEYCODE_BUTTON_Y] |= ((RETRO_DEVICE_ID_JOYPAD_L+1) << shift);
|
||||
keycode_lut[AKEYCODE_BUTTON_Z] |= ((RETRO_DEVICE_ID_JOYPAD_R+1) << shift);
|
||||
|
||||
keycode_lut[AKEYCODE_BUTTON_Z] |= ((RETRO_DEVICE_ID_JOYPAD_L+1) << shift); /* request hack */
|
||||
|
||||
keycode_lut[AKEYCODE_BUTTON_L1] |= ((RETRO_DEVICE_ID_JOYPAD_L2+1) << shift);
|
||||
keycode_lut[AKEYCODE_BUTTON_R1] |= ((RETRO_DEVICE_ID_JOYPAD_R2+1) << shift);
|
||||
|
||||
keycode_lut[AKEYCODE_BUTTON_R1] |= ((RETRO_DEVICE_ID_JOYPAD_R+1) << shift); /* request hack */
|
||||
|
||||
keycode_lut[AKEYCODE_BUTTON_L2] |= ((RETRO_DEVICE_ID_JOYPAD_SELECT+1) << shift);
|
||||
keycode_lut[AKEYCODE_BUTTON_R2] |= ((RETRO_DEVICE_ID_JOYPAD_START+1) << shift);
|
||||
@ -479,7 +483,7 @@ void input_autodetect_setup (void *data, char *msg, size_t sizeof_msg, unsigned
|
||||
keycode_lut[AKEYCODE_BUTTON_THUMBL] |= ((RETRO_DEVICE_ID_JOYPAD_L3+1) << shift);
|
||||
keycode_lut[AKEYCODE_BUTTON_THUMBR] |= ((RETRO_DEVICE_ID_JOYPAD_R3+1) << shift);
|
||||
}
|
||||
else if (strstr(name_buf, "2-Axis , 8 -Button"))
|
||||
else if (strstr(name_buf, "2-Axis, 8-Button"))
|
||||
{
|
||||
/* Genius MaxFire G-08XU */
|
||||
keycode_lut[AKEYCODE_BUTTON_B] |= ((RETRO_DEVICE_ID_JOYPAD_A+1) << shift);
|
||||
|
@ -1,6 +1,6 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.retroarch"
|
||||
android:versionCode="11"
|
||||
android:versionCode="12"
|
||||
android:versionName="0.9.8.3" >
|
||||
<uses-feature android:glEsVersion="0x00020000" />
|
||||
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
|
||||
|
@ -18,13 +18,20 @@
|
||||
#include "resampler.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include "../boolean.h"
|
||||
#include "../general.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#ifndef RESAMPLER_TEST
|
||||
#include "../general.h"
|
||||
#else
|
||||
#define RARCH_LOG(...) fprintf(stderr, __VA_ARGS__)
|
||||
#define RARCH_WARN(...) fprintf(stderr, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define CHANNELS 2
|
||||
|
||||
typedef struct rarch_hermite_resampler
|
||||
@ -51,8 +58,11 @@ static inline float hermite_kernel(float mu1, float a, float b, float c, float d
|
||||
return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c);
|
||||
}
|
||||
|
||||
void *resampler_hermite_new(void)
|
||||
void *resampler_hermite_new(double bandwidth_mod)
|
||||
{
|
||||
if (bandwidth_mod < 1.0)
|
||||
RARCH_WARN("Hermite resampler is likely to sound absolutely terrible when downsampling.\n");
|
||||
|
||||
#ifndef RESAMPLER_TEST
|
||||
RARCH_LOG("Hermite resampler [C]\n");
|
||||
#endif
|
||||
|
@ -29,7 +29,7 @@ static const rarch_resampler_t *backends[] = {
|
||||
&hermite_resampler,
|
||||
};
|
||||
|
||||
bool rarch_resampler_realloc(void **re, const rarch_resampler_t **backend, const char *ident)
|
||||
bool rarch_resampler_realloc(void **re, const rarch_resampler_t **backend, const char *ident, double bw_ratio)
|
||||
{
|
||||
if (*re && *backend)
|
||||
(*backend)->free(*re);
|
||||
@ -54,7 +54,7 @@ bool rarch_resampler_realloc(void **re, const rarch_resampler_t **backend, const
|
||||
if (!*backend)
|
||||
return false;
|
||||
|
||||
*re = (*backend)->init();
|
||||
*re = (*backend)->init(bw_ratio);
|
||||
if (!*re)
|
||||
{
|
||||
*backend = NULL;
|
||||
|
@ -46,7 +46,7 @@ struct resampler_data
|
||||
|
||||
typedef struct rarch_resampler
|
||||
{
|
||||
void *(*init)(void);
|
||||
void *(*init)(double bandwidth_mod); // Bandwidth factor. Will be < 1.0 for downsampling, > 1.0 for upsamling. Corresponds to expected resampling ratio.
|
||||
void (*process)(void *re, struct resampler_data *data);
|
||||
void (*free)(void *re);
|
||||
const char *ident;
|
||||
@ -57,7 +57,7 @@ extern const rarch_resampler_t sinc_resampler;
|
||||
|
||||
// Reallocs resampler. Will free previous handle before allocating a new one.
|
||||
// If ident is NULL, first resampler will be used.
|
||||
bool rarch_resampler_realloc(void **re, const rarch_resampler_t **backend, const char *ident);
|
||||
bool rarch_resampler_realloc(void **re, const rarch_resampler_t **backend, const char *ident, double bw_ratio);
|
||||
|
||||
// Convenience macros.
|
||||
// freep makes sure to set handles to NULL to avoid double-free in rarch_resampler_realloc.
|
||||
|
272
audio/sinc.c
272
audio/sinc.c
@ -14,7 +14,7 @@
|
||||
*/
|
||||
|
||||
// Bog-standard windowed SINC implementation.
|
||||
// Only suitable as an upsampler, as there is no low-pass filter stage.
|
||||
// Only suitable as an upsampler, as cutoff frequency isn't dynamically configurable (yet).
|
||||
|
||||
#include "resampler.h"
|
||||
#include "../performance.h"
|
||||
@ -22,27 +22,67 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef RESAMPLER_TEST
|
||||
#include "../general.h"
|
||||
#else
|
||||
#define RARCH_LOG(...)
|
||||
#define RARCH_LOG(...) fprintf(stderr, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifdef __SSE__
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
|
||||
#ifdef SINC_LOWER_QUALITY
|
||||
// Rough SNR values for upsampling:
|
||||
// LOWEST: 40 dB
|
||||
// LOWER: 55 dB
|
||||
// NORMAL: 70 dB
|
||||
// HIGHER: 110 dB
|
||||
// HIGHEST: 140 dB
|
||||
|
||||
// TODO, make all this more configurable.
|
||||
#if defined(SINC_LOWEST_QUALITY)
|
||||
#define SINC_WINDOW_LANCZOS
|
||||
#define CUTOFF 0.98
|
||||
#define PHASE_BITS 12
|
||||
#define SINC_COEFF_LERP 0
|
||||
#define SUBPHASE_BITS 10
|
||||
#define SIDELOBES 2
|
||||
#define ENABLE_AVX 0
|
||||
#elif defined(SINC_LOWER_QUALITY)
|
||||
#define SINC_WINDOW_LANCZOS
|
||||
#define CUTOFF 0.98
|
||||
#define PHASE_BITS 12
|
||||
#define SUBPHASE_BITS 10
|
||||
#define SINC_COEFF_LERP 0
|
||||
#define SIDELOBES 4
|
||||
#define ENABLE_AVX 0
|
||||
#elif defined(SINC_HIGHER_QUALITY)
|
||||
#define PHASE_BITS 16
|
||||
#define SINC_WINDOW_KAISER
|
||||
#define SINC_WINDOW_KAISER_BETA 10.5
|
||||
#define CUTOFF 0.90
|
||||
#define PHASE_BITS 10
|
||||
#define SUBPHASE_BITS 14
|
||||
#define SINC_COEFF_LERP 1
|
||||
#define SIDELOBES 32
|
||||
#define ENABLE_AVX 1
|
||||
#elif defined(SINC_HIGHEST_QUALITY)
|
||||
#define SINC_WINDOW_KAISER
|
||||
#define SINC_WINDOW_KAISER_BETA 14.5
|
||||
#define CUTOFF 0.95
|
||||
#define PHASE_BITS 10
|
||||
#define SUBPHASE_BITS 14
|
||||
#define SINC_COEFF_LERP 1
|
||||
#define SIDELOBES 128
|
||||
#define ENABLE_AVX 1
|
||||
#else
|
||||
#define PHASE_BITS 16
|
||||
#define SINC_WINDOW_KAISER
|
||||
#define SINC_WINDOW_KAISER_BETA 5.5
|
||||
#define CUTOFF 0.825
|
||||
#define PHASE_BITS 8
|
||||
#define SUBPHASE_BITS 16
|
||||
#define SINC_COEFF_LERP 1
|
||||
#define SIDELOBES 8
|
||||
#define ENABLE_AVX 0
|
||||
#endif
|
||||
@ -56,20 +96,26 @@
|
||||
#include <immintrin.h>
|
||||
#endif
|
||||
|
||||
#define SUBPHASE_BITS 10
|
||||
#define PHASES (1 << (PHASE_BITS + SUBPHASE_BITS))
|
||||
|
||||
#define TAPS (SIDELOBES * 2)
|
||||
#define CUTOFF 0.98
|
||||
#define SUBPHASE_MASK ((1 << SUBPHASE_BITS) - 1)
|
||||
#define SUBPHASE_MOD (1.0f / (1 << SUBPHASE_BITS))
|
||||
|
||||
typedef struct rarch_sinc_resampler
|
||||
{
|
||||
sample_t phase_table[1 << PHASE_BITS][TAPS];
|
||||
sample_t buffer_l[2 * TAPS];
|
||||
sample_t buffer_r[2 * TAPS];
|
||||
sample_t *phase_table;
|
||||
sample_t *buffer_l;
|
||||
sample_t *buffer_r;
|
||||
|
||||
unsigned taps;
|
||||
|
||||
unsigned ptr;
|
||||
uint32_t time;
|
||||
|
||||
// A buffer for phase_table, buffer_l and buffer_r are created in a single calloc().
|
||||
// Ensure that we get as good cache locality as we can hope for.
|
||||
sample_t *main_buffer;
|
||||
} rarch_sinc_resampler_t;
|
||||
|
||||
static inline double sinc(double val)
|
||||
@ -80,23 +126,90 @@ static inline double sinc(double val)
|
||||
return sin(val) / val;
|
||||
}
|
||||
|
||||
static inline double lanzcos(double index)
|
||||
#if defined(SINC_WINDOW_LANCZOS)
|
||||
static inline double window_function(double index)
|
||||
{
|
||||
return sinc(index);
|
||||
return sinc(M_PI * index);
|
||||
}
|
||||
#elif defined(SINC_WINDOW_KAISER)
|
||||
// Modified Bessel function of first order.
|
||||
// Check Wiki for mathematical definition ...
|
||||
static inline double besseli0(double x)
|
||||
{
|
||||
double sum = 0.0;
|
||||
|
||||
double factorial = 1.0;
|
||||
double factorial_mult = 0.0;
|
||||
double x_pow = 1.0;
|
||||
double two_div_pow = 1.0;
|
||||
double x_sqr = x * x;
|
||||
|
||||
// Approximate. This is an infinite sum.
|
||||
// Luckily, it converges rather fast.
|
||||
for (unsigned i = 0; i < 18; i++)
|
||||
{
|
||||
sum += x_pow * two_div_pow / (factorial * factorial);
|
||||
|
||||
factorial_mult += 1.0;
|
||||
x_pow *= x_sqr;
|
||||
two_div_pow *= 0.25;
|
||||
factorial *= factorial_mult;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
static void init_sinc_table(rarch_sinc_resampler_t *resamp)
|
||||
static inline double window_function(double index)
|
||||
{
|
||||
// Sinc phases: [..., p + 3, p + 2, p + 1, p + 0, p - 1, p - 2, p - 3, p - 4, ...]
|
||||
for (int i = 0; i < (1 << PHASE_BITS); i++)
|
||||
{
|
||||
for (int j = 0; j < TAPS; j++)
|
||||
{
|
||||
double p = (double)i / (1 << PHASE_BITS);
|
||||
double sinc_phase = M_PI * (p + (SIDELOBES - 1 - j));
|
||||
return besseli0(SINC_WINDOW_KAISER_BETA * sqrt(1 - index * index));
|
||||
}
|
||||
#else
|
||||
#error "No SINC window function defined."
|
||||
#endif
|
||||
|
||||
float val = CUTOFF * sinc(CUTOFF * sinc_phase) * lanzcos(sinc_phase / SIDELOBES);
|
||||
resamp->phase_table[i][j] = val;
|
||||
static void init_sinc_table(rarch_sinc_resampler_t *resamp, double cutoff,
|
||||
float *phase_table, int phases, int taps, bool calculate_delta)
|
||||
{
|
||||
double window_mod = window_function(0.0); // Need to normalize w(0) to 1.0.
|
||||
int stride = calculate_delta ? 2 : 1;
|
||||
|
||||
double sidelobes = taps / 2.0;
|
||||
for (int i = 0; i < phases; i++)
|
||||
{
|
||||
for (int j = 0; j < taps; j++)
|
||||
{
|
||||
int n = j * phases + i;
|
||||
double window_phase = (double)n / (phases * taps); // [0, 1).
|
||||
window_phase = 2.0 * window_phase - 1.0; // [-1, 1)
|
||||
double sinc_phase = sidelobes * window_phase;
|
||||
|
||||
float val = cutoff * sinc(M_PI * sinc_phase * cutoff) * window_function(window_phase) / window_mod;
|
||||
phase_table[i * stride * taps + j] = val;
|
||||
}
|
||||
}
|
||||
|
||||
if (calculate_delta)
|
||||
{
|
||||
for (int p = 0; p < phases - 1; p++)
|
||||
{
|
||||
for (int j = 0; j < taps; j++)
|
||||
{
|
||||
float delta = phase_table[(p + 1) * stride * taps + j] - phase_table[p * stride * taps + j];
|
||||
phase_table[(p * stride + 1) * taps + j] = delta;
|
||||
}
|
||||
}
|
||||
|
||||
int phase = phases - 1;
|
||||
for (int j = 0; j < taps; j++)
|
||||
{
|
||||
int n = j * phases + (phase + 1);
|
||||
double window_phase = (double)n / (phases * taps); // (0, 1].
|
||||
window_phase = 2.0 * window_phase - 1.0; // (-1, 1]
|
||||
double sinc_phase = sidelobes * window_phase;
|
||||
|
||||
float val = cutoff * sinc(M_PI * sinc_phase * cutoff) * window_function(window_phase) / window_mod;
|
||||
float delta = (val - phase_table[phase * stride * taps + j]);
|
||||
phase_table[(phase * stride + 1) * taps + j] = delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -128,12 +241,23 @@ static inline void process_sinc_C(rarch_sinc_resampler_t *resamp, float *out_buf
|
||||
const float *buffer_l = resamp->buffer_l + resamp->ptr;
|
||||
const float *buffer_r = resamp->buffer_r + resamp->ptr;
|
||||
|
||||
unsigned taps = resamp->taps;
|
||||
unsigned phase = resamp->time >> SUBPHASE_BITS;
|
||||
const float *phase_table = resamp->phase_table[phase];
|
||||
#if SINC_COEFF_LERP
|
||||
const float *phase_table = resamp->phase_table + phase * taps * 2;
|
||||
const float *delta_table = phase_table + taps;
|
||||
float delta = (float)(resamp->time & SUBPHASE_MASK) * SUBPHASE_MOD;
|
||||
#else
|
||||
const float *phase_table = resamp->phase_table + phase * taps;
|
||||
#endif
|
||||
|
||||
for (unsigned i = 0; i < TAPS; i++)
|
||||
for (unsigned i = 0; i < taps; i++)
|
||||
{
|
||||
#if SINC_COEFF_LERP
|
||||
float sinc_val = phase_table[i] + delta_table[i] * delta;
|
||||
#else
|
||||
float sinc_val = phase_table[i];
|
||||
#endif
|
||||
sum_l += buffer_l[i] * sinc_val;
|
||||
sum_r += buffer_r[i] * sinc_val;
|
||||
}
|
||||
@ -152,15 +276,27 @@ static void process_sinc(rarch_sinc_resampler_t *resamp, float *out_buffer)
|
||||
const float *buffer_l = resamp->buffer_l + resamp->ptr;
|
||||
const float *buffer_r = resamp->buffer_r + resamp->ptr;
|
||||
|
||||
unsigned taps = resamp->taps;
|
||||
unsigned phase = resamp->time >> SUBPHASE_BITS;
|
||||
const float *phase_table = resamp->phase_table[phase];
|
||||
#if SINC_COEFF_LERP
|
||||
const float *phase_table = resamp->phase_table + phase * taps * 2;
|
||||
const float *delta_table = phase_table + taps;
|
||||
__m256 delta = _mm256_set1_ps((float)(resamp->time & SUBPHASE_MASK) * SUBPHASE_MOD);
|
||||
#else
|
||||
const float *phase_table = resamp->phase_table + phase * taps;
|
||||
#endif
|
||||
|
||||
for (unsigned i = 0; i < TAPS; i += 8)
|
||||
for (unsigned i = 0; i < taps; i += 8)
|
||||
{
|
||||
__m256 buf_l = _mm256_loadu_ps(buffer_l + i);
|
||||
__m256 buf_r = _mm256_loadu_ps(buffer_r + i);
|
||||
|
||||
#if SINC_COEFF_LERP
|
||||
__m256 deltas = _mm256_load_ps(delta_table + i);
|
||||
__m256 sinc = _mm256_add_ps(_mm256_load_ps(phase_table + i), _mm256_mul_ps(deltas, delta));
|
||||
#else
|
||||
__m256 sinc = _mm256_load_ps(phase_table + i);
|
||||
#endif
|
||||
sum_l = _mm256_add_ps(sum_l, _mm256_mul_ps(buf_l, sinc));
|
||||
sum_r = _mm256_add_ps(sum_r, _mm256_mul_ps(buf_r, sinc));
|
||||
}
|
||||
@ -188,15 +324,27 @@ static void process_sinc(rarch_sinc_resampler_t *resamp, float *out_buffer)
|
||||
const float *buffer_l = resamp->buffer_l + resamp->ptr;
|
||||
const float *buffer_r = resamp->buffer_r + resamp->ptr;
|
||||
|
||||
unsigned taps = resamp->taps;
|
||||
unsigned phase = resamp->time >> SUBPHASE_BITS;
|
||||
const float *phase_table = resamp->phase_table[phase];
|
||||
#if SINC_COEFF_LERP
|
||||
const float *phase_table = resamp->phase_table + phase * taps * 2;
|
||||
const float *delta_table = phase_table + taps;
|
||||
__m128 delta = _mm_set1_ps((float)(resamp->time & SUBPHASE_MASK) * SUBPHASE_MOD);
|
||||
#else
|
||||
const float *phase_table = resamp->phase_table + phase * taps;
|
||||
#endif
|
||||
|
||||
for (unsigned i = 0; i < TAPS; i += 4)
|
||||
for (unsigned i = 0; i < taps; i += 4)
|
||||
{
|
||||
__m128 buf_l = _mm_loadu_ps(buffer_l + i);
|
||||
__m128 buf_r = _mm_loadu_ps(buffer_r + i);
|
||||
|
||||
#if SINC_COEFF_LERP
|
||||
__m128 deltas = _mm_load_ps(delta_table + i);
|
||||
__m128 sinc = _mm_add_ps(_mm_load_ps(phase_table + i), _mm_mul_ps(deltas, delta));
|
||||
#else
|
||||
__m128 sinc = _mm_load_ps(phase_table + i);
|
||||
#endif
|
||||
sum_l = _mm_add_ps(sum_l, _mm_mul_ps(buf_l, sinc));
|
||||
sum_r = _mm_add_ps(sum_r, _mm_mul_ps(buf_r, sinc));
|
||||
}
|
||||
@ -224,6 +372,10 @@ static void process_sinc(rarch_sinc_resampler_t *resamp, float *out_buffer)
|
||||
}
|
||||
#elif defined(HAVE_NEON)
|
||||
|
||||
#if SINC_COEFF_LERP
|
||||
#error "NEON asm does not support SINC lerp."
|
||||
#endif
|
||||
|
||||
// Need to make this function pointer as Android doesn't have built-in targets
|
||||
// for NEON and plain ARMv7a.
|
||||
static void (*process_sinc_func)(rarch_sinc_resampler_t *resamp, float *out_buffer);
|
||||
@ -239,7 +391,7 @@ static void process_sinc_neon(rarch_sinc_resampler_t *resamp, float *out_buffer)
|
||||
unsigned phase = resamp->time >> SUBPHASE_BITS;
|
||||
const float *phase_table = resamp->phase_table[phase];
|
||||
|
||||
process_sinc_neon_asm(out_buffer, buffer_l, buffer_r, phase_table, TAPS);
|
||||
process_sinc_neon_asm(out_buffer, buffer_l, buffer_r, phase_table, resamp->taps);
|
||||
}
|
||||
#else // Plain ol' C99
|
||||
#define process_sinc_func process_sinc_C
|
||||
@ -249,9 +401,6 @@ static void resampler_sinc_process(void *re_, struct resampler_data *data)
|
||||
{
|
||||
rarch_sinc_resampler_t *re = (rarch_sinc_resampler_t*)re_;
|
||||
|
||||
// If data->ratio is < 1, we are downsampling.
|
||||
// The sinc table is not set up for this, as it always assumes upsampling.
|
||||
// Downsampling will work, but with some added noise due to aliasing might be present.
|
||||
uint32_t ratio = PHASES / data->ratio;
|
||||
|
||||
const sample_t *input = data->data_in;
|
||||
@ -263,9 +412,13 @@ static void resampler_sinc_process(void *re_, struct resampler_data *data)
|
||||
{
|
||||
while (frames && re->time >= PHASES)
|
||||
{
|
||||
re->buffer_l[re->ptr + TAPS] = re->buffer_l[re->ptr] = *input++;
|
||||
re->buffer_r[re->ptr + TAPS] = re->buffer_r[re->ptr] = *input++;
|
||||
re->ptr = (re->ptr + 1) & (TAPS - 1);
|
||||
// Push in reverse to make filter more obvious.
|
||||
if (!re->ptr)
|
||||
re->ptr = re->taps;
|
||||
re->ptr--;
|
||||
|
||||
re->buffer_l[re->ptr + re->taps] = re->buffer_l[re->ptr] = *input++;
|
||||
re->buffer_r[re->ptr + re->taps] = re->buffer_r[re->ptr] = *input++;
|
||||
|
||||
re->time -= PHASES;
|
||||
frames--;
|
||||
@ -285,18 +438,52 @@ static void resampler_sinc_process(void *re_, struct resampler_data *data)
|
||||
|
||||
static void resampler_sinc_free(void *re)
|
||||
{
|
||||
aligned_free__(re);
|
||||
rarch_sinc_resampler_t *resampler = (rarch_sinc_resampler_t*)re;
|
||||
if (resampler)
|
||||
aligned_free__(resampler->main_buffer);
|
||||
free(resampler);
|
||||
}
|
||||
|
||||
static void *resampler_sinc_new(void)
|
||||
static void *resampler_sinc_new(double bandwidth_mod)
|
||||
{
|
||||
rarch_sinc_resampler_t *re = (rarch_sinc_resampler_t*)aligned_alloc__(128, sizeof(*re));
|
||||
rarch_sinc_resampler_t *re = (rarch_sinc_resampler_t*)calloc(1, sizeof(*re));
|
||||
if (!re)
|
||||
return NULL;
|
||||
|
||||
memset(re, 0, sizeof(*re));
|
||||
|
||||
init_sinc_table(re);
|
||||
re->taps = TAPS;
|
||||
double cutoff = CUTOFF;
|
||||
|
||||
// Downsampling, must lower cutoff, and extend number of taps accordingly to keep same stopband attenuation.
|
||||
if (bandwidth_mod < 1.0)
|
||||
{
|
||||
cutoff *= bandwidth_mod;
|
||||
re->taps = (unsigned)ceil(re->taps / bandwidth_mod);
|
||||
}
|
||||
|
||||
// Be SIMD-friendly.
|
||||
#if (defined(__AVX__) && ENABLE_AVX) || defined(HAVE_NEON)
|
||||
re->taps = (re->taps + 7) & ~7;
|
||||
#else
|
||||
re->taps = (re->taps + 3) & ~3;
|
||||
#endif
|
||||
|
||||
size_t phase_elems = (1 << PHASE_BITS) * re->taps;
|
||||
#if SINC_COEFF_LERP
|
||||
phase_elems *= 2;
|
||||
#endif
|
||||
size_t elems = phase_elems + 4 * re->taps;
|
||||
|
||||
re->main_buffer = (sample_t*)aligned_alloc__(128, sizeof(sample_t) * elems);
|
||||
if (!re->main_buffer)
|
||||
goto error;
|
||||
|
||||
re->phase_table = re->main_buffer;
|
||||
re->buffer_l = re->main_buffer + phase_elems;
|
||||
re->buffer_r = re->buffer_l + 2 * re->taps;
|
||||
|
||||
init_sinc_table(re, cutoff, re->phase_table, 1 << PHASE_BITS, re->taps, SINC_COEFF_LERP);
|
||||
|
||||
#if defined(__AVX__) && ENABLE_AVX
|
||||
RARCH_LOG("Sinc resampler [AVX]\n");
|
||||
@ -311,9 +498,12 @@ static void *resampler_sinc_new(void)
|
||||
RARCH_LOG("Sinc resampler [C]\n");
|
||||
#endif
|
||||
|
||||
RARCH_LOG("SINC params (%u phase bits, %u taps).\n", PHASE_BITS, TAPS);
|
||||
|
||||
RARCH_LOG("SINC params (%u phase bits, %u taps).\n", PHASE_BITS, re->taps);
|
||||
return re;
|
||||
|
||||
error:
|
||||
resampler_sinc_free(re);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const rarch_resampler_t sinc_resampler = {
|
||||
|
@ -1,20 +1,25 @@
|
||||
TESTS := test-hermite test-sinc test-snr-sinc test-snr-hermite
|
||||
TESTS := test-hermite \
|
||||
test-snr-hermite \
|
||||
test-sinc-lowest \
|
||||
test-snr-sinc-lowest \
|
||||
test-sinc-lower \
|
||||
test-snr-sinc-lower \
|
||||
test-sinc \
|
||||
test-snr-sinc \
|
||||
test-sinc-higher \
|
||||
test-snr-sinc-higher \
|
||||
test-sinc-highest \
|
||||
test-snr-sinc-highest
|
||||
|
||||
CFLAGS += -O3 -g -Wall -pedantic -std=gnu99 -DRESAMPLER_TEST
|
||||
CFLAGS += -O3 -ffast-math -g -Wall -pedantic -march=native -std=gnu99 -DRESAMPLER_TEST
|
||||
LDFLAGS += -lm
|
||||
|
||||
all: $(TESTS)
|
||||
|
||||
test-hermite: ../hermite.o ../utils.o main.o resampler-hermite.o
|
||||
test-hermite: hermite.o ../utils.o main.o resampler-hermite.o
|
||||
$(CC) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test-sinc: ../sinc.o ../utils.o main.o ../hermite.o resampler-sinc.o
|
||||
$(CC) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test-snr-sinc: ../sinc.o ../utils.o snr.o ../hermite.o resampler-sinc.o
|
||||
$(CC) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test-snr-hermite: ../hermite.o ../utils.o snr.o resampler-hermite.o
|
||||
test-snr-hermite: hermite.o ../utils.o snr.o resampler-hermite.o
|
||||
$(CC) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
resampler-sinc.o: ../resampler.c
|
||||
@ -23,6 +28,54 @@ resampler-sinc.o: ../resampler.c
|
||||
resampler-hermite.o: ../resampler.c
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
hermite.o: ../hermite.c
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
sinc-lowest.o: ../sinc.c
|
||||
$(CC) -c -o $@ $< $(CFLAGS) -DHAVE_SINC -DSINC_LOWEST_QUALITY
|
||||
|
||||
sinc-lower.o: ../sinc.c
|
||||
$(CC) -c -o $@ $< $(CFLAGS) -DHAVE_SINC -DSINC_LOWER_QUALITY
|
||||
|
||||
sinc.o: ../sinc.c
|
||||
$(CC) -c -o $@ $< $(CFLAGS) -DHAVE_SINC
|
||||
|
||||
sinc-higher.o: ../sinc.c
|
||||
$(CC) -c -o $@ $< $(CFLAGS) -DHAVE_SINC -DSINC_HIGHER_QUALITY
|
||||
|
||||
sinc-highest.o: ../sinc.c
|
||||
$(CC) -c -o $@ $< $(CFLAGS) -DHAVE_SINC -DSINC_HIGHEST_QUALITY
|
||||
|
||||
test-sinc-lowest: sinc-lowest.o ../utils.o main.o ../hermite.o resampler-sinc.o
|
||||
$(CC) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test-snr-sinc-lowest: sinc-lowest.o ../utils.o snr.o ../hermite.o resampler-sinc.o
|
||||
$(CC) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test-sinc-lower: sinc-lower.o ../utils.o main.o ../hermite.o resampler-sinc.o
|
||||
$(CC) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test-snr-sinc-lower: sinc-lower.o ../utils.o snr.o ../hermite.o resampler-sinc.o
|
||||
$(CC) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test-sinc: sinc.o ../utils.o main.o ../hermite.o resampler-sinc.o
|
||||
$(CC) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test-snr-sinc: sinc.o ../utils.o snr.o ../hermite.o resampler-sinc.o
|
||||
$(CC) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test-sinc-higher: sinc-higher.o ../utils.o main.o ../hermite.o resampler-sinc.o
|
||||
$(CC) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test-snr-sinc-higher: sinc-higher.o ../utils.o snr.o ../hermite.o resampler-sinc.o
|
||||
$(CC) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test-sinc-highest: sinc-highest.o ../utils.o main.o ../hermite.o resampler-sinc.o
|
||||
$(CC) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test-snr-sinc-highest: sinc-highest.o ../utils.o snr.o ../hermite.o resampler-sinc.o
|
||||
$(CC) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
|
6
audio/test/kaiser_window.m
Normal file
6
audio/test/kaiser_window.m
Normal file
@ -0,0 +1,6 @@
|
||||
function win = kaiser_window(N, beta)
|
||||
% Create an N-point kaiser window with given beta.
|
||||
|
||||
indices = 2 * (0 : N - 1) / (N - 1) - 1;
|
||||
mod = modified_bessel(beta);
|
||||
win = modified_bessel(beta * sqrt(1 - indices.^2)) / mod;
|
@ -47,7 +47,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
const rarch_resampler_t *resampler = NULL;
|
||||
void *re = NULL;
|
||||
if (!rarch_resampler_realloc(&re, &resampler, NULL))
|
||||
if (!rarch_resampler_realloc(&re, &resampler, NULL, out_rate / in_rate))
|
||||
{
|
||||
fprintf(stderr, "Failed to allocate resampler ...\n");
|
||||
return 1;
|
||||
|
21
audio/test/modified_bessel.m
Normal file
21
audio/test/modified_bessel.m
Normal file
@ -0,0 +1,21 @@
|
||||
function val = modified_bessel(x)
|
||||
|
||||
% Mirrors operation as done in RetroArch. Verify accuracy against Matlab's
|
||||
% implementation.
|
||||
|
||||
sum = zeros(size(x));
|
||||
factorial = ones(size(x));
|
||||
factorial_mult = zeros(size(x));
|
||||
x_pow = ones(size(x));
|
||||
two_div_pow = ones(size(x));
|
||||
x_sqr = x .* x;
|
||||
|
||||
for i = 0 : 17
|
||||
sum = sum + x_pow .* two_div_pow ./ (factorial .* factorial);
|
||||
factorial_mult = factorial_mult + 1.0;
|
||||
x_pow = x_pow .* x_sqr;
|
||||
two_div_pow = two_div_pow * 0.25;
|
||||
factorial = factorial .* factorial_mult;
|
||||
end
|
||||
|
||||
val = sum;
|
49
audio/test/sinc_test.m
Normal file
49
audio/test/sinc_test.m
Normal file
@ -0,0 +1,49 @@
|
||||
% MATLAB test case for RetroArch SINC upsampler.
|
||||
close all;
|
||||
|
||||
%%
|
||||
% Test RetroArch's kaiser function.
|
||||
real_kaiser = kaiser(1024, 10.0)';
|
||||
rarch_kaiser = kaiser_window(1024, 10.0);
|
||||
figure('name', 'Bessel function test');
|
||||
subplot(2, 1, 1), plot(rarch_kaiser), title('RetroArch kaiser');
|
||||
subplot(2, 1, 2), plot(rarch_kaiser - real_kaiser), title('Error');
|
||||
|
||||
%%
|
||||
% 4-tap and 8-tap are Lanczos windowed, but include here for completeness.
|
||||
phases = 256;
|
||||
bw = 0.375;
|
||||
downsample = round(phases / bw);
|
||||
cutoffs = bw * [0.65 0.75 0.825 0.90 0.95];
|
||||
betas = [2.0 3.0 5.5 10.5 14.5];
|
||||
|
||||
sidelobes = round([2 4 8 32 128] / bw);
|
||||
taps = sidelobes * 2;
|
||||
|
||||
freqs = 0.05 : 0.02 : 0.99;
|
||||
|
||||
filters = length(taps);
|
||||
for i = 1 : filters
|
||||
filter_length = taps(i) * phases;
|
||||
|
||||
% Generate SINC.
|
||||
sinc_indices = 2 * ((0 : (filter_length - 1)) / (filter_length - 1)) - 1;
|
||||
s = cutoffs(i) * sinc(cutoffs(i) * sinc_indices * sidelobes(i));
|
||||
win = kaiser(filter_length, betas(i))';
|
||||
filter = s .* win;
|
||||
|
||||
impulse_response_half = 0.5 * upfirdn(1, filter, phases, downsample);
|
||||
figure('name', sprintf('Response SINC: %d taps', taps(i)));
|
||||
freqz(impulse_response_half);
|
||||
ylim([-200 0]);
|
||||
|
||||
signal = zeros(1, 8001);
|
||||
for freq = freqs
|
||||
signal = signal + sin(pi * freq * (0 : 8000));
|
||||
end
|
||||
|
||||
resampled = upfirdn(signal, filter, phases, downsample);
|
||||
figure('name', sprintf('Kaiser SINC: %d taps, w = %.f', taps(i), freq));
|
||||
freqz(resampled .* kaiser(length(resampled), 40.0)');
|
||||
ylim([-80 70]);
|
||||
end
|
@ -23,6 +23,9 @@
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#undef min
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
static void gen_signal(float *out, double omega, double bias_samples, size_t samples)
|
||||
{
|
||||
for (size_t i = 0; i < samples; i += 2)
|
||||
@ -244,15 +247,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
const unsigned fft_samples = 1024 * 128;
|
||||
unsigned out_rate = fft_samples / 2;
|
||||
unsigned in_rate = out_rate / ratio;
|
||||
unsigned in_rate = round(out_rate / ratio);
|
||||
ratio = (double)out_rate / in_rate;
|
||||
|
||||
if (ratio <= 1.0)
|
||||
{
|
||||
fprintf(stderr, "Ratio too low ...\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const float freq_list[] = {
|
||||
0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009,
|
||||
0.010, 0.015, 0.020, 0.025, 0.030, 0.035, 0.040, 0.045, 0.050,
|
||||
@ -265,19 +262,18 @@ int main(int argc, char *argv[])
|
||||
|
||||
unsigned samples = in_rate * 4;
|
||||
float *input = calloc(sizeof(float), samples);
|
||||
float *output = calloc(sizeof(float), (fft_samples + 1) * 2);
|
||||
float *output = calloc(sizeof(float), (fft_samples + 16) * 2);
|
||||
complex double *butterfly_buf = calloc(sizeof(complex double), fft_samples / 2);
|
||||
assert(input);
|
||||
assert(output);
|
||||
|
||||
void *re = NULL;
|
||||
const rarch_resampler_t *resampler = NULL;
|
||||
if (!rarch_resampler_realloc(&re, &resampler, NULL))
|
||||
if (!rarch_resampler_realloc(&re, &resampler, NULL, ratio))
|
||||
return 1;
|
||||
|
||||
test_fft();
|
||||
|
||||
printf("Omega,SNR,Gain\n");
|
||||
for (unsigned i = 0; i < sizeof(freq_list) / sizeof(freq_list[0]); i++)
|
||||
{
|
||||
unsigned freq = freq_list[i] * in_rate;
|
||||
@ -293,12 +289,13 @@ int main(int argc, char *argv[])
|
||||
|
||||
rarch_resampler_process(resampler, re, &data);
|
||||
|
||||
unsigned out_samples = data.output_frames * 2;
|
||||
assert(out_samples >= fft_samples * 2);
|
||||
|
||||
// We generate 2 seconds worth of audio, however, only the last second is considered so phase has stabilized.
|
||||
struct snr_result res;
|
||||
calculate_snr(&res, freq, in_rate / 2, output + fft_samples, butterfly_buf, fft_samples);
|
||||
struct snr_result res = {0};
|
||||
unsigned max_freq = min(in_rate, out_rate) / 2;
|
||||
if (freq > max_freq)
|
||||
continue;
|
||||
|
||||
calculate_snr(&res, freq, max_freq, output + fft_samples - 2048, butterfly_buf, fft_samples);
|
||||
|
||||
printf("SNR @ w = %5.3f : %6.2lf dB, Gain: %6.1lf dB\n",
|
||||
freq_list[i], res.snr, res.gain);
|
||||
|
@ -37,7 +37,6 @@ CONSOLE EXTENSIONS
|
||||
|
||||
#ifdef HW_DOL
|
||||
#include "../../ngc/ssaram.c"
|
||||
#include "../../ngc/sidestep.c"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DEFAULT_RETROPAD_INPUT
|
||||
@ -229,22 +228,6 @@ INPUT
|
||||
#include "../../input/overlay.c"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WIIUSE
|
||||
#include "../../wii/wiiuse/classic.c"
|
||||
#include "../../wii/wiiuse/dynamics.c"
|
||||
#include "../../wii/wiiuse/events.c"
|
||||
#include "../../wii/wiiuse/io.c"
|
||||
#include "../../wii/wiiuse/io_wii.c"
|
||||
#include "../../wii/wiiuse/ir.c"
|
||||
#include "../../wii/wiiuse/motion_plus.c"
|
||||
#include "../../wii/wiiuse/nunchuk.c"
|
||||
#ifdef HAVE_WIIUSE_SPEAKER
|
||||
#include "../../wii/wiiuse/speaker.c"
|
||||
#endif
|
||||
#include "../../wii/wiiuse/wiiuse.c"
|
||||
#include "../../wii/wiiuse/wpad.c"
|
||||
#endif
|
||||
|
||||
#if defined(__CELLOS_LV2__)
|
||||
#include "../../ps3/ps3_input.c"
|
||||
#elif defined(SN_TARGET_PSP2) || defined(PSP)
|
||||
|
16
dist-scripts/ngc-cores.sh
Executable file
16
dist-scripts/ngc-cores.sh
Executable file
@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
make -C ../ -f Makefile.ngc clean || exit 1
|
||||
|
||||
for f in *_ngc.a ; do
|
||||
name=`echo "$f" | sed 's/\(_libretro\|\)_ngc.a$//'`
|
||||
whole_archive=
|
||||
if [ $name = "nxengine" ] ; then
|
||||
whole_archive="WHOLE_ARCHIVE_LINK=1"
|
||||
echo $name yes
|
||||
fi
|
||||
cp -f "$f" ../libretro_ngc.a
|
||||
make -C ../ -f Makefile.ngc $whole_archive -j3 || exit 1
|
||||
mv -f ../retroarch_ngc.dol ../ngc/pkg/$name.dol
|
||||
rm -f ../retroarch_ngc.dol ../retroarch_ngc.elf ../retroarch_ngc.elf.map
|
||||
done
|
@ -1,5 +1,5 @@
|
||||
------------------------------------------------------------------------------
|
||||
RETROARCH 360 - 0.9.8.3
|
||||
RETROARCH 360 - 0.9.8.4
|
||||
------------------------------------------------------------------------------
|
||||
RetroConsole Level: 2
|
||||
Author: Themaister, Squarepusher/Twin Aphex
|
||||
|
@ -1,5 +1,14 @@
|
||||
RETROARCH CONSOLE
|
||||
------------------------------------------------------------------------------
|
||||
v0.9.8.4
|
||||
------------------------------------------------------------------------------
|
||||
* [FBA core] [For Wii/Gamecube/Xbox 1 only] The main FBA version now has CPS1/CPS2/
|
||||
Neogeo and Mega Drive/PC Engine drivers removed. To play CPS1, use FBA Cores CPS1.
|
||||
To play CPS2, use FBA Cores CPS2. To play NeoGoe, use FBA Cores Neo.
|
||||
* [FBA core] Made FBA Cores CPS1 - use this to play CPS1 games (all CPS1 ROMs
|
||||
fit into memory on Gamecube).
|
||||
* [Gamecube] Made RetroArch cores 'standalone' - ie. no core switching.
|
||||
------------------------------------------------------------------------------
|
||||
v0.9.8.3
|
||||
------------------------------------------------------------------------------
|
||||
* [FBA core] Various changes/fixes
|
||||
|
226
dist-scripts/retroarch-ngc-readme.txt
Normal file
226
dist-scripts/retroarch-ngc-readme.txt
Normal file
@ -0,0 +1,226 @@
|
||||
------------------------------------------------------------------------------
|
||||
RETROARCH GX - GAMECUBE - 0.9.8.4
|
||||
------------------------------------------------------------------------------
|
||||
RetroConsole Level: 0
|
||||
Author: Themaister, Toad King, Squarepusher/Twin Aphex
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
HOW TO INSTALL THIS
|
||||
------------------------------------------------------------------------------
|
||||
Copy the entire directory (retroarch-ngc) to your SD card in your 'apps'
|
||||
directory. Start up something like SDLOAD (or whatever you're using for
|
||||
loading DOL files) and load any of the cores.
|
||||
|
||||
|
||||
On first startup, RetroArch will create a folder in the root of your storage
|
||||
device called 'retroarch'. All RetroArch configuration files are stored here.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
HOW TO USE THIS
|
||||
------------------------------------------------------------------------------
|
||||
On first startup, RetroArch will select one of the dozen or so
|
||||
emulator/game cores. The name of the core currently loaded will be
|
||||
shown at the bottom side of the screen.
|
||||
|
||||
You can now select a ROM that this core supports and load it in the Filebrowser.
|
||||
|
||||
To select a different core - go to the Settings menu (see 'Ingame controls').
|
||||
Select the option 'Core' and hit the A button. A filebrowser will appear
|
||||
where you can select a different core. Press A to switch to the
|
||||
emulator/game core.
|
||||
|
||||
After doing so, select 'Restart RetroArch' to load the newly selected core.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
CONTROLS
|
||||
------------------------------------------------------------------------------
|
||||
RetroArch will create a new input config file for each core you load.
|
||||
All input settings will be saved when RetroArch exits.
|
||||
|
||||
NOTE: When starting up a new core for the first time, you might have to first
|
||||
initialize the input settings. Go to the Settings menu (see 'Ingame controls')
|
||||
and go to 'Controller #number config'. Re-set the 'Device' by going back and
|
||||
forth between a previous device. The controls will be automatically applied.
|
||||
|
||||
This only has to be done once per core.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
INGAME CONTROLS
|
||||
------------------------------------------------------------------------------
|
||||
During ingame operation you can do some extra actions:
|
||||
|
||||
|
||||
Gamecube pad Z - Go to Settings
|
||||
Gamecube pad L + R + LStick Up + Rstick Up - Go back to 'Menu'
|
||||
Gamecube pad L + R + LStick Down + Rstick Down - Quit RetroArch
|
||||
|
||||
Right Thumb Stick - Down - Fast-forwards the game
|
||||
Right Thumb Stick - Up - Rewinds the game in real-time
|
||||
('Rewind' has to be enabled in the
|
||||
'Settings' menu - warning - comes at a
|
||||
performance decrease but will be worth it
|
||||
if you love this feature)
|
||||
RStick Left + Z - Decrease save state slot
|
||||
Rtick Right + Z - Increase save state slot
|
||||
RStick Up + Z - Load selected save state slot
|
||||
RStick Down + Z - Save selected save state slot
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
WHAT IS RETROARCH?
|
||||
------------------------------------------------------------------------------
|
||||
RetroArch is a modular multi-system emulator system that is designed to
|
||||
be fast, lightweight and portable.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
WHAT IS LIBRETRO?
|
||||
------------------------------------------------------------------------------
|
||||
Libretro is the API that RetroArch uses. It makes it easy to port games
|
||||
and emulators to a single core backend, such as RetroArch.
|
||||
|
||||
For the user, this means - more ports to play with, more crossplatform
|
||||
portability, less worrying about developers having to reinvent the wheel
|
||||
writing boilerplate UI/port code - so that they can get busy with writing
|
||||
the emulator/porting the emulator/game.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
WHAT'S THE BIG DEAL?
|
||||
------------------------------------------------------------------------------
|
||||
Right now it's unique in that it runs the same emulator cores on
|
||||
multiple systems (such as Xbox 360, Xbox 1, PS3, PC, Wii, Android,
|
||||
etc).
|
||||
|
||||
For each emulator 'core', RetroArch makes use of a library API that we
|
||||
like to call 'libretro'.
|
||||
|
||||
Think of libretro as an interface for emulator and game ports. You can
|
||||
make a libretro port once and expect the same code to run on all the
|
||||
platforms that RetroArch supports. It's designed with simplicity and
|
||||
ease of use in mind so that the porter can worry about the port at hand
|
||||
instead of having to wrestle with an obfuscatory API.
|
||||
|
||||
The purpose of libretro is to help ease the work of the emulator/game
|
||||
porter by giving him an API that allows him to target multiple platforms
|
||||
at once without having to redo any code. He doesn't have to worry about
|
||||
writing input/video/audio drivers - all of that is supplied to him by
|
||||
RetroArch. All he has to do is to have the emulator port hook into the
|
||||
libretro API and that's it - we take care of the rest.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
WII PORT
|
||||
------------------------------------------------------------------------------
|
||||
The Gamecube port of RetroArch has the following features:
|
||||
|
||||
- Real-time rewinding (probably too slow for most cores)
|
||||
- Switching between emulator cores seamlessly, and ability to install
|
||||
new libretro cores
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
EMULATOR/GAME CORES BUNDLED WITH WII PORT
|
||||
------------------------------------------------------------------------------
|
||||
The following emulators/games have been ported to RetroArch and are included in
|
||||
the Gamecube release of RetroArch.
|
||||
|
||||
For more information about them, see the included
|
||||
'retroarch-libretro-README.txt' file.
|
||||
|
||||
- Final Burn Alpha [version 0.2.97.28]
|
||||
- Final Burn Alpha Cores (CPS1 - CPS2 - NeoGeo) [version 0.2.97.28] (**)
|
||||
- FCEUmm (Nintendo Entertainment System) [recent SVN version]
|
||||
- NEStopia (Nintendo Entertainment System) [1.44]
|
||||
- Gambatte (Game Boy | Super Game Boy | Game Boy Color) [version 0.5.0 WIP]
|
||||
- Genesis Plus GX (Sega SG-1000 | Master System | Game Gear | Genesis/Mega Drive |
|
||||
Sega CD) [version 1.7.3]
|
||||
- SNES9x Next (Super Nintendo/Super Famicom)
|
||||
- VBA Next (Game Boy Advance) (*)
|
||||
- Prboom (for playing Doom 1/Doom 2/Ultimate Doom/Final Doom)
|
||||
- Mednafen PCE Fast (PC Engine/PC Engine CD/Turbografx 16)
|
||||
- Mednafen Wonderswan (WonderSwan/WonderSwan Color/WonderSwan Crystal)
|
||||
- Mednafen NGP (Neo Geo Pocket Color)
|
||||
- Mednafen VB (Virtual Boy)
|
||||
|
||||
All of the emulators listed above are the latest versions currently
|
||||
available. Most of them have been specifically optimized so that
|
||||
they will run better on Gamecube (some games would not reach fullspeed
|
||||
without these optimizations).
|
||||
|
||||
* Most (all) games don't run at fullspeed on Gamecube (VBA Next is a
|
||||
RetroConsole Level 2 emulator port).
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
WHAT EXTENSIONS ARE SUPPORTED BY EACH CORE
|
||||
------------------------------------------------------------------------------
|
||||
- Prboom WAD|wad
|
||||
- SNES9x Next smc|fig|sfc|gd3|gd7|dx2|bsx|swc|zip|SMC|FIG|SFC|BSX|GD3|
|
||||
GD7|DX2|SWC
|
||||
- Genesis Plus GX md|smd|bin|gen|zip|MD|SMD|bin|GEN|ZIP|sms|SMS|gg|GG|sg|SG|
|
||||
cue|CUE
|
||||
- VBA Next GBA|gba
|
||||
- FCEUmm nes|NES|unif|UNIF
|
||||
- NEStopia nes|NES|fds|FDS
|
||||
- Gambatte gb|gbc|dmg|zip|GB|GBC|DMG|ZIP
|
||||
- Final Burn Alpha zip|ZIP
|
||||
- Mednafen PCE pce|PCE|cue|CUE
|
||||
- Mednafen Wonderswan ws|WS|wsc|WSC
|
||||
- Mednafen NGP ngp|NGP
|
||||
- Mednafen VB vb|VB
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
ZIP SUPPORT (IN GENERAL)
|
||||
------------------------------------------------------------------------------
|
||||
Selecting a ZIP file will temporarily unzip that file to the harddrive. The
|
||||
temporary file will be deleted as soon as the game gets unloaded and/or when
|
||||
you quit RetroArch.
|
||||
|
||||
NOTE: For the FBA core (and other cores that have 'block_extract' set to
|
||||
true) - selecting a ZIP file from the Filebrowser will load that game
|
||||
directly.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Troubleshooting
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
If you find that RetroArch no longer works for whatever reason, there is
|
||||
a way to get it back to work -
|
||||
|
||||
- Remove retroarch.cfg from the 'retroarch' folder on your storage device,
|
||||
then start up again. The Libretro management service in RetroArch should
|
||||
automatically pick a random libretro core and write this to the config file.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
What can you expect in the future?
|
||||
------------------------------------------------------------------------------
|
||||
- Do a Blackberry Playbook/Blackberry 10 RetroArch port
|
||||
- Do an iOS port of RetroArch (will need hardware for this - gifts appreciated)
|
||||
- Make the libxenon port release-worthy.
|
||||
- Add console-friendly features (nicely formatted names for FBA, some better
|
||||
way to do core switching, etc)
|
||||
- Fix NxEngine issues on consoles
|
||||
- Finish up MAME 0.72 port
|
||||
- Finish up ScummVM port
|
||||
- Port of VICE to libretro
|
||||
- More emulators, more games that will run on RetroArch
|
||||
- Lots of other crazy ideas that might or might not pan out
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Credits
|
||||
------------------------------------------------------------------------------
|
||||
- Hyllian for the xBR shader family.
|
||||
- Opium2k for the nice manual shaders (bundled with PS3 release).
|
||||
- Deank for assistance with RetroArch Salamander on CFW PS3s and
|
||||
- Mudlord for his Waterpaint/Noise shaders.
|
||||
Multiman interoperability.
|
||||
- FBA devs for adopting the libretro port.
|
||||
- Ekeeke for help with the Genesis Plus GX port.
|
||||
- ToadKing for having done a lot of work on RetroArch Wii.
|
||||
- Freakdave for helping out with the Xbox 1 port.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Websites
|
||||
------------------------------------------------------------------------------
|
||||
Twitter: http://twitter.com/libretro
|
||||
Source: http://github.com/libretro
|
||||
Homepage: http://www.libretro.org
|
||||
IRC: #retroarch (freenode)
|
||||
|
||||
------------------------------------------------------------------------------
|
@ -1,5 +1,5 @@
|
||||
------------------------------------------------------------------------------
|
||||
RETROARCH PS3 - 0.9.8.3
|
||||
RETROARCH PS3 - 0.9.8.4
|
||||
------------------------------------------------------------------------------
|
||||
RetroConsole Level: 2
|
||||
Author: Themaister, Squarepusher/Twin Aphex
|
||||
|
@ -1,5 +1,5 @@
|
||||
------------------------------------------------------------------------------
|
||||
RETROARCH WII - 0.9.8.3
|
||||
RETROARCH GX - WII - 0.9.8.4
|
||||
------------------------------------------------------------------------------
|
||||
RetroConsole Level: 1
|
||||
Author: Themaister, Toad King, Squarepusher/Twin Aphex
|
||||
|
@ -1,5 +1,5 @@
|
||||
------------------------------------------------------------------------------
|
||||
RETROARCH XBOX 1 - 0.9.8.3
|
||||
RETROARCH XBOX 1 - 0.9.8.4
|
||||
------------------------------------------------------------------------------
|
||||
RetroConsole Level: 1
|
||||
Author: Themaister, Squarepusher/Twin Aphex, Freakdave
|
||||
|
10
driver.c
10
driver.c
@ -409,9 +409,13 @@ void init_audio(void)
|
||||
g_extern.audio_data.chunk_size = g_extern.audio_data.nonblock_chunk_size;
|
||||
}
|
||||
|
||||
g_extern.audio_data.orig_src_ratio =
|
||||
g_extern.audio_data.src_ratio =
|
||||
(double)g_settings.audio.out_rate / g_settings.audio.in_rate;
|
||||
|
||||
const char *resampler = *g_settings.audio.resampler ? g_settings.audio.resampler : NULL;
|
||||
if (!rarch_resampler_realloc(&g_extern.audio_data.resampler_data, &g_extern.audio_data.resampler,
|
||||
resampler))
|
||||
resampler, g_extern.audio_data.orig_src_ratio))
|
||||
{
|
||||
RARCH_ERR("Failed to initialize resampler \"%s\".\n", resampler ? resampler : "(default)");
|
||||
g_extern.audio_active = false;
|
||||
@ -424,10 +428,6 @@ void init_audio(void)
|
||||
rarch_assert(g_settings.audio.out_rate < g_settings.audio.in_rate * AUDIO_MAX_RATIO);
|
||||
rarch_assert(g_extern.audio_data.outsamples = (sample_t*)malloc(outsamples_max * sizeof(sample_t)));
|
||||
|
||||
g_extern.audio_data.orig_src_ratio =
|
||||
g_extern.audio_data.src_ratio =
|
||||
(double)g_settings.audio.out_rate / g_settings.audio.in_rate;
|
||||
|
||||
if (g_extern.audio_active && g_settings.audio.rate_control)
|
||||
{
|
||||
if (driver.audio->buffer_size && driver.audio->write_avail)
|
||||
|
@ -28,7 +28,9 @@
|
||||
#include "platform/platform_ps3_exec.c"
|
||||
#elif defined(GEKKO)
|
||||
#include "platform/platform_gx.c"
|
||||
#ifdef HW_RVL
|
||||
#include "platform/platform_gx_exec.c"
|
||||
#endif
|
||||
#elif defined(_XBOX)
|
||||
#include "platform/platform_xdk.c"
|
||||
#include "platform/platform_xdk_exec.c"
|
||||
@ -111,8 +113,6 @@ static void verbose_log_init(void)
|
||||
RARCH_LOG("Turning on verbose logging...\n");
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBRETRO_MANAGEMENT
|
||||
|
||||
// Transforms a library id to a name suitable as a pathname.
|
||||
static void get_libretro_core_name(char *name, size_t size)
|
||||
{
|
||||
@ -141,6 +141,8 @@ static void get_libretro_core_name(char *name, size_t size)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBRETRO_MANAGEMENT
|
||||
|
||||
// If a CORE executable of name CORE.extension exists, rename filename
|
||||
// to a more sane name.
|
||||
static bool install_libretro_core(const char *core_exe_path, const char *tmp_path, const char *extension)
|
||||
|
@ -18,7 +18,9 @@
|
||||
#define _FRONTEND_CONSOLE_H
|
||||
|
||||
//optional RetroArch forward declarations
|
||||
#ifdef HAVE_RARCH_EXEC
|
||||
static void rarch_console_exec(const char *path);
|
||||
#endif
|
||||
static void verbose_log_init(void);
|
||||
|
||||
#ifdef IS_SALAMANDER
|
||||
@ -28,8 +30,6 @@ static void find_first_libretro_core(char *first_file,
|
||||
const char * ext);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBRETRO_MANAGEMENT
|
||||
static void get_libretro_core_name(char *name, size_t size);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -380,9 +380,12 @@ static void render_text(rgui_handle_t *rgui)
|
||||
rgui_file_type_t menu_type = 0;
|
||||
rgui_list_back(rgui->path_stack, &dir, &menu_type, NULL);
|
||||
|
||||
#ifdef HAVE_LIBRETRO_MANAGEMENT
|
||||
if (menu_type == RGUI_SETTINGS_CORE)
|
||||
snprintf(title, sizeof(title), "CORE SELECTION");
|
||||
else if (rgui_is_controller_menu(menu_type) || rgui_is_viewport_menu(menu_type) || menu_type == RGUI_SETTINGS)
|
||||
else
|
||||
#endif
|
||||
if (rgui_is_controller_menu(menu_type) || rgui_is_viewport_menu(menu_type) || menu_type == RGUI_SETTINGS)
|
||||
snprintf(title, sizeof(title), "SETTINGS: %s", dir);
|
||||
else
|
||||
snprintf(title, sizeof(title), "FILE BROWSER: %s", dir);
|
||||
@ -481,7 +484,9 @@ static void render_text(rgui_handle_t *rgui)
|
||||
snprintf(type_str, sizeof(type_str), (g_extern.lifecycle_mode_state & (1ULL << MODE_FPS_DRAW)) ? "ON" : "OFF");
|
||||
break;
|
||||
case RGUI_SETTINGS_CUSTOM_VIEWPORT:
|
||||
#ifdef HAVE_LIBRETRO_MANAGEMENT
|
||||
case RGUI_SETTINGS_CORE:
|
||||
#endif
|
||||
case RGUI_SETTINGS_CONTROLLER_1:
|
||||
case RGUI_SETTINGS_CONTROLLER_2:
|
||||
case RGUI_SETTINGS_CONTROLLER_3:
|
||||
@ -668,9 +673,11 @@ static int rgui_settings_toggle_setting(rgui_file_type_t setting, rgui_action_t
|
||||
{
|
||||
if(rgui_current_gx_resolution < GX_RESOLUTIONS_LAST - 1)
|
||||
{
|
||||
#ifdef HW_RVL
|
||||
if ((rgui_current_gx_resolution + 1) > GX_RESOLUTIONS_640_480)
|
||||
if (CONF_GetVideo() != CONF_VIDEO_PAL)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
rgui_current_gx_resolution++;
|
||||
gx_set_video_mode(rgui_gx_resolutions[rgui_current_gx_resolution][0], rgui_gx_resolutions[rgui_current_gx_resolution][1]);
|
||||
@ -784,7 +791,7 @@ static int rgui_settings_toggle_setting(rgui_file_type_t setting, rgui_action_t
|
||||
if (g_extern.main_is_init && changed)
|
||||
{
|
||||
if (!rarch_resampler_realloc(&g_extern.audio_data.resampler_data, &g_extern.audio_data.resampler,
|
||||
g_settings.audio.resampler))
|
||||
g_settings.audio.resampler, g_extern.audio_data.orig_src_ratio == 0.0 ? 1.0 : g_extern.audio_data.orig_src_ratio))
|
||||
{
|
||||
RARCH_ERR("Failed to initialize resampler \"%s\".\n", g_settings.audio.resampler);
|
||||
g_extern.audio_active = false;
|
||||
@ -924,7 +931,9 @@ static void rgui_settings_populate_entries(rgui_handle_t *rgui)
|
||||
RGUI_MENU_ITEM("Audio Resampler", RGUI_SETTINGS_RESAMPLER_TYPE);
|
||||
RGUI_MENU_ITEM("SRAM Saves in \"sram\" Dir", RGUI_SETTINGS_SRAM_DIR);
|
||||
RGUI_MENU_ITEM("State Saves in \"state\" Dir", RGUI_SETTINGS_STATE_DIR);
|
||||
#ifdef HAVE_LIBRETRO_MANAGEMENT
|
||||
RGUI_MENU_ITEM("Core", RGUI_SETTINGS_CORE);
|
||||
#endif
|
||||
RGUI_MENU_ITEM("Controller #1 Config", RGUI_SETTINGS_CONTROLLER_1);
|
||||
RGUI_MENU_ITEM("Controller #2 Config", RGUI_SETTINGS_CONTROLLER_2);
|
||||
RGUI_MENU_ITEM("Controller #3 Config", RGUI_SETTINGS_CONTROLLER_3);
|
||||
@ -1085,8 +1094,10 @@ int rgui_settings_iterate(rgui_handle_t *rgui, rgui_action_t action)
|
||||
rgui_file_type_t type = 0;
|
||||
const char *label = 0;
|
||||
rgui_list_at(rgui->folder_buf, rgui->directory_ptr, &label, &type, NULL);
|
||||
#ifdef HAVE_LIBRETRO_MANAGEMENT
|
||||
if (type == RGUI_SETTINGS_CORE)
|
||||
label = default_paths.core_dir;
|
||||
#endif
|
||||
const char *dir = 0;
|
||||
rgui_file_type_t menu_type = 0;
|
||||
size_t directory_ptr = 0;
|
||||
@ -1122,7 +1133,12 @@ int rgui_settings_iterate(rgui_handle_t *rgui, rgui_action_t action)
|
||||
case RGUI_ACTION_RIGHT:
|
||||
case RGUI_ACTION_OK:
|
||||
case RGUI_ACTION_START:
|
||||
if ((rgui_is_controller_menu(type) || type == RGUI_SETTINGS_CORE) && action == RGUI_ACTION_OK)
|
||||
if ((rgui_is_controller_menu(type)
|
||||
#ifdef HAVE_LIBRETRO_MANAGEMENT
|
||||
|| type == RGUI_SETTINGS_CORE
|
||||
#endif
|
||||
)
|
||||
&& action == RGUI_ACTION_OK)
|
||||
{
|
||||
rgui_list_push(rgui->path_stack, label, type, rgui->directory_ptr);
|
||||
rgui->directory_ptr = 0;
|
||||
@ -1158,7 +1174,11 @@ int rgui_settings_iterate(rgui_handle_t *rgui, rgui_action_t action)
|
||||
|
||||
rgui_list_back(rgui->path_stack, &dir, &menu_type, &directory_ptr);
|
||||
|
||||
if (rgui->need_refresh && !(menu_type == RGUI_FILE_DIRECTORY || menu_type == RGUI_FILE_DEVICE || menu_type == RGUI_SETTINGS_CORE))
|
||||
if (rgui->need_refresh && !(menu_type == RGUI_FILE_DIRECTORY || menu_type == RGUI_FILE_DEVICE
|
||||
#ifdef HAVE_LIBRETRO_MANAGEMENT
|
||||
|| menu_type == RGUI_SETTINGS_CORE
|
||||
#endif
|
||||
))
|
||||
{
|
||||
rgui->need_refresh = false;
|
||||
if (rgui_is_controller_menu(menu_type))
|
||||
@ -1260,6 +1280,7 @@ int rgui_iterate(rgui_handle_t *rgui, rgui_action_t action)
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_LIBRETRO_MANAGEMENT
|
||||
if (menu_type == RGUI_SETTINGS_CORE)
|
||||
{
|
||||
strlcpy(g_settings.libretro, path, sizeof(g_settings.libretro));
|
||||
@ -1275,6 +1296,7 @@ int rgui_iterate(rgui_handle_t *rgui, rgui_action_t action)
|
||||
g_extern.lifecycle_mode_state |= (1ULL << MODE_EXITSPAWN);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
snprintf(rgui->path_buf, sizeof(rgui->path_buf), "%s/%s", dir, path);
|
||||
|
||||
@ -1297,6 +1319,7 @@ int rgui_iterate(rgui_handle_t *rgui, rgui_action_t action)
|
||||
break;
|
||||
|
||||
case RGUI_ACTION_SETTINGS:
|
||||
#ifdef HAVE_LIBRETRO_MANAGEMENT
|
||||
if (menu_type == RGUI_SETTINGS_CORE)
|
||||
{
|
||||
rgui->directory_ptr = directory_ptr;
|
||||
@ -1304,6 +1327,7 @@ int rgui_iterate(rgui_handle_t *rgui, rgui_action_t action)
|
||||
rgui_list_pop(rgui->path_stack);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
rgui_list_push(rgui->path_stack, "", RGUI_SETTINGS, rgui->directory_ptr);
|
||||
rgui->directory_ptr = 0;
|
||||
@ -1321,7 +1345,11 @@ int rgui_iterate(rgui_handle_t *rgui, rgui_action_t action)
|
||||
// refresh values in case the stack changed
|
||||
rgui_list_back(rgui->path_stack, &dir, &menu_type, &directory_ptr);
|
||||
|
||||
if (rgui->need_refresh && (menu_type == RGUI_FILE_DIRECTORY || menu_type == RGUI_FILE_DEVICE || menu_type == RGUI_SETTINGS_CORE))
|
||||
if (rgui->need_refresh && (menu_type == RGUI_FILE_DIRECTORY || menu_type == RGUI_FILE_DEVICE
|
||||
#ifdef HAVE_LIBRETRO_MANAGEMENT
|
||||
|| menu_type == RGUI_SETTINGS_CORE
|
||||
#endif
|
||||
))
|
||||
{
|
||||
rgui->need_refresh = false;
|
||||
rgui_list_clear(rgui->folder_buf);
|
||||
|
@ -58,7 +58,9 @@ typedef enum
|
||||
RGUI_SETTINGS_ZIP_EXTRACT,
|
||||
RGUI_SETTINGS_SRAM_DIR,
|
||||
RGUI_SETTINGS_STATE_DIR,
|
||||
#ifdef HAVE_LIBRETRO_MANAGEMENT
|
||||
RGUI_SETTINGS_CORE,
|
||||
#endif
|
||||
RGUI_SETTINGS_CONTROLLER_1,
|
||||
RGUI_SETTINGS_CONTROLLER_2,
|
||||
RGUI_SETTINGS_CONTROLLER_3,
|
||||
|
@ -1341,8 +1341,10 @@ static int set_setting_action(void *data, unsigned switchvalue, uint64_t input)
|
||||
case SETTING_DEFAULT_VIDEO_ALL:
|
||||
if(input & (1ULL << RMENU_DEVICE_NAV_START))
|
||||
{
|
||||
#if defined(HAVE_CG) || defined(HAVE_HLSL) || defined(HAVE_GLSL)
|
||||
set_setting_action(NULL, SETTING_SHADER, 1ULL << RMENU_DEVICE_NAV_START);
|
||||
set_setting_action(NULL, SETTING_SHADER_2, 1ULL << RMENU_DEVICE_NAV_START);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case SETTING_SOUND_MODE:
|
||||
|
@ -68,7 +68,11 @@ enum
|
||||
static bool folder_cb(const char *directory, rgui_file_enum_cb_t file_cb,
|
||||
void *userdata, void *ctx)
|
||||
{
|
||||
#ifdef HAVE_LIBRETRO_MANAGEMENT
|
||||
bool core_chooser = (userdata) ? *(rgui_file_type_t *)userdata == RGUI_SETTINGS_CORE : false;
|
||||
#else
|
||||
bool core_chooser = false;
|
||||
#endif
|
||||
|
||||
if (!*directory)
|
||||
{
|
||||
|
@ -334,9 +334,9 @@ static void system_init(void)
|
||||
|
||||
static void system_exitspawn(void)
|
||||
{
|
||||
#ifdef IS_SALAMANDER
|
||||
#if defined(IS_SALAMANDER)
|
||||
rarch_console_exec(default_paths.libretro_path);
|
||||
#else
|
||||
#elif defined(HW_RVL)
|
||||
// try to launch the core directly first, then fallback to salamander
|
||||
rarch_console_exec(g_settings.libretro);
|
||||
rarch_console_exec(g_extern.fullpath);
|
||||
|
@ -250,21 +250,7 @@ static bool gfx_ctx_init(void)
|
||||
if (g_inited)
|
||||
return false;
|
||||
|
||||
static const char *modules[] = {
|
||||
"i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", NULL
|
||||
};
|
||||
|
||||
for (int i = 0; modules[i]; i++)
|
||||
{
|
||||
RARCH_LOG("[KMS/EGL]: Trying to load module %s ...\n", modules[i]);
|
||||
g_drm_fd = drmOpen(modules[i], NULL);
|
||||
if (g_drm_fd >= 0)
|
||||
{
|
||||
RARCH_LOG("[KMS/EGL]: Found module %s.\n", modules[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_drm_fd = open("/dev/dri/card0", O_RDWR);
|
||||
if (g_drm_fd < 0)
|
||||
{
|
||||
RARCH_ERR("[KMS/EGL]: Couldn't open DRM device.\n");
|
||||
@ -281,58 +267,48 @@ static bool gfx_ctx_init(void)
|
||||
for (int i = 0; i < g_resources->count_connectors; i++)
|
||||
{
|
||||
g_connector = drmModeGetConnector(g_drm_fd, g_resources->connectors[i]);
|
||||
if (g_connector->connection == DRM_MODE_CONNECTED)
|
||||
|
||||
if (!g_connector)
|
||||
continue;
|
||||
if (g_connector->connection == DRM_MODE_CONNECTED && g_connector->count_modes > 0)
|
||||
break;
|
||||
|
||||
drmModeFreeConnector(g_connector);
|
||||
g_connector = NULL;
|
||||
}
|
||||
|
||||
// TODO: Figure out what index for crtcs to use ...
|
||||
g_orig_crtc = drmModeGetCrtc(g_drm_fd, g_resources->crtcs[0]);
|
||||
if (!g_orig_crtc)
|
||||
RARCH_WARN("[KMS/EGL]: Cannot find original CRTC.\n");
|
||||
|
||||
if (!g_connector)
|
||||
{
|
||||
RARCH_ERR("[KMS/EGL]: Couldn't get device connector.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (int i = 0, area = 0; i < g_connector->count_modes; i++)
|
||||
for (int i = 0; i < g_resources->count_encoders; i++)
|
||||
{
|
||||
drmModeModeInfo *current_mode = &g_connector->modes[i];
|
||||
int current_area = current_mode->hdisplay * current_mode->vdisplay;
|
||||
if (current_area > area)
|
||||
{
|
||||
g_drm_mode = current_mode;
|
||||
area = current_area;
|
||||
}
|
||||
g_encoder = drmModeGetEncoder(g_drm_fd, g_resources->encoders[i]);
|
||||
|
||||
if (!g_encoder)
|
||||
continue;
|
||||
if (g_encoder->encoder_id == g_connector->encoder_id)
|
||||
break;
|
||||
|
||||
drmModeFreeEncoder(g_encoder);
|
||||
g_encoder = NULL;
|
||||
}
|
||||
|
||||
if (!g_drm_mode)
|
||||
{
|
||||
RARCH_ERR("[KMS/EGL]: Couldn't find DRM mode.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (int i = 0; i < g_resources->count_encoders; i++)
|
||||
{
|
||||
g_encoder = drmModeGetEncoder(g_drm_fd, g_resources->encoders[i]);
|
||||
if (g_encoder->encoder_id == g_connector->encoder_id)
|
||||
break;
|
||||
|
||||
drmModeFreeEncoder(g_encoder);
|
||||
g_encoder = NULL;
|
||||
}
|
||||
|
||||
if (!g_encoder)
|
||||
if (!g_encoder)
|
||||
{
|
||||
RARCH_ERR("[KMS/EGL]: Couldn't find DRM encoder.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
g_crtc_id = g_encoder->crtc_id;
|
||||
g_drm_mode = &g_connector->modes[0];
|
||||
|
||||
g_crtc_id = g_encoder->crtc_id;
|
||||
g_orig_crtc = drmModeGetCrtc(g_drm_fd, g_crtc_id);
|
||||
if (!g_orig_crtc)
|
||||
RARCH_WARN("[KMS/EGL]: Cannot find original CRTC.\n");
|
||||
|
||||
g_connector_id = g_connector->connector_id;
|
||||
|
||||
g_fb_width = g_drm_mode->hdisplay;
|
||||
@ -381,6 +357,8 @@ static struct drm_fb *drm_fb_get_from_bo(struct gbm_bo *bo)
|
||||
unsigned stride = gbm_bo_get_stride(bo);
|
||||
unsigned handle = gbm_bo_get_handle(bo).u32;
|
||||
|
||||
RARCH_LOG("[KMS/EGL]: New FB: %ux%u (stride: %u).\n", width, height, stride);
|
||||
|
||||
int ret = drmModeAddFB(g_drm_fd, width, height, 24, 32, stride, handle, &fb->fb_id);
|
||||
if (ret < 0)
|
||||
{
|
||||
@ -412,11 +390,11 @@ static bool gfx_ctx_set_video_mode(
|
||||
|
||||
#define EGL_ATTRIBS_BASE \
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, \
|
||||
EGL_RED_SIZE, 0, \
|
||||
EGL_GREEN_SIZE, 0, \
|
||||
EGL_BLUE_SIZE, 0, \
|
||||
EGL_DEPTH_SIZE, 0, \
|
||||
EGL_STENCIL_SIZE, 0
|
||||
EGL_RED_SIZE, 1, \
|
||||
EGL_GREEN_SIZE, 1, \
|
||||
EGL_BLUE_SIZE, 1, \
|
||||
EGL_ALPHA_SIZE, 0, \
|
||||
EGL_DEPTH_SIZE, 0
|
||||
|
||||
static const EGLint egl_attribs_gl[] = {
|
||||
EGL_ATTRIBS_BASE,
|
||||
@ -575,7 +553,7 @@ void gfx_ctx_destroy(void)
|
||||
g_next_bo = NULL;
|
||||
|
||||
if (g_drm_fd >= 0)
|
||||
drmClose(g_drm_fd);
|
||||
close(g_drm_fd);
|
||||
g_drm_fd = -1;
|
||||
|
||||
unsigned frames = last_page_flip - first_page_flip;
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
static Display *g_dpy;
|
||||
static Window g_win;
|
||||
static GLXWindow g_glx_win;
|
||||
static Colormap g_cmap;
|
||||
static Atom g_quit_atom;
|
||||
static bool g_has_focus;
|
||||
@ -229,7 +230,7 @@ static void gfx_ctx_check_window(bool *quit,
|
||||
static void gfx_ctx_swap_buffers(void)
|
||||
{
|
||||
if (g_is_double)
|
||||
glXSwapBuffers(g_dpy, g_win);
|
||||
glXSwapBuffers(g_dpy, g_glx_win);
|
||||
}
|
||||
|
||||
static void gfx_ctx_set_resize(unsigned width, unsigned height)
|
||||
@ -281,6 +282,8 @@ static bool gfx_ctx_init(void)
|
||||
if (g_inited)
|
||||
return false;
|
||||
|
||||
XInitThreads();
|
||||
|
||||
static const int visual_attribs[] = {
|
||||
GLX_X_RENDERABLE , True,
|
||||
GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
|
||||
@ -402,6 +405,8 @@ static bool gfx_ctx_set_video_mode(
|
||||
CWBorderPixel | CWColormap | CWEventMask | (true_full ? CWOverrideRedirect : 0), &swa);
|
||||
XSetWindowBackground(g_dpy, g_win, 0);
|
||||
|
||||
g_glx_win = glXCreateWindow(g_dpy, g_fbc, g_win, 0);
|
||||
|
||||
gfx_ctx_update_window_title(true);
|
||||
x11_set_window_attr(g_dpy, g_win);
|
||||
|
||||
@ -444,7 +449,7 @@ static bool gfx_ctx_set_video_mode(
|
||||
goto error;
|
||||
}
|
||||
|
||||
glXMakeCurrent(g_dpy, g_win, g_ctx);
|
||||
glXMakeContextCurrent(g_dpy, g_glx_win, g_glx_win, g_ctx);
|
||||
XSync(g_dpy, False);
|
||||
|
||||
g_quit_atom = XInternAtom(g_dpy, "WM_DELETE_WINDOW", False);
|
||||
@ -493,13 +498,16 @@ static void gfx_ctx_destroy(void)
|
||||
{
|
||||
if (g_dpy && g_ctx)
|
||||
{
|
||||
glXMakeCurrent(g_dpy, None, NULL);
|
||||
glXMakeContextCurrent(g_dpy, None, None, NULL);
|
||||
glXDestroyContext(g_dpy, g_ctx);
|
||||
g_ctx = NULL;
|
||||
}
|
||||
|
||||
if (g_win)
|
||||
{
|
||||
glXDestroyWindow(g_dpy, g_glx_win);
|
||||
g_glx_win = 0;
|
||||
|
||||
// Save last used monitor for later.
|
||||
#ifdef HAVE_XINERAMA
|
||||
XWindowAttributes target;
|
||||
|
@ -180,13 +180,15 @@ static bool gfx_ctx_init(void)
|
||||
if (g_inited)
|
||||
return false;
|
||||
|
||||
XInitThreads();
|
||||
|
||||
#define EGL_ATTRIBS_BASE \
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, \
|
||||
EGL_RED_SIZE, 0, \
|
||||
EGL_GREEN_SIZE, 0, \
|
||||
EGL_BLUE_SIZE, 0, \
|
||||
EGL_DEPTH_SIZE, 0, \
|
||||
EGL_STENCIL_SIZE, 0
|
||||
EGL_RED_SIZE, 1, \
|
||||
EGL_GREEN_SIZE, 1, \
|
||||
EGL_BLUE_SIZE, 1, \
|
||||
EGL_ALPHA_SIZE, 0, \
|
||||
EGL_DEPTH_SIZE, 0
|
||||
|
||||
static const EGLint egl_attribs_gl[] = {
|
||||
EGL_ATTRIBS_BASE,
|
||||
|
@ -229,12 +229,8 @@ void gx_set_video_mode(unsigned fbWidth, unsigned lines)
|
||||
VIDEO_SetPostRetraceCallback(retrace_callback);
|
||||
VIDEO_SetBlack(false);
|
||||
VIDEO_Flush();
|
||||
//VIDEO_WaitVSync();
|
||||
//if (gx_mode.viTVMode & VI_NON_INTERLACE)
|
||||
// VIDEO_WaitVSync();
|
||||
|
||||
GX_SetViewport(0, 0, gx_mode.fbWidth, gx_mode.efbHeight, 0, 1);
|
||||
//GX_SetScissor(0, 0, gx_mode.fbWidth, gx_mode.efbHeight);
|
||||
GX_SetDispCopySrc(0, 0, gx_mode.fbWidth, gx_mode.efbHeight);
|
||||
|
||||
f32 y_scale = GX_GetYScaleFactor(gx_mode.efbHeight, gx_mode.xfbHeight);
|
||||
@ -693,6 +689,8 @@ static void gx_resize(void *data)
|
||||
unsigned width = gx->win_width, height = gx->win_height;
|
||||
uint64_t lifecycle_mode_state = g_extern.lifecycle_mode_state;
|
||||
|
||||
(void)lifecycle_mode_state;
|
||||
|
||||
#ifdef HW_RVL
|
||||
VIDEO_SetTrapFilter(lifecycle_mode_state & (1ULL << MODE_VIDEO_SOFT_FILTER_ENABLE));
|
||||
#endif
|
||||
|
@ -113,7 +113,7 @@
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PreprocessorDefinitions>_DEBUG;_XBOX;HAVE_XINPUT2;PACKAGE_VERSION="0.9.8.3";%(PreprocessorDefinitions);HAVE_DEFAULT_RETROPAD_INPUT;_CRT_SECURE_NO_WARNINGS;main=rarch_main;RARCH_CONSOLE;HAVE_RMENU;HAVE_FILEBROWSER;HAVE_NETPLAY;HAVE_SOCKET_LEGACY;HAVE_ZLIB;HAVE_RARCH_MAIN_WRAP;HAVE_RARCH_EXEC;HAVE_LIBRETRO_MANAGEMENT;D3DCOMPILE_USEVOIDS;HAVE_GRIFFIN;HAVE_HLSL;HAVE_VID_CONTEXT;HAVE_D3D9;_XBOX360;HAVE_FBO;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY;HAVE_XAUDIO</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_DEBUG;_XBOX;HAVE_XINPUT2;PACKAGE_VERSION="0.9.8.4";%(PreprocessorDefinitions);HAVE_DEFAULT_RETROPAD_INPUT;_CRT_SECURE_NO_WARNINGS;main=rarch_main;RARCH_CONSOLE;HAVE_RMENU;HAVE_FILEBROWSER;HAVE_NETPLAY;HAVE_SOCKET_LEGACY;HAVE_ZLIB;HAVE_RARCH_MAIN_WRAP;HAVE_RARCH_EXEC;HAVE_LIBRETRO_MANAGEMENT;D3DCOMPILE_USEVOIDS;HAVE_GRIFFIN;HAVE_HLSL;HAVE_VID_CONTEXT;HAVE_D3D9;_XBOX360;HAVE_FBO;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY;HAVE_XAUDIO</PreprocessorDefinitions>
|
||||
<CallAttributedProfiling>Callcap</CallAttributedProfiling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@ -151,7 +151,7 @@
|
||||
<PREfast>AnalyzeOnly</PREfast>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PreprocessorDefinitions>_DEBUG;_XBOX;%(PreprocessorDefinitions);HAVE_XINPUT2;PACKAGE_VERSION="0.9.8.3";HAVE_DEFAULT_RETROPAD_INPUT;_CRT_SECURE_NO_WARNINGS;main=rarch_main;HAVE_FILEBROWSER;RARCH_CONSOLE;HAVE_RMENU;HAVE_ZLIB;HAVE_RARCH_MAIN_WRAP;HAVE_RARCH_EXEC;HAVE_LIBRETRO_MANAGEMENT;D3DCOMPILE_USEVOIDS;HAVE_GRIFFIN;HAVE_HLSL;HAVE_VID_CONTEXT;HAVE_D3D9;_XBOX360;HAVE_FBO;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_DEBUG;_XBOX;%(PreprocessorDefinitions);HAVE_XINPUT2;PACKAGE_VERSION="0.9.8.4";HAVE_DEFAULT_RETROPAD_INPUT;_CRT_SECURE_NO_WARNINGS;main=rarch_main;HAVE_FILEBROWSER;RARCH_CONSOLE;HAVE_RMENU;HAVE_ZLIB;HAVE_RARCH_MAIN_WRAP;HAVE_RARCH_EXEC;HAVE_LIBRETRO_MANAGEMENT;D3DCOMPILE_USEVOIDS;HAVE_GRIFFIN;HAVE_HLSL;HAVE_VID_CONTEXT;HAVE_D3D9;_XBOX360;HAVE_FBO;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY</PreprocessorDefinitions>
|
||||
<CallAttributedProfiling>Callcap</CallAttributedProfiling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@ -190,7 +190,7 @@
|
||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PreprocessorDefinitions>NDEBUG;_XBOX;PROFILE;%(PreprocessorDefinitions);HAVE_XINPUT2;PACKAGE_VERSION="0.9.8.3";HAVE_DEFAULT_RETROPAD_INPUT;_CRT_SECURE_NO_WARNINGS;RARCH_CONSOLE;HAVE_RMENU;main=rarch_main;HAVE_FILEBROWSER;HAVE_ZLIB;HAVE_RARCH_MAIN_WRAP;HAVE_RARCH_EXEC;HAVE_LIBRETRO_MANAGEMENT;D3DCOMPILE_USEVOIDS;HAVE_GRIFFIN;HAVE_HLSL;HAVE_VID_CONTEXT;HAVE_D3D9;_XBOX360;HAVE_FBO;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY;HAVE_XAUDIO</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>NDEBUG;_XBOX;PROFILE;%(PreprocessorDefinitions);HAVE_XINPUT2;PACKAGE_VERSION="0.9.8.4";HAVE_DEFAULT_RETROPAD_INPUT;_CRT_SECURE_NO_WARNINGS;RARCH_CONSOLE;HAVE_RMENU;main=rarch_main;HAVE_FILEBROWSER;HAVE_ZLIB;HAVE_RARCH_MAIN_WRAP;HAVE_RARCH_EXEC;HAVE_LIBRETRO_MANAGEMENT;D3DCOMPILE_USEVOIDS;HAVE_GRIFFIN;HAVE_HLSL;HAVE_VID_CONTEXT;HAVE_D3D9;_XBOX360;HAVE_FBO;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY;HAVE_XAUDIO</PreprocessorDefinitions>
|
||||
<CallAttributedProfiling>Callcap</CallAttributedProfiling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
@ -234,7 +234,7 @@
|
||||
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PreprocessorDefinitions>NDEBUG;_XBOX;PROFILE;FASTCAP;%(PreprocessorDefinitions);HAVE_XINPUT2;PACKAGE_VERSION="0.9.8.3";HAVE_DEFAULT_RETROPAD_INPUT;_CRT_SECURE_NO_WARNINGS;main=rarch_main;HAVE_FILEBROWSER;HAVE_ZLIB;HAVE_RARCH_MAIN_WRAP;HAVE_RARCH_EXEC;HAVE_LIBRETRO_MANAGEMENT;D3DCOMPILE_USEVOIDS;HAVE_GRIFFIN;HAVE_HLSL;HAVE_VID_CONTEXT;HAVE_D3D9;_XBOX360;HAVE_FBO;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY;HAVE_RMENU;HAVE_XAUDIO</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>NDEBUG;_XBOX;PROFILE;FASTCAP;%(PreprocessorDefinitions);HAVE_XINPUT2;PACKAGE_VERSION="0.9.8.4";HAVE_DEFAULT_RETROPAD_INPUT;_CRT_SECURE_NO_WARNINGS;main=rarch_main;HAVE_FILEBROWSER;HAVE_ZLIB;HAVE_RARCH_MAIN_WRAP;HAVE_RARCH_EXEC;HAVE_LIBRETRO_MANAGEMENT;D3DCOMPILE_USEVOIDS;HAVE_GRIFFIN;HAVE_HLSL;HAVE_VID_CONTEXT;HAVE_D3D9;_XBOX360;HAVE_FBO;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY;HAVE_RMENU;HAVE_XAUDIO</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@ -275,7 +275,7 @@
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PreprocessorDefinitions>NDEBUG;_XBOX;%(PreprocessorDefinitions);HAVE_XINPUT2;PACKAGE_VERSION="0.9.8.3";_CRT_SECURE_NO_WARNINGS;HAVE_DEFAULT_RETROPAD_INPUT;main=rarch_main;RARCH_CONSOLE=1;HAVE_FILEBROWSER;HAVE_NETPLAY;HAVE_SOCKET_LEGACY;HAVE_ZLIB;HAVE_RARCH_MAIN_WRAP;HAVE_RARCH_EXEC;HAVE_LIBRETRO_MANAGEMENT;D3DCOMPILE_USEVOIDS;HAVE_GRIFFIN;HAVE_HLSL;HAVE_VID_CONTEXT;HAVE_D3D9;_XBOX360;HAVE_FBO;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY;HAVE_RMENU;HAVE_XAUDIO</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>NDEBUG;_XBOX;%(PreprocessorDefinitions);HAVE_XINPUT2;PACKAGE_VERSION="0.9.8.4";_CRT_SECURE_NO_WARNINGS;HAVE_DEFAULT_RETROPAD_INPUT;main=rarch_main;RARCH_CONSOLE=1;HAVE_FILEBROWSER;HAVE_NETPLAY;HAVE_SOCKET_LEGACY;HAVE_ZLIB;HAVE_RARCH_MAIN_WRAP;HAVE_RARCH_EXEC;HAVE_LIBRETRO_MANAGEMENT;D3DCOMPILE_USEVOIDS;HAVE_GRIFFIN;HAVE_HLSL;HAVE_VID_CONTEXT;HAVE_D3D9;_XBOX360;HAVE_FBO;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY;HAVE_RMENU;HAVE_XAUDIO</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
@ -316,7 +316,7 @@
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PreprocessorDefinitions>NDEBUG;_XBOX;LTCG;%(PreprocessorDefinitions);HAVE_XINPUT2;PACKAGE_VERSION="0.9.8.3";_CRT_SECURE_NO_WARNINGS;HAVE_DEFAULT_RETROPAD_INPUT;RARCH_CONSOLE;HAVE_RMENU;main=rarch_main;HAVE_FILEBROWSER;HAVE_NETPLAY;HAVE_SOCKET_LEGACY;HAVE_ZLIB;HAVE_RARCH_MAIN_WRAP;HAVE_RARCH_EXEC;HAVE_LIBRETRO_MANAGEMENT;D3DCOMPILE_USEVOIDS;HAVE_GRIFFIN;HAVE_HLSL;HAVE_VID_CONTEXT;HAVE_D3D9;_XBOX360;HAVE_FBO;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY;HAVE_XAUDIO</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>NDEBUG;_XBOX;LTCG;%(PreprocessorDefinitions);HAVE_XINPUT2;PACKAGE_VERSION="0.9.8.4";_CRT_SECURE_NO_WARNINGS;HAVE_DEFAULT_RETROPAD_INPUT;RARCH_CONSOLE;HAVE_RMENU;main=rarch_main;HAVE_FILEBROWSER;HAVE_NETPLAY;HAVE_SOCKET_LEGACY;HAVE_ZLIB;HAVE_RARCH_MAIN_WRAP;HAVE_RARCH_EXEC;HAVE_LIBRETRO_MANAGEMENT;D3DCOMPILE_USEVOIDS;HAVE_GRIFFIN;HAVE_HLSL;HAVE_VID_CONTEXT;HAVE_D3D9;_XBOX360;HAVE_FBO;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY;HAVE_XAUDIO</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
@ -22,7 +22,7 @@
|
||||
Optimization="3"
|
||||
OptimizeForProcessor="2"
|
||||
AdditionalIncludeDirectories=""$(SolutionDir)\msvc-stdint";"$(SolutionDir)\msvc-71""
|
||||
PreprocessorDefinitions="_DEBUG;_XBOX;_XBOX1;HAVE_RMENU;HAVE_RMENU_GUI;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;PACKAGE_VERSION=\"0.9.8.3\";__STDC_CONSTANT_MACROS;HAVE_ZLIB;HAVE_GRIFFIN;HAVE_RARCH_MAIN_WRAP;HAVE_LIBRETRO_MANAGEMENT;HAVE_RARCH_EXEC;HAVE_DEFAULT_RETROPAD_INPUT;HAVE_VID_CONTEXT;HAVE_DSOUND;HAVE_D3D8;HAVE_FILEBROWSER;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY"
|
||||
PreprocessorDefinitions="_DEBUG;_XBOX;_XBOX1;HAVE_RMENU;HAVE_RMENU_GUI;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;PACKAGE_VERSION=\"0.9.8.4\";__STDC_CONSTANT_MACROS;HAVE_ZLIB;HAVE_GRIFFIN;HAVE_RARCH_MAIN_WRAP;HAVE_LIBRETRO_MANAGEMENT;HAVE_RARCH_EXEC;HAVE_DEFAULT_RETROPAD_INPUT;HAVE_VID_CONTEXT;HAVE_DSOUND;HAVE_D3D8;HAVE_FILEBROWSER;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="0"
|
||||
RuntimeLibrary="1"
|
||||
@ -72,7 +72,7 @@
|
||||
OmitFramePointers="TRUE"
|
||||
OptimizeForProcessor="2"
|
||||
AdditionalIncludeDirectories=""$(SolutionDir)\msvc-stdint";"$(SolutionDir)\msvc-71""
|
||||
PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RMENU;HAVE_RMENU_GUI;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;PACKAGE_VERSION=\"0.9.8.3\";__STDC_CONSTANT_MACROS;HAVE_ZLIB;PROFILE;HAVE_GRIFFIN;HAVE_RARCH_MAIN_WRAP;HAVE_LIBRETRO_MANAGEMENT;HAVE_RARCH_EXEC;HAVE_DEFAULT_RETROPAD_INPUT;HAVE_VID_CONTEXT;HAVE_DSOUND;HAVE_D3D8;HAVE_FILEBROWSER;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY"
|
||||
PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RMENU;HAVE_RMENU_GUI;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;PACKAGE_VERSION=\"0.9.8.4\";__STDC_CONSTANT_MACROS;HAVE_ZLIB;PROFILE;HAVE_GRIFFIN;HAVE_RARCH_MAIN_WRAP;HAVE_LIBRETRO_MANAGEMENT;HAVE_RARCH_EXEC;HAVE_DEFAULT_RETROPAD_INPUT;HAVE_VID_CONTEXT;HAVE_DSOUND;HAVE_D3D8;HAVE_FILEBROWSER;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="TRUE"
|
||||
@ -127,7 +127,7 @@
|
||||
OmitFramePointers="TRUE"
|
||||
OptimizeForProcessor="2"
|
||||
AdditionalIncludeDirectories=""$(SolutionDir)\msvc-stdint";"$(SolutionDir)\msvc-71""
|
||||
PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RMENU;HAVE_RMENU_GUI;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;PACKAGE_VERSION=\"0.9.8.3\";__STDC_CONSTANT_MACROS;HAVE_ZLIB;PROFILE;FASTCAP;HAVE_GRIFFIN;HAVE_RARCH_MAIN_WRAP;HAVE_LIBRETRO_MANAGEMENT;HAVE_RARCH_EXEC;HAVE_DEFAULT_RETROPAD_INPUT;HAVE_VID_CONTEXT;HAVE_DSOUND;HAVE_D3D8;HAVE_FILEBROWSER;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY"
|
||||
PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RMENU;HAVE_RMENU_GUI;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;PACKAGE_VERSION=\"0.9.8.4\";__STDC_CONSTANT_MACROS;HAVE_ZLIB;PROFILE;FASTCAP;HAVE_GRIFFIN;HAVE_RARCH_MAIN_WRAP;HAVE_LIBRETRO_MANAGEMENT;HAVE_RARCH_EXEC;HAVE_DEFAULT_RETROPAD_INPUT;HAVE_VID_CONTEXT;HAVE_DSOUND;HAVE_D3D8;HAVE_FILEBROWSER;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="TRUE"
|
||||
@ -188,7 +188,7 @@
|
||||
EnableFiberSafeOptimizations="TRUE"
|
||||
OptimizeForProcessor="2"
|
||||
AdditionalIncludeDirectories=""$(SolutionDir)\msvc-stdint";"$(SolutionDir)\msvc-71""
|
||||
PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RMENU;HAVE_RMENU_GUI;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;PACKAGE_VERSION=\"0.9.8.3\";__STDC_CONSTANT_MACROS;HAVE_ZLIB;HAVE_GRIFFIN;inline=_inline;HAVE_RARCH_MAIN_WRAP;HAVE_LIBRETRO_MANAGEMENT;HAVE_RARCH_EXEC;HAVE_DEFAULT_RETROPAD_INPUT;HAVE_VID_CONTEXT;HAVE_DSOUND;HAVE_D3D8;HAVE_FILEBROWSER;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY"
|
||||
PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RMENU;HAVE_RMENU_GUI;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;PACKAGE_VERSION=\"0.9.8.4\";__STDC_CONSTANT_MACROS;HAVE_ZLIB;HAVE_GRIFFIN;inline=_inline;HAVE_RARCH_MAIN_WRAP;HAVE_LIBRETRO_MANAGEMENT;HAVE_RARCH_EXEC;HAVE_DEFAULT_RETROPAD_INPUT;HAVE_VID_CONTEXT;HAVE_DSOUND;HAVE_D3D8;HAVE_FILEBROWSER;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="TRUE"
|
||||
@ -241,7 +241,7 @@
|
||||
OmitFramePointers="TRUE"
|
||||
OptimizeForProcessor="2"
|
||||
AdditionalIncludeDirectories=""$(SolutionDir)\msvc-stdint";"$(SolutionDir)\msvc-71""
|
||||
PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RMENU;HAVE_RMENU_GUI;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;PACKAGE_VERSION=\"0.9.8.3\";__STDC_CONSTANT_MACROS;HAVE_ZLIB;LTCG;HAVE_GRIFFIN;HAVE_RARCH_MAIN_WRAP;HAVE_LIBRETRO_MANAGEMENT;HAVE_RARCH_EXEC;HAVE_DEFAULT_RETROPAD_INPUT;HAVE_VID_CONTEXT;HAVE_DSOUND;HAVE_D3D8;HAVE_FILEBROWSER;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY"
|
||||
PreprocessorDefinitions="NDEBUG;_XBOX;_XBOX1;HAVE_RMENU;HAVE_RMENU_GUI;RARCH_CONSOLE;HAVE_XINPUT_XBOX1;PACKAGE_VERSION=\"0.9.8.4\";__STDC_CONSTANT_MACROS;HAVE_ZLIB;LTCG;HAVE_GRIFFIN;HAVE_RARCH_MAIN_WRAP;HAVE_LIBRETRO_MANAGEMENT;HAVE_RARCH_EXEC;HAVE_DEFAULT_RETROPAD_INPUT;HAVE_VID_CONTEXT;HAVE_DSOUND;HAVE_D3D8;HAVE_FILEBROWSER;HAVE_SCREENSHOTS;WANT_RZLIB;HAVE_SINC;SINC_LOWER_QUALITY"
|
||||
StringPooling="TRUE"
|
||||
RuntimeLibrary="0"
|
||||
BufferSecurityCheck="TRUE"
|
||||
|
329
ngc/sidestep.c
329
ngc/sidestep.c
@ -1,329 +0,0 @@
|
||||
/** This code is licensed to you under the terms of the GNU GPL, version 2;
|
||||
see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt */
|
||||
|
||||
/****************************************************************************
|
||||
* SideStep DOL Loading
|
||||
*
|
||||
* This module runs a DOL file from Auxilliary RAM. This removes any memory
|
||||
* issues which might occur - and also means you can easily overwrite yourself!
|
||||
*
|
||||
* softdev March 2007
|
||||
***************************************************************************/
|
||||
#ifndef HW_RVL
|
||||
#include <gccore.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <network.h>
|
||||
#include <smb.h>
|
||||
|
||||
#include "sidestep.h"
|
||||
#include "ssaram.h"
|
||||
#include "../retroarch_logger.h"
|
||||
|
||||
#define ARAMSTART 0x8000
|
||||
|
||||
/*** A global or two ***/
|
||||
static DOLHEADER *dolhdr;
|
||||
static u32 minaddress = 0;
|
||||
static u32 maxaddress = 0;
|
||||
static char dol_readbuf[2048];
|
||||
|
||||
typedef int (*BOOTSTUB) (u32 entrypoint, u32 dst, u32 src, int len, u32 invlen, u32 invaddress);
|
||||
|
||||
/*--- Auxilliary RAM Support ----------------------------------------------*/
|
||||
/****************************************************************************
|
||||
* ARAMStub
|
||||
*
|
||||
* This is an assembly routine and should only be called through ARAMRun
|
||||
* *DO NOT CALL DIRECTLY!*
|
||||
****************************************************************************/
|
||||
static void ARAMStub(void)
|
||||
{
|
||||
/*** The routine expects to receive
|
||||
R3 = entrypoint
|
||||
R4 = Destination in main RAM
|
||||
R5 = Source from ARAM
|
||||
R6 = Data length
|
||||
R7 = Invalidate Length / 32
|
||||
R8 = Invalidate Start Address
|
||||
***/
|
||||
|
||||
asm("mtctr 7");
|
||||
asm("Invalidate:");
|
||||
asm("dcbi 0,8");
|
||||
asm("addi 8,8,32");
|
||||
asm("bdnz Invalidate");
|
||||
|
||||
asm("lis 8,0xcc00");
|
||||
asm("ori 8,8,0x3004");
|
||||
asm("lis 7,0");
|
||||
asm("stw 7,0(8)");
|
||||
|
||||
asm("mfmsr 8");
|
||||
asm("ori 8,8,2");
|
||||
asm("rlwinm 8,8,0,17,15");
|
||||
asm("mtmsr 8");
|
||||
|
||||
asm("lis 7,0xcc00");
|
||||
asm("ori 7,7,0x5020");
|
||||
asm("stw 4,0(7)"); /*** Store Memory Address ***/
|
||||
asm("stw 5,4(7)"); /*** Store ARAM Address ***/
|
||||
asm("stw 6,8(7)"); /*** Store Length ***/
|
||||
|
||||
asm("lis 7,0xcc00");
|
||||
asm("ori 7,7,0x500a");
|
||||
asm("WaitDMA:");
|
||||
asm("lhz 5,0(7)");
|
||||
asm("andi. 5,5,0x200");
|
||||
asm("cmpwi 5,5,0");
|
||||
asm("bne WaitDMA"); /*** Wait DMA Complete ***/
|
||||
|
||||
/*** Update exceptions ***/
|
||||
asm("lis 8,0x8000");
|
||||
asm("lis 5,0x4c00");
|
||||
asm("ori 5,5,0x64");
|
||||
asm("stw 5,0x100(8)");
|
||||
asm("stw 5,0x200(8)");
|
||||
asm("stw 5,0x300(8)");
|
||||
asm("stw 5,0x400(8)");
|
||||
asm("stw 5,0x500(8)");
|
||||
asm("stw 5,0x600(8)");
|
||||
asm("stw 5,0x700(8)");
|
||||
asm("stw 5,0x800(8)");
|
||||
asm("stw 5,0x900(8)");
|
||||
asm("stw 5,0xC00(8)");
|
||||
asm("stw 5,0xD00(8)");
|
||||
asm("stw 5,0xF00(8)");
|
||||
asm("stw 5,0x1300(8)");
|
||||
asm("stw 5,0x1400(8)");
|
||||
asm("stw 5,0x1700(8)");
|
||||
|
||||
/*** Flush it all again ***/
|
||||
asm("lis 7,0x30");
|
||||
asm("lis 8,0x8000");
|
||||
asm("mtctr 7");
|
||||
asm("flush:");
|
||||
asm("dcbst 0,8");
|
||||
asm("sync");
|
||||
asm("icbi 0,8");
|
||||
asm("addi 8,8,8");
|
||||
asm("bdnz flush");
|
||||
asm("isync");
|
||||
|
||||
/*** Fix ints ***/
|
||||
asm("mfmsr 8");
|
||||
asm("rlwinm 8,8,0,17,15");
|
||||
asm("mtmsr 8");
|
||||
|
||||
asm("mfmsr 8");
|
||||
asm("ori 8,8,8194");
|
||||
asm("mtmsr 8");
|
||||
|
||||
/*** Party! ***/
|
||||
asm("mtlr 3");
|
||||
asm("blr"); /*** Boot DOL ***/
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* ARAMRun
|
||||
*
|
||||
* This actually runs the new DOL ... eventually ;)
|
||||
****************************************************************************/
|
||||
void ARAMRun(u32 entrypoint, u32 dst, u32 src, u32 len)
|
||||
{
|
||||
char *p;
|
||||
char *s = (char *) ARAMStub;
|
||||
BOOTSTUB stub;
|
||||
|
||||
/*** Shutdown libOGC ***/
|
||||
SYS_ResetSystem(SYS_SHUTDOWN, 0, 0);
|
||||
|
||||
/*** Copy ARAMStub to 81300000 ***/
|
||||
if (dst + len < 0x81300000) p = (void *) 0x81300000;
|
||||
else p = (void *) 0x80003100;
|
||||
memcpy(p, s, 256); /*** Way too much - but who cares ***/
|
||||
|
||||
/*** Round length to 32 bytes ***/
|
||||
if (len & 0x1f) len = (len & ~0x1f) + 0x20;
|
||||
|
||||
/*** Flush everything! ***/
|
||||
DCFlushRange((void *) 0x80000000, 0x1800000);
|
||||
|
||||
/*** Boot the bugger :D ***/
|
||||
stub = (BOOTSTUB) p;
|
||||
RARCH_LOG("Launching relocated stub at %08x\n", (unsigned) p);
|
||||
stub((u32) entrypoint, dst, src, len | 0x80000000, len >> 5, dst);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* ARAMClear
|
||||
*
|
||||
* To make life easy, just clear out the Auxilliary RAM completely.
|
||||
****************************************************************************/
|
||||
static void ARAMClear(void)
|
||||
{
|
||||
int i;
|
||||
char *buffer = memalign(32, 2048); /*** A little 2k buffer ***/
|
||||
|
||||
memset(buffer, 0, 2048);
|
||||
DCFlushRange(buffer, 2048);
|
||||
|
||||
for (i = ARAMSTART; i < 0x1000000; i += 2048)
|
||||
{
|
||||
ARAMPut(buffer, (char *) i, 2048);
|
||||
while (AR_GetDMAStatus());
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
/*--- DOL Decoding functions -----------------------------------------------*/
|
||||
/****************************************************************************
|
||||
* DOLMinMax
|
||||
*
|
||||
* Calculate the DOL minimum and maximum memory addresses
|
||||
****************************************************************************/
|
||||
static void DOLMinMax(DOLHEADER * dol)
|
||||
{
|
||||
int i;
|
||||
|
||||
maxaddress = 0;
|
||||
minaddress = 0x87100000;
|
||||
|
||||
/*** Go through DOL sections ***/
|
||||
/*** Text sections ***/
|
||||
for (i = 0; i < MAXTEXTSECTION; i++)
|
||||
{
|
||||
if (dol->textAddress[i] && dol->textLength[i])
|
||||
{
|
||||
if (dol->textAddress[i] < minaddress)
|
||||
minaddress = dol->textAddress[i];
|
||||
if ((dol->textAddress[i] + dol->textLength[i]) > maxaddress)
|
||||
maxaddress = dol->textAddress[i] + dol->textLength[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*** Data sections ***/
|
||||
for (i = 0; i < MAXDATASECTION; i++)
|
||||
{
|
||||
if (dol->dataAddress[i] && dol->dataLength[i])
|
||||
{
|
||||
if (dol->dataAddress[i] < minaddress)
|
||||
minaddress = dol->dataAddress[i];
|
||||
if ((dol->dataAddress[i] + dol->dataLength[i]) > maxaddress)
|
||||
maxaddress = dol->dataAddress[i] + dol->dataLength[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*** And of course, any BSS section ***/
|
||||
if (dol->bssAddress)
|
||||
{
|
||||
if ((dol->bssAddress + dol->bssLength) > maxaddress)
|
||||
maxaddress = dol->bssAddress + dol->bssLength;
|
||||
}
|
||||
|
||||
/*** Some OLD dols, Xrick in particular, require ~128k clear memory ***/
|
||||
maxaddress += 0x20000;
|
||||
|
||||
RARCH_LOG("Min Address: %08x Max Address: %08x\n", minaddress, maxaddress);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DOLtoARAM
|
||||
*
|
||||
* Moves the DOL from main memory to ARAM, positioning as it goes
|
||||
*
|
||||
* Pass in a memory pointer to a previously loaded DOL
|
||||
****************************************************************************/
|
||||
int DOLtoARAM(const char *dol_name)
|
||||
{
|
||||
u32 sizeinbytes;
|
||||
int i, j;
|
||||
static DOLHEADER dolhead;
|
||||
FILE *f = fopen(dol_name, "rb");
|
||||
|
||||
if (!f)
|
||||
{
|
||||
RARCH_ERR("Could not open\"%s\"\n", dol_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fread(&dolhead, 1, sizeof(DOLHEADER), f);
|
||||
/*** Make sure ARAM subsystem is alive! ***/
|
||||
AR_Init(NULL, 0); /*** No stack - we need it all ***/
|
||||
ARAMClear();
|
||||
|
||||
/*** Get DOL header ***/
|
||||
dolhdr = (DOLHEADER *) &dolhead;
|
||||
|
||||
/*** First, does this look like a DOL? ***/
|
||||
if (dolhdr->textOffset[0] != DOLHDRLENGTH)
|
||||
{
|
||||
RARCH_ERR("\"%s\" is not a .dol file\n", dol_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*** Get DOL stats ***/
|
||||
DOLMinMax(dolhdr);
|
||||
sizeinbytes = maxaddress - minaddress;
|
||||
|
||||
/*** Move all DOL sections into ARAM ***/
|
||||
/*** Move text sections ***/
|
||||
for (i = 0; i < MAXTEXTSECTION; i++)
|
||||
{
|
||||
/*** This may seem strange, but in developing d0lLZ we found some with section addresses with zero length ***/
|
||||
if (dolhdr->textAddress[i] && dolhdr->textLength[i])
|
||||
{
|
||||
fseek(f, dolhdr->textOffset[i], SEEK_SET);
|
||||
unsigned count = dolhdr->textLength[i] / sizeof(dol_readbuf);
|
||||
for (j = 0; j < count; j++)
|
||||
{
|
||||
fread(dol_readbuf, 1, sizeof(dol_readbuf), f);
|
||||
ARAMPut(dol_readbuf, (char *) ((dolhdr->textAddress[i] - minaddress) + (sizeof(dol_readbuf) * j) + ARAMSTART),
|
||||
sizeof(dol_readbuf));
|
||||
}
|
||||
unsigned remaining = dolhdr->textLength[i] % sizeof(dol_readbuf);
|
||||
if (remaining)
|
||||
{
|
||||
fread(dol_readbuf, 1, remaining, f);
|
||||
ARAMPut(dol_readbuf, (char *) ((dolhdr->textAddress[i] - minaddress) + (sizeof(dol_readbuf) * count) + ARAMSTART),
|
||||
remaining);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*** Move data sections ***/
|
||||
for (i = 0; i < MAXDATASECTION; i++)
|
||||
{
|
||||
if (dolhdr->dataAddress[i] && dolhdr->dataLength[i])
|
||||
{
|
||||
fseek(f, dolhdr->dataOffset[i], SEEK_SET);
|
||||
unsigned count = dolhdr->dataLength[i] / sizeof(dol_readbuf);
|
||||
for (j = 0; j < count; j++)
|
||||
{
|
||||
fread(dol_readbuf, 1, sizeof(dol_readbuf), f);
|
||||
ARAMPut(dol_readbuf, (char *) ((dolhdr->dataAddress[i] - minaddress) + (sizeof(dol_readbuf) * j) + ARAMSTART),
|
||||
sizeof(dol_readbuf));
|
||||
}
|
||||
unsigned remaining = dolhdr->dataLength[i] % sizeof(dol_readbuf);
|
||||
if (remaining)
|
||||
{
|
||||
fread(dol_readbuf, 1, remaining, f);
|
||||
ARAMPut(dol_readbuf, (char *) ((dolhdr->dataAddress[i] - minaddress) + (sizeof(dol_readbuf) * count) + ARAMSTART),
|
||||
remaining);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
/*** Now go run it ***/
|
||||
ARAMRun(dolhdr->entryPoint, minaddress, ARAMSTART, sizeinbytes);
|
||||
|
||||
/*** Will never return ***/
|
||||
return 1;
|
||||
}
|
||||
#endif
|
@ -1,39 +0,0 @@
|
||||
/****************************************************************************
|
||||
* SideStep DOL Loading
|
||||
*
|
||||
* This module runs a DOL file from Auxilliary RAM. This removes any memory
|
||||
* issues which might occur - and also means you can easily overwrite yourself!
|
||||
*
|
||||
* softdev March 2007
|
||||
***************************************************************************/
|
||||
#ifndef HW_RVL
|
||||
#ifndef __SIDESTEP__
|
||||
#define __SIDESTEP__
|
||||
|
||||
/*** A standard DOL header ***/
|
||||
#define DOLHDRLENGTH 256 /*** All DOLS must have a 256 byte header ***/
|
||||
#define MAXTEXTSECTION 7
|
||||
#define MAXDATASECTION 11
|
||||
|
||||
/*** A handy DOL structure ***/
|
||||
typedef struct {
|
||||
unsigned int textOffset[MAXTEXTSECTION];
|
||||
unsigned int dataOffset[MAXDATASECTION];
|
||||
|
||||
unsigned int textAddress[MAXTEXTSECTION];
|
||||
unsigned int dataAddress[MAXDATASECTION];
|
||||
|
||||
unsigned int textLength[MAXTEXTSECTION];
|
||||
unsigned int dataLength[MAXDATASECTION];
|
||||
|
||||
unsigned int bssAddress;
|
||||
unsigned int bssLength;
|
||||
|
||||
unsigned int entryPoint;
|
||||
unsigned int unused[MAXTEXTSECTION];
|
||||
} DOLHEADER;
|
||||
|
||||
int DOLtoARAM(const char *dol_name);
|
||||
|
||||
#endif
|
||||
#endif
|
@ -281,7 +281,8 @@ static bool ffemu_init_audio(ffemu_t *handle)
|
||||
|
||||
rarch_resampler_realloc(&audio->resampler_data,
|
||||
&audio->resampler,
|
||||
*g_settings.audio.resampler ? g_settings.audio.resampler : NULL);
|
||||
*g_settings.audio.resampler ? g_settings.audio.resampler : NULL,
|
||||
audio->ratio);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2,7 +2,7 @@
|
||||
<app version="1">
|
||||
<name>RetroArch GX</name>
|
||||
<coder>Maister, Squarepusher, ToadKing</coder>
|
||||
<version>0.9.8.3</version>
|
||||
<version>0.9.8.4</version>
|
||||
<release_date>2012-2013</release_date>
|
||||
<short_description>Multi-system emulator</short_description>
|
||||
<long_description>A port of RetroArch to the GameCube/Wii.</long_description>
|
||||
|
@ -1,200 +0,0 @@
|
||||
/*
|
||||
* wiiuse
|
||||
*
|
||||
* Written By:
|
||||
* Michael Laforest < para >
|
||||
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||
*
|
||||
* Copyright 2006-2007
|
||||
*
|
||||
* This file is part of wiiuse.
|
||||
*
|
||||
* This program 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 Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* $Header: /lvm/shared/ds/ds/cvs/devkitpro-cvsbackup/libogc/wiiuse/classic.c,v 1.7 2008-11-14 13:34:57 shagkur Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Classic controller expansion device.
|
||||
*/
|
||||
|
||||
/* This source as presented is a modified version of original wiiuse for use
|
||||
* with RetroArch, and must not be confused with the original software. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <Winsock2.h>
|
||||
#endif
|
||||
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "dynamics.h"
|
||||
#include "events.h"
|
||||
#include "classic.h"
|
||||
#include "io.h"
|
||||
|
||||
static void classic_ctrl_pressed_buttons(struct classic_ctrl_t* cc, short now);
|
||||
|
||||
/**
|
||||
* @brief Handle the handshake data from the classic controller.
|
||||
*
|
||||
* @param cc A pointer to a classic_ctrl_t structure.
|
||||
* @param data The data read in from the device.
|
||||
* @param len The length of the data block, in bytes.
|
||||
*
|
||||
* @return Returns 1 if handshake was successful, 0 if not.
|
||||
*/
|
||||
|
||||
#define HANDSHAKE_BYTES_USED 12
|
||||
|
||||
int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, ubyte* data, uword len) {
|
||||
//int i;
|
||||
//int offset = 0;
|
||||
|
||||
cc->btns = 0;
|
||||
cc->btns_held = 0;
|
||||
cc->btns_released = 0;
|
||||
|
||||
/* decrypt data */
|
||||
/*
|
||||
for (i = 0; i < len; ++i)
|
||||
data[i] = (data[i] ^ 0x17) + 0x17;
|
||||
*/
|
||||
if (data[0] == 0xFF || len < HANDSHAKE_BYTES_USED) {
|
||||
/*
|
||||
* Sometimes the data returned here is not correct.
|
||||
* This might happen because the wiimote is lagging
|
||||
* behind our initialization sequence.
|
||||
* To fix this just request the handshake again.
|
||||
*
|
||||
* Other times it's just the first 16 bytes are 0xFF,
|
||||
* but since the next 16 bytes are the same, just use
|
||||
* those.
|
||||
*/
|
||||
if (len < 17 || len < HANDSHAKE_BYTES_USED + 16 || data[16] == 0xFF) {
|
||||
/* get the calibration data again */
|
||||
//WIIUSE_DEBUG("Classic controller handshake appears invalid, trying again.");
|
||||
wiiuse_read_data(wm, data, WM_EXP_MEM_CALIBR, EXP_HANDSHAKE_LEN, wiiuse_handshake_expansion);
|
||||
} else
|
||||
data += 16;
|
||||
}
|
||||
|
||||
|
||||
/* joystick stuff */
|
||||
cc->ljs.max.x = data[0] / 4;
|
||||
cc->ljs.min.x = data[1] / 4;
|
||||
cc->ljs.center.x = data[2] / 4;
|
||||
cc->ljs.max.y = data[3] / 4;
|
||||
cc->ljs.min.y = data[4] / 4;
|
||||
cc->ljs.center.y = data[5] / 4;
|
||||
|
||||
cc->rjs.max.x = data[6] / 8;
|
||||
cc->rjs.min.x = data[7] / 8;
|
||||
cc->rjs.center.x = data[8] / 8;
|
||||
cc->rjs.max.y = data[9] / 8;
|
||||
cc->rjs.min.y = data[10] / 8;
|
||||
cc->rjs.center.y = data[11] / 8;
|
||||
|
||||
/* handshake done */
|
||||
wm->event = WIIUSE_CLASSIC_CTRL_INSERTED;
|
||||
wm->exp.type = EXP_CLASSIC;
|
||||
|
||||
#ifdef WIN32
|
||||
wm->timeout = WIIMOTE_DEFAULT_TIMEOUT;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief The classic controller disconnected.
|
||||
*
|
||||
* @param cc A pointer to a classic_ctrl_t structure.
|
||||
*/
|
||||
void classic_ctrl_disconnected(struct classic_ctrl_t* cc)
|
||||
{
|
||||
memset(cc, 0, sizeof(struct classic_ctrl_t));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handle classic controller event.
|
||||
*
|
||||
* @param cc A pointer to a classic_ctrl_t structure.
|
||||
* @param msg The message specified in the event packet.
|
||||
*/
|
||||
void classic_ctrl_event(struct classic_ctrl_t* cc, ubyte* msg) {
|
||||
//int i;
|
||||
|
||||
/* decrypt data */
|
||||
/*
|
||||
for (i = 0; i < 6; ++i)
|
||||
msg[i] = (msg[i] ^ 0x17) + 0x17;
|
||||
*/
|
||||
classic_ctrl_pressed_buttons(cc, BIG_ENDIAN_SHORT(*(short*)(msg + 4)));
|
||||
|
||||
/* left/right buttons */
|
||||
cc->ls_raw = (((msg[2] & 0x60) >> 2) | ((msg[3] & 0xE0) >> 5));
|
||||
cc->rs_raw = (msg[3] & 0x1F);
|
||||
|
||||
/*
|
||||
* TODO - LR range hardcoded from 0x00 to 0x1F.
|
||||
* This is probably in the calibration somewhere.
|
||||
*/
|
||||
#ifndef GEKKO
|
||||
cc->r_shoulder = ((float)r / 0x1F);
|
||||
cc->l_shoulder = ((float)l / 0x1F);
|
||||
#endif
|
||||
/* calculate joystick orientation */
|
||||
cc->ljs.pos.x = (msg[0] & 0x3F);
|
||||
cc->ljs.pos.y = (msg[1] & 0x3F);
|
||||
cc->rjs.pos.x = ((msg[0] & 0xC0) >> 3) | ((msg[1] & 0xC0) >> 5) | ((msg[2] & 0x80) >> 7);
|
||||
cc->rjs.pos.y = (msg[2] & 0x1F);
|
||||
#ifndef GEKKO
|
||||
calc_joystick_state(&cc->ljs, cc->ljs.pos.x, cc->ljs.pos.y);
|
||||
calc_joystick_state(&cc->rjs, cc->rjs.pos.x, cc->rjs.pos.y);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Find what buttons are pressed.
|
||||
*
|
||||
* @param cc A pointer to a classic_ctrl_t structure.
|
||||
* @param msg The message byte specified in the event packet.
|
||||
*/
|
||||
static void classic_ctrl_pressed_buttons(struct classic_ctrl_t* cc, short now) {
|
||||
/* message is inverted (0 is active, 1 is inactive) */
|
||||
now = ~now & CLASSIC_CTRL_BUTTON_ALL;
|
||||
|
||||
/* preserve old btns pressed */
|
||||
cc->btns_last = cc->btns;
|
||||
|
||||
/* pressed now & were pressed, then held */
|
||||
cc->btns_held = (now & cc->btns);
|
||||
|
||||
/* were pressed or were held & not pressed now, then released */
|
||||
cc->btns_released = ((cc->btns | cc->btns_held) & ~now);
|
||||
|
||||
/* buttons pressed now */
|
||||
cc->btns = now;
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
/*
|
||||
* wiiuse
|
||||
*
|
||||
* Written By:
|
||||
* Michael Laforest < para >
|
||||
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||
*
|
||||
* Copyright 2006-2007
|
||||
*
|
||||
* This file is part of wiiuse.
|
||||
*
|
||||
* This program 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 Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* $Header: /lvm/shared/ds/ds/cvs/devkitpro-cvsbackup/libogc/wiiuse/classic.h,v 1.1 2008-05-08 09:42:14 shagkur Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Classic controller expansion device.
|
||||
*/
|
||||
|
||||
/* This source as presented is a modified version of original wiiuse for use
|
||||
* with RetroArch, and must not be confused with the original software. */
|
||||
|
||||
#ifndef CLASSIC_H_INCLUDED
|
||||
#define CLASSIC_H_INCLUDED
|
||||
|
||||
#include "wiiuse_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int classic_ctrl_handshake(struct wiimote_t* wm, struct classic_ctrl_t* cc, ubyte* data, uword len);
|
||||
|
||||
void classic_ctrl_disconnected(struct classic_ctrl_t* cc);
|
||||
|
||||
void classic_ctrl_event(struct classic_ctrl_t* cc, ubyte* msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // CLASSIC_H_INCLUDED
|
@ -1,55 +0,0 @@
|
||||
#ifndef __DEFINITIONS_H__
|
||||
#define __DEFINITIONS_H__
|
||||
|
||||
#include "os.h"
|
||||
|
||||
#define WIIMOTE_PI 3.14159265f
|
||||
|
||||
//#define WITH_WIIUSE_DEBUG
|
||||
|
||||
/* Error output macros */
|
||||
#define WIIUSE_ERROR(fmt, ...) fprintf(stderr, "[ERROR] " fmt "\n", ##__VA_ARGS__)
|
||||
|
||||
/* Warning output macros */
|
||||
#define WIIUSE_WARNING(fmt, ...) fprintf(stderr, "[WARNING] " fmt "\n", ##__VA_ARGS__)
|
||||
|
||||
/* Information output macros */
|
||||
#define WIIUSE_INFO(fmt, ...) fprintf(stderr, "[INFO] " fmt "\n", ##__VA_ARGS__)
|
||||
|
||||
#ifdef WITH_WIIUSE_DEBUG
|
||||
#ifdef WIN32
|
||||
#define WIIUSE_DEBUG(fmt, ...) do { \
|
||||
char* file = __FILE__; \
|
||||
int i = strlen(file) - 1; \
|
||||
for (; i && (file[i] != '\\'); --i); \
|
||||
fprintf(stderr, "[DEBUG] %s:%i: " fmt "\n", file+i+1, __LINE__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
#else
|
||||
#define WIIUSE_DEBUG(fmt, ...) fprintf(stderr, "[DEBUG] " __FILE__ ":%i: " fmt "\n", __LINE__, ##__VA_ARGS__)
|
||||
#endif
|
||||
#else
|
||||
#define WIIUSE_DEBUG(fmt, ...)
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#define WII_DEBUG(fmt, ...) do { \
|
||||
printf("[WDEBUG] " __FILE__ ":%i: " fmt "\n", __LINE__, ##__VA_ARGS__); \
|
||||
usleep(3000000); \
|
||||
} while (0)
|
||||
#else
|
||||
#define WII_DEBUG(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
/* Convert between radians and degrees */
|
||||
#define RAD_TO_DEGREE(r) ((r * 180.0f) / WIIMOTE_PI)
|
||||
#define DEGREE_TO_RAD(d) (d * (WIIMOTE_PI / 180.0f))
|
||||
|
||||
/* Convert to big endian */
|
||||
#define BIG_ENDIAN_LONG(i) (htonl(i))
|
||||
#define BIG_ENDIAN_SHORT(i) (htons(i))
|
||||
|
||||
#define absf(x) ((x >= 0) ? (x) : (x * -1.0f))
|
||||
#define diff_f(x, y) ((x >= y) ? (absf(x - y)) : (absf(y - x)))
|
||||
|
||||
#endif
|
@ -1,230 +0,0 @@
|
||||
/*
|
||||
* wiiuse
|
||||
*
|
||||
* Written By:
|
||||
* Michael Laforest < para >
|
||||
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||
*
|
||||
* Copyright 2006-2007
|
||||
*
|
||||
* This file is part of wiiuse.
|
||||
*
|
||||
* This program 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 Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* $Header: /lvm/shared/ds/ds/cvs/devkitpro-cvsbackup/libogc/wiiuse/dynamics.c,v 1.2 2008-11-14 13:34:57 shagkur Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Handles the dynamics of the wiimote.
|
||||
*
|
||||
* The file includes functions that handle the dynamics
|
||||
* of the wiimote. Such dynamics include orientation and
|
||||
* motion sensing.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <float.h>
|
||||
#endif
|
||||
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "ir.h"
|
||||
#include "dynamics.h"
|
||||
|
||||
/**
|
||||
* @brief Calculate the roll, pitch, yaw.
|
||||
*
|
||||
* @param ac An accelerometer (accel_t) structure.
|
||||
* @param accel [in] Pointer to a vec3w_t structure that holds the raw acceleration data.
|
||||
* @param orient [out] Pointer to a orient_t structure that will hold the orientation data.
|
||||
* @param rorient [out] Pointer to a orient_t structure that will hold the non-smoothed orientation data.
|
||||
* @param smooth If smoothing should be performed on the angles calculated. 1 to enable, 0 to disable.
|
||||
*
|
||||
* Given the raw acceleration data from the accelerometer struct, calculate
|
||||
* the orientation of the device and set it in the \a orient parameter.
|
||||
*/
|
||||
void calculate_orientation(struct accel_t* ac, struct vec3w_t* accel, struct orient_t* orient, int smooth) {
|
||||
float xg, yg, zg;
|
||||
float x, y, z;
|
||||
|
||||
/*
|
||||
* roll - use atan(z / x) [ ranges from -180 to 180 ]
|
||||
* pitch - use atan(z / y) [ ranges from -180 to 180 ]
|
||||
* yaw - impossible to tell without IR
|
||||
*/
|
||||
|
||||
/* yaw - set to 0, IR will take care of it if it's enabled */
|
||||
orient->yaw = 0.0f;
|
||||
|
||||
/* find out how much it has to move to be 1g */
|
||||
xg = (float)ac->cal_g.x;
|
||||
yg = (float)ac->cal_g.y;
|
||||
zg = (float)ac->cal_g.z;
|
||||
|
||||
/* find out how much it actually moved and normalize to +/- 1g */
|
||||
x = ((float)accel->x - (float)ac->cal_zero.x) / xg;
|
||||
y = ((float)accel->y - (float)ac->cal_zero.y) / yg;
|
||||
z = ((float)accel->z - (float)ac->cal_zero.z) / zg;
|
||||
|
||||
/* make sure x,y,z are between -1 and 1 for the tan functions */
|
||||
if (x < -1.0f) x = -1.0f;
|
||||
else if (x > 1.0f) x = 1.0f;
|
||||
if (y < -1.0f) y = -1.0f;
|
||||
else if (y > 1.0f) y = 1.0f;
|
||||
if (z < -1.0f) z = -1.0f;
|
||||
else if (z > 1.0f) z = 1.0f;
|
||||
|
||||
/* if it is over 1g then it is probably accelerating and not reliable */
|
||||
if (abs(accel->x - ac->cal_zero.x) <= (ac->cal_g.x+10)) {
|
||||
/* roll */
|
||||
x = RAD_TO_DEGREE(atan2f(x, z));
|
||||
if(isfinite(x)) {
|
||||
orient->roll = x;
|
||||
orient->a_roll = x;
|
||||
}
|
||||
}
|
||||
|
||||
if (abs(accel->y - ac->cal_zero.y) <= (ac->cal_g.y+10)) {
|
||||
/* pitch */
|
||||
y = RAD_TO_DEGREE(atan2f(y, z));
|
||||
if(isfinite(y)) {
|
||||
orient->pitch = y;
|
||||
orient->a_pitch = y;
|
||||
}
|
||||
}
|
||||
|
||||
/* smooth the angles if enabled */
|
||||
if (smooth) {
|
||||
apply_smoothing(ac, orient, SMOOTH_ROLL);
|
||||
apply_smoothing(ac, orient, SMOOTH_PITCH);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Calculate the gravity forces on each axis.
|
||||
*
|
||||
* @param ac An accelerometer (accel_t) structure.
|
||||
* @param accel [in] Pointer to a vec3w_t structure that holds the raw acceleration data.
|
||||
* @param gforce [out] Pointer to a gforce_t structure that will hold the gravity force data.
|
||||
*/
|
||||
void calculate_gforce(struct accel_t* ac, struct vec3w_t* accel, struct gforce_t* gforce) {
|
||||
float xg, yg, zg;
|
||||
|
||||
/* find out how much it has to move to be 1g */
|
||||
xg = (float)ac->cal_g.x;
|
||||
yg = (float)ac->cal_g.y;
|
||||
zg = (float)ac->cal_g.z;
|
||||
|
||||
/* find out how much it actually moved and normalize to +/- 1g */
|
||||
gforce->x = ((float)accel->x - (float)ac->cal_zero.x) / xg;
|
||||
gforce->y = ((float)accel->y - (float)ac->cal_zero.y) / yg;
|
||||
gforce->z = ((float)accel->z - (float)ac->cal_zero.z) / zg;
|
||||
}
|
||||
|
||||
static float applyCalibration(float inval,float minval, float maxval,float centerval)
|
||||
{
|
||||
float ret;
|
||||
/* We don't use the exact ranges but the ranges +1 in case we get bad calibration
|
||||
* data - avoid div0 */
|
||||
|
||||
if (inval == centerval)
|
||||
ret = 0;
|
||||
else if (inval < centerval)
|
||||
ret = (inval - centerval) / (centerval - minval + 1);
|
||||
else
|
||||
ret = (inval - centerval) / (maxval - centerval + 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate the angle and magnitude of a joystick.
|
||||
*
|
||||
* @param js [out] Pointer to a joystick_t structure.
|
||||
* @param x The raw x-axis value.
|
||||
* @param y The raw y-axis value.
|
||||
*/
|
||||
void calc_joystick_state(struct joystick_t* js, float x, float y) {
|
||||
float rx, ry, ang;
|
||||
|
||||
/*
|
||||
* Since the joystick center may not be exactly:
|
||||
* (min + max) / 2
|
||||
* Then the range from the min to the center and the center to the max
|
||||
* may be different.
|
||||
* Because of this, depending on if the current x or y value is greater
|
||||
* or less than the assoicated axis center value, it needs to be interpolated
|
||||
* between the center and the minimum or maxmimum rather than between
|
||||
* the minimum and maximum.
|
||||
*
|
||||
* So we have something like this:
|
||||
* (x min) [-1] ---------*------ [0] (x center) [0] -------- [1] (x max)
|
||||
* Where the * is the current x value.
|
||||
* The range is therefore -1 to 1, 0 being the exact center rather than
|
||||
* the middle of min and max.
|
||||
*/
|
||||
rx = applyCalibration(x, js->min.x, js->max.x, js->center.x);
|
||||
ry = applyCalibration(y, js->min.y, js->max.y, js->center.y);
|
||||
|
||||
/* calculate the joystick angle and magnitude */
|
||||
ang = RAD_TO_DEGREE(atan2f(ry, rx));
|
||||
js->mag = sqrtf((rx * rx) + (ry * ry));
|
||||
js->ang = ang + 180.0f;
|
||||
}
|
||||
|
||||
|
||||
void apply_smoothing(struct accel_t* ac, struct orient_t* orient, int type) {
|
||||
switch (type) {
|
||||
case SMOOTH_ROLL:
|
||||
{
|
||||
/* it's possible last iteration was nan or inf, so set it to 0 if that happened */
|
||||
if (isnan(ac->st_roll) || isinf(ac->st_roll))
|
||||
ac->st_roll = 0.0f;
|
||||
|
||||
/*
|
||||
* If the sign changes (which will happen if going from -180 to 180)
|
||||
* or from (-1 to 1) then don't smooth, just use the new angle.
|
||||
*/
|
||||
if (((ac->st_roll < 0) && (orient->roll > 0)) || ((ac->st_roll > 0) && (orient->roll < 0))) {
|
||||
ac->st_roll = orient->roll;
|
||||
} else {
|
||||
orient->roll = ac->st_roll + (ac->st_alpha * (orient->a_roll - ac->st_roll));
|
||||
ac->st_roll = orient->roll;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case SMOOTH_PITCH:
|
||||
{
|
||||
if (isnan(ac->st_pitch) || isinf(ac->st_pitch))
|
||||
ac->st_pitch = 0.0f;
|
||||
|
||||
if (((ac->st_pitch < 0) && (orient->pitch > 0)) || ((ac->st_pitch > 0) && (orient->pitch < 0))) {
|
||||
ac->st_pitch = orient->pitch;
|
||||
} else {
|
||||
orient->pitch = ac->st_pitch + (ac->st_alpha * (orient->a_pitch - ac->st_pitch));
|
||||
ac->st_pitch = orient->pitch;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* wiiuse
|
||||
*
|
||||
* Written By:
|
||||
* Michael Laforest < para >
|
||||
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||
*
|
||||
* Copyright 2006-2007
|
||||
*
|
||||
* This file is part of wiiuse.
|
||||
*
|
||||
* This program 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 Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* $Header: /lvm/shared/ds/ds/cvs/devkitpro-cvsbackup/libogc/wiiuse/dynamics.h,v 1.2 2008-11-14 13:34:57 shagkur Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Handles the dynamics of the wiimote.
|
||||
*
|
||||
* The file includes functions that handle the dynamics
|
||||
* of the wiimote. Such dynamics include orientation and
|
||||
* motion sensing.
|
||||
*/
|
||||
|
||||
/* This source as presented is a modified version of original wiiuse for use
|
||||
* with RetroArch, and must not be confused with the original software. */
|
||||
|
||||
#ifndef DYNAMICS_H_INCLUDED
|
||||
#define DYNAMICS_H_INCLUDED
|
||||
|
||||
#include "wiiuse_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void calculate_orientation(struct accel_t* ac, struct vec3w_t* accel, struct orient_t* orient, int smooth);
|
||||
void calculate_gforce(struct accel_t* ac, struct vec3w_t* accel, struct gforce_t* gforce);
|
||||
void calc_joystick_state(struct joystick_t* js, float x, float y);
|
||||
void apply_smoothing(struct accel_t* ac, struct orient_t* orient, int type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // DYNAMICS_H_INCLUDED
|
@ -1,336 +0,0 @@
|
||||
/* This source as presented is a modified version of original wiiuse for use
|
||||
* with RetroArch, and must not be confused with the original software. */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dynamics.h"
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "events.h"
|
||||
#include "nunchuk.h"
|
||||
#include "classic.h"
|
||||
#include "motion_plus.h"
|
||||
#include "ir.h"
|
||||
#include "io.h"
|
||||
|
||||
|
||||
static void event_data_read(struct wiimote_t *wm,ubyte *msg)
|
||||
{
|
||||
ubyte err;
|
||||
ubyte len;
|
||||
uword offset;
|
||||
struct op_t *op;
|
||||
struct cmd_blk_t *cmd = wm->cmd_head;
|
||||
|
||||
wiiuse_pressed_buttons(wm,msg);
|
||||
|
||||
if(!cmd) return;
|
||||
if(!(cmd->state==CMD_SENT && cmd->data[0]==WM_CMD_READ_DATA)) return;
|
||||
|
||||
//printf("event_data_read(%p)\n",cmd);
|
||||
|
||||
err = msg[2]&0x0f;
|
||||
op = (struct op_t*)cmd->data;
|
||||
if(err) {
|
||||
wm->cmd_head = cmd->next;
|
||||
|
||||
cmd->state = CMD_DONE;
|
||||
if(cmd->cb!=NULL) cmd->cb(wm,op->buffer,(op->readdata.size - op->wait));
|
||||
|
||||
__lwp_queue_append(&wm->cmdq,&cmd->node);
|
||||
wiiuse_send_next_command(wm);
|
||||
return;
|
||||
}
|
||||
|
||||
len = ((msg[2]&0xf0)>>4)+1;
|
||||
offset = BIG_ENDIAN_SHORT(*(uword*)(msg+3));
|
||||
|
||||
//printf("addr: %08x\noffset: %d\nlen: %d\n",req->addr,offset,len);
|
||||
|
||||
op->readdata.addr = (op->readdata.addr&0xffff);
|
||||
op->wait -= len;
|
||||
if(op->wait>=op->readdata.size) op->wait = 0;
|
||||
|
||||
memcpy((op->buffer+offset-op->readdata.addr),(msg+5),len);
|
||||
if(!op->wait) {
|
||||
wm->cmd_head = cmd->next;
|
||||
|
||||
wm->event = WIIUSE_READ_DATA;
|
||||
cmd->state = CMD_DONE;
|
||||
if(cmd->cb!=NULL) cmd->cb(wm,op->buffer,op->readdata.size);
|
||||
|
||||
__lwp_queue_append(&wm->cmdq,&cmd->node);
|
||||
wiiuse_send_next_command(wm);
|
||||
}
|
||||
}
|
||||
|
||||
static void event_ack(struct wiimote_t *wm,ubyte *msg)
|
||||
{
|
||||
struct cmd_blk_t *cmd = wm->cmd_head;
|
||||
|
||||
wiiuse_pressed_buttons(wm,msg);
|
||||
|
||||
if(!cmd || cmd->state!=CMD_SENT || cmd->data[0]==WM_CMD_READ_DATA || cmd->data[0]==WM_CMD_CTRL_STATUS || cmd->data[0]!=msg[2] || msg[3]) {
|
||||
//WIIUSE_WARNING("Unsolicited event ack: report %02x status %02x", msg[2], msg[3]);
|
||||
return;
|
||||
}
|
||||
|
||||
//WIIUSE_DEBUG("Received ack for command %02x %02x", cmd->data[0], cmd->data[1]);
|
||||
|
||||
wm->cmd_head = cmd->next;
|
||||
|
||||
wm->event = WIIUSE_ACK;
|
||||
cmd->state = CMD_DONE;
|
||||
if(cmd->cb) cmd->cb(wm,NULL,0);
|
||||
|
||||
__lwp_queue_append(&wm->cmdq,&cmd->node);
|
||||
wiiuse_send_next_command(wm);
|
||||
}
|
||||
|
||||
static void event_status(struct wiimote_t *wm,ubyte *msg)
|
||||
{
|
||||
int ir = 0;
|
||||
int attachment = 0;
|
||||
#ifdef HAVE_WIIUSE_SPEAKER
|
||||
int speaker = 0;
|
||||
#endif
|
||||
//int led[4]= {0};
|
||||
struct cmd_blk_t *cmd = wm->cmd_head;
|
||||
|
||||
wiiuse_pressed_buttons(wm,msg);
|
||||
|
||||
wm->event = WIIUSE_STATUS;
|
||||
//if(msg[2]&WM_CTRL_STATUS_BYTE1_LED_1) led[0] = 1;
|
||||
//if(msg[2]&WM_CTRL_STATUS_BYTE1_LED_2) led[1] = 1;
|
||||
//if(msg[2]&WM_CTRL_STATUS_BYTE1_LED_3) led[2] = 1;
|
||||
//if(msg[2]&WM_CTRL_STATUS_BYTE1_LED_4) led[3] = 1;
|
||||
|
||||
if((msg[2]&WM_CTRL_STATUS_BYTE1_ATTACHMENT)==WM_CTRL_STATUS_BYTE1_ATTACHMENT) attachment = 1;
|
||||
#ifdef HAVE_WIIUSE_SPEAKER
|
||||
if((msg[2]&WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED)==WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED) speaker = 1;
|
||||
#endif
|
||||
if((msg[2]&WM_CTRL_STATUS_BYTE1_IR_ENABLED)==WM_CTRL_STATUS_BYTE1_IR_ENABLED) ir = 1;
|
||||
|
||||
wm->battery_level = msg[5];
|
||||
|
||||
if(!ir && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_IR_INIT)) {
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR_INIT);
|
||||
wiiuse_set_ir(wm, 1);
|
||||
goto done;
|
||||
}
|
||||
if(ir && !WIIMOTE_IS_SET(wm,WIIMOTE_STATE_IR)) WIIMOTE_ENABLE_STATE(wm,WIIMOTE_STATE_IR);
|
||||
else if(!ir && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_IR)) WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR);
|
||||
|
||||
#ifdef HAVE_WIIUSE_SPEAKER
|
||||
if(!speaker && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_SPEAKER_INIT)) {
|
||||
WIIMOTE_DISABLE_STATE(wm,WIIMOTE_STATE_SPEAKER_INIT);
|
||||
wiiuse_set_speaker(wm,1);
|
||||
goto done;
|
||||
}
|
||||
if(speaker && !WIIMOTE_IS_SET(wm,WIIMOTE_STATE_SPEAKER)) WIIMOTE_ENABLE_STATE(wm,WIIMOTE_STATE_SPEAKER);
|
||||
else if(!speaker && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_SPEAKER)) WIIMOTE_DISABLE_STATE(wm,WIIMOTE_STATE_SPEAKER);
|
||||
#endif
|
||||
|
||||
if(attachment) {
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP) && !WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP_FAILED) && !WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP_HANDSHAKE)) {
|
||||
wiiuse_handshake_expansion_start(wm);
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
WIIMOTE_DISABLE_STATE(wm,WIIMOTE_STATE_EXP_FAILED);
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP)) {
|
||||
wiiuse_disable_expansion(wm);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
wiiuse_set_report_type(wm,NULL);
|
||||
|
||||
done:
|
||||
if(!cmd) return;
|
||||
if(!(cmd->state==CMD_SENT && cmd->data[0]==WM_CMD_CTRL_STATUS)) return;
|
||||
|
||||
wm->cmd_head = cmd->next;
|
||||
|
||||
cmd->state = CMD_DONE;
|
||||
if(cmd->cb!=NULL) cmd->cb(wm,msg,6);
|
||||
|
||||
__lwp_queue_append(&wm->cmdq,&cmd->node);
|
||||
wiiuse_send_next_command(wm);
|
||||
}
|
||||
|
||||
static void handle_expansion(struct wiimote_t *wm,ubyte *msg)
|
||||
{
|
||||
switch (wm->exp.type) {
|
||||
case EXP_NUNCHUK:
|
||||
nunchuk_event(&wm->exp.nunchuk, msg);
|
||||
break;
|
||||
case EXP_CLASSIC:
|
||||
classic_ctrl_event(&wm->exp.classic, msg);
|
||||
break;
|
||||
case EXP_MOTION_PLUS:
|
||||
motion_plus_event(&wm->exp.mp, msg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called on a cycle where no significant change occurs.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
*/
|
||||
void idle_cycle(struct wiimote_t* wm)
|
||||
{
|
||||
/*
|
||||
* Smooth the angles.
|
||||
*
|
||||
* This is done to make sure that on every cycle the orientation
|
||||
* angles are smoothed. Normally when an event occurs the angles
|
||||
* are updated and smoothed, but if no packet comes in then the
|
||||
* angles remain the same. This means the angle wiiuse reports
|
||||
* is still an old value. Smoothing needs to be applied in this
|
||||
* case in order for the angle it reports to converge to the true
|
||||
* angle of the device.
|
||||
*/
|
||||
//printf("idle_cycle()\n");///
|
||||
if (WIIUSE_USING_ACC(wm) && WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING)) {
|
||||
apply_smoothing(&wm->accel_calib, &wm->orient, SMOOTH_ROLL);
|
||||
apply_smoothing(&wm->accel_calib, &wm->orient, SMOOTH_PITCH);
|
||||
}
|
||||
}
|
||||
|
||||
void parse_event(struct wiimote_t *wm)
|
||||
{
|
||||
ubyte event;
|
||||
ubyte *msg;
|
||||
|
||||
event = wm->event_buf[0];
|
||||
msg = wm->event_buf+1;
|
||||
//printf("parse_event(%02x,%p)\n",event,msg);
|
||||
switch(event) {
|
||||
case WM_RPT_CTRL_STATUS:
|
||||
event_status(wm,msg);
|
||||
return;
|
||||
case WM_RPT_READ:
|
||||
event_data_read(wm,msg);
|
||||
return;
|
||||
case WM_RPT_ACK:
|
||||
event_ack(wm,msg);
|
||||
return;
|
||||
case WM_RPT_BTN:
|
||||
wiiuse_pressed_buttons(wm,msg);
|
||||
break;
|
||||
case WM_RPT_BTN_ACC:
|
||||
wiiuse_pressed_buttons(wm,msg);
|
||||
|
||||
wm->accel.x = (msg[2]<<2)|((msg[0]>>5)&3);
|
||||
wm->accel.y = (msg[3]<<2)|((msg[1]>>4)&2);
|
||||
wm->accel.z = (msg[4]<<2)|((msg[1]>>5)&2);
|
||||
#ifndef GEKKO
|
||||
/* calculate the remote orientation */
|
||||
calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
|
||||
|
||||
/* calculate the gforces on each axis */
|
||||
calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
|
||||
#endif
|
||||
break;
|
||||
case WM_RPT_BTN_ACC_IR:
|
||||
wiiuse_pressed_buttons(wm,msg);
|
||||
|
||||
wm->accel.x = (msg[2]<<2)|((msg[0]>>5)&3);
|
||||
wm->accel.y = (msg[3]<<2)|((msg[1]>>4)&2);
|
||||
wm->accel.z = (msg[4]<<2)|((msg[1]>>5)&2);
|
||||
#ifndef GEKKO
|
||||
/* calculate the remote orientation */
|
||||
calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
|
||||
|
||||
/* calculate the gforces on each axis */
|
||||
calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
|
||||
#endif
|
||||
calculate_extended_ir(wm, msg+5);
|
||||
break;
|
||||
case WM_RPT_BTN_EXP:
|
||||
wiiuse_pressed_buttons(wm,msg);
|
||||
handle_expansion(wm,msg+2);
|
||||
break;
|
||||
case WM_RPT_BTN_ACC_EXP:
|
||||
/* button - motion - expansion */
|
||||
wiiuse_pressed_buttons(wm, msg);
|
||||
|
||||
wm->accel.x = (msg[2]<<2)|((msg[0]>>5)&3);
|
||||
wm->accel.y = (msg[3]<<2)|((msg[1]>>4)&2);
|
||||
wm->accel.z = (msg[4]<<2)|((msg[1]>>5)&2);
|
||||
#ifndef GEKKO
|
||||
calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
|
||||
calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
|
||||
#endif
|
||||
handle_expansion(wm, msg+5);
|
||||
break;
|
||||
case WM_RPT_BTN_IR_EXP:
|
||||
wiiuse_pressed_buttons(wm,msg);
|
||||
calculate_basic_ir(wm, msg+2);
|
||||
handle_expansion(wm,msg+12);
|
||||
break;
|
||||
case WM_RPT_BTN_ACC_IR_EXP:
|
||||
/* button - motion - ir - expansion */
|
||||
wiiuse_pressed_buttons(wm, msg);
|
||||
|
||||
wm->accel.x = (msg[2]<<2)|((msg[0]>>5)&3);
|
||||
wm->accel.y = (msg[3]<<2)|((msg[1]>>4)&2);
|
||||
wm->accel.z = (msg[4]<<2)|((msg[1]>>5)&2);
|
||||
#ifndef GEKKO
|
||||
calculate_orientation(&wm->accel_calib, &wm->accel, &wm->orient, WIIMOTE_IS_FLAG_SET(wm, WIIUSE_SMOOTHING));
|
||||
calculate_gforce(&wm->accel_calib, &wm->accel, &wm->gforce);
|
||||
#endif
|
||||
/* ir */
|
||||
calculate_basic_ir(wm, msg+5);
|
||||
|
||||
handle_expansion(wm, msg+15);
|
||||
break;
|
||||
default:
|
||||
WIIUSE_WARNING("Unknown event, can not handle it [Code 0x%x].", event);
|
||||
return;
|
||||
}
|
||||
|
||||
/* was there an event? */
|
||||
wm->event = WIIUSE_EVENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find what buttons are pressed.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param msg The message specified in the event packet.
|
||||
*/
|
||||
void wiiuse_pressed_buttons(struct wiimote_t* wm, ubyte* msg) {
|
||||
short now;
|
||||
|
||||
/* convert to big endian */
|
||||
now = BIG_ENDIAN_SHORT(*(short*)msg) & WIIMOTE_BUTTON_ALL;
|
||||
|
||||
/* preserve old btns pressed */
|
||||
wm->btns_last = wm->btns;
|
||||
|
||||
/* pressed now & were pressed, then held */
|
||||
wm->btns_held = (now & wm->btns);
|
||||
|
||||
/* were pressed or were held & not pressed now, then released */
|
||||
wm->btns_released = ((wm->btns | wm->btns_held) & ~now);
|
||||
|
||||
/* buttons pressed now */
|
||||
wm->btns = now;
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
/* This source as presented is a modified version of original wiiuse for use
|
||||
* with RetroArch, and must not be confused with the original software. */
|
||||
|
||||
#ifndef __EVENTS_H__
|
||||
#define __EVENTS_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void wiiuse_pressed_buttons(struct wiimote_t* wm, ubyte* msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
152
wii/wiiuse/io.c
152
wii/wiiuse/io.c
@ -1,152 +0,0 @@
|
||||
/* This source as presented is a modified version of original wiiuse for use
|
||||
* with RetroArch, and must not be confused with the original software. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "nunchuk.h"
|
||||
#include "classic.h"
|
||||
#include "motion_plus.h"
|
||||
#include "io.h"
|
||||
|
||||
void wiiuse_handshake(struct wiimote_t *wm,ubyte *data,uword len)
|
||||
{
|
||||
ubyte *buf = NULL;
|
||||
struct accel_t *accel = &wm->accel_calib;
|
||||
|
||||
//printf("wiiuse_handshake(%d,%p,%d)\n",wm->handshake_state,data,len);
|
||||
|
||||
switch(wm->handshake_state) {
|
||||
case 0:
|
||||
wm->handshake_state++;
|
||||
|
||||
wiiuse_set_leds(wm,WIIMOTE_LED_NONE,NULL);
|
||||
|
||||
buf = __lwp_heap_allocate(&__wkspace_heap, sizeof(ubyte) * 8);
|
||||
wiiuse_read_data(wm,buf,WM_MEM_OFFSET_CALIBRATION,7,wiiuse_handshake);
|
||||
break;
|
||||
case 1:
|
||||
wm->handshake_state++;
|
||||
|
||||
accel->cal_zero.x = ((data[0]<<2)|((data[3]>>4)&3));
|
||||
accel->cal_zero.y = ((data[1]<<2)|((data[3]>>2)&3));
|
||||
accel->cal_zero.z = ((data[2]<<2)|(data[3]&3));
|
||||
|
||||
accel->cal_g.x = (((data[4]<<2)|((data[7]>>4)&3)) - accel->cal_zero.x);
|
||||
accel->cal_g.y = (((data[5]<<2)|((data[7]>>2)&3)) - accel->cal_zero.y);
|
||||
accel->cal_g.z = (((data[6]<<2)|(data[7]&3)) - accel->cal_zero.z);
|
||||
__lwp_heap_free(&__wkspace_heap, data);
|
||||
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE);
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_HANDSHAKE_COMPLETE);
|
||||
|
||||
wm->event = WIIUSE_CONNECT;
|
||||
wiiuse_status(wm,NULL);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void wiiuse_handshake_expansion_start(struct wiimote_t *wm)
|
||||
{
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP) || WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP_FAILED) || WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP_HANDSHAKE))
|
||||
return;
|
||||
|
||||
wm->expansion_state = 0;
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_EXP_HANDSHAKE);
|
||||
wiiuse_handshake_expansion(wm, NULL, 0);
|
||||
}
|
||||
|
||||
void wiiuse_handshake_expansion(struct wiimote_t *wm,ubyte *data,uword len)
|
||||
{
|
||||
int id;
|
||||
ubyte val;
|
||||
ubyte *buf = NULL;
|
||||
|
||||
switch(wm->expansion_state) {
|
||||
/* These two initialization writes disable the encryption */
|
||||
case 0:
|
||||
wm->expansion_state = 1;
|
||||
val = 0x55;
|
||||
wiiuse_write_data(wm,WM_EXP_MEM_ENABLE1,&val,1,wiiuse_handshake_expansion);
|
||||
break;
|
||||
case 1:
|
||||
wm->expansion_state = 2;
|
||||
val = 0x00;
|
||||
wiiuse_write_data(wm,WM_EXP_MEM_ENABLE2,&val,1,wiiuse_handshake_expansion);
|
||||
break;
|
||||
case 2:
|
||||
wm->expansion_state = 3;
|
||||
buf = __lwp_heap_allocate(&__wkspace_heap, sizeof(ubyte) * EXP_HANDSHAKE_LEN);
|
||||
wiiuse_read_data(wm,buf,WM_EXP_MEM_CALIBR,EXP_HANDSHAKE_LEN,wiiuse_handshake_expansion);
|
||||
break;
|
||||
case 3:
|
||||
if(!data || !len) return;
|
||||
id = BIG_ENDIAN_LONG(*(int*)(&data[220]));
|
||||
|
||||
switch(id) {
|
||||
case EXP_ID_CODE_NUNCHUK:
|
||||
if(!nunchuk_handshake(wm,&wm->exp.nunchuk,data,len)) return;
|
||||
break;
|
||||
case EXP_ID_CODE_CLASSIC_CONTROLLER:
|
||||
case EXP_ID_CODE_CLASSIC_CONTROLLER_NYKOWING:
|
||||
case EXP_ID_CODE_CLASSIC_CONTROLLER_NYKOWING2:
|
||||
case EXP_ID_CODE_CLASSIC_CONTROLLER_NYKOWING3:
|
||||
case EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC:
|
||||
case EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC2:
|
||||
case EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC3:
|
||||
case EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC4:
|
||||
case EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC5:
|
||||
if(!classic_ctrl_handshake(wm,&wm->exp.classic,data,len)) return;
|
||||
break;
|
||||
default:
|
||||
if(!classic_ctrl_handshake(wm,&wm->exp.classic,data,len)) return;
|
||||
/*WIIMOTE_DISABLE_STATE(wm,WIIMOTE_STATE_EXP_HANDSHAKE);
|
||||
WIIMOTE_ENABLE_STATE(wm,WIIMOTE_STATE_EXP_FAILED);
|
||||
_lwp_heap_free(&__wkspace_heap, data);
|
||||
wiiuse_status(wm,NULL);
|
||||
return;*/
|
||||
}
|
||||
__lwp_heap_free(&__wkspace_heap, data);
|
||||
|
||||
WIIMOTE_DISABLE_STATE(wm,WIIMOTE_STATE_EXP_HANDSHAKE);
|
||||
WIIMOTE_ENABLE_STATE(wm,WIIMOTE_STATE_EXP);
|
||||
wiiuse_set_ir_mode(wm);
|
||||
wiiuse_status(wm,NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void wiiuse_disable_expansion(struct wiimote_t *wm)
|
||||
{
|
||||
if(!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP)) return;
|
||||
|
||||
/* tell the associated module the expansion was removed */
|
||||
switch(wm->exp.type) {
|
||||
case EXP_NUNCHUK:
|
||||
nunchuk_disconnected(&wm->exp.nunchuk);
|
||||
wm->event = WIIUSE_NUNCHUK_REMOVED;
|
||||
break;
|
||||
case EXP_CLASSIC:
|
||||
classic_ctrl_disconnected(&wm->exp.classic);
|
||||
wm->event = WIIUSE_CLASSIC_CTRL_REMOVED;
|
||||
break;
|
||||
case EXP_MOTION_PLUS:
|
||||
motion_plus_disconnected(&wm->exp.mp);
|
||||
wm->event = WIIUSE_MOTION_PLUS_REMOVED;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP);
|
||||
wm->exp.type = EXP_NONE;
|
||||
|
||||
wiiuse_set_ir_mode(wm);
|
||||
wiiuse_status(wm,NULL);
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
/* This source as presented is a modified version of original wiiuse for use
|
||||
* with RetroArch, and must not be confused with the original software. */
|
||||
|
||||
#ifndef __IO_H__
|
||||
#define __IO_H__
|
||||
|
||||
#include "wiiuse_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void wiiuse_handshake(struct wiimote_t* wm,ubyte *data,uword len);
|
||||
void wiiuse_handshake_expansion_start(struct wiimote_t *wm);
|
||||
void wiiuse_handshake_expansion(struct wiimote_t *wm,ubyte *data,uword len);
|
||||
void wiiuse_disable_expansion(struct wiimote_t *wm);
|
||||
|
||||
int wiiuse_io_read(struct wiimote_t* wm);
|
||||
int wiiuse_io_write(struct wiimote_t* wm, ubyte* buf, int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,181 +0,0 @@
|
||||
/* This source as presented is a modified version of original wiiuse for use
|
||||
* with RetroArch, and must not be confused with the original software. */
|
||||
|
||||
#ifdef GEKKO
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "events.h"
|
||||
#include "io.h"
|
||||
#include "lwp_wkspace.h"
|
||||
|
||||
#define MAX_COMMANDS 0x100
|
||||
#define MAX_WIIMOTES 5
|
||||
|
||||
static vu32* const _ipcReg = (u32*)0xCD000000;
|
||||
static u8 *__queue_buffer[MAX_WIIMOTES] = { 0, 0, 0, 0, 0 };
|
||||
|
||||
extern void parse_event(struct wiimote_t *wm);
|
||||
extern void idle_cycle(struct wiimote_t* wm);
|
||||
extern void hexdump(void *d, int len);
|
||||
|
||||
static __inline__ u32 ACR_ReadReg(u32 reg)
|
||||
{
|
||||
return _ipcReg[reg>>2];
|
||||
}
|
||||
|
||||
static __inline__ void ACR_WriteReg(u32 reg,u32 val)
|
||||
{
|
||||
_ipcReg[reg>>2] = val;
|
||||
}
|
||||
|
||||
static s32 __wiiuse_disconnected(void *arg,struct bte_pcb *pcb,u8 err)
|
||||
{
|
||||
struct wiimote_listen_t *wml = (struct wiimote_listen_t*)arg;
|
||||
struct wiimote_t *wm = wml->wm;
|
||||
|
||||
if(!wm) return ERR_OK;
|
||||
|
||||
//printf("wiimote disconnected\n");
|
||||
WIIMOTE_DISABLE_STATE(wm, (WIIMOTE_STATE_IR|WIIMOTE_STATE_IR_INIT));
|
||||
#ifdef HAVE_WIIUSE_SPEAKER
|
||||
WIIMOTE_DISABLE_STATE(wm, (WIIMOTE_STATE_SPEAKER|WIIMOTE_STATE_SPEAKER_INIT));
|
||||
#endif
|
||||
WIIMOTE_DISABLE_STATE(wm, (WIIMOTE_STATE_EXP|WIIMOTE_STATE_EXP_HANDSHAKE|WIIMOTE_STATE_EXP_FAILED));
|
||||
WIIMOTE_DISABLE_STATE(wm,(WIIMOTE_STATE_CONNECTED|WIIMOTE_STATE_HANDSHAKE|WIIMOTE_STATE_HANDSHAKE_COMPLETE));
|
||||
|
||||
while(wm->cmd_head) {
|
||||
__lwp_queue_append(&wm->cmdq,&wm->cmd_head->node);
|
||||
wm->cmd_head = wm->cmd_head->next;
|
||||
}
|
||||
wm->cmd_tail = NULL;
|
||||
|
||||
if(wm->event_cb) wm->event_cb(wm,WIIUSE_DISCONNECT);
|
||||
|
||||
wml->wm = NULL;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static s32 __wiiuse_receive(void *arg,void *buffer,u16 len)
|
||||
{
|
||||
struct wiimote_listen_t *wml = (struct wiimote_listen_t*)arg;
|
||||
struct wiimote_t *wm = wml->wm;
|
||||
|
||||
if(!wm || !buffer || len==0) return ERR_OK;
|
||||
|
||||
//printf("__wiiuse_receive[%02x]\n",*(char*)buffer);
|
||||
wm->event = WIIUSE_NONE;
|
||||
|
||||
memcpy(wm->event_buf,buffer,len);
|
||||
memset(&(wm->event_buf[len]),0,(MAX_PAYLOAD - len));
|
||||
parse_event(wm);
|
||||
|
||||
if(wm->event!=WIIUSE_NONE) {
|
||||
if(wm->event_cb) wm->event_cb(wm,wm->event);
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static s32 __wiiuse_connected(void *arg,struct bte_pcb *pcb,u8 err)
|
||||
{
|
||||
struct wiimote_listen_t *wml = (struct wiimote_listen_t*)arg;
|
||||
struct wiimote_t *wm;
|
||||
|
||||
wm = wml->assign_cb(&wml->bdaddr);
|
||||
|
||||
if(!wm) {
|
||||
bte_disconnect(wml->sock);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
wml->wm = wm;
|
||||
|
||||
wm->sock = wml->sock;
|
||||
wm->bdaddr = wml->bdaddr;
|
||||
|
||||
//printf("__wiiuse_connected()\n");
|
||||
WIIMOTE_ENABLE_STATE(wm,(WIIMOTE_STATE_CONNECTED|WIIMOTE_STATE_HANDSHAKE));
|
||||
|
||||
wm->handshake_state = 0;
|
||||
wiiuse_handshake(wm,NULL,0);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void __wiiuse_sensorbar_enable(int enable)
|
||||
{
|
||||
u32 val;
|
||||
u32 level;
|
||||
|
||||
level = IRQ_Disable();
|
||||
val = (ACR_ReadReg(0xc0)&~0x100);
|
||||
if(enable) val |= 0x100;
|
||||
ACR_WriteReg(0xc0,val);
|
||||
IRQ_Restore(level);
|
||||
}
|
||||
|
||||
int wiiuse_register(struct wiimote_listen_t *wml, struct bd_addr *bdaddr, struct wiimote_t *(*assign_cb)(struct bd_addr *bdaddr))
|
||||
{
|
||||
s32 err;
|
||||
|
||||
if(!wml || !bdaddr || !assign_cb) return 0;
|
||||
|
||||
wml->wm = NULL;
|
||||
wml->bdaddr = *bdaddr;
|
||||
wml->sock = bte_new();
|
||||
wml->assign_cb = assign_cb;
|
||||
if(wml->sock==NULL) return 0;
|
||||
|
||||
bte_arg(wml->sock,wml);
|
||||
bte_received(wml->sock,__wiiuse_receive);
|
||||
bte_disconnected(wml->sock,__wiiuse_disconnected);
|
||||
|
||||
err = bte_registerdeviceasync(wml->sock,bdaddr,__wiiuse_connected);
|
||||
if(err==ERR_OK) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wiiuse_disconnect(struct wiimote_t *wm)
|
||||
{
|
||||
if(wm==NULL || wm->sock==NULL) return;
|
||||
|
||||
WIIMOTE_DISABLE_STATE(wm,WIIMOTE_STATE_CONNECTED);
|
||||
bte_disconnect(wm->sock);
|
||||
}
|
||||
|
||||
void wiiuse_sensorbar_enable(int enable)
|
||||
{
|
||||
__wiiuse_sensorbar_enable(enable);
|
||||
}
|
||||
|
||||
|
||||
void wiiuse_init_cmd_queue(struct wiimote_t *wm)
|
||||
{
|
||||
u32 size;
|
||||
|
||||
if (!__queue_buffer[wm->unid]) {
|
||||
size = (MAX_COMMANDS*sizeof(struct cmd_blk_t));
|
||||
__queue_buffer[wm->unid] = __lwp_heap_allocate(&__wkspace_heap,size);
|
||||
if(!__queue_buffer[wm->unid]) return;
|
||||
}
|
||||
|
||||
__lwp_queue_initialize(&wm->cmdq,__queue_buffer[wm->unid],MAX_COMMANDS,sizeof(struct cmd_blk_t));
|
||||
}
|
||||
|
||||
int wiiuse_io_write(struct wiimote_t *wm,ubyte *buf,int len)
|
||||
{
|
||||
if(wm->sock) {
|
||||
return bte_senddata(wm->sock,buf,len);
|
||||
}
|
||||
|
||||
return ERR_CONN;
|
||||
}
|
||||
|
||||
#endif
|
837
wii/wiiuse/ir.c
837
wii/wiiuse/ir.c
@ -1,837 +0,0 @@
|
||||
/* This source as presented is a modified version of original wiiuse for use
|
||||
* with RetroArch, and must not be confused with the original software. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef GEKKO
|
||||
#include <ogcsys.h>
|
||||
#endif
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "ir.h"
|
||||
|
||||
static int ir_correct_for_bounds(float* x, float* y, enum aspect_t aspect, int offset_x, int offset_y);
|
||||
static void ir_convert_to_vres(float* x, float* y, enum aspect_t aspect, unsigned int vx, unsigned int vy);
|
||||
|
||||
/**
|
||||
* @brief Get the IR sensitivity settings.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param block1 [out] Pointer to where block1 will be set.
|
||||
* @param block2 [out] Pointer to where block2 will be set.
|
||||
*
|
||||
* @return Returns the sensitivity level.
|
||||
*/
|
||||
static int get_ir_sens(struct wiimote_t* wm, char** block1, char** block2) {
|
||||
if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL1)) {
|
||||
*block1 = WM_IR_BLOCK1_LEVEL1;
|
||||
*block2 = WM_IR_BLOCK2_LEVEL1;
|
||||
return 1;
|
||||
} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL2)) {
|
||||
*block1 = WM_IR_BLOCK1_LEVEL2;
|
||||
*block2 = WM_IR_BLOCK2_LEVEL2;
|
||||
return 2;
|
||||
} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL3)) {
|
||||
*block1 = WM_IR_BLOCK1_LEVEL3;
|
||||
*block2 = WM_IR_BLOCK2_LEVEL3;
|
||||
return 3;
|
||||
} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL4)) {
|
||||
*block1 = WM_IR_BLOCK1_LEVEL4;
|
||||
*block2 = WM_IR_BLOCK2_LEVEL4;
|
||||
return 4;
|
||||
} else if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR_SENS_LVL5)) {
|
||||
*block1 = WM_IR_BLOCK1_LEVEL5;
|
||||
*block2 = WM_IR_BLOCK2_LEVEL5;
|
||||
return 5;
|
||||
}
|
||||
|
||||
*block1 = NULL;
|
||||
*block2 = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rotate_dots(struct fdot_t* in, struct fdot_t *out, int count, float ang) {
|
||||
float s, c;
|
||||
int i;
|
||||
|
||||
if (ang == 0) {
|
||||
for (i = 0; i < count; ++i) {
|
||||
out[i].x = in[i].x;
|
||||
out[i].y = in[i].y;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
s = sin(DEGREE_TO_RAD(ang));
|
||||
c = cos(DEGREE_TO_RAD(ang));
|
||||
|
||||
/*
|
||||
* [ cos(theta) -sin(theta) ][ ir->rx ]
|
||||
* [ sin(theta) cos(theta) ][ ir->ry ]
|
||||
*/
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
out[i].x = (c * in[i].x) + (-s * in[i].y);
|
||||
out[i].y = (s * in[i].x) + (c * in[i].y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Correct for the IR bounding box.
|
||||
*
|
||||
* @param x [out] The current X, it will be updated if valid.
|
||||
* @param y [out] The current Y, it will be updated if valid.
|
||||
* @param aspect Aspect ratio of the screen.
|
||||
* @param offset_x The X offset of the bounding box.
|
||||
* @param offset_y The Y offset of the bounding box.
|
||||
*
|
||||
* @return Returns 1 if the point is valid and was updated.
|
||||
*
|
||||
* Nintendo was smart with this bit. They sacrifice a little
|
||||
* precision for a big increase in usability.
|
||||
*/
|
||||
static int ir_correct_for_bounds(float* x, float* y, enum aspect_t aspect, int offset_x, int offset_y) {
|
||||
float x0, y0;
|
||||
int xs, ys;
|
||||
|
||||
if (aspect == WIIUSE_ASPECT_16_9) {
|
||||
xs = WM_ASPECT_16_9_X;
|
||||
ys = WM_ASPECT_16_9_Y;
|
||||
} else {
|
||||
xs = WM_ASPECT_4_3_X;
|
||||
ys = WM_ASPECT_4_3_Y;
|
||||
}
|
||||
|
||||
x0 = ((1024 - xs) / 2) + offset_x;
|
||||
y0 = ((768 - ys) / 2) + offset_y;
|
||||
|
||||
if ((*x >= x0)
|
||||
&& (*x <= (x0 + xs))
|
||||
&& (*y >= y0)
|
||||
&& (*y <= (y0 + ys)))
|
||||
{
|
||||
*x -= offset_x;
|
||||
*y -= offset_y;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Interpolate the point to the user defined virtual screen resolution.
|
||||
*/
|
||||
static void ir_convert_to_vres(float* x, float* y, enum aspect_t aspect, unsigned int vx, unsigned int vy) {
|
||||
int xs, ys;
|
||||
|
||||
if (aspect == WIIUSE_ASPECT_16_9) {
|
||||
xs = WM_ASPECT_16_9_X;
|
||||
ys = WM_ASPECT_16_9_Y;
|
||||
} else {
|
||||
xs = WM_ASPECT_4_3_X;
|
||||
ys = WM_ASPECT_4_3_Y;
|
||||
}
|
||||
|
||||
*x -= ((1024-xs)/2);
|
||||
*y -= ((768-ys)/2);
|
||||
|
||||
*x = (*x / (float)xs) * vx;
|
||||
*y = (*y / (float)ys) * vy;
|
||||
}
|
||||
|
||||
void wiiuse_set_ir_mode(struct wiimote_t *wm)
|
||||
{
|
||||
ubyte buf = 0x00;
|
||||
|
||||
if(!wm) return;
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_IR)) return;
|
||||
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP)) buf = WM_IR_TYPE_BASIC;
|
||||
else buf = WM_IR_TYPE_EXTENDED;
|
||||
wiiuse_write_data(wm,WM_REG_IR_MODENUM, &buf, 1, NULL);
|
||||
}
|
||||
|
||||
void wiiuse_set_ir(struct wiimote_t *wm,int status)
|
||||
{
|
||||
ubyte buf = 0x00;
|
||||
int ir_level = 0;
|
||||
char* block1 = NULL;
|
||||
char* block2 = NULL;
|
||||
|
||||
if(!wm) return;
|
||||
|
||||
/*
|
||||
* Wait for the handshake to finish first.
|
||||
* When it handshake finishes and sees that
|
||||
* IR is enabled, it will call this function
|
||||
* again to actually enable IR.
|
||||
*/
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)) {
|
||||
WIIUSE_DEBUG("Tried to enable IR, will wait until handshake finishes.\n");
|
||||
if(status)
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_INIT);
|
||||
else
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_IR_INIT);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to make sure a sensitivity setting is selected.
|
||||
*/
|
||||
ir_level = get_ir_sens(wm, &block1, &block2);
|
||||
if (!ir_level) {
|
||||
WIIUSE_ERROR("No IR sensitivity setting selected.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
/* if already enabled then stop */
|
||||
if (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) {
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* if already disabled then stop */
|
||||
if (!WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR)) {
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
buf = (status ? 0x04 : 0x00);
|
||||
wiiuse_sendcmd(wm,WM_CMD_IR,&buf,1,NULL);
|
||||
wiiuse_sendcmd(wm,WM_CMD_IR_2,&buf,1,NULL);
|
||||
|
||||
if (!status) {
|
||||
WIIUSE_DEBUG("Disabled IR cameras for wiimote id %i.", wm->unid);
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/* enable IR, set sensitivity */
|
||||
buf = 0x08;
|
||||
wiiuse_write_data(wm,WM_REG_IR,&buf,1,NULL);
|
||||
|
||||
wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (ubyte*)block1, 9, NULL);
|
||||
wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (ubyte*)block2, 2, NULL);
|
||||
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP)) buf = WM_IR_TYPE_BASIC;
|
||||
else buf = WM_IR_TYPE_EXTENDED;
|
||||
wiiuse_write_data(wm,WM_REG_IR_MODENUM, &buf, 1, NULL);
|
||||
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the virtual screen resolution for IR tracking.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param status 1 to enable, 0 to disable.
|
||||
*/
|
||||
void wiiuse_set_ir_vres(struct wiimote_t* wm, unsigned int x, unsigned int y) {
|
||||
if (!wm) return;
|
||||
|
||||
wm->ir.vres[0] = (x-1);
|
||||
wm->ir.vres[1] = (y-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the XY position for the IR cursor.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
*/
|
||||
void wiiuse_set_ir_position(struct wiimote_t* wm, enum ir_position_t pos) {
|
||||
if (!wm) return;
|
||||
|
||||
wm->ir.pos = pos;
|
||||
|
||||
switch (pos) {
|
||||
|
||||
case WIIUSE_IR_ABOVE:
|
||||
wm->ir.offset[0] = 0;
|
||||
|
||||
if (wm->ir.aspect == WIIUSE_ASPECT_16_9)
|
||||
wm->ir.offset[1] = WM_ASPECT_16_9_Y/2 - 70;
|
||||
else if (wm->ir.aspect == WIIUSE_ASPECT_4_3)
|
||||
wm->ir.offset[1] = WM_ASPECT_4_3_Y/2 - 100;
|
||||
|
||||
return;
|
||||
|
||||
case WIIUSE_IR_BELOW:
|
||||
wm->ir.offset[0] = 0;
|
||||
|
||||
if (wm->ir.aspect == WIIUSE_ASPECT_16_9)
|
||||
wm->ir.offset[1] = -WM_ASPECT_16_9_Y/2 + 70;
|
||||
else if (wm->ir.aspect == WIIUSE_ASPECT_4_3)
|
||||
wm->ir.offset[1] = -WM_ASPECT_4_3_Y/2 + 100;
|
||||
|
||||
return;
|
||||
|
||||
default:
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the aspect ratio of the TV/monitor.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param aspect Either WIIUSE_ASPECT_16_9 or WIIUSE_ASPECT_4_3
|
||||
*/
|
||||
void wiiuse_set_aspect_ratio(struct wiimote_t* wm, enum aspect_t aspect) {
|
||||
if (!wm) return;
|
||||
|
||||
wm->ir.aspect = aspect;
|
||||
|
||||
if (aspect == WIIUSE_ASPECT_4_3) {
|
||||
wm->ir.vres[0] = WM_ASPECT_4_3_X;
|
||||
wm->ir.vres[1] = WM_ASPECT_4_3_Y;
|
||||
} else {
|
||||
wm->ir.vres[0] = WM_ASPECT_16_9_X;
|
||||
wm->ir.vres[1] = WM_ASPECT_16_9_Y;
|
||||
}
|
||||
|
||||
/* reset the position offsets */
|
||||
wiiuse_set_ir_position(wm, wm->ir.pos);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the IR sensitivity.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param level 1-5, same as Wii system sensitivity setting.
|
||||
*
|
||||
* If the level is < 1, then level will be set to 1.
|
||||
* If the level is > 5, then level will be set to 5.
|
||||
*/
|
||||
void wiiuse_set_ir_sensitivity(struct wiimote_t* wm, int level) {
|
||||
char* block1 = NULL;
|
||||
char* block2 = NULL;
|
||||
|
||||
if (!wm) return;
|
||||
|
||||
if (level > 5) level = 5;
|
||||
if (level < 1) level = 1;
|
||||
|
||||
WIIMOTE_DISABLE_STATE(wm, (WIIMOTE_STATE_IR_SENS_LVL1 |
|
||||
WIIMOTE_STATE_IR_SENS_LVL2 |
|
||||
WIIMOTE_STATE_IR_SENS_LVL3 |
|
||||
WIIMOTE_STATE_IR_SENS_LVL4 |
|
||||
WIIMOTE_STATE_IR_SENS_LVL5));
|
||||
|
||||
switch (level) {
|
||||
case 1:
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL1);
|
||||
break;
|
||||
case 2:
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL2);
|
||||
break;
|
||||
case 3:
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL3);
|
||||
break;
|
||||
case 4:
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL4);
|
||||
break;
|
||||
case 5:
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_IR_SENS_LVL5);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_IR)) return;
|
||||
|
||||
/* set the new sensitivity */
|
||||
get_ir_sens(wm, &block1, &block2);
|
||||
|
||||
wiiuse_write_data(wm, WM_REG_IR_BLOCK1, (ubyte*)block1, 9,NULL);
|
||||
wiiuse_write_data(wm, WM_REG_IR_BLOCK2, (ubyte*)block2, 2,NULL);
|
||||
|
||||
WIIUSE_DEBUG("Set IR sensitivity to level %i (unid %i)", level, wm->unid);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Calculate the data from the IR spots. Basic IR mode.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param data Data returned by the wiimote for the IR spots.
|
||||
*/
|
||||
void calculate_basic_ir(struct wiimote_t* wm, ubyte* data) {
|
||||
struct ir_dot_t* dot = wm->ir.dot;
|
||||
int i;
|
||||
|
||||
dot[0].rx = 1023 - (data[0] | ((data[2] & 0x30) << 4));
|
||||
dot[0].ry = data[1] | ((data[2] & 0xC0) << 2);
|
||||
|
||||
dot[1].rx = 1023 - (data[3] | ((data[2] & 0x03) << 8));
|
||||
dot[1].ry = data[4] | ((data[2] & 0x0C) << 6);
|
||||
|
||||
dot[2].rx = 1023 - (data[5] | ((data[7] & 0x30) << 4));
|
||||
dot[2].ry = data[6] | ((data[7] & 0xC0) << 2);
|
||||
|
||||
dot[3].rx = 1023 - (data[8] | ((data[7] & 0x03) << 8));
|
||||
dot[3].ry = data[9] | ((data[7] & 0x0C) << 6);
|
||||
|
||||
/* set each IR spot to visible if spot is in range */
|
||||
for (i = 0; i < 4; ++i) {
|
||||
dot[i].rx = BIG_ENDIAN_SHORT(dot[i].rx);
|
||||
dot[i].ry = BIG_ENDIAN_SHORT(dot[i].ry);
|
||||
|
||||
if (dot[i].ry == 1023)
|
||||
dot[i].visible = 0;
|
||||
else {
|
||||
dot[i].visible = 1;
|
||||
dot[i].size = 0; /* since we don't know the size, set it as 0 */
|
||||
}
|
||||
}
|
||||
#ifndef GEKKO
|
||||
interpret_ir_data(&wm->ir,&wm->orient,WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC));
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate the data from the IR spots. Extended IR mode.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param data Data returned by the wiimote for the IR spots.
|
||||
*/
|
||||
void calculate_extended_ir(struct wiimote_t* wm, ubyte* data) {
|
||||
struct ir_dot_t* dot = wm->ir.dot;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
dot[i].rx = 1023 - (data[3*i] | ((data[(3*i)+2] & 0x30) << 4));
|
||||
dot[i].ry = data[(3*i)+1] | ((data[(3*i)+2] & 0xC0) << 2);
|
||||
|
||||
dot[i].size = data[(3*i)+2];
|
||||
|
||||
dot[i].rx = BIG_ENDIAN_SHORT(dot[i].rx);
|
||||
dot[i].ry = BIG_ENDIAN_SHORT(dot[i].ry);
|
||||
|
||||
dot[i].size = dot[i].size&0x0f;
|
||||
|
||||
/* if in range set to visible */
|
||||
if (dot[i].ry == 1023)
|
||||
dot[i].visible = 0;
|
||||
else
|
||||
dot[i].visible = 1;
|
||||
}
|
||||
#ifndef GEKKO
|
||||
interpret_ir_data(&wm->ir,&wm->orient,WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC));
|
||||
#endif
|
||||
}
|
||||
|
||||
enum {
|
||||
IR_STATE_DEAD = 0,
|
||||
IR_STATE_GOOD,
|
||||
IR_STATE_SINGLE,
|
||||
IR_STATE_LOST,
|
||||
};
|
||||
|
||||
// half-height of the IR sensor if half-width is 1
|
||||
#define HEIGHT (384.0f / 512.0f)
|
||||
// maximum sensor bar slope (tan(35 degrees))
|
||||
#define MAX_SB_SLOPE 0.7f
|
||||
// minimum sensor bar width in view, relative to half of the IR sensor area
|
||||
#define MIN_SB_WIDTH 0.1f
|
||||
// reject "sensor bars" that happen to have a dot towards the middle
|
||||
#define SB_MIDDOT_REJECT 0.05f
|
||||
|
||||
// physical dimensions
|
||||
// cm center to center of emitters
|
||||
#define SB_WIDTH 19.5f
|
||||
// half-width in cm of emitters
|
||||
#define SB_DOT_WIDTH 2.25f
|
||||
// half-height in cm of emitters (with some tolerance)
|
||||
#define SB_DOT_HEIGHT 1.0f
|
||||
|
||||
#define SB_DOT_WIDTH_RATIO (SB_DOT_WIDTH / SB_WIDTH)
|
||||
#define SB_DOT_HEIGHT_RATIO (SB_DOT_HEIGHT / SB_WIDTH)
|
||||
|
||||
// dots further out than these coords are allowed to not be picked up
|
||||
// otherwise assume something's wrong
|
||||
//#define SB_OFF_SCREEN_X 0.8f
|
||||
//#define SB_OFF_SCREEN_Y (0.8f * HEIGHT)
|
||||
|
||||
// disable, may be doing more harm than good due to sensor pickup glitches
|
||||
#define SB_OFF_SCREEN_X 0.0f
|
||||
#define SB_OFF_SCREEN_Y 0.0f
|
||||
|
||||
// if a point is closer than this to one of the previous SB points
|
||||
// when it reappears, consider it the same instead of trying to guess
|
||||
// which one of the two it is
|
||||
#define SB_SINGLE_NOGUESS_DISTANCE (100.0 * 100.0)
|
||||
|
||||
// width of the sensor bar in pixels at one meter from the Wiimote
|
||||
#define SB_Z_COEFFICIENT 256.0f
|
||||
|
||||
// distance in meters from the center of the FOV to the left or right edge,
|
||||
// when the wiimote is at one meter
|
||||
#define WIIMOTE_FOV_COEFFICIENT 0.39f
|
||||
|
||||
#define SQUARED(x) ((x)*(x))
|
||||
#define WMAX(x,y) ((x>y)?(x):(y))
|
||||
#define WMIN(x,y) ((x<y)?(x):(y))
|
||||
|
||||
/**
|
||||
* @brief Interpret IR data into more user friendly variables.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
*/
|
||||
void find_sensorbar(struct ir_t* ir, struct orient_t *orient) {
|
||||
struct fdot_t dots[4];
|
||||
struct fdot_t acc_dots[4];
|
||||
struct sb_t cand;
|
||||
struct sb_t candidates[6];
|
||||
struct sb_t sb;
|
||||
|
||||
fdot_t difference;
|
||||
|
||||
int num_candidates = 0;
|
||||
|
||||
int i;
|
||||
int j;
|
||||
int first, second;
|
||||
|
||||
WIIUSE_DEBUG("IR: orient angle: %.02f\n",orient->roll);
|
||||
|
||||
/* count visible dots and populate dots structure */
|
||||
/* dots[] is in -1..1 units for width */
|
||||
ir->num_dots = 0;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (ir->dot[i].visible) {
|
||||
dots[ir->num_dots].x = (ir->dot[i].rx - 512.0f) / 512.0f;
|
||||
dots[ir->num_dots].y = (ir->dot[i].ry - 384.0f) / 512.0f;
|
||||
WIIUSE_DEBUG("IR: dot %d at (%d,%d) (%.03f,%.03f)\n",ir->num_dots,ir->dot[i].rx,ir->dot[i].ry,dots[ir->num_dots].x,dots[ir->num_dots].y);
|
||||
ir->num_dots++;
|
||||
}
|
||||
}
|
||||
|
||||
WIIUSE_DEBUG("IR: found %d dots\n",ir->num_dots);
|
||||
|
||||
// nothing to track
|
||||
if(ir->num_dots == 0) {
|
||||
if(ir->state != IR_STATE_DEAD)
|
||||
ir->state = IR_STATE_LOST;
|
||||
ir->ax = 0;
|
||||
ir->ay = 0;
|
||||
ir->distance = 0.0f;
|
||||
ir->raw_valid = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* ==== Find the Sensor Bar ==== */
|
||||
|
||||
// first rotate according to accelerometer orientation
|
||||
rotate_dots(dots, acc_dots, ir->num_dots, orient->roll);
|
||||
if(ir->num_dots > 1) {
|
||||
WIIUSE_DEBUG("IR: locating sensor bar candidates\n");
|
||||
|
||||
// iterate through all dot pairs
|
||||
for(first=0; first < (ir->num_dots-1); first++) {
|
||||
for(second=(first+1); second < ir->num_dots; second++) {
|
||||
WIIUSE_DEBUG("IR: trying dots %d and %d\n",first,second);
|
||||
// order the dots leftmost first into cand
|
||||
// storing both the raw dots and the accel-rotated dots
|
||||
if(acc_dots[first].x > acc_dots[second].x) {
|
||||
cand.dots[0] = dots[second];
|
||||
cand.dots[1] = dots[first];
|
||||
cand.acc_dots[0] = acc_dots[second];
|
||||
cand.acc_dots[1] = acc_dots[first];
|
||||
} else {
|
||||
cand.dots[0] = dots[first];
|
||||
cand.dots[1] = dots[second];
|
||||
cand.acc_dots[0] = acc_dots[first];
|
||||
cand.acc_dots[1] = acc_dots[second];
|
||||
}
|
||||
difference.x = cand.acc_dots[1].x - cand.acc_dots[0].x;
|
||||
difference.y = cand.acc_dots[1].y - cand.acc_dots[0].y;
|
||||
|
||||
// check angle
|
||||
if(fabsf(difference.y / difference.x) > MAX_SB_SLOPE)
|
||||
continue;
|
||||
WIIUSE_DEBUG("IR: passed angle check\n");
|
||||
// rotate to the true sensor bar angle
|
||||
cand.off_angle = -RAD_TO_DEGREE(atan2(difference.y, difference.x));
|
||||
cand.angle = cand.off_angle + orient->roll;
|
||||
rotate_dots(cand.dots, cand.rot_dots, 2, cand.angle);
|
||||
WIIUSE_DEBUG("IR: off_angle: %.02f, angle: %.02f\n", cand.off_angle, cand.angle);
|
||||
// recalculate x distance - y should be zero now, so ignore it
|
||||
difference.x = cand.rot_dots[1].x - cand.rot_dots[0].x;
|
||||
|
||||
// check distance
|
||||
if(difference.x < MIN_SB_WIDTH)
|
||||
continue;
|
||||
// middle dot check. If there's another source somewhere in the
|
||||
// middle of this candidate, then this can't be a sensor bar
|
||||
|
||||
for(i=0; i<ir->num_dots; i++) {
|
||||
float wadj, hadj;
|
||||
struct fdot_t tdot;
|
||||
if(i==first || i==second) continue;
|
||||
hadj = SB_DOT_HEIGHT_RATIO * difference.x;
|
||||
wadj = SB_DOT_WIDTH_RATIO * difference.x;
|
||||
rotate_dots(&dots[i], &tdot, 1, cand.angle);
|
||||
if( ((cand.rot_dots[0].x + wadj) < tdot.x) &&
|
||||
((cand.rot_dots[1].x - wadj) > tdot.x) &&
|
||||
((cand.rot_dots[0].y + hadj) > tdot.y) &&
|
||||
((cand.rot_dots[0].y - hadj) < tdot.y))
|
||||
break;
|
||||
}
|
||||
// failed middle dot check
|
||||
if(i < ir->num_dots) continue;
|
||||
WIIUSE_DEBUG("IR: passed middle dot check\n");
|
||||
|
||||
cand.score = 1 / (cand.rot_dots[1].x - cand.rot_dots[0].x);
|
||||
|
||||
// we have a candidate, store it
|
||||
WIIUSE_DEBUG("IR: new candidate %d\n",num_candidates);
|
||||
candidates[num_candidates++] = cand;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(num_candidates == 0) {
|
||||
int closest = -1;
|
||||
int closest_to = 0;
|
||||
float best = 999.0f;
|
||||
float d;
|
||||
float dx[2];
|
||||
struct sb_t sbx[2];
|
||||
// no sensor bar candidates, try to work with a lone dot
|
||||
WIIUSE_DEBUG("IR: no candidates\n");
|
||||
switch(ir->state) {
|
||||
case IR_STATE_DEAD:
|
||||
WIIUSE_DEBUG("IR: we're dead\n");
|
||||
// we've never seen a sensor bar before, so we're screwed
|
||||
ir->ax = 0.0f;
|
||||
ir->ay = 0.0f;
|
||||
ir->distance = 0.0f;
|
||||
ir->raw_valid = 0;
|
||||
return;
|
||||
case IR_STATE_GOOD:
|
||||
case IR_STATE_SINGLE:
|
||||
case IR_STATE_LOST:
|
||||
WIIUSE_DEBUG("IR: trying to keep track of single dot\n");
|
||||
// try to find the dot closest to the previous sensor bar position
|
||||
for(i=0; i<ir->num_dots; i++) {
|
||||
WIIUSE_DEBUG("IR: checking dot %d (%.02f, %.02f)\n",i, acc_dots[i].x,acc_dots[i].y);
|
||||
for(j=0; j<2; j++) {
|
||||
WIIUSE_DEBUG(" to dot %d (%.02f, %.02f)\n",j, ir->sensorbar.acc_dots[j].x,ir->sensorbar.acc_dots[j].y);
|
||||
d = SQUARED(acc_dots[i].x - ir->sensorbar.acc_dots[j].x);
|
||||
d += SQUARED(acc_dots[i].y - ir->sensorbar.acc_dots[j].y);
|
||||
if(d < best) {
|
||||
best = d;
|
||||
closest_to = j;
|
||||
closest = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
WIIUSE_DEBUG("IR: closest dot is %d to %d\n",closest,closest_to);
|
||||
if(ir->state != IR_STATE_LOST || best < SB_SINGLE_NOGUESS_DISTANCE) {
|
||||
// now work out where the other dot would be, in the acc frame
|
||||
sb.acc_dots[closest_to] = acc_dots[closest];
|
||||
sb.acc_dots[closest_to^1].x = ir->sensorbar.acc_dots[closest_to^1].x - ir->sensorbar.acc_dots[closest_to].x + acc_dots[closest].x;
|
||||
sb.acc_dots[closest_to^1].y = ir->sensorbar.acc_dots[closest_to^1].y - ir->sensorbar.acc_dots[closest_to].y + acc_dots[closest].y;
|
||||
// get the raw frame
|
||||
rotate_dots(sb.acc_dots, sb.dots, 2, -orient->roll);
|
||||
if((fabsf(sb.dots[closest_to^1].x) < SB_OFF_SCREEN_X) && (fabsf(sb.dots[closest_to^1].y) < SB_OFF_SCREEN_Y)) {
|
||||
// this dot should be visible but isn't, since the candidate section failed.
|
||||
// fall through and try to pick out the sensor bar without previous information
|
||||
WIIUSE_DEBUG("IR: dot falls on screen, falling through\n");
|
||||
} else {
|
||||
// calculate the rotated dots frame
|
||||
// angle tends to drift, so recalculate
|
||||
sb.off_angle = -RAD_TO_DEGREE(atan2(sb.acc_dots[1].y - sb.acc_dots[0].y, sb.acc_dots[1].x - sb.acc_dots[0].x));
|
||||
sb.angle = ir->sensorbar.off_angle + orient->roll;
|
||||
rotate_dots(sb.acc_dots, sb.rot_dots, 2, ir->sensorbar.off_angle);
|
||||
WIIUSE_DEBUG("IR: kept track of single dot\n");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
WIIUSE_DEBUG("IR: lost the dot and new one is too far away\n");
|
||||
}
|
||||
// try to find the dot closest to the sensor edge
|
||||
WIIUSE_DEBUG("IR: trying to find best dot\n");
|
||||
for(i=0; i<ir->num_dots; i++) {
|
||||
d = WMIN(1.0f - fabsf(dots[i].x), HEIGHT - fabsf(dots[i].y));
|
||||
if(d < best) {
|
||||
best = d;
|
||||
closest = i;
|
||||
}
|
||||
}
|
||||
WIIUSE_DEBUG("IR: best dot: %d\n",closest);
|
||||
// now try it as both places in the sensor bar
|
||||
// and pick the one that places the other dot furthest off-screen
|
||||
for(i=0; i<2; i++) {
|
||||
sbx[i].acc_dots[i] = acc_dots[closest];
|
||||
sbx[i].acc_dots[i^1].x = ir->sensorbar.acc_dots[i^1].x - ir->sensorbar.acc_dots[i].x + acc_dots[closest].x;
|
||||
sbx[i].acc_dots[i^1].y = ir->sensorbar.acc_dots[i^1].y - ir->sensorbar.acc_dots[i].y + acc_dots[closest].y;
|
||||
rotate_dots(sbx[i].acc_dots, sbx[i].dots, 2, -orient->roll);
|
||||
dx[i] = WMAX(fabsf(sbx[i].dots[i^1].x),fabsf(sbx[i].dots[i^1].y / HEIGHT));
|
||||
}
|
||||
if(dx[0] > dx[1]) {
|
||||
WIIUSE_DEBUG("IR: dot is LEFT: %.02f > %.02f\n",dx[0],dx[1]);
|
||||
sb = sbx[0];
|
||||
} else {
|
||||
WIIUSE_DEBUG("IR: dot is RIGHT: %.02f < %.02f\n",dx[0],dx[1]);
|
||||
sb = sbx[1];
|
||||
}
|
||||
// angle tends to drift, so recalculate
|
||||
sb.off_angle = -RAD_TO_DEGREE(atan2(sb.acc_dots[1].y - sb.acc_dots[0].y, sb.acc_dots[1].x - sb.acc_dots[0].x));
|
||||
sb.angle = ir->sensorbar.off_angle + orient->roll;
|
||||
rotate_dots(sb.acc_dots, sb.rot_dots, 2, ir->sensorbar.off_angle);
|
||||
WIIUSE_DEBUG("IR: found new dot to track\n");
|
||||
break;
|
||||
}
|
||||
sb.score = 0;
|
||||
ir->state = IR_STATE_SINGLE;
|
||||
} else {
|
||||
int bestidx = 0;
|
||||
float best = 0.0f;
|
||||
WIIUSE_DEBUG("IR: finding best candidate\n");
|
||||
// look for the best candidate
|
||||
// for now, the formula is simple: pick the one with the smallest distance
|
||||
for(i=0; i<num_candidates; i++) {
|
||||
if(candidates[i].score > best) {
|
||||
bestidx = i;
|
||||
best = candidates[i].score;
|
||||
}
|
||||
}
|
||||
WIIUSE_DEBUG("IR: best candidate: %d\n",bestidx);
|
||||
sb = candidates[bestidx];
|
||||
ir->state = IR_STATE_GOOD;
|
||||
}
|
||||
|
||||
ir->raw_valid = 1;
|
||||
ir->ax = ((sb.rot_dots[0].x + sb.rot_dots[1].x) / 2) * 512.0 + 512.0;
|
||||
ir->ay = ((sb.rot_dots[0].y + sb.rot_dots[1].y) / 2) * 512.0 + 384.0;
|
||||
ir->sensorbar = sb;
|
||||
ir->distance = (sb.rot_dots[1].x - sb.rot_dots[0].x) * 512.0;
|
||||
|
||||
}
|
||||
|
||||
#define SMOOTH_IR_RADIUS 8.0f
|
||||
#define SMOOTH_IR_SPEED 0.25f
|
||||
#define SMOOTH_IR_DEADZONE 2.5f
|
||||
|
||||
/**
|
||||
* @brief Smooth the IR pointer position
|
||||
*
|
||||
* @param ir Pointer to an ir_t structure.
|
||||
*/
|
||||
void apply_ir_smoothing(struct ir_t *ir) {
|
||||
f32 dx, dy, d, theta;
|
||||
|
||||
WIIUSE_DEBUG("Smooth: OK (%.02f, %.02f) LAST (%.02f, %.02f) ", ir->ax, ir->ay, ir->sx, ir->sy);
|
||||
dx = ir->ax - ir->sx;
|
||||
dy = ir->ay - ir->sy;
|
||||
d = sqrtf(dx*dx + dy*dy);
|
||||
if (d > SMOOTH_IR_DEADZONE) {
|
||||
if (d < SMOOTH_IR_RADIUS) {
|
||||
WIIUSE_DEBUG("INSIDE\n");
|
||||
ir->sx += dx * SMOOTH_IR_SPEED;
|
||||
ir->sy += dy * SMOOTH_IR_SPEED;
|
||||
} else {
|
||||
WIIUSE_DEBUG("OUTSIDE\n");
|
||||
theta = atan2f(dy, dx);
|
||||
ir->sx = ir->ax - cosf(theta) * SMOOTH_IR_RADIUS;
|
||||
ir->sy = ir->ay - sinf(theta) * SMOOTH_IR_RADIUS;
|
||||
}
|
||||
} else {
|
||||
WIIUSE_DEBUG("DEADZONE\n");
|
||||
}
|
||||
}
|
||||
|
||||
// max number of errors before cooked data drops out
|
||||
#define ERROR_MAX_COUNT 8
|
||||
// max number of glitches before cooked data updates
|
||||
#define GLITCH_MAX_COUNT 5
|
||||
// squared delta over which we consider something a glitch
|
||||
#define GLITCH_DIST (150.0f * 150.0f)
|
||||
|
||||
/**
|
||||
* @brief Interpret IR data into more user friendly variables.
|
||||
*
|
||||
* @param ir Pointer to an ir_t structure.
|
||||
* @param orient Pointer to an orient_t structure.
|
||||
*/
|
||||
void interpret_ir_data(struct ir_t* ir, struct orient_t *orient) {
|
||||
|
||||
float x,y;
|
||||
float d;
|
||||
|
||||
find_sensorbar(ir, orient);
|
||||
|
||||
if(ir->raw_valid) {
|
||||
ir->angle = ir->sensorbar.angle;
|
||||
ir->z = SB_Z_COEFFICIENT / ir->distance;
|
||||
orient->yaw = calc_yaw(ir);
|
||||
if(ir->error_cnt >= ERROR_MAX_COUNT) {
|
||||
ir->sx = ir->ax;
|
||||
ir->sy = ir->ay;
|
||||
ir->glitch_cnt = 0;
|
||||
} else {
|
||||
d = SQUARED(ir->ax - ir->sx) + SQUARED(ir->ay - ir->sy);
|
||||
if(d > GLITCH_DIST) {
|
||||
if(ir->glitch_cnt > GLITCH_MAX_COUNT) {
|
||||
apply_ir_smoothing(ir);
|
||||
ir->glitch_cnt = 0;
|
||||
} else {
|
||||
ir->glitch_cnt++;
|
||||
}
|
||||
} else {
|
||||
ir->glitch_cnt = 0;
|
||||
apply_ir_smoothing(ir);
|
||||
}
|
||||
}
|
||||
ir->smooth_valid = 1;
|
||||
ir->error_cnt = 0;
|
||||
} else {
|
||||
if(ir->error_cnt >= ERROR_MAX_COUNT) {
|
||||
ir->smooth_valid = 0;
|
||||
} else {
|
||||
ir->smooth_valid = 1;
|
||||
ir->error_cnt++;
|
||||
}
|
||||
}
|
||||
if(ir->smooth_valid) {
|
||||
x = ir->sx;
|
||||
y = ir->sy;
|
||||
if (ir_correct_for_bounds(&x, &y, ir->aspect, ir->offset[0], ir->offset[1])) {
|
||||
ir_convert_to_vres(&x, &y, ir->aspect, ir->vres[0], ir->vres[1]);
|
||||
ir->x = x;
|
||||
ir->y = y;
|
||||
ir->valid = 1;
|
||||
} else {
|
||||
ir->valid = 0;
|
||||
}
|
||||
} else {
|
||||
ir->valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculate yaw given the IR data.
|
||||
*
|
||||
* @param ir IR data structure.
|
||||
*/
|
||||
float calc_yaw(struct ir_t* ir) {
|
||||
float x;
|
||||
|
||||
x = ir->ax - 512;
|
||||
x *= WIIMOTE_FOV_COEFFICIENT / 512.0;
|
||||
|
||||
return RAD_TO_DEGREE( atanf(x) );
|
||||
}
|
||||
|
@ -1,25 +0,0 @@
|
||||
/* This source as presented is a modified version of original wiiuse for use
|
||||
* with RetroArch, and must not be confused with the original software. */
|
||||
|
||||
#ifndef __IR_H__
|
||||
#define __IR_H__
|
||||
|
||||
#include "wiiuse_internal.h"
|
||||
|
||||
#define WII_VRES_X 560
|
||||
#define WII_VRES_Y 340
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void calculate_basic_ir(struct wiimote_t* wm, ubyte* data);
|
||||
void calculate_extended_ir(struct wiimote_t* wm, ubyte* data);
|
||||
float calc_yaw(struct ir_t* ir);
|
||||
void interpret_ir_data(struct ir_t* ir, struct orient_t *orient);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,641 +0,0 @@
|
||||
This license is valid ONLY for libogc and what this license
|
||||
defines as a "covered work" or a "combined work" with libogc.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an officialder
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
18. Exceptions
|
||||
|
||||
Linking this library statically or dynamically with other modules is
|
||||
making a combined work based on this library. Thus, the terms and
|
||||
conditions of the GNU General Public License cover the whole combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give
|
||||
you permission to link this library with independent modules to produce
|
||||
an executable, regardless of the license terms of these independent
|
||||
modules, and to copy and distribute the resulting executable under
|
||||
terms of your choice, provided that you also meet, for each linked
|
||||
independent module, the terms and conditions of the license of that
|
||||
module. An independent module is a module which is not derived from or
|
||||
based on this library. If you modify this library, you may extend this
|
||||
exception to your version of the library, but you are not obligated to
|
||||
do so. If you do not wish to do so, delete this exception statement from
|
||||
your version.
|
||||
|
@ -1,95 +0,0 @@
|
||||
/* This source as presented is a modified version of original wiiuse for use
|
||||
* with RetroArch, and must not be confused with the original software. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <Winsock2.h>
|
||||
#endif
|
||||
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "dynamics.h"
|
||||
#include "events.h"
|
||||
#include "io.h"
|
||||
|
||||
void wiiuse_motion_plus_check(struct wiimote_t *wm,ubyte *data,uword len)
|
||||
{
|
||||
u32 val;
|
||||
if(data == NULL)
|
||||
{
|
||||
wiiuse_read_data(wm, wm->motion_plus_id, WM_EXP_ID, 6, wiiuse_motion_plus_check);
|
||||
}
|
||||
else
|
||||
{
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP);
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP_FAILED);
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP_HANDSHAKE);
|
||||
val = (data[3] << 16) | (data[2] << 24) | (data[4] << 8) | data[5];
|
||||
if(val == EXP_ID_CODE_MOTION_PLUS)
|
||||
{
|
||||
/* handshake done */
|
||||
wm->event = WIIUSE_MOTION_PLUS_ACTIVATED;
|
||||
wm->exp.type = EXP_MOTION_PLUS;
|
||||
|
||||
WIIMOTE_ENABLE_STATE(wm,WIIMOTE_STATE_EXP);
|
||||
wiiuse_set_ir_mode(wm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void wiiuse_set_motion_plus_clear2(struct wiimote_t *wm,ubyte *data,uword len)
|
||||
{
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP);
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP_FAILED);
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_EXP_HANDSHAKE);
|
||||
wiiuse_set_ir_mode(wm);
|
||||
wiiuse_status(wm,NULL);
|
||||
}
|
||||
|
||||
static void wiiuse_set_motion_plus_clear1(struct wiimote_t *wm,ubyte *data,uword len)
|
||||
{
|
||||
ubyte val = 0x00;
|
||||
wiiuse_write_data(wm,WM_EXP_MEM_ENABLE1,&val,1,wiiuse_set_motion_plus_clear2);
|
||||
}
|
||||
|
||||
|
||||
void wiiuse_set_motion_plus(struct wiimote_t *wm, int status)
|
||||
{
|
||||
ubyte val;
|
||||
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_EXP_HANDSHAKE))
|
||||
return;
|
||||
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_EXP_HANDSHAKE);
|
||||
if(status)
|
||||
{
|
||||
val = 0x04;
|
||||
wiiuse_write_data(wm,WM_EXP_MOTION_PLUS_ENABLE,&val,1,wiiuse_motion_plus_check);
|
||||
}
|
||||
else
|
||||
{
|
||||
wiiuse_disable_expansion(wm);
|
||||
val = 0x55;
|
||||
wiiuse_write_data(wm,WM_EXP_MEM_ENABLE1,&val,1,wiiuse_set_motion_plus_clear1);
|
||||
}
|
||||
}
|
||||
|
||||
void motion_plus_disconnected(struct motion_plus_t* mp)
|
||||
{
|
||||
WIIUSE_DEBUG("Motion plus disconnected");
|
||||
memset(mp, 0, sizeof(struct motion_plus_t));
|
||||
}
|
||||
|
||||
void motion_plus_event(struct motion_plus_t* mp, ubyte* msg)
|
||||
{
|
||||
mp->rx = ((msg[5] & 0xFC) << 6) | msg[2]; // Pitch
|
||||
mp->ry = ((msg[4] & 0xFC) << 6) | msg[1]; // Roll
|
||||
mp->rz = ((msg[3] & 0xFC) << 6) | msg[0]; // Yaw
|
||||
|
||||
mp->ext = msg[4] & 0x1;
|
||||
mp->status = (msg[3] & 0x3) | ((msg[4] & 0x2) << 1); // roll, yaw, pitch
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Motion plus extension
|
||||
*/
|
||||
|
||||
/* This source as presented is a modified version of original wiiuse for use
|
||||
* with RetroArch, and must not be confused with the original software. */
|
||||
|
||||
#ifndef MOTION_PLUS_H_INCLUDED
|
||||
#define MOTION_PLUS_H_INCLUDED
|
||||
|
||||
#include "wiiuse_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void motion_plus_disconnected(struct motion_plus_t* mp);
|
||||
|
||||
void motion_plus_event(struct motion_plus_t* mp, ubyte* msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,157 +0,0 @@
|
||||
/* This source as presented is a modified version of original wiiuse for use
|
||||
* with RetroArch, and must not be confused with the original software. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dynamics.h"
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "nunchuk.h"
|
||||
#include "io.h"
|
||||
|
||||
/**
|
||||
* @brief Find what buttons are pressed.
|
||||
*
|
||||
* @param nc Pointer to a nunchuk_t structure.
|
||||
* @param msg The message byte specified in the event packet.
|
||||
*/
|
||||
static void nunchuk_pressed_buttons(struct nunchuk_t* nc, ubyte now) {
|
||||
/* message is inverted (0 is active, 1 is inactive) */
|
||||
now = ~now & NUNCHUK_BUTTON_ALL;
|
||||
|
||||
/* preserve old btns pressed */
|
||||
nc->btns_last = nc->btns;
|
||||
|
||||
/* pressed now & were pressed, then held */
|
||||
nc->btns_held = (now & nc->btns);
|
||||
|
||||
/* were pressed or were held & not pressed now, then released */
|
||||
nc->btns_released = ((nc->btns | nc->btns_held) & ~now);
|
||||
|
||||
/* buttons pressed now */
|
||||
nc->btns = now;
|
||||
}
|
||||
|
||||
int nunchuk_handshake(struct wiimote_t *wm,struct nunchuk_t *nc,ubyte *data,uword len)
|
||||
{
|
||||
//int i;
|
||||
int offset = 0;
|
||||
|
||||
nc->btns = 0;
|
||||
nc->btns_held = 0;
|
||||
nc->btns_released = 0;
|
||||
nc->flags = &wm->flags;
|
||||
nc->accel_calib = wm->accel_calib;
|
||||
|
||||
//for(i=0;i<len;i++) data[i] = (data[i]^0x17)+0x17;
|
||||
if(data[offset]==0xff) {
|
||||
if(data[offset+16]==0xff) {
|
||||
// try to read the calibration data again
|
||||
wiiuse_read_data(wm,data,WM_EXP_MEM_CALIBR,EXP_HANDSHAKE_LEN,wiiuse_handshake_expansion);
|
||||
} else
|
||||
offset += 16;
|
||||
}
|
||||
|
||||
nc->accel_calib.cal_zero.x = (data[offset + 0]<<2)|((data[offset + 3]>>4)&3);
|
||||
nc->accel_calib.cal_zero.y = (data[offset + 1]<<2)|((data[offset + 3]>>2)&3);
|
||||
nc->accel_calib.cal_zero.z = (data[offset + 2]<<2)|(data[offset + 3]&3);
|
||||
nc->accel_calib.cal_g.x = (data[offset + 4]<<2)|((data[offset + 7]>>4)&3);
|
||||
nc->accel_calib.cal_g.y = (data[offset + 5]<<2)|((data[offset + 7]>>2)&3);
|
||||
nc->accel_calib.cal_g.z = (data[offset + 6]<<2)|(data[offset + 7]&3);
|
||||
nc->js.max.x = data[offset + 8];
|
||||
nc->js.min.x = data[offset + 9];
|
||||
nc->js.center.x = data[offset + 10];
|
||||
nc->js.max.y = data[offset + 11];
|
||||
nc->js.min.y = data[offset + 12];
|
||||
nc->js.center.y = data[offset + 13];
|
||||
|
||||
// set to defaults (averages from 5 nunchuks) if calibration data is invalid
|
||||
if(nc->accel_calib.cal_zero.x == 0)
|
||||
nc->accel_calib.cal_zero.x = 499;
|
||||
if(nc->accel_calib.cal_zero.y == 0)
|
||||
nc->accel_calib.cal_zero.y = 509;
|
||||
if(nc->accel_calib.cal_zero.z == 0)
|
||||
nc->accel_calib.cal_zero.z = 507;
|
||||
if(nc->accel_calib.cal_g.x == 0)
|
||||
nc->accel_calib.cal_g.x = 703;
|
||||
if(nc->accel_calib.cal_g.y == 0)
|
||||
nc->accel_calib.cal_g.y = 709;
|
||||
if(nc->accel_calib.cal_g.z == 0)
|
||||
nc->accel_calib.cal_g.z = 709;
|
||||
if(nc->js.max.x == 0)
|
||||
nc->js.max.x = 223;
|
||||
if(nc->js.min.x == 0)
|
||||
nc->js.min.x = 27;
|
||||
if(nc->js.center.x == 0)
|
||||
nc->js.center.x = 126;
|
||||
if(nc->js.max.y == 0)
|
||||
nc->js.max.y = 222;
|
||||
if(nc->js.min.y == 0)
|
||||
nc->js.min.y = 30;
|
||||
if(nc->js.center.y == 0)
|
||||
nc->js.center.y = 131;
|
||||
|
||||
wm->event = WIIUSE_NUNCHUK_INSERTED;
|
||||
wm->exp.type = EXP_NUNCHUK;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The nunchuk disconnected.
|
||||
*
|
||||
* @param nc A pointer to a nunchuk_t structure.
|
||||
*/
|
||||
void nunchuk_disconnected(struct nunchuk_t* nc)
|
||||
{
|
||||
//printf("nunchuk_disconnected()\n");
|
||||
memset(nc, 0, sizeof(struct nunchuk_t));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle nunchuk event.
|
||||
*
|
||||
* @param nc A pointer to a nunchuk_t structure.
|
||||
* @param msg The message specified in the event packet.
|
||||
*/
|
||||
void nunchuk_event(struct nunchuk_t* nc, ubyte* msg) {
|
||||
//int i;
|
||||
|
||||
/* decrypt data */
|
||||
/*
|
||||
for (i = 0; i < 6; ++i)
|
||||
msg[i] = (msg[i] ^ 0x17) + 0x17;
|
||||
*/
|
||||
/* get button states */
|
||||
nunchuk_pressed_buttons(nc, msg[5]);
|
||||
|
||||
nc->js.pos.x = msg[0];
|
||||
nc->js.pos.y = msg[1];
|
||||
|
||||
/* extend min and max values to physical range of motion */
|
||||
if (nc->js.center.x) {
|
||||
if (nc->js.min.x > nc->js.pos.x) nc->js.min.x = nc->js.pos.x;
|
||||
if (nc->js.max.x < nc->js.pos.x) nc->js.max.x = nc->js.pos.x;
|
||||
}
|
||||
if (nc->js.center.y) {
|
||||
if (nc->js.min.y > nc->js.pos.y) nc->js.min.y = nc->js.pos.y;
|
||||
if (nc->js.max.y < nc->js.pos.y) nc->js.max.y = nc->js.pos.y;
|
||||
}
|
||||
|
||||
#ifndef GEKKO
|
||||
/* calculate joystick state */
|
||||
calc_joystick_state(&nc->js, nc->js.pos.x, nc->js.pos.y);
|
||||
#endif
|
||||
/* calculate orientation */
|
||||
nc->accel.x = (msg[2]<<2) + ((msg[5]>>2)&3);
|
||||
nc->accel.y = (msg[3]<<2) + ((msg[5]>>4)&3);
|
||||
nc->accel.z = (msg[4]<<2) + ((msg[5]>>6)&3);
|
||||
#ifndef GEKKO
|
||||
calculate_orientation(&nc->accel_calib, &nc->accel, &nc->orient, NUNCHUK_IS_FLAG_SET(nc, WIIUSE_SMOOTHING));
|
||||
calculate_gforce(&nc->accel_calib, &nc->accel, &nc->gforce);
|
||||
#endif
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
/* This source as presented is a modified version of original wiiuse for use
|
||||
* with RetroArch, and must not be confused with the original software. */
|
||||
|
||||
#ifndef __NUNCHUK_H__
|
||||
#define __NUNCHUK_H__
|
||||
|
||||
#include "wiiuse_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int nunchuk_handshake(struct wiimote_t* wm, struct nunchuk_t* nc, ubyte* data, uword len);
|
||||
void nunchuk_disconnected(struct nunchuk_t* nc);
|
||||
void nunchuk_event(struct nunchuk_t* nc, ubyte* msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,31 +0,0 @@
|
||||
/* This source as presented is a modified version of original wiiuse for use
|
||||
* with RetroArch, and must not be confused with the original software. */
|
||||
|
||||
#ifndef __OS_H__
|
||||
#define __OS_H__
|
||||
|
||||
#ifdef WIN32
|
||||
/* windows */
|
||||
#define isnan(x) _isnan(x)
|
||||
#define isinf(x) !_finite(x)
|
||||
|
||||
/* disable warnings I don't care about */
|
||||
#pragma warning(disable:4244) /* possible loss of data conversion */
|
||||
#pragma warning(disable:4273) /* inconsistent dll linkage */
|
||||
#pragma warning(disable:4217)
|
||||
#else
|
||||
/* nix/gekko */
|
||||
#ifdef GEKKO
|
||||
#include <gccore.h>
|
||||
#include <ogcsys.h>
|
||||
#include <bte/bte.h>
|
||||
#include "network.h"
|
||||
#include <ogc/lwp_queue.h>
|
||||
#include <ogc/machine/asm.h>
|
||||
#include <ogc/machine/processor.h>
|
||||
#include <ogc/lwp_wkspace.h>
|
||||
#else
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,145 +0,0 @@
|
||||
/* This source as presented is a modified version of original wiiuse for use
|
||||
* with RetroArch, and must not be confused with the original software. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef GEKKO
|
||||
#include <ogcsys.h>
|
||||
#endif
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "speaker.h"
|
||||
|
||||
#define WENCMIN(a,b) ((a)>(b)?(b):(a))
|
||||
#define ABS(x) ((s32)(x)>0?(s32)(x):-((s32)(x)))
|
||||
|
||||
static const int yamaha_indexscale[] = {
|
||||
230, 230, 230, 230, 307, 409, 512, 614,
|
||||
230, 230, 230, 230, 307, 409, 512, 614
|
||||
};
|
||||
|
||||
static const int yamaha_difflookup[] = {
|
||||
1, 3, 5, 7, 9, 11, 13, 15,
|
||||
-1, -3, -5, -7, -9, -11, -13, -15
|
||||
};
|
||||
|
||||
static ubyte __wiiuse_speaker_vol = 0x40;
|
||||
static ubyte __wiiuse_speaker_defconf[7] = { 0x00,0x00,0xD0,0x07,0x40,0x0C,0x0E };
|
||||
|
||||
static __inline__ short wenc_clip_short(int a)
|
||||
{
|
||||
if((a+32768)&~65535) return (a>>31)^32767;
|
||||
else return a;
|
||||
}
|
||||
|
||||
static __inline__ int wenc_clip(int a,int amin,int amax)
|
||||
{
|
||||
if(a<amin) return amin;
|
||||
else if(a>amax) return amax;
|
||||
else return a;
|
||||
}
|
||||
|
||||
ubyte wencdata(WENCStatus *info,short sample)
|
||||
{
|
||||
int nibble,delta;
|
||||
|
||||
if(!info->step) {
|
||||
info->predictor = 0;
|
||||
info->step = 127;
|
||||
}
|
||||
|
||||
delta = sample - info->predictor;
|
||||
nibble = WENCMIN(7,(ABS(delta)*4)/info->step) + ((delta<0)*8);
|
||||
|
||||
info->predictor += ((info->step*yamaha_difflookup[nibble])/8);
|
||||
info->predictor = wenc_clip_short(info->predictor);
|
||||
info->step = (info->step*yamaha_indexscale[nibble])>>8;
|
||||
info->step = wenc_clip(info->step,127,24576);
|
||||
|
||||
return nibble;
|
||||
}
|
||||
|
||||
void wiiuse_set_speaker(struct wiimote_t *wm,int status)
|
||||
{
|
||||
ubyte conf[7];
|
||||
ubyte buf = 0x00;
|
||||
|
||||
if(!wm) return;
|
||||
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)) {
|
||||
WIIUSE_DEBUG("Tried to enable speaker, will wait until handshake finishes.\n");
|
||||
if(status)
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_SPEAKER_INIT);
|
||||
else
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_SPEAKER_INIT);
|
||||
return;
|
||||
}
|
||||
|
||||
if(status) {
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_SPEAKER)) {
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_SPEAKER)) {
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
buf = 0x04;
|
||||
wiiuse_sendcmd(wm,WM_CMD_SPEAKER_MUTE,&buf,1,NULL);
|
||||
|
||||
if (!status) {
|
||||
WIIUSE_DEBUG("Disabled speaker for wiimote id %i.", wm->unid);
|
||||
|
||||
buf = 0x01;
|
||||
wiiuse_write_data(wm,WM_REG_SPEAKER_REG1,&buf,1,NULL);
|
||||
|
||||
buf = 0x00;
|
||||
wiiuse_write_data(wm,WM_REG_SPEAKER_REG3,&buf,1,NULL);
|
||||
|
||||
buf = 0x00;
|
||||
wiiuse_sendcmd(wm,WM_CMD_SPEAKER_ENABLE,&buf,1,NULL);
|
||||
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(conf,__wiiuse_speaker_defconf,7);
|
||||
|
||||
buf = 0x04;
|
||||
wiiuse_sendcmd(wm,WM_CMD_SPEAKER_ENABLE,&buf,1,NULL);
|
||||
|
||||
buf = 0x01;
|
||||
wiiuse_write_data(wm,WM_REG_SPEAKER_REG3,&buf,1,NULL);
|
||||
|
||||
buf = 0x08;
|
||||
wiiuse_write_data(wm,WM_REG_SPEAKER_REG1,&buf,1,NULL);
|
||||
|
||||
conf[2] = 0xd0;
|
||||
conf[3] = 0x07;
|
||||
conf[4] = __wiiuse_speaker_vol;
|
||||
wiiuse_write_data(wm,WM_REG_SPEAKER_BLOCK,conf,7,NULL);
|
||||
|
||||
buf = 0x01;
|
||||
wiiuse_write_data(wm,WM_REG_SPEAKER_REG2,&buf,1,NULL);
|
||||
|
||||
buf = 0x00;
|
||||
wiiuse_sendcmd(wm,WM_CMD_SPEAKER_MUTE,&buf,1,NULL);
|
||||
|
||||
wiiuse_status(wm,NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
void set_speakervol(struct wiimote_t *wm,ubyte vol)
|
||||
{
|
||||
__wiiuse_speaker_vol = vol;
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
/* This source as presented is a modified version of original wiiuse for use
|
||||
* with RetroArch, and must not be confused with the original software. */
|
||||
|
||||
#ifndef __SPEAKER_H__
|
||||
#define __SPEAKER_H__
|
||||
|
||||
#include "wiiuse_internal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct _wencstatus
|
||||
{
|
||||
s32 predictor;
|
||||
s16 step_index;
|
||||
s32 step;
|
||||
s32 prev_sample;
|
||||
s16 sample1;
|
||||
s16 sample2;
|
||||
s32 coeff1;
|
||||
s32 coeff2;
|
||||
s32 idelta;
|
||||
} WENCStatus;
|
||||
|
||||
u8 wencdata(WENCStatus *info,s16 sample);
|
||||
void set_speakervol(struct wiimote_t *wm,ubyte vol);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,337 +0,0 @@
|
||||
/* This source as presented is a modified version of original wiiuse for use
|
||||
* with RetroArch, and must not be confused with the original software. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <Winsock2.h>
|
||||
#endif
|
||||
|
||||
#include "definitions.h"
|
||||
#include "wiiuse_internal.h"
|
||||
#include "io.h"
|
||||
|
||||
static struct wiimote_t** __wm = NULL;
|
||||
|
||||
void wiiuse_send_next_command(struct wiimote_t *wm)
|
||||
{
|
||||
struct cmd_blk_t *cmd = wm->cmd_head;
|
||||
|
||||
if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return;
|
||||
|
||||
if(!cmd) return;
|
||||
if(cmd->state!=CMD_READY) return;
|
||||
|
||||
cmd->state = CMD_SENT;
|
||||
#ifdef HAVE_WIIUSE_RUMBLE
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_RUMBLE)) cmd->data[1] |= 0x01;
|
||||
#endif
|
||||
|
||||
//WIIUSE_DEBUG("Sending command: %02x %02x", cmd->data[0], cmd->data[1]);
|
||||
wiiuse_io_write(wm,cmd->data,cmd->len);
|
||||
}
|
||||
|
||||
static inline void __wiiuse_push_command(struct wiimote_t *wm,struct cmd_blk_t *cmd)
|
||||
{
|
||||
uint level;
|
||||
|
||||
if(!wm || !cmd) return;
|
||||
|
||||
cmd->next = NULL;
|
||||
cmd->state = CMD_READY;
|
||||
|
||||
_CPU_ISR_Disable(level);
|
||||
if(wm->cmd_head==NULL) {
|
||||
wm->cmd_head = wm->cmd_tail = cmd;
|
||||
wiiuse_send_next_command(wm);
|
||||
} else {
|
||||
wm->cmd_tail->next = cmd;
|
||||
wm->cmd_tail = cmd;
|
||||
}
|
||||
_CPU_ISR_Restore(level);
|
||||
}
|
||||
|
||||
#ifndef GEKKO
|
||||
struct wiimote_t** wiiuse_init(int wiimotes) {
|
||||
#else
|
||||
extern void __wiiuse_sensorbar_enable(int enable);
|
||||
struct wiimote_t** wiiuse_init(int wiimotes, wii_event_cb event_cb) {
|
||||
#endif
|
||||
int i = 0;
|
||||
|
||||
if (!wiimotes)
|
||||
return NULL;
|
||||
|
||||
if (!__wm) {
|
||||
__wm = __lwp_heap_allocate(&__wkspace_heap, sizeof(struct wiimote_t*) * wiimotes);
|
||||
if(!__wm) return NULL;
|
||||
memset(__wm, 0, sizeof(struct wiimote_t*) * wiimotes);
|
||||
}
|
||||
|
||||
for (i = 0; i < wiimotes; ++i) {
|
||||
if(!__wm[i])
|
||||
__wm[i] = __lwp_heap_allocate(&__wkspace_heap, sizeof(struct wiimote_t));
|
||||
|
||||
memset(__wm[i], 0, sizeof(struct wiimote_t));
|
||||
__wm[i]->unid = i;
|
||||
|
||||
#if defined(WIN32)
|
||||
__wm[i]->dev_handle = 0;
|
||||
__wm[i]->stack = WIIUSE_STACK_UNKNOWN;
|
||||
__wm[i]->normal_timeout = WIIMOTE_DEFAULT_TIMEOUT;
|
||||
__wm[i]->exp_timeout = WIIMOTE_EXP_TIMEOUT;
|
||||
__wm[i]->timeout = __wm[i]->normal_timeout;
|
||||
#elif defined(GEKKO)
|
||||
__wm[i]->sock = NULL;
|
||||
__wm[i]->bdaddr = *BD_ADDR_ANY;
|
||||
__wm[i]->event_cb = event_cb;
|
||||
wiiuse_init_cmd_queue(__wm[i]);
|
||||
#elif defined(unix)
|
||||
__wm[i]->bdaddr = *BDADDR_ANY;
|
||||
__wm[i]->out_sock = -1;
|
||||
__wm[i]->in_sock = -1;
|
||||
#endif
|
||||
|
||||
__wm[i]->state = WIIMOTE_INIT_STATES;
|
||||
__wm[i]->flags = WIIUSE_INIT_FLAGS;
|
||||
|
||||
__wm[i]->event = WIIUSE_NONE;
|
||||
|
||||
__wm[i]->exp.type = EXP_NONE;
|
||||
|
||||
wiiuse_set_aspect_ratio(__wm[i], WIIUSE_ASPECT_4_3);
|
||||
wiiuse_set_ir_position(__wm[i], WIIUSE_IR_ABOVE);
|
||||
|
||||
__wm[i]->accel_calib.st_alpha = WIIUSE_DEFAULT_SMOOTH_ALPHA;
|
||||
}
|
||||
|
||||
return __wm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set flags for the specified wiimote.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param enable Flags to enable.
|
||||
* @param disable Flags to disable.
|
||||
*
|
||||
* @return The flags set after 'enable' and 'disable' have been applied.
|
||||
*
|
||||
* The values 'enable' and 'disable' may be any flags OR'ed together.
|
||||
* Flags are defined in wiiuse.h.
|
||||
*/
|
||||
int wiiuse_set_flags(struct wiimote_t* wm, int enable, int disable) {
|
||||
if (!wm) return 0;
|
||||
|
||||
/* remove mutually exclusive flags */
|
||||
enable &= ~disable;
|
||||
disable &= ~enable;
|
||||
|
||||
wm->flags |= enable;
|
||||
wm->flags &= ~disable;
|
||||
|
||||
return wm->flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set if the wiimote should report motion sensing.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param status 1 to enable, 0 to disable.
|
||||
*
|
||||
* Since reporting motion sensing sends a lot of data,
|
||||
* the wiimote saves power by not transmitting it
|
||||
* by default.
|
||||
*/
|
||||
void wiiuse_motion_sensing(struct wiimote_t* wm, int status)
|
||||
{
|
||||
if (status) {
|
||||
if(WIIMOTE_IS_SET(wm,WIIMOTE_STATE_ACC)) return;
|
||||
WIIMOTE_ENABLE_STATE(wm, WIIMOTE_STATE_ACC);
|
||||
} else {
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_ACC)) return;
|
||||
WIIMOTE_DISABLE_STATE(wm, WIIMOTE_STATE_ACC);
|
||||
}
|
||||
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)) return;
|
||||
|
||||
wiiuse_status(wm,NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Toggle the state of the rumble.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
*/
|
||||
#ifdef HAVE_WIIUSE_RUMBLE
|
||||
void wiiuse_toggle_rumble(struct wiimote_t* wm)
|
||||
{
|
||||
if (!wm) return;
|
||||
|
||||
WIIMOTE_TOGGLE_STATE(wm, WIIMOTE_STATE_RUMBLE);
|
||||
if(!WIIMOTE_IS_SET(wm,WIIMOTE_STATE_HANDSHAKE_COMPLETE)) return;
|
||||
|
||||
wiiuse_set_leds(wm,wm->leds,NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the rumble.
|
||||
*
|
||||
* @param wm Pointer to a wiimote_t structure.
|
||||
* @param status 1 to enable, 0 to disable.
|
||||
*/
|
||||
void wiiuse_rumble(struct wiimote_t* wm, int status)
|
||||
{
|
||||
if (status && WIIMOTE_IS_SET(wm,WIIMOTE_STATE_RUMBLE)) return;
|
||||
else if(!status && !WIIMOTE_IS_SET(wm,WIIMOTE_STATE_RUMBLE)) return;
|
||||
wiiuse_toggle_rumble(wm);
|
||||
}
|
||||
#endif
|
||||
|
||||
void wiiuse_set_leds(struct wiimote_t *wm,int leds,cmd_blk_cb cb)
|
||||
{
|
||||
ubyte buf;
|
||||
|
||||
if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return;
|
||||
|
||||
wm->leds = (leds&0xf0);
|
||||
|
||||
buf = wm->leds;
|
||||
wiiuse_sendcmd(wm,WM_CMD_LED,&buf,1,cb);
|
||||
}
|
||||
|
||||
int wiiuse_set_report_type(struct wiimote_t *wm,cmd_blk_cb cb)
|
||||
{
|
||||
ubyte buf[2];
|
||||
int motion,ir,exp;
|
||||
|
||||
if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0;
|
||||
|
||||
buf[0] = (WIIMOTE_IS_FLAG_SET(wm, WIIUSE_CONTINUOUS) ? 0x04 : 0x00); /* set to 0x04 for continuous reporting */
|
||||
buf[1] = 0x00;
|
||||
|
||||
motion = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_ACC) || WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR);
|
||||
exp = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_EXP);
|
||||
ir = WIIMOTE_IS_SET(wm, WIIMOTE_STATE_IR);
|
||||
|
||||
if (motion && ir && exp) buf[1] = WM_RPT_BTN_ACC_IR_EXP;
|
||||
else if (motion && exp) buf[1] = WM_RPT_BTN_ACC_EXP;
|
||||
else if (motion && ir) buf[1] = WM_RPT_BTN_ACC_IR;
|
||||
else if (ir && exp) buf[1] = WM_RPT_BTN_IR_EXP;
|
||||
else if (ir) buf[1] = WM_RPT_BTN_ACC_IR;
|
||||
else if (exp) buf[1] = WM_RPT_BTN_EXP;
|
||||
else if (motion) buf[1] = WM_RPT_BTN_ACC;
|
||||
else buf[1] = WM_RPT_BTN;
|
||||
|
||||
//WIIUSE_DEBUG("Setting report type: 0x%x", buf[1]);
|
||||
|
||||
wiiuse_sendcmd(wm,WM_CMD_REPORT_TYPE,buf,2,cb);
|
||||
return buf[1];
|
||||
}
|
||||
|
||||
void wiiuse_status(struct wiimote_t *wm,cmd_blk_cb cb)
|
||||
{
|
||||
ubyte buf;
|
||||
|
||||
if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return;
|
||||
|
||||
buf = 0x00;
|
||||
wiiuse_sendcmd(wm,WM_CMD_CTRL_STATUS,&buf,1,cb);
|
||||
}
|
||||
|
||||
int wiiuse_read_data(struct wiimote_t *wm,ubyte *buffer,uint addr,uword len,cmd_blk_cb cb)
|
||||
{
|
||||
struct op_t *op;
|
||||
struct cmd_blk_t *cmd;
|
||||
|
||||
if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0;
|
||||
if(!buffer || !len) return 0;
|
||||
|
||||
cmd = (struct cmd_blk_t*)__lwp_queue_get(&wm->cmdq);
|
||||
if(!cmd) return 0;
|
||||
|
||||
cmd->cb = cb;
|
||||
cmd->len = 7;
|
||||
|
||||
op = (struct op_t*)cmd->data;
|
||||
op->cmd = WM_CMD_READ_DATA;
|
||||
op->buffer = buffer;
|
||||
op->wait = len;
|
||||
op->readdata.addr = BIG_ENDIAN_LONG(addr);
|
||||
op->readdata.size = BIG_ENDIAN_SHORT(len);
|
||||
__wiiuse_push_command(wm,cmd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int wiiuse_write_data(struct wiimote_t *wm,uint addr,ubyte *data,ubyte len,cmd_blk_cb cb)
|
||||
{
|
||||
struct op_t *op;
|
||||
struct cmd_blk_t *cmd;
|
||||
|
||||
if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0;
|
||||
if(!data || !len) return 0;
|
||||
|
||||
cmd = (struct cmd_blk_t*)__lwp_queue_get(&wm->cmdq);
|
||||
if(!cmd) return 0;
|
||||
|
||||
cmd->cb = cb;
|
||||
cmd->len = 22;
|
||||
|
||||
op = (struct op_t*)cmd->data;
|
||||
op->cmd = WM_CMD_WRITE_DATA;
|
||||
op->buffer = NULL;
|
||||
op->wait = 0;
|
||||
op->writedata.addr = BIG_ENDIAN_LONG(addr);
|
||||
op->writedata.size = (len&0x0f);
|
||||
memcpy(op->writedata.data,data,len);
|
||||
memset(op->writedata.data+len,0,(16 - len));
|
||||
__wiiuse_push_command(wm,cmd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int wiiuse_write_streamdata(struct wiimote_t *wm,ubyte *data,ubyte len,cmd_blk_cb cb)
|
||||
{
|
||||
struct cmd_blk_t *cmd;
|
||||
|
||||
if(!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0;
|
||||
if(!data || !len || len>20) return 0;
|
||||
|
||||
cmd = (struct cmd_blk_t*)__lwp_queue_get(&wm->cmdq);
|
||||
if(!cmd) return 0;
|
||||
|
||||
cmd->cb = cb;
|
||||
cmd->len = 22;
|
||||
cmd->data[0] = WM_CMD_STREAM_DATA;
|
||||
cmd->data[1] = (len<<3);
|
||||
memcpy(cmd->data+2,data,len);
|
||||
__wiiuse_push_command(wm,cmd);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int wiiuse_sendcmd(struct wiimote_t *wm,ubyte report_type,ubyte *msg,int len,cmd_blk_cb cb)
|
||||
{
|
||||
struct cmd_blk_t *cmd;
|
||||
|
||||
cmd = (struct cmd_blk_t*)__lwp_queue_get(&wm->cmdq);
|
||||
if(!cmd) return 0;
|
||||
|
||||
cmd->cb = cb;
|
||||
cmd->len = (1+len);
|
||||
|
||||
cmd->data[0] = report_type;
|
||||
memcpy(cmd->data+1,msg,len);
|
||||
if(report_type!=WM_CMD_READ_DATA && report_type!=WM_CMD_CTRL_STATUS)
|
||||
cmd->data[1] |= 0x02;
|
||||
|
||||
//WIIUSE_DEBUG("Pushing command: %02x %02x", cmd->data[0], cmd->data[1]);
|
||||
__wiiuse_push_command(wm,cmd);
|
||||
|
||||
return 1;
|
||||
}
|
@ -1,278 +0,0 @@
|
||||
/*
|
||||
* wiiuse
|
||||
*
|
||||
* Written By:
|
||||
* Michael Laforest < para >
|
||||
* Email: < thepara (--AT--) g m a i l [--DOT--] com >
|
||||
*
|
||||
* Copyright 2006-2007
|
||||
*
|
||||
* This file is part of wiiuse.
|
||||
*
|
||||
* This program 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 Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* $Header: /lvm/shared/ds/ds/cvs/devkitpro-cvsbackup/libogc/wiiuse/wiiuse_internal.h,v 1.8 2008-12-10 16:16:40 shagkur Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief General internal wiiuse stuff.
|
||||
*
|
||||
* Since Wiiuse is a library, wiiuse.h is a duplicate
|
||||
* of the API header.
|
||||
*
|
||||
* The code that would normally go in that file, but
|
||||
* which is not needed by third party developers,
|
||||
* is put here.
|
||||
*
|
||||
* So wiiuse_internal.h is included by other files
|
||||
* internally, wiiuse.h is included only here.
|
||||
*/
|
||||
|
||||
/* This source as presented is a modified version of original wiiuse for use
|
||||
* with RetroArch, and must not be confused with the original software. */
|
||||
|
||||
#ifndef WIIUSE_INTERNAL_H_INCLUDED
|
||||
#define WIIUSE_INTERNAL_H_INCLUDED
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <arpa/inet.h> /* htons() */
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#endif
|
||||
|
||||
#include "definitions.h"
|
||||
|
||||
/* wiiuse version */
|
||||
#define WIIUSE_VERSION "0.12"
|
||||
|
||||
/********************
|
||||
*
|
||||
* Wiimote internal codes
|
||||
*
|
||||
********************/
|
||||
|
||||
/* Communication channels */
|
||||
#define WM_OUTPUT_CHANNEL 0x11
|
||||
#define WM_INPUT_CHANNEL 0x13
|
||||
|
||||
#define WM_SET_REPORT 0x50
|
||||
#define WM_DATA 0xA0
|
||||
|
||||
/* commands */
|
||||
#define WM_CMD_RUMBLE 0x10
|
||||
#define WM_CMD_LED 0x11
|
||||
#define WM_CMD_REPORT_TYPE 0x12
|
||||
#define WM_CMD_IR 0x13
|
||||
#define WM_CMD_SPEAKER_ENABLE 0x14
|
||||
#define WM_CMD_CTRL_STATUS 0x15
|
||||
#define WM_CMD_WRITE_DATA 0x16
|
||||
#define WM_CMD_READ_DATA 0x17
|
||||
#define WM_CMD_STREAM_DATA 0x18
|
||||
#define WM_CMD_SPEAKER_MUTE 0x19
|
||||
#define WM_CMD_IR_2 0x1A
|
||||
|
||||
/* input report ids */
|
||||
#define WM_RPT_CTRL_STATUS 0x20
|
||||
#define WM_RPT_READ 0x21
|
||||
#define WM_RPT_ACK 0x22
|
||||
#define WM_RPT_BTN 0x30
|
||||
#define WM_RPT_BTN_ACC 0x31
|
||||
#define WM_RPT_BTN_ACC_IR 0x33
|
||||
#define WM_RPT_BTN_EXP 0x34
|
||||
#define WM_RPT_BTN_ACC_EXP 0x35
|
||||
#define WM_RPT_BTN_IR_EXP 0x36
|
||||
#define WM_RPT_BTN_ACC_IR_EXP 0x37
|
||||
|
||||
#define WM_BT_INPUT 0x01
|
||||
#define WM_BT_OUTPUT 0x02
|
||||
|
||||
/* Identify the wiimote device by its class */
|
||||
#define WM_DEV_CLASS_0 0x04
|
||||
#define WM_DEV_CLASS_1 0x25
|
||||
#define WM_DEV_CLASS_2 0x00
|
||||
#define WM_VENDOR_ID 0x057E
|
||||
#define WM_PRODUCT_ID 0x0306
|
||||
|
||||
/* controller status stuff */
|
||||
#define WM_MAX_BATTERY_CODE 0xC8
|
||||
|
||||
/* offsets in wiimote memory */
|
||||
#define WM_MEM_OFFSET_CALIBRATION 0x16
|
||||
#define WM_EXP_MEM_BASE 0x04A40000
|
||||
#define WM_EXP_MEM_ENABLE1 0x04A400F0
|
||||
#define WM_EXP_MEM_ENABLE2 0x04A400FB
|
||||
#define WM_EXP_MEM_KEY 0x04A40040
|
||||
#define WM_EXP_MEM_CALIBR 0x04A40020
|
||||
#define WM_EXP_MOTION_PLUS_ENABLE 0x04A600FE
|
||||
#define WM_EXP_ID 0x04A400FA
|
||||
|
||||
#define WM_REG_IR 0x04B00030
|
||||
#define WM_REG_IR_BLOCK1 0x04B00000
|
||||
#define WM_REG_IR_BLOCK2 0x04B0001A
|
||||
#define WM_REG_IR_MODENUM 0x04B00033
|
||||
|
||||
#define WM_REG_SPEAKER_REG1 0x04A20001
|
||||
#define WM_REG_SPEAKER_REG2 0x04A20008
|
||||
#define WM_REG_SPEAKER_REG3 0x04A20009
|
||||
#define WM_REG_SPEAKER_BLOCK 0x04A20001
|
||||
|
||||
/* ir block data */
|
||||
#define WM_IR_BLOCK1_LEVEL1 "\x02\x00\x00\x71\x01\x00\x64\x00\xfe"
|
||||
#define WM_IR_BLOCK2_LEVEL1 "\xfd\x05"
|
||||
#define WM_IR_BLOCK1_LEVEL2 "\x02\x00\x00\x71\x01\x00\x96\x00\xb4"
|
||||
#define WM_IR_BLOCK2_LEVEL2 "\xb3\x04"
|
||||
#define WM_IR_BLOCK1_LEVEL3 "\x02\x00\x00\x71\x01\x00\xaa\x00\x64"
|
||||
#define WM_IR_BLOCK2_LEVEL3 "\x63\x03"
|
||||
#define WM_IR_BLOCK1_LEVEL4 "\x02\x00\x00\x71\x01\x00\xc8\x00\x36"
|
||||
#define WM_IR_BLOCK2_LEVEL4 "\x35\x03"
|
||||
#define WM_IR_BLOCK1_LEVEL5 "\x07\x00\x00\x71\x01\x00\x72\x00\x20"
|
||||
#define WM_IR_BLOCK2_LEVEL5 "\x1f\x03"
|
||||
|
||||
#define WM_IR_TYPE_BASIC 0x01
|
||||
#define WM_IR_TYPE_EXTENDED 0x03
|
||||
#define WM_IR_TYPE_FULL 0x05
|
||||
|
||||
/* controller status flags for the first message byte */
|
||||
/* bit 1 is unknown */
|
||||
#define WM_CTRL_STATUS_BYTE1_ATTACHMENT 0x02
|
||||
#define WM_CTRL_STATUS_BYTE1_SPEAKER_ENABLED 0x04
|
||||
#define WM_CTRL_STATUS_BYTE1_IR_ENABLED 0x08
|
||||
#define WM_CTRL_STATUS_BYTE1_LED_1 0x10
|
||||
#define WM_CTRL_STATUS_BYTE1_LED_2 0x20
|
||||
#define WM_CTRL_STATUS_BYTE1_LED_3 0x40
|
||||
#define WM_CTRL_STATUS_BYTE1_LED_4 0x80
|
||||
|
||||
/* aspect ratio */
|
||||
#define WM_ASPECT_16_9_X 660
|
||||
#define WM_ASPECT_16_9_Y 370
|
||||
#define WM_ASPECT_4_3_X 560
|
||||
#define WM_ASPECT_4_3_Y 420
|
||||
|
||||
|
||||
/**
|
||||
* Expansion stuff
|
||||
*/
|
||||
|
||||
/* encrypted expansion id codes (located at 0x04A400FC) */
|
||||
#define EXP_ID_CODE_NUNCHUK 0xa4200000
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER 0xa4200101
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_NYKOWING 0x90908f00
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_NYKOWING2 0x9e9f9c00
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_NYKOWING3 0x908f8f00
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC 0xa5a2a300
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC2 0x98999900
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC3 0xa0a1a000
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC4 0x8d8d8e00
|
||||
#define EXP_ID_CODE_CLASSIC_CONTROLLER_GENERIC5 0x93949400
|
||||
//#define EXP_ID_CODE_GUITAR 0xa4200103
|
||||
//#define EXP_ID_CODE_WIIBOARD 0xa4200402
|
||||
#define EXP_ID_CODE_MOTION_PLUS 0xa4200405
|
||||
|
||||
#define EXP_HANDSHAKE_LEN 224
|
||||
|
||||
/********************
|
||||
*
|
||||
* End Wiimote internal codes
|
||||
*
|
||||
********************/
|
||||
|
||||
/* wiimote state flags - (some duplicated in wiiuse.h)*/
|
||||
#define WIIMOTE_STATE_DEV_FOUND 0x00001
|
||||
//#define WIIMOTE_STATE_DEV_REGISTER 0x00002
|
||||
#define WIIMOTE_STATE_HANDSHAKE 0x00004 /* actual connection exists but no handshake yet */
|
||||
#define WIIMOTE_STATE_HANDSHAKE_COMPLETE 0x00008 /* actual connection exists but no handshake yet */
|
||||
#define WIIMOTE_STATE_CONNECTED 0x00010
|
||||
#define WIIMOTE_STATE_EXP_HANDSHAKE 0x00020 /* actual connection exists but no handshake yet */
|
||||
#define WIIMOTE_STATE_EXP_FAILED 0x00040 /* actual connection exists but no handshake yet */
|
||||
#define WIIMOTE_STATE_RUMBLE 0x00080
|
||||
#define WIIMOTE_STATE_ACC 0x00100
|
||||
#define WIIMOTE_STATE_EXP 0x00200
|
||||
#define WIIMOTE_STATE_IR 0x00400
|
||||
#define WIIMOTE_STATE_SPEAKER 0x00800
|
||||
#define WIIMOTE_STATE_IR_SENS_LVL1 0x01000
|
||||
#define WIIMOTE_STATE_IR_SENS_LVL2 0x02000
|
||||
#define WIIMOTE_STATE_IR_SENS_LVL3 0x04000
|
||||
#define WIIMOTE_STATE_IR_SENS_LVL4 0x08000
|
||||
#define WIIMOTE_STATE_IR_SENS_LVL5 0x10000
|
||||
#define WIIMOTE_STATE_IR_INIT 0x20000
|
||||
#define WIIMOTE_STATE_SPEAKER_INIT 0x40000
|
||||
|
||||
#define WIIMOTE_INIT_STATES (WIIMOTE_STATE_IR_SENS_LVL3)
|
||||
|
||||
/* macro to manage states */
|
||||
#define WIIMOTE_IS_SET(wm, s) ((wm->state & (s)) == (s))
|
||||
#define WIIMOTE_ENABLE_STATE(wm, s) (wm->state |= (s))
|
||||
#define WIIMOTE_DISABLE_STATE(wm, s) (wm->state &= ~(s))
|
||||
#define WIIMOTE_TOGGLE_STATE(wm, s) ((wm->state & (s)) ? WIIMOTE_DISABLE_STATE(wm, s) : WIIMOTE_ENABLE_STATE(wm, s))
|
||||
|
||||
#define WIIMOTE_IS_FLAG_SET(wm, s) ((wm->flags & (s)) == (s))
|
||||
#define WIIMOTE_ENABLE_FLAG(wm, s) (wm->flags |= (s))
|
||||
#define WIIMOTE_DISABLE_FLAG(wm, s) (wm->flags &= ~(s))
|
||||
#define WIIMOTE_TOGGLE_FLAG(wm, s) ((wm->flags & (s)) ? WIIMOTE_DISABLE_FLAG(wm, s) : WIIMOTE_ENABLE_FLAG(wm, s))
|
||||
|
||||
#define NUNCHUK_IS_FLAG_SET(wm, s) ((*(wm->flags) & (s)) == (s))
|
||||
|
||||
/* misc macros */
|
||||
#define WIIMOTE_ID(wm) (wm->unid)
|
||||
#define WIIMOTE_IS_CONNECTED(wm) (WIIMOTE_IS_SET(wm, WIIMOTE_STATE_CONNECTED))
|
||||
|
||||
/*
|
||||
* Smooth tilt calculations are computed with the
|
||||
* exponential moving average formula:
|
||||
* St = St_last + (alpha * (tilt - St_last))
|
||||
* alpha is between 0 and 1
|
||||
*/
|
||||
#define WIIUSE_DEFAULT_SMOOTH_ALPHA 0.3f
|
||||
|
||||
#define SMOOTH_ROLL 0x01
|
||||
#define SMOOTH_PITCH 0x02
|
||||
|
||||
#include <wiiuse/wiiuse.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct op_t
|
||||
{
|
||||
ubyte cmd;
|
||||
union {
|
||||
struct {
|
||||
uint addr;
|
||||
uword size;
|
||||
} readdata;
|
||||
struct {
|
||||
uint addr;
|
||||
ubyte size;
|
||||
ubyte data[16];
|
||||
} writedata;
|
||||
ubyte __data[MAX_PAYLOAD];
|
||||
};
|
||||
|
||||
void *buffer;
|
||||
int wait;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* not part of the api */
|
||||
void wiiuse_init_cmd_queue(struct wiimote_t *wm);
|
||||
void wiiuse_send_next_command(struct wiimote_t *wm);
|
||||
int wiiuse_set_report_type(struct wiimote_t* wm,cmd_blk_cb cb);
|
||||
int wiiuse_sendcmd(struct wiimote_t *wm,ubyte report_type,ubyte *msg,int len,cmd_blk_cb cb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WIIUSE_INTERNAL_H_INCLUDED */
|
1106
wii/wiiuse/wpad.c
1106
wii/wiiuse/wpad.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user