diff --git a/Makefile.wiiu b/Makefile.wiiu new file mode 100644 index 000000000..7574f36fd --- /dev/null +++ b/Makefile.wiiu @@ -0,0 +1,72 @@ +BASEDIR := $(dir $(firstword $(MAKEFILE_LIST))) +VPATH := $(BASEDIR) + +#--------------------------------------------------------------------------------- +# Build options +#--------------------------------------------------------------------------------- +TARGET = libSDL2.a +SOURCES = \ + src/*.c \ + src/atomic/*.c \ + src/audio/*.c \ + src/audio/wiiu/*.c \ + src/cpuinfo/*.c \ + src/events/*.c \ + src/file/*.c \ + src/haptic/*.c \ + src/haptic/dummy/*.c \ + src/joystick/*.c \ + src/joystick/wiiu/*.c \ + src/joystick/dummy/*.c \ + src/loadso/dummy/*.c \ + src/power/*.c \ + src/filesystem/dummy/*.c \ + src/render/*.c \ + src/render/wiiu/*.c \ + src/render/software/*.c \ + src/stdlib/*.c \ + src/sensor/*.c \ + src/thread/*.c \ + src/thread/wiiu/*.c \ + src/timer/*.c \ + src/timer/wiiu/*.c \ + src/timer/dummy/*.c \ + src/video/*.c \ + src/video/wiiu/*.c \ + src/video/yuv2rgb/*.c \ + src/video/dummy/*.c + +OBJECTS = $(shell echo $(SOURCES) | sed -e 's,\.c,\.o,g') +INCLUDE = -I./include + +#--------------------------------------------------------------------------------- +# Compile flags +#--------------------------------------------------------------------------------- +CFLAGS += -O2 $(INCLUDE) +CXXFLAGS += -O2 $(INCLUDE) + +#--------------------------------------------------------------------------------- +# Build rules +#--------------------------------------------------------------------------------- +.PHONY: clean install + +$(TARGET): $(OBJECTS) + +install: $(TARGET) + @echo INSTALL $(TARGET) + @mkdir -p $(PORTLIBS)/lib + @mkdir -p $(PORTLIBS)/include/SDL2 + @cp $(TARGET) $(PORTLIBS)/lib/ + @cp -f ./include/*.h $(PORTLIBS)/include/SDL2/ + +clean: + @echo CLEAN ... + @rm -rf $(OBJECTS) $(OBJECTS:.o=.d) $(TARGET) + +#--------------------------------------------------------------------------------- +# Toolchain +#--------------------------------------------------------------------------------- +include $(WUT_ROOT)/share/wut.mk +LDFLAGS += -L$(DEVKITPRO)/portlibs/ppc/lib +CFLAGS += -I$(DEVKITPRO)/portlibs/ppc/include +CXXFLAGS += -I$(DEVKITPRO)/portlibs/ppc/include diff --git a/README.md b/README.md index fa7f7ba0b..d1719bb6f 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ - -# Simple DirectMedia Layer (SDL) Version 2.0 - -https://www.libsdl.org/ - -Simple DirectMedia Layer is a cross-platform development library designed -to provide low level access to audio, keyboard, mouse, joystick, and graphics -hardware via OpenGL and Direct3D. It is used by video playback software, -emulators, and popular games including Valve's award winning catalog -and many Humble Bundle games. - -More extensive documentation is available in the docs directory, starting -with README.md - -Enjoy! - -Sam Lantinga (slouken@libsdl.org) + +# Simple DirectMedia Layer (SDL) Version 2.0 + +https://www.libsdl.org/ + +Simple DirectMedia Layer is a cross-platform development library designed +to provide low level access to audio, keyboard, mouse, joystick, and graphics +hardware via OpenGL and Direct3D. It is used by video playback software, +emulators, and popular games including Valve's award winning catalog +and many Humble Bundle games. + +More extensive documentation is available in the docs directory, starting +with README.md + +Enjoy! + +Sam Lantinga (slouken@libsdl.org) diff --git a/include/SDL_config.h.cmake b/include/SDL_config.h.cmake index 35923d020..ab5b33274 100644 --- a/include/SDL_config.h.cmake +++ b/include/SDL_config.h.cmake @@ -329,6 +329,7 @@ #cmakedefine SDL_AUDIO_DRIVER_PSP @SDL_AUDIO_DRIVER_PSP@ #cmakedefine SDL_AUDIO_DRIVER_PS2 @SDL_AUDIO_DRIVER_PS2@ #cmakedefine SDL_AUDIO_DRIVER_N3DS @SDL_AUDIO_DRIVER_N3DS@ +#cmakedefine SDL_AUDIO_DRIVER_WIIU @SDL_AUDIO_DRIVER_WIIU@ /* Enable various input drivers */ #cmakedefine SDL_INPUT_LINUXEV @SDL_INPUT_LINUXEV@ @@ -355,6 +356,7 @@ #cmakedefine SDL_JOYSTICK_PSP @SDL_JOYSTICK_PSP@ #cmakedefine SDL_JOYSTICK_PS2 @SDL_JOYSTICK_PS2@ #cmakedefine SDL_JOYSTICK_N3DS @SDL_JOYSTICK_N3DS@ +#cmakedefine SDL_JOYSTICK_WIIU @SDL_JOYSTICK_WIIU@ #cmakedefine SDL_HAPTIC_DUMMY @SDL_HAPTIC_DUMMY@ #cmakedefine SDL_HAPTIC_LINUX @SDL_HAPTIC_LINUX@ #cmakedefine SDL_HAPTIC_IOKIT @SDL_HAPTIC_IOKIT@ @@ -390,6 +392,7 @@ #cmakedefine SDL_THREAD_PSP @SDL_THREAD_PSP@ #cmakedefine SDL_THREAD_PS2 @SDL_THREAD_PS2@ #cmakedefine SDL_THREAD_N3DS @SDL_THREAD_N3DS@ +#cmakedefine SDL_THREAD_WIIU @SDL_THREAD_WIIU@ /* Enable various timer systems */ #cmakedefine SDL_TIMER_HAIKU @SDL_TIMER_HAIKU@ @@ -401,6 +404,7 @@ #cmakedefine SDL_TIMER_PSP @SDL_TIMER_PSP@ #cmakedefine SDL_TIMER_PS2 @SDL_TIMER_PS2@ #cmakedefine SDL_TIMER_N3DS @SDL_TIMER_N3DS@ +#cmakedefine SDL_TIMER_WIIU @SDL_TIMER_WIIU@ /* Enable various video drivers */ #cmakedefine SDL_VIDEO_DRIVER_ANDROID @SDL_VIDEO_DRIVER_ANDROID@ @@ -423,6 +427,7 @@ #cmakedefine SDL_VIDEO_DRIVER_RISCOS @SDL_VIDEO_DRIVER_RISCOS@ #cmakedefine SDL_VIDEO_DRIVER_PSP @SDL_VIDEO_DRIVER_PSP@ #cmakedefine SDL_VIDEO_DRIVER_PS2 @SDL_VIDEO_DRIVER_PS2@ +#cmakedefine SDL_VIDEO_DRIVER_WIIU @SDL_VIDEO_DRIVER_WIIU@ #cmakedefine SDL_VIDEO_DRIVER_KMSDRM @SDL_VIDEO_DRIVER_KMSDRM@ #cmakedefine SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC @SDL_VIDEO_DRIVER_KMSDRM_DYNAMIC@ @@ -467,6 +472,7 @@ #cmakedefine SDL_VIDEO_RENDER_VITA_GXM @SDL_VIDEO_RENDER_VITA_GXM@ #cmakedefine SDL_VIDEO_RENDER_PS2 @SDL_VIDEO_RENDER_PS2@ #cmakedefine SDL_VIDEO_RENDER_PSP @SDL_VIDEO_RENDER_PSP@ +#cmakedefine SDL_VIDEO_RENDER_WIIU @SDL_VIDEO_RENDER_WIIU@ /* Enable OpenGL support */ #cmakedefine SDL_VIDEO_OPENGL @SDL_VIDEO_OPENGL@ diff --git a/include/SDL_config_wiiu.h b/include/SDL_config_wiiu.h new file mode 100644 index 000000000..75be00578 --- /dev/null +++ b/include/SDL_config_wiiu.h @@ -0,0 +1,167 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_config_wiiu_h_ +#define SDL_config_wiiu_h_ +#define SDL_config_h_ + +#include "SDL_platform.h" + + + +#ifdef __GNUC__ +#define HAVE_GCC_SYNC_LOCK_TEST_AND_SET 1 +#endif + +#define HAVE_GCC_ATOMICS 1 + +#define STDC_HEADERS 1 +#define HAVE_ALLOCA_H 1 +#define HAVE_CTYPE_H 1 +#define HAVE_INTTYPES_H 1 +#define HAVE_LIMITS_H 1 +#define HAVE_MATH_H 1 +#define HAVE_SIGNAL_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_STDIO_H 1 +#define HAVE_STRING_H 1 +#define HAVE_SYS_TYPES_H 1 + +/* C library functions */ +#define HAVE_MALLOC 1 +#define HAVE_CALLOC 1 +#define HAVE_REALLOC 1 +#define HAVE_FREE 1 +#define HAVE_ALLOCA 1 +#define HAVE_GETENV 1 +#define HAVE_SETENV 1 +#define HAVE_PUTENV 1 +#define HAVE_SETENV 1 +#define HAVE_UNSETENV 1 +#define HAVE_QSORT 1 +#define HAVE_ABS 1 +#define HAVE_BCOPY 1 +#define HAVE_MEMSET 1 +#define HAVE_MEMCPY 1 +#define HAVE_MEMMOVE 1 +#define HAVE_MEMCMP 1 +#define HAVE_STRLEN 1 +#define HAVE_STRLCPY 1 +#define HAVE_STRLCAT 1 +#define HAVE_STRCHR 1 +#define HAVE_STRRCHR 1 +#define HAVE_STRSTR 1 +#define HAVE_STRTOL 1 +#define HAVE_STRTOUL 1 +#define HAVE_STRTOLL 1 +#define HAVE_STRTOULL 1 +#define HAVE_STRTOD 1 +#define HAVE_ATOI 1 +#define HAVE_ATOF 1 +#define HAVE_STRCMP 1 +#define HAVE_STRNCMP 1 +#define HAVE_STRCASECMP 1 +#define HAVE_STRNCASECMP 1 +#define HAVE_VSSCANF 1 +#define HAVE_VSNPRINTF 1 +#define HAVE_M_PI 1 +#define HAVE_ACOS 1 +#define HAVE_ACOSF 1 +#define HAVE_ASIN 1 +#define HAVE_ASINF 1 +#define HAVE_ATAN 1 +#define HAVE_ATANF 1 +#define HAVE_ATAN2 1 +#define HAVE_ATAN2F 1 +#define HAVE_CEIL 1 +#define HAVE_CEILF 1 +#define HAVE_COPYSIGN 1 +#define HAVE_COPYSIGNF 1 +#define HAVE_COS 1 +#define HAVE_COSF 1 +#define HAVE_EXP 1 +#define HAVE_FABS 1 +#define HAVE_FABSF 1 +#define HAVE_FLOOR 1 +#define HAVE_FLOORF 1 +#define HAVE_FMOD 1 +#define HAVE_FMODF 1 +#define HAVE_LOG 1 +#define HAVE_LOGF 1 +#define HAVE_LOG10 1 +#define HAVE_LOG10F 1 +#define HAVE_POW 1 +#define HAVE_POWF 1 +#define HAVE_SCALBN 1 +#define HAVE_SCALBNF 1 +#define HAVE_SIN 1 +#define HAVE_SINF 1 +#define HAVE_SQRT 1 +#define HAVE_SQRTF 1 +#define HAVE_TAN 1 +#define HAVE_TANF 1 +#define HAVE_SETJMP 1 +#define HAVE_NANOSLEEP 1 +/* #define HAVE_SYSCONF 1 */ +/* #define HAVE_SIGACTION 1 */ + + +/* Wii U isn't that sophisticated */ +#define LACKS_SYS_MMAN_H 1 + +/* Wii U thread support (src/thread/wiiu/\*.c) */ +#define SDL_THREAD_WIIU 1 +#define SDL_THREADS_DISABLED 0 + +/* Wii U timer support (src/timer/wiiu/\*.c) */ +#define SDL_TIMER_WIIU 1 + +/* Wii U joystick driver (src/joystick/wiiu/\*.c) */ +#define SDL_JOYSTICK_WIIU 1 + +/* Enable the wiiu audio driver (src/audio/wiiu/\*.c) */ +#define SDL_AUDIO_DRIVER_WIIU 1 + +/* Wii U video dirver */ +#define SDL_VIDEO_DRIVER_WIIU 1 + +/* Wii U render driver (src/render/wiiu/\*.c) */ +#define SDL_VIDEO_RENDER_WIIU 1 + +/* There's no battery for the console unit */ +#define SDL_POWER_DISABLED 1 + +/* !!! FIXME: what does Wii U do for filesystem stuff? */ +#define SDL_FILESYSTEM_DUMMY 1 + +/* Wii U does have an haptic device, but it's not ported to sdl yet (src/haptic/dummy/\*.c) */ +#define SDL_HAPTIC_DISABLED 1 + +/* Wii U can't load shared object (src/loadso/dummy/\*.c) */ +#define SDL_LOADSO_DISABLED 1 + +/* Hack: for some reason some arch defines are missing in the + toolchain, so SDL_endian.h will think we're little endian + without that */ +#define SDL_BYTEORDER SDL_BIG_ENDIAN + + +#endif /* SDL_config_wiiu_h_ */ diff --git a/include/SDL_endian.h b/include/SDL_endian.h index 71bc06729..94a790378 100644 --- a/include/SDL_endian.h +++ b/include/SDL_endian.h @@ -79,7 +79,7 @@ _m_prefetch(void *__P) defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \ (defined(__MIPS__) && defined(__MIPSEB__)) || \ defined(__ppc__) || defined(__POWERPC__) || defined(__powerpc__) || defined(__PPC__) || \ - defined(__sparc__) + defined(__sparc__) || defined(_BIG_ENDIAN) || (__BIG_ENDIAN__ == 1) #define SDL_BYTEORDER SDL_BIG_ENDIAN #else #define SDL_BYTEORDER SDL_LIL_ENDIAN diff --git a/include/SDL_platform.h b/include/SDL_platform.h index d2a7e052d..262e1c37f 100644 --- a/include/SDL_platform.h +++ b/include/SDL_platform.h @@ -200,6 +200,10 @@ #if defined(PS2) #define __PS2__ 1 #endif +#if defined(__WIIU__) +#undef __WIIU__ +#define __WIIU__ 1 +#endif /* The NACL compiler defines __native_client__ and __pnacl__ * Ref: http://www.chromium.org/nativeclient/pnacl/stability-of-the-pnacl-bitcode-abi diff --git a/include/SDL_test_common.h b/include/SDL_test_common.h index 6de63cad6..76c6c6c8d 100644 --- a/include/SDL_test_common.h +++ b/include/SDL_test_common.h @@ -40,6 +40,9 @@ #elif defined(__VITA__) #define DEFAULT_WINDOW_WIDTH 960 #define DEFAULT_WINDOW_HEIGHT 544 +#elif defined(__WIIU__) +#define DEFAULT_WINDOW_WIDTH 1280 +#define DEFAULT_WINDOW_HEIGHT 720 #else #define DEFAULT_WINDOW_WIDTH 640 #define DEFAULT_WINDOW_HEIGHT 480 diff --git a/src/SDL.c b/src/SDL.c index 56049adf0..66ab88ab1 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -610,6 +610,8 @@ const char *SDL_GetPlatform(void) return "Nokia N-Gage"; #elif __3DS__ return "Nintendo 3DS"; +#elif __WIIU__ + return "Wii U"; #else return "Unknown (see SDL_platform.h)"; #endif diff --git a/src/SDL_log.c b/src/SDL_log.c index ab6e7c2cb..41461c96e 100644 --- a/src/SDL_log.c +++ b/src/SDL_log.c @@ -39,6 +39,10 @@ #include #endif +#if defined(__WIIU__) +#include +#endif + #include "stdlib/SDL_vacopy.h" /* The size of the stack buffer to use for rendering log messages. */ @@ -449,6 +453,10 @@ static void SDLCALL SDL_LogOutput(void *userdata, int category, SDL_LogPriority SDL_NSLog(SDL_priority_prefixes[priority], message); return; } +#elif defined(__WIIU__) + { + OSReport("SDL: %s: %s\n", SDL_priority_prefixes[priority], message); + } #elif defined(__PSP__) || defined(__PS2__) { FILE *pFile; diff --git a/src/atomic/SDL_spinlock.c b/src/atomic/SDL_spinlock.c index 9fd3e6167..420d49623 100644 --- a/src/atomic/SDL_spinlock.c +++ b/src/atomic/SDL_spinlock.c @@ -36,6 +36,10 @@ #include #endif +#if defined(__WIIU__) +#include +#endif + #if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) #include #endif @@ -163,6 +167,10 @@ SDL_bool SDL_AtomicTryLock(SDL_SpinLock *lock) EIntr(); } return res; +#elif defined(__WIIU__) + uint64_t val = 0; + return (SDL_bool) atomic_compare_exchange_strong((volatile _Atomic uint64_t*)lock, &val, 1); + #else #error Please implement for your platform. return SDL_FALSE; diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 60242e60a..936404d95 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -123,6 +123,9 @@ static const AudioBootStrap *const bootstrap[] = { #if SDL_AUDIO_DRIVER_OS2 &OS2AUDIO_bootstrap, #endif +#if SDL_AUDIO_DRIVER_WIIU + &WIIUAUDIO_bootstrap, +#endif #if SDL_AUDIO_DRIVER_DISK &DISKAUDIO_bootstrap, #endif diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index c755d4341..052e2cd65 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -209,6 +209,7 @@ extern AudioBootStrap VITAAUD_bootstrap; extern AudioBootStrap N3DSAUDIO_bootstrap; extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap; extern AudioBootStrap OS2AUDIO_bootstrap; +extern AudioBootStrap WIIUAUDIO_bootstrap; #endif /* SDL_sysaudio_h_ */ diff --git a/src/audio/wiiu/SDL_wiiuaudio.c b/src/audio/wiiu/SDL_wiiuaudio.c new file mode 100644 index 000000000..12a08857b --- /dev/null +++ b/src/audio/wiiu/SDL_wiiuaudio.c @@ -0,0 +1,390 @@ +/* + Simple DirectMedia Layer + Copyright (C) 2018-2018 Ash Logan + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_AUDIO_DRIVER_WIIU + +#include + +#include "SDL_audio.h" +#include "SDL_error.h" +#include "SDL_timer.h" +#include "../SDL_audio_c.h" +#include "../SDL_audiodev_c.h" +#include "../SDL_sysaudio.h" +#include "SDL_wiiuaudio.h" +#include "SDL_wiiuaudio_mix.h" + +#include +#include +#include +#include +#include +#include +#include + +#define WIIUAUDIO_DRIVER_NAME "wiiu" + +#define AX_MAIN_AFFINITY OS_THREAD_ATTRIB_AFFINITY_CPU1 + +static void _WIIUAUDIO_framecallback(); +static SDL_AudioDevice* cb_this; +#define cb_hidden cb_this->hidden + +/* Some helpers for AX-related math */ +/* Absolute address to an AXVoiceOffsets offset */ +#define calc_ax_offset(offs, addr) (((void*)addr - offs.data) \ + / sizeof_sample(offs)) + +#define sizeof_sample(offs) (offs.dataType == AX_VOICE_FORMAT_LPCM8 ? 1 : 2) + +/* +1, but never goes above NUM_BUFFERS */ +#define next_id(id) (id + 1) % NUM_BUFFERS + +static int WIIUAUDIO_OpenDevice(_THIS, void* handle, const char* devname, int iscapture) { + AXVoiceOffsets offs; + AXVoiceVeData vol = { + .volume = 0x8000, + }; + uint32_t old_affinity; + float srcratio; + + this->hidden = (struct SDL_PrivateAudioData*)SDL_malloc(sizeof(*this->hidden)); + if (this->hidden == NULL) return SDL_OutOfMemory(); + SDL_zerop(this->hidden); + +/* We *must not* change cores when setting stuff up */ + old_affinity = OSGetThreadAffinity(OSGetCurrentThread()); + OSSetThreadAffinity(OSGetCurrentThread(), AX_MAIN_AFFINITY); + +/* Take a quick aside to init the wiiu audio */ + if (!AXIsInit()) { + /* Init the AX audio engine */ + AXInitParams initparams = { + .renderer = AX_INIT_RENDERER_48KHZ, + .pipeline = AX_INIT_PIPELINE_SINGLE, + }; + AXInitWithParams(&initparams); + } else printf("DEBUG: AX already up?\n"); + + if (this->spec.channels < 1) this->spec.channels = 1; + if (this->spec.channels > WIIU_MAX_VALID_CHANNELS) + this->spec.channels = WIIU_MAX_VALID_CHANNELS; + +/* Force wiiu-compatible audio formats. + TODO verify - unsigned or signed? */ + switch (SDL_AUDIO_BITSIZE(this->spec.format)) { + case 8: + /* TODO 8-bit audio sounds broken */ + /*this->spec.format = AUDIO_S8; + break;*/ + case 16: + default: + this->spec.format = AUDIO_S16MSB; + break; + } + + //TODO maybe round this->spec.samples up even when >? + //maybe even force at least 2* so we get more frame callbacks to think + if (this->spec.samples < AXGetInputSamplesPerFrame()) { + this->spec.samples = AXGetInputSamplesPerFrame(); + } + +/* We changed channels and samples, so recalculate the spec */ + SDL_CalculateAudioSpec(&this->spec); + +/* Allocate buffers for double-buffering and samples */ + for (int i = 0; i < NUM_BUFFERS; i++) { + this->hidden->mixbufs[i] = SDL_malloc(this->spec.size); + if (this->hidden->mixbufs[i] == NULL) { + AXQuit(); + printf("DEBUG: Couldn't allocate buffer"); + return SDL_SetError("Couldn't allocate buffer"); + } + + memset(this->hidden->mixbufs[i], 0, this->spec.size); + DCStoreRange(this->hidden->mixbufs[i], this->spec.size); + } + +/* Allocate a scratch buffer for deinterleaving operations */ + this->hidden->deintvbuf = SDL_malloc(this->spec.size); + if (this->hidden->deintvbuf == NULL) { + AXQuit(); + printf("DEBUG: Couldn't allocate deinterleave buffer"); + return SDL_SetError("Couldn't allocate deinterleave buffer"); + } + + + for (int i = 0; i < this->spec.channels; i++) { + /* Get a voice, top priority */ + this->hidden->voice[i] = AXAcquireVoice(31, NULL, NULL); + if (!this->hidden->voice[i]) { + AXQuit(); + printf("DEBUG: couldn't get voice\n"); + return SDL_OutOfMemory(); + } + + /* Start messing with it */ + AXVoiceBegin(this->hidden->voice[i]); + AXSetVoiceType(this->hidden->voice[i], 0); + + /* Set the voice's volume. */ + AXSetVoiceVe(this->hidden->voice[i], &vol); + switch (this->spec.channels) { + case 1: /* mono */ { + AXSetVoiceDeviceMix(this->hidden->voice[i], + AX_DEVICE_TYPE_DRC, 0, mono_mix[i]); + AXSetVoiceDeviceMix(this->hidden->voice[i], + AX_DEVICE_TYPE_TV, 0, mono_mix[i]); + } break; + case 2: /* stereo */ { + AXSetVoiceDeviceMix(this->hidden->voice[i], + AX_DEVICE_TYPE_DRC, 0, stereo_mix[i]); + AXSetVoiceDeviceMix(this->hidden->voice[i], + AX_DEVICE_TYPE_TV, 0, stereo_mix[i]); + } break; + } + + /* Set the samplerate conversion ratio + / */ + srcratio = (float)this->spec.freq / (float)AXGetInputSamplesPerSec(); + AXSetVoiceSrcRatio(this->hidden->voice[i], srcratio); + AXSetVoiceSrcType(this->hidden->voice[i], AX_VOICE_SRC_TYPE_LINEAR); + + /* Set up the offsets for the first mixbuf */ + switch (SDL_AUDIO_BITSIZE(this->spec.format)) { + case 8: + offs.dataType = AX_VOICE_FORMAT_LPCM8; + offs.endOffset = this->spec.samples; + break; + case 16: + default: + offs.dataType = AX_VOICE_FORMAT_LPCM16; + offs.endOffset = this->spec.samples; + break; + } + offs.loopingEnabled = AX_VOICE_LOOP_ENABLED; + offs.loopOffset = 0; + offs.currentOffset = 0; + + if (offs.dataType == AX_VOICE_FORMAT_LPCM8) { + offs.data = this->hidden->mixbufs[0] + + this->spec.samples * i * sizeof(Uint8); + } else if (offs.dataType == AX_VOICE_FORMAT_LPCM16) { + offs.data = this->hidden->mixbufs[0] + + this->spec.samples * i * sizeof(Uint16); + } + AXSetVoiceOffsets(this->hidden->voice[i], &offs); + + /* Set the last good loopcount */ + this->hidden->last_loopcount = AXGetVoiceLoopCount(this->hidden->voice[i]); + + /* Offsets are set for playing the first mixbuf, so we should render the second */ + this->hidden->playingid = 0; + this->hidden->renderingid = 1; + + /* Start playing. */ + AXSetVoiceState(this->hidden->voice[i], AX_VOICE_STATE_PLAYING); + + /* Okay, we're good */ + AXVoiceEnd(this->hidden->voice[i]); + } + + cb_this = this; //wish there was a better way + AXRegisterAppFrameCallback(_WIIUAUDIO_framecallback); + +/* Put the thread affinity back to normal - we won't call any more AX funcs */ + OSSetThreadAffinity(OSGetCurrentThread(), old_affinity); + return 0; +} + +/* Called every 3ms before a frame of audio is rendered. Keep it fast! */ +static void _WIIUAUDIO_framecallback() { + int playing_buffer = -1; + AXVoiceOffsets offs[6]; + void* endaddr; + + for (int i = 0; i < cb_this->spec.channels; i++) { + AXGetVoiceOffsets(cb_hidden->voice[i], &offs[i]); + } + +/* Figure out which buffer is being played by the hardware */ + for (int i = 0; i < NUM_BUFFERS; i++) { + void* buf = cb_hidden->mixbufs[i]; + uint32_t startOffset = calc_ax_offset(offs[0], buf); + uint32_t endOffset = startOffset + cb_this->spec.samples; + + /* NOTE endOffset definitely needs to be <= (AX plays the sample at + endOffset), dunno about startOffset */ + if (offs[0].currentOffset >= startOffset && + offs[0].currentOffset <= endOffset) { + playing_buffer = i; + break; + } + } + + if (playing_buffer < 0 || playing_buffer >= NUM_BUFFERS) { + /* UM */ + /* Uncomment for craploads of debug info */ + /*printf("bad buffer %d\n" "|> %08X, %08X-%08X\n" \ + "0: xxxxxxxx, %08X-%08X (%08X@%08X)\n" \ + "1: xxxxxxxx, %08X-%08X (%08X@%08X)\n", \ + playing_buffer, offs.currentOffset, offs.loopOffset, offs.endOffset, + calc_ax_offset(offs, (void*)cb_hidden->mixbufs[0]), + calc_ax_offset(offs, (void*)cb_hidden->mixbufs[0] + cb_this->spec.size), + cb_this->spec.size, (void*)cb_hidden->mixbufs[0], + calc_ax_offset(offs, (void*)cb_hidden->mixbufs[1]), + calc_ax_offset(offs, (void*)cb_hidden->mixbufs[1] + cb_this->spec.size), + cb_this->spec.size, (void*)cb_hidden->mixbufs[1]);*/ + printf("DEBUG: Playing an invalid buffer? This is not a good sign.\n"); + playing_buffer = 0; + } + +/* Make sure playingid is in sync with the hardware */ + cb_hidden->playingid = playing_buffer; + +/* Make sure the end offset is correct for the playing buffer */ + for (int i = 0; i < cb_this->spec.channels; i++) { + /* Calculate end address, aka start of the next (i+1) channel's buffer */ + endaddr = cb_hidden->mixbufs[cb_hidden->playingid] + + (cb_this->spec.samples * sizeof_sample(offs[i]) * (i + 1)); + + /* Trial end error to try and limit popping */ + endaddr -= 2; + + AXSetVoiceEndOffset( + cb_hidden->voice[i], + calc_ax_offset(offs[i], endaddr) + ); + + /* The next buffer is good to go, set the loop offset */ + if (cb_hidden->renderingid != next_id(cb_hidden->playingid)) { + /* Calculate start address for this channel's buffer */ + void* loopaddr = cb_hidden->mixbufs[next_id(cb_hidden->playingid)] + + (cb_this->spec.samples * sizeof_sample(offs[i]) * i); + + AXSetVoiceLoopOffset(cb_hidden->voice[i], calc_ax_offset(offs[i], loopaddr)); + /* Otherwise, make sure the loop offset is correct for the playing buffer */ + } else { + void* loopaddr = cb_hidden->mixbufs[cb_hidden->playingid] + + (cb_this->spec.samples * sizeof_sample(offs[i]) * i); + + AXSetVoiceLoopOffset(cb_hidden->voice[i], calc_ax_offset(offs[i], loopaddr)); + } + } +} + +static void WIIUAUDIO_PlayDevice(_THIS) { +/* Deinterleave stereo audio */ + switch (SDL_AUDIO_BITSIZE(this->spec.format)) { + case 8: { + Uint8* samples = (Uint8*)this->hidden->mixbufs[this->hidden->renderingid]; + Uint8* deintv = (Uint8*)this->hidden->deintvbuf; + + /* Store the samples in a separate deinterleaved buffer */ + for (int ch = 0; ch < this->spec.channels; ch++) { + for (int i = 0; i < this->spec.samples; i++) { + deintv[this->spec.samples * ch + i] = samples[i * this->spec.channels + ch]; + } + } + } break; + case 16: { + Uint16* samples = (Uint16*)this->hidden->mixbufs[this->hidden->renderingid]; + Uint16* deintv = (Uint16*)this->hidden->deintvbuf; + + /* Store the samples in a separate deinterleaved buffer */ + for (int ch = 0; ch < this->spec.channels; ch++) { + for (int i = 0; i < this->spec.samples; i++) { + deintv[this->spec.samples * ch + i] = samples[i * this->spec.channels + ch]; + } + } + } break; + default: {} break; + } + +/* Copy the deinterleaved buffer to the mixing buffer */ + memcpy( + this->hidden->mixbufs[this->hidden->renderingid], + this->hidden->deintvbuf, + this->spec.size + ); +/* Comment this out for broken-record mode ;3 */ + DCStoreRange(this->hidden->mixbufs[this->hidden->renderingid], this->spec.size); +/* Signal we're no longer rendering this buffer, AX callback will notice later */ + this->hidden->renderingid = next_id(this->hidden->renderingid); +} + +static void WIIUAUDIO_WaitDevice(_THIS) { +/* TODO use real thread sync stuff */ + while (SDL_AtomicGet(&this->enabled) && this->hidden->renderingid == this->hidden->playingid) { + OSSleepTicks(OSMillisecondsToTicks(3)); + } +} + +static Uint8* WIIUAUDIO_GetDeviceBuf(_THIS) { +/* SDL will write audio samples into this buffer */ + return this->hidden->mixbufs[this->hidden->renderingid]; +} + +static void WIIUAUDIO_CloseDevice(_THIS) { + if (AXIsInit()) { + AXDeregisterAppFrameCallback(_WIIUAUDIO_framecallback); + for (int i = 0; i < SIZEOF_ARR(this->hidden->voice); i++) { + if (this->hidden->voice[i]) { + AXFreeVoice(this->hidden->voice[i]); + this->hidden->voice[i] = NULL; + } + } + AXQuit(); + } + for (int i = 0; i < NUM_BUFFERS; i++) { + if (this->hidden->mixbufs[i]) SDL_free(this->hidden->mixbufs[i]); + } + if (this->hidden->deintvbuf) SDL_free(this->hidden->deintvbuf); + SDL_free(this->hidden); +} + +static void WIIUAUDIO_ThreadInit(_THIS) { +/* Bump our thread's priority a bit */ + OSThread* currentThread = OSGetCurrentThread(); + int32_t priority = OSGetThreadPriority(currentThread); + priority -= 1; + OSSetThreadPriority(currentThread, priority); +} + +static int WIIUAUDIO_Init(SDL_AudioDriverImpl* impl) { + impl->OpenDevice = WIIUAUDIO_OpenDevice; + impl->PlayDevice = WIIUAUDIO_PlayDevice; + impl->WaitDevice = WIIUAUDIO_WaitDevice; + impl->GetDeviceBuf = WIIUAUDIO_GetDeviceBuf; + impl->CloseDevice = WIIUAUDIO_CloseDevice; + impl->ThreadInit = WIIUAUDIO_ThreadInit; + + impl->OnlyHasDefaultOutputDevice = 1; + + return 1; +} + +AudioBootStrap WIIUAUDIO_bootstrap = { + WIIUAUDIO_DRIVER_NAME, "Wii U AX Audio Driver", WIIUAUDIO_Init, 0, +}; + +#endif //SDL_AUDIO_DRIVER_WIIU diff --git a/src/audio/wiiu/SDL_wiiuaudio.h b/src/audio/wiiu/SDL_wiiuaudio.h new file mode 100644 index 000000000..41cb4a48b --- /dev/null +++ b/src/audio/wiiu/SDL_wiiuaudio.h @@ -0,0 +1,51 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_wiiuaudio_h_ +#define SDL_wiiuaudio_h_ + +#include "../SDL_sysaudio.h" + +#include + +/* Hidden "this" pointer for the audio functions */ +#define _THIS SDL_AudioDevice *this + +#define NUM_BUFFERS 2 + +#define SIZEOF_ARR(arr) (sizeof(arr) / sizeof(arr[0])) + +struct SDL_PrivateAudioData { + /* 6 possible voices for 6 channels */ + AXVoice* voice[6]; + /* The raw allocated mixing buffer. */ + Uint8 *rawbuf; + /* Individual mixing buffers. */ + Uint8 *mixbufs[NUM_BUFFERS]; + /* Deinterleaving buffer. */ + Uint8 *deintvbuf; + + int renderingid; + int playingid; + uint32_t last_loopcount; +}; + +#endif /* SDL_wiiuaudio_h_ */ diff --git a/src/audio/wiiu/SDL_wiiuaudio_mix.h b/src/audio/wiiu/SDL_wiiuaudio_mix.h new file mode 100644 index 000000000..57b661c89 --- /dev/null +++ b/src/audio/wiiu/SDL_wiiuaudio_mix.h @@ -0,0 +1,65 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef SDL_wiiuaudio_mix_h_ +#define SDL_wiiuaudio_mix_h_ + +/* Some defines to help make the code below more readable */ +#define AX_VOICE(x) x +#define AX_CHANNEL_LEFT 0 +#define AX_CHANNEL_RIGHT 1 +#define AX_BUS_MASTER 0 + +/* TODO: AXGetDeviceChannelCount. For now we'll use Decaf's values. + * According to Decaf, the TV has 6 channels and the gamepad has 4. We set up + * both arrays with 6, the Gamepad callbacks just won't use the whole buffer. */ +#define AX_NUM_CHANNELS 6 + +static AXVoiceDeviceMixData stereo_mix[2 /* voices */][AX_NUM_CHANNELS] = { + [AX_VOICE(0)] = { + [AX_CHANNEL_LEFT] = { + .bus = { + [AX_BUS_MASTER] = { .volume = 0x8000 }, + } + }, + }, + [AX_VOICE(1)] = { + [AX_CHANNEL_RIGHT] = { + .bus = { + [AX_BUS_MASTER] = { .volume = 0x8000 }, + } + }, + }, +}; +static AXVoiceDeviceMixData mono_mix[1 /* voice */][AX_NUM_CHANNELS] = { + [AX_VOICE(0)] = { + [AX_CHANNEL_LEFT] = { .bus = { + [AX_BUS_MASTER] = { .volume = 0x8000 }, + }}, + [AX_CHANNEL_RIGHT] = { .bus = { + [AX_BUS_MASTER] = { .volume = 0x8000 }, + }}, + }, +}; + +#define WIIU_MAX_VALID_CHANNELS 2 + +#endif //SDL_wiiuaudio_mix_h_ diff --git a/src/dynapi/SDL_dynapi.h b/src/dynapi/SDL_dynapi.h index 99ca08008..d684b5fed 100644 --- a/src/dynapi/SDL_dynapi.h +++ b/src/dynapi/SDL_dynapi.h @@ -59,6 +59,8 @@ #define SDL_DYNAMIC_API 0 #elif defined(__riscos__) && __riscos__ /* probably not useful on RISC OS, since dlopen() can't be used when using static linking. */ #define SDL_DYNAMIC_API 0 +#elif defined(__WIIU__) && __WIIU__ +#define SDL_DYNAMIC_API 0 #elif defined(__clang_analyzer__) || defined(SDL_THREAD_SAFETY_ANALYSIS) #define SDL_DYNAMIC_API 0 /* Turn off for static analysis, so reports are more clear. */ #elif defined(__VITA__) diff --git a/src/joystick/SDL_gamecontrollerdb.h b/src/joystick/SDL_gamecontrollerdb.h index f926c1612..bb38d0455 100644 --- a/src/joystick/SDL_gamecontrollerdb.h +++ b/src/joystick/SDL_gamecontrollerdb.h @@ -991,6 +991,9 @@ static const char *s_ControllerMappings[] = { #endif #if SDL_JOYSTICK_N3DS "000000004e696e74656e646f20334400,Nintendo 3DS,crc:3210,a:b0,b:b1,back:b2,dpdown:b7,dpleft:b5,dpright:b4,dpup:b6,leftshoulder:b9,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b15,rightx:a2,righty:a3,start:b3,x:b10,y:b11,", +#endif +#if defined(SDL_JOYSTICK_WIIU) + "576969552047616d6570616400000000,Wii U Gamepad,a:b1,b:b0,back:b11,dpdown:b15,dpleft:b12,dpright:b14,dpup:b13,leftshoulder:b6,leftstick:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a2,righty:a3,start:b10,x:b3,y:b2,", #endif "hidapi,*,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", NULL diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 834e83d99..2bc162aee 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -84,7 +84,10 @@ static SDL_JoystickDriver *SDL_joystick_drivers[] = { #ifdef SDL_JOYSTICK_HAIKU &SDL_HAIKU_JoystickDriver, #endif -#ifdef SDL_JOYSTICK_USBHID /* !!! FIXME: "USBHID" is a generic name, and doubly-confusing with HIDAPI next to it. This is the *BSD interface, rename this. */ +#ifdef SDL_JOYSTICK_WIIU + &SDL_WIIU_JoystickDriver, +#endif +#ifdef SDL_JOYSTICK_USBHID /* !!! FIXME: "USBHID" is a generic name, and doubly-confusing with HIDAPI next to it. This is the *BSD interface, rename this. */ &SDL_BSD_JoystickDriver, #endif #ifdef SDL_JOYSTICK_OS2 diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h index a93fa662c..4f0c0df77 100644 --- a/src/joystick/SDL_sysjoystick.h +++ b/src/joystick/SDL_sysjoystick.h @@ -249,6 +249,7 @@ extern SDL_JoystickDriver SDL_PS2_JoystickDriver; extern SDL_JoystickDriver SDL_PSP_JoystickDriver; extern SDL_JoystickDriver SDL_VITA_JoystickDriver; extern SDL_JoystickDriver SDL_N3DS_JoystickDriver; +extern SDL_JoystickDriver SDL_WIIU_JoystickDriver; /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/src/joystick/wiiu/SDL_wiiujoystick.c b/src/joystick/wiiu/SDL_wiiujoystick.c new file mode 100644 index 000000000..d345b24e7 --- /dev/null +++ b/src/joystick/wiiu/SDL_wiiujoystick.c @@ -0,0 +1,531 @@ +/* + Simple DirectMedia Layer + Copyright (C) 2018 Roberto Van Eeden + Copyright (C) 2019 Ash Logan + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "../../SDL_internal.h" + +#if SDL_JOYSTICK_WIIU + +#include +#include +#include +#include + +#include "SDL_joystick.h" +#include "../SDL_sysjoystick.h" +#include "../SDL_joystick_c.h" +#include "../../events/SDL_touch_c.h" + +#include "SDL_log.h" +#include "SDL_assert.h" +#include "SDL_events.h" + +#include "SDL_wiiujoystick.h" + +//index with device_index, get WIIU_DEVICE* +static int deviceMap[MAX_CONTROLLERS]; +//index with device_index, get SDL_JoystickID +static SDL_JoystickID instanceMap[MAX_CONTROLLERS]; +static WPADExtensionType lastKnownExts[WIIU_NUM_WPADS]; + +static int WIIU_GetDeviceForIndex(int device_index) { + return deviceMap[device_index]; +} +static int WIIU_GetIndexForDevice(int wiiu_device) { + for (int i = 0; i < MAX_CONTROLLERS; i++) { + if (deviceMap[i] == wiiu_device) return i; + } + return -1; +} + +static int WIIU_GetNextDeviceIndex() { + return WIIU_GetIndexForDevice(WIIU_DEVICE_INVALID); +} + +static SDL_JoystickID WIIU_GetInstForIndex(int device_index) { + if (device_index == -1) return -1; + return instanceMap[device_index]; +} +static SDL_JoystickID WIIU_GetInstForDevice(int wiiu_device) { + int device_index = WIIU_GetIndexForDevice(wiiu_device); + return WIIU_GetInstForIndex(device_index); +} +static int WIIU_GetDeviceForInst(SDL_JoystickID instance) { + for (int i = 0; i < MAX_CONTROLLERS; i++) { + if (instanceMap[i] == instance) return deviceMap[i]; + } + return WIIU_DEVICE_INVALID; +} + +static void WIIU_RemoveDevice(int wiiu_device) { + int device_index = WIIU_GetIndexForDevice(wiiu_device); + if (device_index == -1) return; + /* Move all the other controllers back, so all device_indexes are valid */ + for (int i = device_index; i < MAX_CONTROLLERS; i++) { + if (i + 1 < MAX_CONTROLLERS) { + deviceMap[i] = deviceMap[i + 1]; + instanceMap[i] = instanceMap[i + 1]; + } else { + deviceMap[i] = -1; + instanceMap[i] = -1; + } + } +} + +/* Function to scan the system for joysticks. + * Joystick 0 should be the system default joystick. + * This function should return 0, or -1 on an unrecoverable error. + */ +static int WIIU_JoystickInit(void) +{ + VPADInit(); + KPADInit(); + WPADEnableURCC(1); + + for (int i = 0; i < MAX_CONTROLLERS; i++) { + deviceMap[i] = WIIU_DEVICE_INVALID; + instanceMap[i] = -1; + } + WIIU_JoystickDetect(); + return 0; +} + +/* Function to return the number of joystick devices plugged in right now */ +static int WIIU_JoystickGetCount(void) +{ + return WIIU_GetNextDeviceIndex(); +} + +/* Function to cause any queued joystick insertions to be processed */ +static void WIIU_JoystickDetect(void) +{ +/* Make sure there are no dangling instances or device indexes + These checks *should* be unneccesary, remove once battle-tested */ + for (int i = 0; i < MAX_CONTROLLERS; i++) { + if (deviceMap[i] == WIIU_DEVICE_INVALID && instanceMap[i] != -1) { + + SDL_LogWarn(SDL_LOG_CATEGORY_INPUT, + "WiiU device_index %d dangling instance %d!\n", + i, instanceMap[i] + ); + /* Make sure that joystick actually got removed */ + SDL_PrivateJoystickRemoved(instanceMap[i]); + instanceMap[i] = -1; + } + if (deviceMap[i] != WIIU_DEVICE_INVALID && instanceMap[i] == -1) { + SDL_LogWarn(SDL_LOG_CATEGORY_INPUT, + "WiiU device_index %d assigned to %d, but has no instance!\n", + i, deviceMap[i] + ); + instanceMap[i] = -1; + } + } +/* Check if we are missing the WiiU Gamepad and try to connect it + if the gamepad is disconnected that's handled in SDL_UpdateJoystick */ + if (WIIU_GetIndexForDevice(WIIU_DEVICE_GAMEPAD) == -1) { + /* Try and detect a gamepad */ + VPADStatus status; + VPADReadError err; + VPADRead(VPAD_CHAN_0, &status, 1, &err); + if (err == VPAD_READ_SUCCESS || err == VPAD_READ_NO_SAMPLES) { + /* We have a gamepad! Assign a device index and instance ID. */ + int device_index = WIIU_GetNextDeviceIndex(); + if (device_index != -1) { + /* Save its device index */ + deviceMap[device_index] = WIIU_DEVICE_GAMEPAD; + instanceMap[device_index] = SDL_GetNextJoystickInstanceID(); + SDL_PrivateJoystickAdded(instanceMap[device_index]); + SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, + "WiiU: Detected Gamepad, assigned device %d/instance %d\n", + device_index, instanceMap[device_index]); + } + } + } + /* Check for WPAD/KPAD controllers */ + for (int i = 0; i < WIIU_NUM_WPADS; i++) { + WPADExtensionType ext; + int wiiu_device = WIIU_DEVICE_WPAD(i); + int ret = WPADProbe(WIIU_WPAD_CHAN(wiiu_device), &ext); + if (ret == 0) { //controller connected + /* Is this already connected? */ + if (WIIU_GetIndexForDevice(wiiu_device) == -1) { + /* No! Let's add it. */ + int device_index = WIIU_GetNextDeviceIndex(); + if (device_index != -1) { + /* Save its device index */ + deviceMap[device_index] = WIIU_DEVICE_WPAD(i); + instanceMap[device_index] = SDL_GetNextJoystickInstanceID(); + /* Save its extension controller */ + lastKnownExts[WIIU_WPAD_CHAN(wiiu_device)] = ext; + SDL_PrivateJoystickAdded(instanceMap[device_index]); + SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, + "WiiU: Detected WPAD, assigned device %d/instance %d\n", + device_index, instanceMap[device_index]); + } + } else if (ext != lastKnownExts[WIIU_WPAD_CHAN(wiiu_device)]) { + /* If this controller has changed extensions, we should + disconnect and reconnect it. */ + SDL_JoystickID instance = WIIU_GetInstForDevice(wiiu_device); + /* Yes! We should disconnect it. */ + SDL_PrivateJoystickRemoved(instance); + /* Unlink device_index, instance_id */ + WIIU_RemoveDevice(wiiu_device); + } + } else if (ret == -1) { //no controller + /* Is this controller connected? */ + if (WIIU_GetIndexForDevice(wiiu_device) != -1) { + SDL_JoystickID instance = WIIU_GetInstForDevice(wiiu_device); + /* Yes! We should disconnect it. */ + SDL_PrivateJoystickRemoved(instance); + /* Unlink device_index, instance_id */ + WIIU_RemoveDevice(wiiu_device); + } + } // otherwise do nothing (-2: pairing) + } +} + +/* Function to get the device-dependent name of a joystick */ +static const char *WIIU_JoystickGetDeviceName(int device_index) +{ + int wiiu_device = WIIU_GetDeviceForIndex(device_index); + /* Gamepad */ + if (wiiu_device == WIIU_DEVICE_GAMEPAD) { + return "WiiU Gamepad"; + } else if (wiiu_device == WIIU_DEVICE_WPAD(0)) { + RETURN_WPAD_NAME(1, lastKnownExts[0]); + } else if (wiiu_device == WIIU_DEVICE_WPAD(1)) { + RETURN_WPAD_NAME(2, lastKnownExts[1]); + } else if (wiiu_device == WIIU_DEVICE_WPAD(2)) { + RETURN_WPAD_NAME(3, lastKnownExts[2]); + } else if (wiiu_device == WIIU_DEVICE_WPAD(3)) { + RETURN_WPAD_NAME(4, lastKnownExts[3]); + } + + return "Unknown"; +} + +/* Function to get the player index of a joystick */ +static int WIIU_JoystickGetDevicePlayerIndex(int device_index) +{ + int wiiu_device = WIIU_GetDeviceForIndex(device_index); + switch (wiiu_device) { + case WIIU_DEVICE_GAMEPAD: { return 0; } + case WIIU_DEVICE_WPAD(1): { return 1; } + case WIIU_DEVICE_WPAD(2): { return 2; } + case WIIU_DEVICE_WPAD(3): { return 3; } + case WIIU_DEVICE_WPAD(4): { return 4; } + default: { return -1; } + } + +} + +/* Function to return the stable GUID for a plugged in device */ +static SDL_JoystickGUID WIIU_JoystickGetDeviceGUID(int device_index) +{ + SDL_JoystickGUID guid; + /* the GUID is just the first 16 chars of the name for now */ + const char *name = WIIU_JoystickGetDeviceName(device_index); + SDL_zero(guid); + SDL_memcpy(&guid, name, SDL_min(sizeof(guid), SDL_strlen(name))); + return guid; +} + +/* Function to get the current instance id of the joystick located at device_index */ +static SDL_JoystickID WIIU_JoystickGetDeviceInstanceID(int device_index) +{ + return WIIU_GetInstForIndex(device_index); +} + +/* Function to open a joystick for use. + The joystick to open is specified by the device index. + This should fill the nbuttons and naxes fields of the joystick structure. + It returns 0, or -1 if there is an error. + */ +static int WIIU_JoystickOpen(SDL_Joystick *joystick, int device_index) +{ + int wiiu_device = WIIU_GetDeviceForIndex(device_index); + switch (wiiu_device) { + case WIIU_DEVICE_GAMEPAD: { + SDL_AddTouch(0, "WiiU Gamepad Touchscreen"); + joystick->nbuttons = SIZEOF_ARR(vpad_button_map); + joystick->naxes = 4; + joystick->nhats = 0; + + break; + } + case WIIU_DEVICE_WPAD(0): + case WIIU_DEVICE_WPAD(1): + case WIIU_DEVICE_WPAD(2): + case WIIU_DEVICE_WPAD(3): { + WPADExtensionType ext; + int ret = WPADProbe(WIIU_WPAD_CHAN(wiiu_device), &ext); + if (ret != 0) { + SDL_LogWarn(SDL_LOG_CATEGORY_INPUT, + "WiiU_JoystickOpen: WPAD device %d failed probe!", + WIIU_WPAD_CHAN(wiiu_device)); + return -1; + } + + switch (ext) { + case WPAD_EXT_CORE: + case WPAD_EXT_MPLUS: + default: { + joystick->nbuttons = SIZEOF_ARR(wiimote_button_map); + joystick->naxes = 0; + joystick->nhats = 0; + break; + } + case WPAD_EXT_NUNCHUK: + case WPAD_EXT_MPLUS_NUNCHUK: { + joystick->nbuttons = SIZEOF_ARR(wiimote_button_map); + joystick->naxes = 2; + joystick->nhats = 0; + break; + } + case WPAD_EXT_CLASSIC: + case WPAD_EXT_MPLUS_CLASSIC: { + joystick->nbuttons = SIZEOF_ARR(classic_button_map); + joystick->naxes = 4; + joystick->nhats = 0; + break; + } + case WPAD_EXT_PRO_CONTROLLER: { + joystick->nbuttons = SIZEOF_ARR(pro_button_map); + joystick->naxes = 4; + joystick->nhats = 0; + break; + } + } + break; + } + } + + joystick->instance_id = WIIU_GetInstForIndex(device_index); + return 0; +} + +/* Rumble functionality */ +static int WIIU_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms) +{ + /* TODO */ + return SDL_Unsupported(); +} + +/* Function to update the state of a joystick - called as a device poll. + * This function shouldn't update the joystick structure directly, + * but instead should call SDL_PrivateJoystick*() to deliver events + * and update joystick device state. + */ +static void WIIU_JoystickUpdate(SDL_Joystick *joystick) +{ + int16_t x1, y1, x2, y2; + /* Gamepad */ + if (joystick->instance_id == WIIU_GetInstForDevice(WIIU_DEVICE_GAMEPAD)) { + static uint16_t last_touch_x = 0; + static uint16_t last_touch_y = 0; + static uint16_t last_touched = 0; + + static int16_t x1_old = 0; + static int16_t y1_old = 0; + static int16_t x2_old = 0; + static int16_t y2_old = 0; + + VPADStatus vpad; + VPADReadError error; + VPADTouchData tpdata; + VPADRead(VPAD_CHAN_0, &vpad, 1, &error); + if (error == VPAD_READ_INVALID_CONTROLLER) { + /* Gamepad disconnected! */ + SDL_PrivateJoystickRemoved(joystick->instance_id); + /* Unlink Gamepad, device_index, instance_id */ + WIIU_RemoveDevice(WIIU_DEVICE_GAMEPAD); + } else if (error != VPAD_READ_SUCCESS) { + return; + } + + /* touchscreen */ + VPADGetTPCalibratedPoint(VPAD_CHAN_0, &tpdata, &vpad.tpNormal); + if (tpdata.touched) { + /* Send an initial touch */ + SDL_SendTouch(0, 0, SDL_TRUE, + (float) tpdata.x / 1280.0f, + (float) tpdata.y / 720.0f, 1); + + /* Always send the motion */ + SDL_SendTouchMotion(0, 0, + (float) tpdata.x / 1280.0f, + (float) tpdata.y / 720.0f, 1); + + /* Update old values */ + last_touch_x = tpdata.x; + last_touch_y = tpdata.y; + last_touched = 1; + } else if (last_touched) { + /* Finger released from screen */ + SDL_SendTouch(0, 0, SDL_FALSE, + (float) last_touch_x / 1280.0f, + (float) last_touch_y / 720.0f, 1); + last_touched = 0; + } + + /* axys */ + x1 = (int16_t) ((vpad.leftStick.x) * 0x7ff0); + y1 = (int16_t) -((vpad.leftStick.y) * 0x7ff0); + x2 = (int16_t) ((vpad.rightStick.x) * 0x7ff0); + y2 = (int16_t) -((vpad.rightStick.y) * 0x7ff0); + + if(x1 != x1_old) { + SDL_PrivateJoystickAxis(joystick, 0, x1); + x1_old = x1; + } + if(y1 != y1_old) { + SDL_PrivateJoystickAxis(joystick, 1, y1); + y1_old = y1; + } + if(x2 != x2_old) { + SDL_PrivateJoystickAxis(joystick, 2, x2); + x2_old = x2; + } + if(y2 != y2_old) { + SDL_PrivateJoystickAxis(joystick, 3, y2); + y2_old = y2; + } + + /* buttons */ + for(int i = 0; i < joystick->nbuttons; i++) + if (vpad.trigger & vpad_button_map[i]) + SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_PRESSED); + for(int i = 0; i < joystick->nbuttons; i++) + if (vpad.release & vpad_button_map[i]) + SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_RELEASED); + } else if ( + joystick->instance_id == WIIU_GetInstForDevice(WIIU_DEVICE_WPAD(0)) || + joystick->instance_id == WIIU_GetInstForDevice(WIIU_DEVICE_WPAD(1)) || + joystick->instance_id == WIIU_GetInstForDevice(WIIU_DEVICE_WPAD(2)) || + joystick->instance_id == WIIU_GetInstForDevice(WIIU_DEVICE_WPAD(3))) { + int wiiu_device = WIIU_GetDeviceForInst(joystick->instance_id); + WPADExtensionType ext; + KPADStatus kpad; + int32_t err; + + if (WPADProbe(WIIU_WPAD_CHAN(wiiu_device), &ext) != 0) { + /* Do nothing, we'll catch it in Detect() */ + return; + } + + KPADReadEx(WIIU_WPAD_CHAN(wiiu_device), &kpad, 1, &err); + if (err != KPAD_ERROR_OK) return; + + switch (ext) { + case WPAD_EXT_CORE: + case WPAD_EXT_MPLUS: + default: { + for(int i = 0; i < joystick->nbuttons; i++) + if (kpad.trigger & wiimote_button_map[i]) + SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_PRESSED); + for(int i = 0; i < joystick->nbuttons; i++) + if (kpad.release & wiimote_button_map[i]) + SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_RELEASED); + break; + } + case WPAD_EXT_NUNCHUK: + case WPAD_EXT_MPLUS_NUNCHUK: { + for(int i = 0; i < joystick->nbuttons; i++) + if (kpad.trigger & wiimote_button_map[i]) + SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_PRESSED); + for(int i = 0; i < joystick->nbuttons; i++) + if (kpad.release & wiimote_button_map[i]) + SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_RELEASED); + + x1 = (int16_t) ((kpad.nunchuck.stick.x) * 0x7ff0); + y1 = (int16_t) -((kpad.nunchuck.stick.y) * 0x7ff0); + SDL_PrivateJoystickAxis(joystick, 0, x1); + SDL_PrivateJoystickAxis(joystick, 1, y1); + break; + } + case WPAD_EXT_CLASSIC: + case WPAD_EXT_MPLUS_CLASSIC: { + for(int i = 0; i < joystick->nbuttons; i++) + if (kpad.classic.trigger & classic_button_map[i]) + SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_PRESSED); + for(int i = 0; i < joystick->nbuttons; i++) + if (kpad.classic.release & classic_button_map[i]) + SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_RELEASED); + + x1 = (int16_t) ((kpad.classic.leftStick.x) * 0x7ff0); + y1 = (int16_t) -((kpad.classic.leftStick.y) * 0x7ff0); + x2 = (int16_t) ((kpad.classic.rightStick.x) * 0x7ff0); + y2 = (int16_t) -((kpad.classic.rightStick.y) * 0x7ff0); + SDL_PrivateJoystickAxis(joystick, 0, x1); + SDL_PrivateJoystickAxis(joystick, 1, y1); + SDL_PrivateJoystickAxis(joystick, 2, x2); + SDL_PrivateJoystickAxis(joystick, 3, y2); + break; + } + case WPAD_EXT_PRO_CONTROLLER: { + for(int i = 0; i < joystick->nbuttons; i++) + if (kpad.pro.trigger & pro_button_map[i]) + SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_PRESSED); + for(int i = 0; i < joystick->nbuttons; i++) + if (kpad.pro.release & pro_button_map[i]) + SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_RELEASED); + + x1 = (int16_t) ((kpad.pro.leftStick.x) * 0x7ff0); + y1 = (int16_t) -((kpad.pro.leftStick.y) * 0x7ff0); + x2 = (int16_t) ((kpad.pro.rightStick.x) * 0x7ff0); + y2 = (int16_t) -((kpad.pro.rightStick.y) * 0x7ff0); + SDL_PrivateJoystickAxis(joystick, 0, x1); + SDL_PrivateJoystickAxis(joystick, 1, y1); + SDL_PrivateJoystickAxis(joystick, 2, x2); + SDL_PrivateJoystickAxis(joystick, 3, y2); + break; + } + } + } +} + +/* Function to close a joystick after use */ +static void WIIU_JoystickClose(SDL_Joystick *joystick) +{ +} + +/* Function to perform any system-specific joystick related cleanup */ +static void WIIU_JoystickQuit(void) +{ +} + +SDL_JoystickDriver SDL_WIIU_JoystickDriver = +{ + WIIU_JoystickInit, + WIIU_JoystickGetCount, + WIIU_JoystickDetect, + WIIU_JoystickGetDeviceName, + WIIU_JoystickGetDevicePlayerIndex, + WIIU_JoystickGetDeviceGUID, + WIIU_JoystickGetDeviceInstanceID, + WIIU_JoystickOpen, + WIIU_JoystickRumble, + WIIU_JoystickUpdate, + WIIU_JoystickClose, + WIIU_JoystickQuit, +}; + +#endif diff --git a/src/joystick/wiiu/SDL_wiiujoystick.h b/src/joystick/wiiu/SDL_wiiujoystick.h new file mode 100644 index 000000000..64fcf50e5 --- /dev/null +++ b/src/joystick/wiiu/SDL_wiiujoystick.h @@ -0,0 +1,112 @@ +/* + Simple DirectMedia Layer + Copyright (C) 2018 Roberto Van Eeden + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include + +#define WIIU_DEVICE_INVALID (-1) +#define WIIU_DEVICE_GAMEPAD (0) +#define WIIU_DEVICE_WPAD(x) (x + 1) +#define WIIU_WPAD_CHAN(device) (device - 1) +#define WIIU_NUM_WPADS (4) + +#define MAX_CONTROLLERS WIIU_DEVICE_WPAD(WIIU_NUM_WPADS) + +#define SIZEOF_ARR(arr) (sizeof(arr) / sizeof(arr[0])) + +static VPADButtons vpad_button_map[] = +{ + VPAD_BUTTON_A, VPAD_BUTTON_B, VPAD_BUTTON_X, VPAD_BUTTON_Y, + VPAD_BUTTON_STICK_L, VPAD_BUTTON_STICK_R, + VPAD_BUTTON_L, VPAD_BUTTON_R, + VPAD_BUTTON_ZL, VPAD_BUTTON_ZR, + VPAD_BUTTON_PLUS, VPAD_BUTTON_MINUS, + VPAD_BUTTON_LEFT, VPAD_BUTTON_UP, VPAD_BUTTON_RIGHT, VPAD_BUTTON_DOWN, + VPAD_STICK_L_EMULATION_LEFT, VPAD_STICK_L_EMULATION_UP, VPAD_STICK_L_EMULATION_RIGHT, VPAD_STICK_L_EMULATION_DOWN, + VPAD_STICK_R_EMULATION_LEFT, VPAD_STICK_R_EMULATION_UP, VPAD_STICK_R_EMULATION_RIGHT, VPAD_STICK_R_EMULATION_DOWN +}; + +static WPADButton wiimote_button_map[] = { + WPAD_BUTTON_A, WPAD_BUTTON_B, WPAD_BUTTON_Z, WPAD_BUTTON_C, + 0, 0, + WPAD_BUTTON_1, WPAD_BUTTON_2, + 0, 0, + WPAD_BUTTON_PLUS, WPAD_BUTTON_MINUS, + WPAD_BUTTON_LEFT, WPAD_BUTTON_UP, WPAD_BUTTON_RIGHT, WPAD_BUTTON_DOWN, +}; + +static WPADClassicButton classic_button_map[] = { + WPAD_CLASSIC_BUTTON_A, WPAD_CLASSIC_BUTTON_B, WPAD_CLASSIC_BUTTON_X, + WPAD_CLASSIC_BUTTON_Y, + 0, 0, + WPAD_CLASSIC_BUTTON_L, WPAD_CLASSIC_BUTTON_R, + WPAD_CLASSIC_BUTTON_ZL, WPAD_CLASSIC_BUTTON_ZR, + WPAD_CLASSIC_BUTTON_PLUS, WPAD_CLASSIC_BUTTON_MINUS, + WPAD_CLASSIC_BUTTON_LEFT, WPAD_CLASSIC_BUTTON_UP, WPAD_CLASSIC_BUTTON_RIGHT, + WPAD_CLASSIC_BUTTON_DOWN, +}; + +static WPADProButton pro_button_map[] = { + WPAD_PRO_BUTTON_A, WPAD_PRO_BUTTON_B, WPAD_PRO_BUTTON_X, WPAD_PRO_BUTTON_Y, + WPAD_PRO_BUTTON_STICK_L, WPAD_PRO_BUTTON_STICK_R, + WPAD_PRO_TRIGGER_L, WPAD_PRO_TRIGGER_R, + WPAD_PRO_TRIGGER_ZL, WPAD_PRO_TRIGGER_ZR, + WPAD_PRO_BUTTON_PLUS, WPAD_PRO_BUTTON_MINUS, + WPAD_PRO_BUTTON_LEFT, WPAD_PRO_BUTTON_UP, + WPAD_PRO_BUTTON_RIGHT, WPAD_PRO_BUTTON_DOWN, + WPAD_PRO_STICK_L_EMULATION_LEFT, WPAD_PRO_STICK_L_EMULATION_UP, + WPAD_PRO_STICK_L_EMULATION_RIGHT, WPAD_PRO_STICK_L_EMULATION_DOWN, + WPAD_PRO_STICK_R_EMULATION_LEFT, WPAD_PRO_STICK_R_EMULATION_UP, + WPAD_PRO_STICK_R_EMULATION_RIGHT, WPAD_PRO_STICK_R_EMULATION_DOWN +}; + +static int WIIU_JoystickInit(void); +static int WIIU_JoystickGetCount(void); +static void WIIU_JoystickDetect(void); +static const char *WIIU_JoystickGetDeviceName(int device_index); +static int WIIU_JoystickGetDevicePlayerIndex(int device_index); +static SDL_JoystickGUID WIIU_JoystickGetDeviceGUID(int device_index); +static SDL_JoystickID WIIU_JoystickGetDeviceInstanceID(int device_index); +static int WIIU_JoystickOpen(SDL_Joystick *joystick, int device_index); +static int WIIU_JoystickRumble(SDL_Joystick * joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms); +static void WIIU_JoystickUpdate(SDL_Joystick *joystick); +static void WIIU_JoystickClose(SDL_Joystick *joystick); +static void WIIU_JoystickQuit(void); + +#define RETURN_WPAD_NAME(chan, ext) { \ + switch (ext) { \ + case WPAD_EXT_CORE: \ + case WPAD_EXT_MPLUS: \ + default: { \ + return "Wii Remote #" #chan; \ + } \ + case WPAD_EXT_NUNCHUK: \ + case WPAD_EXT_MPLUS_NUNCHUK: { \ + return "Wii Remote #" #chan " and Nunchuk"; \ + } \ + case WPAD_EXT_CLASSIC: \ + case WPAD_EXT_MPLUS_CLASSIC: { \ + return "Wii Classic Controller #" #chan; \ + } \ + case WPAD_EXT_PRO_CONTROLLER: { \ + return "WiiU Pro Controller #" #chan; \ + } \ + } \ +} diff --git a/src/libm/math_private.h b/src/libm/math_private.h index ee67c444e..23fad187b 100644 --- a/src/libm/math_private.h +++ b/src/libm/math_private.h @@ -27,7 +27,7 @@ #define libm_hidden_def(x) #define strong_alias(x, y) -#if !defined(__HAIKU__) && !defined(__PSP__) && !defined(__3DS__) && !defined(__PS2__) /* already defined in a system header. */ +#if !defined(__HAIKU__) && !defined(__PSP__) && !defined(__3DS__) && !defined(__PS2__) && !defined(__WIIU__) /* already defined in a system header. */ typedef unsigned int u_int32_t; #endif diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index b650c6ac4..979a711da 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -124,6 +124,9 @@ static const SDL_RenderDriver *render_drivers[] = { #if SDL_VIDEO_RENDER_VITA_GXM &VITA_GXM_RenderDriver, #endif +#if SDL_VIDEO_RENDER_WIIU + &WIIU_RenderDriver, +#endif #if SDL_VIDEO_RENDER_SW &SW_RenderDriver #endif diff --git a/src/render/SDL_sysrender.h b/src/render/SDL_sysrender.h index 36e9555bb..283fe0e88 100644 --- a/src/render/SDL_sysrender.h +++ b/src/render/SDL_sysrender.h @@ -307,6 +307,7 @@ extern SDL_RenderDriver PS2_RenderDriver; extern SDL_RenderDriver PSP_RenderDriver; extern SDL_RenderDriver SW_RenderDriver; extern SDL_RenderDriver VITA_GXM_RenderDriver; +extern SDL_RenderDriver WIIU_RenderDriver; /* Blend mode functions */ extern SDL_BlendFactor SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode); diff --git a/src/render/wiiu/SDL_rdraw_wiiu.c b/src/render/wiiu/SDL_rdraw_wiiu.c new file mode 100644 index 000000000..78fbee4a2 --- /dev/null +++ b/src/render/wiiu/SDL_rdraw_wiiu.c @@ -0,0 +1,444 @@ +/* + Simple DirectMedia Layer + Copyright (C) 2018-2019 Ash Logan + Copyright (C) 2018-2019 Roberto Van Eeden + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_RENDER_WIIU + +#include "../../video/wiiu/SDL_wiiuvideo.h" +#include "../../video/wiiu/wiiu_shaders.h" +#include "../SDL_sysrender.h" +#include "SDL_hints.h" +#include "SDL_render_wiiu.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +static void WIIU_SDL_SetGX2BlendMode(SDL_BlendMode mode); + +int WIIU_SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_FRect * dstrect) +{ + WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata; + WIIU_TextureData *tdata = (WIIU_TextureData *) texture->driverdata; + GX2RBuffer *a_position, *a_texCoord; + WIIUVec2 *a_position_vals, *a_texCoord_vals; + float x_min, y_min, x_max, y_max; + + if (texture->access & SDL_TEXTUREACCESS_TARGET) { + GX2RInvalidateSurface(&tdata->texture.surface, 0, 0); + } + + /* Update texture rendering state */ + WIIU_TextureStartRendering(data, tdata); + + /* Allocate attribute buffers */ + a_position = WIIU_AllocRenderData(data, (GX2RBuffer) { + .flags = + GX2R_RESOURCE_BIND_VERTEX_BUFFER | + GX2R_RESOURCE_USAGE_CPU_WRITE, + .elemSize = sizeof(WIIUVec2), // float x/y for each corner + .elemCount = 4, // 4 corners + }); + a_texCoord = WIIU_AllocRenderData(data, (GX2RBuffer) { + .flags = + GX2R_RESOURCE_BIND_VERTEX_BUFFER | + GX2R_RESOURCE_USAGE_CPU_WRITE, + .elemSize = sizeof(WIIUVec2), + .elemCount = 4, // 4 corners + }); + + /* Compute vertex points */ + x_min = renderer->viewport.x + dstrect->x; + y_min = renderer->viewport.y + dstrect->y; + x_max = renderer->viewport.x + dstrect->x + dstrect->w; + y_max = renderer->viewport.y + dstrect->y + dstrect->h; + + /* Save them */ + a_position_vals = GX2RLockBufferEx(a_position, 0); + a_position_vals[0] = (WIIUVec2){.x = x_min, .y = y_max}; + a_position_vals[1] = (WIIUVec2){.x = x_max, .y = y_max}; + a_position_vals[2] = (WIIUVec2){.x = x_max, .y = y_min}; + a_position_vals[3] = (WIIUVec2){.x = x_min, .y = y_min}; + GX2RUnlockBufferEx(a_position, 0); + + /* Compute texture coords */ + a_texCoord_vals = GX2RLockBufferEx(a_texCoord, 0); + a_texCoord_vals[0] = (WIIUVec2) { + .x = srcrect->x, + .y = texture->h - srcrect->y - srcrect->h, + }; + a_texCoord_vals[1] = (WIIUVec2) { + .x = srcrect->x + srcrect->w, + .y = texture->h - srcrect->y - srcrect->h, + }; + a_texCoord_vals[2] = (WIIUVec2) { + .x = srcrect->x + srcrect->w, + .y = texture->h - srcrect->y, + }; + a_texCoord_vals[3] = (WIIUVec2) { + .x = srcrect->x, + .y = texture->h - srcrect->y, + }; + GX2RUnlockBufferEx(a_texCoord, 0); + + /* Render */ + wiiuSetTextureShader(); + GX2SetPixelTexture(&tdata->texture, 0); + GX2SetPixelSampler(&tdata->sampler, 0); + GX2RSetAttributeBuffer(a_position, 0, a_position->elemSize, 0); + GX2RSetAttributeBuffer(a_texCoord, 1, a_texCoord->elemSize, 0); + GX2SetVertexUniformReg(wiiuTextureShader.vertexShader->uniformVars[0].offset, 4, (uint32_t *)&data->u_viewSize); + GX2SetVertexUniformReg(wiiuTextureShader.vertexShader->uniformVars[1].offset, 4, (uint32_t *)&tdata->u_texSize); + GX2SetPixelUniformReg(wiiuTextureShader.pixelShader->uniformVars[0].offset, 4, (uint32_t *)&tdata->u_mod); + WIIU_SDL_SetGX2BlendMode(texture->blendMode); + GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1); + + return 0; +} + + +int WIIU_SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_FRect * dstrect, + const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip) +{ + WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata; + WIIU_TextureData *tdata = (WIIU_TextureData *) texture->driverdata; + GX2RBuffer *a_position, *a_texCoord; + WIIUVec2 *a_position_vals, *a_texCoord_vals; + + /* Compute real vertex points */ + float x_min = renderer->viewport.x + dstrect->x; + float y_min = renderer->viewport.y + dstrect->y; + float x_max = x_min + dstrect->w; + float y_max = y_min + dstrect->h; + float cx = x_min + center->x; + float cy = y_min + center->y; + double r = angle * (M_PI / 180.0); + WIIUVec2 rvb[4] = { + { + .x = (flip & SDL_FLIP_HORIZONTAL) ? x_max : x_min, + .y = (flip & SDL_FLIP_VERTICAL) ? y_min : y_max, + }, + { + .x = (flip & SDL_FLIP_HORIZONTAL) ? x_min : x_max, + .y = (flip & SDL_FLIP_VERTICAL) ? y_min : y_max, + }, + { + .x = (flip & SDL_FLIP_HORIZONTAL) ? x_min : x_max, + .y = (flip & SDL_FLIP_VERTICAL) ? y_max : y_min, + }, + { + .x = (flip & SDL_FLIP_HORIZONTAL) ? x_max : x_min, + .y = (flip & SDL_FLIP_VERTICAL) ? y_max : y_min, + }, + }; + + if (texture->access & SDL_TEXTUREACCESS_TARGET) { + GX2RInvalidateSurface(&tdata->texture.surface, 0, 0); + } + + /* Update texture rendering state */ + WIIU_TextureStartRendering(data, tdata); + + /* Allocate attribute buffers */ + a_position = WIIU_AllocRenderData(data, (GX2RBuffer) { + .flags = + GX2R_RESOURCE_BIND_VERTEX_BUFFER | + GX2R_RESOURCE_USAGE_CPU_WRITE, + .elemSize = sizeof(WIIUVec2), // float x/y for each corner + .elemCount = 4, // 4 corners + }); + a_texCoord = WIIU_AllocRenderData(data, (GX2RBuffer) { + .flags = + GX2R_RESOURCE_BIND_VERTEX_BUFFER | + GX2R_RESOURCE_USAGE_CPU_WRITE, + .elemSize = sizeof(WIIUVec2), // float x/y for each corner + .elemCount = 4, // 4 corners + }); + + /* Save vertex points */ + a_position_vals = GX2RLockBufferEx(a_position, 0); + for (int i = 0; i < 4; i++) { + a_position_vals[i] = (WIIUVec2) { + .x = cx + (SDL_cos(r) * (rvb[i].x - cx) - SDL_sin(r) * (rvb[i].y - cy)), + .y = cy + (SDL_cos(r) * (rvb[i].y - cy) + SDL_sin(r) * (rvb[i].x - cx)), + }; + } + GX2RUnlockBufferEx(a_position, 0); + + /* Compute texture coords */ + a_texCoord_vals = GX2RLockBufferEx(a_texCoord, 0); + a_texCoord_vals[0] = (WIIUVec2) { + .x = srcrect->x, + .y = texture->h - srcrect->y - srcrect->h, + }; + a_texCoord_vals[1] = (WIIUVec2) { + .x = srcrect->x + srcrect->w, + .y = texture->h - srcrect->y - srcrect->h, + }; + a_texCoord_vals[2] = (WIIUVec2) { + .x = srcrect->x + srcrect->w, + .y = texture->h - srcrect->y, + }; + a_texCoord_vals[3] = (WIIUVec2) { + .x = srcrect->x, + .y = texture->h - srcrect->y, + }; + GX2RUnlockBufferEx(a_texCoord, 0); + + /* Render */ + wiiuSetTextureShader(); + GX2SetPixelTexture(&tdata->texture, 0); + GX2SetPixelSampler(&tdata->sampler, 0); + GX2RSetAttributeBuffer(a_position, 0, a_position->elemSize, 0); + GX2RSetAttributeBuffer(a_texCoord, 1, a_texCoord->elemSize, 0); + GX2SetVertexUniformReg(wiiuTextureShader.vertexShader->uniformVars[0].offset, 4, (uint32_t *)&data->u_viewSize); + GX2SetVertexUniformReg(wiiuTextureShader.vertexShader->uniformVars[1].offset, 4, (uint32_t *)&tdata->u_texSize); + GX2SetPixelUniformReg(wiiuTextureShader.pixelShader->uniformVars[0].offset, 4, (uint32_t *)&tdata->u_mod); + WIIU_SDL_SetGX2BlendMode(texture->blendMode); + GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1); + + return 0; +} + +int WIIU_SDL_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points, + int count) +{ + WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata; + GX2RBuffer *a_position; + WIIUVec2 *a_position_vals; + + /* Compute colours */ + WIIUVec4 u_colour = { + .r = (float)renderer->r / 255.0f, + .g = (float)renderer->g / 255.0f, + .b = (float)renderer->b / 255.0f, + .a = (float)renderer->a / 255.0f, + }; + + /* Allocate attribute buffers */ + a_position = WIIU_AllocRenderData(data, (GX2RBuffer) { + .flags = + GX2R_RESOURCE_BIND_VERTEX_BUFFER | + GX2R_RESOURCE_USAGE_CPU_WRITE, + .elemSize = sizeof(WIIUVec2), /* float x/y for each point */ + .elemCount = count, + }); + + /* Compute vertex positions */ + a_position_vals = GX2RLockBufferEx(a_position, 0); + for (int i = 0; i < count; ++i) { + a_position_vals[i] = (WIIUVec2) { + .x = (float)renderer->viewport.x + points[i].x, + .y = (float)renderer->viewport.y + points[i].y, + }; + } + GX2RUnlockBufferEx(a_position, 0); + + /* Render points */ + wiiuSetColorShader(); + GX2RSetAttributeBuffer(a_position, 0, a_position->elemSize, 0); + GX2SetVertexUniformReg(wiiuColorShader.vertexShader->uniformVars[0].offset, 4, (uint32_t *)&data->u_viewSize); + GX2SetPixelUniformReg(wiiuColorShader.pixelShader->uniformVars[0].offset, 4, (uint32_t *)&u_colour); + WIIU_SDL_SetGX2BlendMode(renderer->blendMode); + GX2DrawEx(GX2_PRIMITIVE_MODE_POINTS, count, 0, 1); + + return 0; +} + + +int WIIU_SDL_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points, + int count) +{ + WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata; + GX2RBuffer *a_position; + WIIUVec2 *a_position_vals; + + /* Compute colours */ + WIIUVec4 u_colour = { + .r = (float)renderer->r / 255.0f, + .g = (float)renderer->g / 255.0f, + .b = (float)renderer->b / 255.0f, + .a = (float)renderer->a / 255.0f, + }; + + /* Allocate attribute buffers */ + a_position = WIIU_AllocRenderData(data, (GX2RBuffer) { + .flags = + GX2R_RESOURCE_BIND_VERTEX_BUFFER | + GX2R_RESOURCE_USAGE_CPU_WRITE, + .elemSize = sizeof(WIIUVec2), /* float x/y for each point */ + .elemCount = count, + }); + + /* Compute vertex positions */ + a_position_vals = GX2RLockBufferEx(a_position, 0); + for (int i = 0; i < count; ++i) { + a_position_vals[i] = (WIIUVec2) { + .x = (float)renderer->viewport.x + points[i].x, + .y = (float)renderer->viewport.y + points[i].y, + }; + } + GX2RUnlockBufferEx(a_position, 0); + + /* Render lines */ + wiiuSetColorShader(); + GX2RSetAttributeBuffer(a_position, 0, a_position->elemSize, 0); + GX2SetVertexUniformReg(wiiuColorShader.vertexShader->uniformVars[0].offset, 4, (uint32_t *)&data->u_viewSize); + GX2SetPixelUniformReg(wiiuColorShader.pixelShader->uniformVars[0].offset, 4, (uint32_t *)&u_colour); + WIIU_SDL_SetGX2BlendMode(renderer->blendMode); + GX2DrawEx(GX2_PRIMITIVE_MODE_LINE_STRIP, count, 0, 1); + + return 0; +} + +int WIIU_SDL_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, int count) +{ + WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata; + GX2RBuffer *a_position; + WIIUVec2 *a_position_vals; + + /* Compute colours */ + WIIUVec4 u_colour = { + .r = (float)renderer->r / 255.0f, + .g = (float)renderer->g / 255.0f, + .b = (float)renderer->b / 255.0f, + .a = (float)renderer->a / 255.0f, + }; + + /* Compute vertex pos */ + float vx = (float)renderer->viewport.x; + float vy = (float)renderer->viewport.y; + + /* Allocate attribute buffers */ + a_position = WIIU_AllocRenderData(data, (GX2RBuffer) { + .flags = + GX2R_RESOURCE_BIND_VERTEX_BUFFER | + GX2R_RESOURCE_USAGE_CPU_WRITE, + .elemSize = sizeof(WIIUVec2), // x/y float per corner + .elemCount = 4 * count, // 4 corners per square + }); + + /* Compute vertex positions */ + a_position_vals = GX2RLockBufferEx(a_position, 0); + for (int i = 0; i < count; ++i) { + a_position_vals[i*4 + 0] = (WIIUVec2) { + .x = vx + rects[i].x, + .y = vy + rects[i].y, + }; + a_position_vals[i*4 + 1] = (WIIUVec2) { + .x = vx + rects[i].x + rects[i].w, + .y = vy + rects[i].y, + }; + a_position_vals[i*4 + 2] = (WIIUVec2) { + .x = vx + rects[i].x + rects[i].w, + .y = vy + rects[i].y + rects[i].h, + }; + a_position_vals[i*4 + 3] = (WIIUVec2) { + .x = vx + rects[i].x, + .y = vy + rects[i].y + rects[i].h, + }; + } + GX2RUnlockBufferEx(a_position, 0); + + /* Render rects */ + wiiuSetColorShader(); + GX2RSetAttributeBuffer(a_position, 0, a_position->elemSize, 0); + GX2SetVertexUniformReg(wiiuColorShader.vertexShader->uniformVars[0].offset, 4, (uint32_t *)&data->u_viewSize); + GX2SetPixelUniformReg(wiiuColorShader.pixelShader->uniformVars[0].offset, 4, (uint32_t *)&u_colour); + WIIU_SDL_SetGX2BlendMode(renderer->blendMode); + GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4 * count, 0, 1); + + return 0; +} + +int WIIU_SDL_RenderClear(SDL_Renderer * renderer) +{ + WIIU_RenderData* data = (WIIU_RenderData*) renderer->driverdata; + SDL_Texture* target = WIIU_GetRenderTarget(renderer); + WIIU_TextureData* tdata = (WIIU_TextureData*) target->driverdata; + + GX2ClearColor(&tdata->cbuf, + (float)renderer->r / 255.0f, + (float)renderer->g / 255.0f, + (float)renderer->b / 255.0f, + (float)renderer->a / 255.0f); + + /* Restore SDL context state */ + GX2SetContextState(data->ctx); + + return 0; +} + +static void WIIU_SDL_SetGX2BlendMode(SDL_BlendMode mode) +{ + if (mode == SDL_BLENDMODE_NONE) { + GX2SetColorControl(GX2_LOGIC_OP_COPY, 0x00, FALSE, TRUE); + } else if (mode == SDL_BLENDMODE_BLEND) { + GX2SetColorControl(GX2_LOGIC_OP_COPY, 0xFF, FALSE, TRUE); + GX2SetBlendControl(GX2_RENDER_TARGET_0, + /* RGB = [srcRGB * srcA] + [dstRGB * (1-srcA)] */ + GX2_BLEND_MODE_SRC_ALPHA, GX2_BLEND_MODE_INV_SRC_ALPHA, + GX2_BLEND_COMBINE_MODE_ADD, + TRUE, + /* A = [srcA * 1] + [dstA * (1-srcA)] */ + GX2_BLEND_MODE_ONE, GX2_BLEND_MODE_INV_SRC_ALPHA, + GX2_BLEND_COMBINE_MODE_ADD); + } else if (mode == SDL_BLENDMODE_ADD) { + GX2SetColorControl(GX2_LOGIC_OP_COPY, 0xFF, FALSE, TRUE); + GX2SetBlendControl(GX2_RENDER_TARGET_0, + /* RGB = [srcRGB * srcA] + [dstRGB * 1] */ + GX2_BLEND_MODE_SRC_ALPHA, GX2_BLEND_MODE_ONE, + GX2_BLEND_COMBINE_MODE_ADD, + TRUE, + /* A = [srcA * 0] + [dstA * 1] */ + GX2_BLEND_MODE_ZERO, GX2_BLEND_MODE_ONE, + GX2_BLEND_COMBINE_MODE_ADD); + } else if (mode == SDL_BLENDMODE_MOD) { + GX2SetColorControl(GX2_LOGIC_OP_COPY, 0xFF, FALSE, TRUE); + GX2SetBlendControl(GX2_RENDER_TARGET_0, + /* RGB = [srcRGB * dstRGB] + [dstRGB * 0]) */ + GX2_BLEND_MODE_DST_COLOR, GX2_BLEND_MODE_ZERO, + GX2_BLEND_COMBINE_MODE_ADD, + TRUE, + /* A = [srcA * 0] + [dstA * 1] */ + GX2_BLEND_MODE_ZERO, GX2_BLEND_MODE_ONE, + GX2_BLEND_COMBINE_MODE_ADD); + } +} + +#endif /* SDL_VIDEO_RENDER_WIIU */ diff --git a/src/render/wiiu/SDL_render_wiiu.c b/src/render/wiiu/SDL_render_wiiu.c new file mode 100644 index 000000000..633c26b38 --- /dev/null +++ b/src/render/wiiu/SDL_render_wiiu.c @@ -0,0 +1,275 @@ +/* + Simple DirectMedia Layer + Copyright (C) 2018-2019 Ash Logan + Copyright (C) 2018-2019 Roberto Van Eeden + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_RENDER_WIIU + +#include "../../video/wiiu/SDL_wiiuvideo.h" +#include "../../video/wiiu/wiiu_shaders.h" +#include "../SDL_sysrender.h" +#include "SDL_hints.h" +#include "SDL_render_wiiu.h" + +#include +#include +#include + +#include + +SDL_RenderDriver WIIU_RenderDriver; + +SDL_Renderer *WIIU_SDL_CreateRenderer(SDL_Window * window, Uint32 flags) +{ + SDL_Renderer *renderer; + WIIU_RenderData *data; + + renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); + if (!renderer) { + SDL_OutOfMemory(); + return NULL; + } + + data = (WIIU_RenderData *) SDL_calloc(1, sizeof(*data)); + if (!data) { + WIIU_SDL_DestroyRenderer(renderer); + SDL_OutOfMemory(); + return NULL; + } + + /* Setup renderer functions */ + renderer->WindowEvent = WIIU_SDL_WindowEvent; + renderer->GetOutputSize = WIIU_SDL_GetOutputSize; + renderer->CreateTexture = WIIU_SDL_CreateTexture; + renderer->SetTextureColorMod = WIIU_SDL_SetTextureColorMod; + renderer->SetTextureAlphaMod = WIIU_SDL_SetTextureAlphaMod; + renderer->UpdateTexture = WIIU_SDL_UpdateTexture; + renderer->LockTexture = WIIU_SDL_LockTexture; + renderer->UnlockTexture = WIIU_SDL_UnlockTexture; + renderer->SetRenderTarget = WIIU_SDL_SetRenderTarget; + renderer->UpdateViewport = WIIU_SDL_UpdateViewport; + renderer->UpdateClipRect = WIIU_SDL_UpdateClipRect; + renderer->RenderClear = WIIU_SDL_RenderClear; + renderer->RenderDrawPoints = WIIU_SDL_RenderDrawPoints; + renderer->RenderDrawLines = WIIU_SDL_RenderDrawLines; + renderer->RenderFillRects = WIIU_SDL_RenderFillRects; + renderer->RenderCopy = WIIU_SDL_RenderCopy; + renderer->RenderCopyEx = WIIU_SDL_RenderCopyEx; + renderer->RenderReadPixels = WIIU_SDL_RenderReadPixels; + renderer->RenderPresent = WIIU_SDL_RenderPresent; + renderer->DestroyTexture = WIIU_SDL_DestroyTexture; + renderer->DestroyRenderer = WIIU_SDL_DestroyRenderer; + renderer->info = WIIU_RenderDriver.info; + renderer->driverdata = data; + renderer->window = window; + + /* Prepare shaders */ + wiiuInitTextureShader(); + wiiuInitColorShader(); + + /* List of attibutes to free after render */ + data->listfree = NULL; + + /* Setup line and point size */ + GX2SetLineWidth(1.0f); + GX2SetPointSize(1.0f, 1.0f); + + /* Create a fresh context state */ + data->ctx = (GX2ContextState *) memalign(GX2_CONTEXT_STATE_ALIGNMENT, sizeof(GX2ContextState)); + SDL_memset(data->ctx, 0, sizeof(GX2ContextState)); + GX2SetupContextStateEx(data->ctx, TRUE); + GX2SetContextState(data->ctx); + + /* Setup some context state options */ + GX2SetAlphaTest(TRUE, GX2_COMPARE_FUNC_GREATER, 0.0f); + GX2SetDepthOnlyControl(FALSE, FALSE, GX2_COMPARE_FUNC_NEVER); + GX2SetCullOnlyControl(GX2_FRONT_FACE_CCW, FALSE, FALSE); + + /* Make a texture for the window */ + WIIU_SDL_CreateWindowTex(renderer, window); + + /* Setup colour buffer, rendering to the window */ + WIIU_SDL_SetRenderTarget(renderer, NULL); + + return renderer; +} + +void WIIU_SDL_CreateWindowTex(SDL_Renderer * renderer, SDL_Window * window) +{ + WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata; + const char *s_hint; + SDL_ScaleMode s_mode; + + if (data->windowTex.driverdata) { + WIIU_SDL_DestroyTexture(renderer, &data->windowTex); + data->windowTex = (SDL_Texture) {0}; + } + + /* Setup scaling mode; this is normally handled by + SDL_CreateTexture/SDL_GetScaleMode, but those can't + be called before fully initializinig the renderer */ + s_hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY); + if (!s_hint || SDL_strcasecmp(s_hint, "nearest") == 0) { + s_mode = SDL_ScaleModeNearest; + } else if (SDL_strcasecmp(s_hint, "linear") == 0) { + s_mode = SDL_ScaleModeLinear; + } else if (SDL_strcasecmp(s_hint, "best") == 0) { + s_mode = SDL_ScaleModeBest; + } else { + s_mode = (SDL_ScaleMode)SDL_atoi(s_hint); + } + + /* Allocate a buffer for the window */ + data->windowTex = (SDL_Texture) { + .format = SDL_PIXELFORMAT_RGBA8888, + .r = 255, .g = 255, .b = 255, .a = 255, + .driverdata = WIIU_TEXTURE_MEM1_MAGIC, + .scaleMode = s_mode, + }; + + SDL_GetWindowSize(window, &data->windowTex.w, &data->windowTex.h); + + /* Setup texture and color buffer for the window */ + WIIU_SDL_CreateTexture(renderer, &data->windowTex); +} + +int WIIU_SDL_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) +{ + WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata; + + /* Set window or texture as target */ + WIIU_TextureData *tdata = (WIIU_TextureData *)((texture) ? texture->driverdata + : data->windowTex.driverdata); + + /* Wait for the texture rendering to finish */ + WIIU_TextureCheckWaitRendering(data, tdata); + + /* Update u_viewSize */ + data->u_viewSize = (WIIUVec4) { + .x = (float)tdata->cbuf.surface.width, + .y = (float)tdata->cbuf.surface.height, + }; + + /* Update context state */ + GX2SetColorBuffer(&tdata->cbuf, GX2_RENDER_TARGET_0); + + /* These may be unnecessary - see SDL_render.c: SDL_SetRenderTarget's calls + to UpdateViewport and UpdateClipRect. TODO for once the render is + basically working */ + GX2SetViewport(0, 0, (float)tdata->cbuf.surface.width, (float)tdata->cbuf.surface.height, 0.0f, 1.0f); + GX2SetScissor(0, 0, (float)tdata->cbuf.surface.width, (float)tdata->cbuf.surface.height); + + return 0; +} + +void WIIU_SDL_DestroyRenderer(SDL_Renderer * renderer) +{ + WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata; + + GX2DrawDone(); + + WIIU_FreeRenderData(data); + WIIU_TextureDoneRendering(data); + + free(data->ctx); + + wiiuFreeColorShader(); + wiiuFreeTextureShader(); + + SDL_free(data); + SDL_free(renderer); +} + +int WIIU_SDL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, + Uint32 format, void * pixels, int pitch) +{ + SDL_Texture* target = WIIU_GetRenderTarget(renderer); + WIIU_TextureData* tdata = (WIIU_TextureData*) target->driverdata; + Uint8 *src_image; + int ret; + + /* NOTE: The rect is already adjusted according to the viewport by + SDL_RenderReadPixels */ + + if (rect->x < 0 || rect->x+rect->w > tdata->cbuf.surface.width || + rect->y < 0 || rect->y+rect->h > tdata->cbuf.surface.height) { + return SDL_SetError("Tried to read outside of surface bounds"); + } + + src_image = GX2RLockSurfaceEx(&tdata->cbuf.surface, 0, GX2R_RESOURCE_LOCKED_READ_ONLY); + + /* Convert and copy the pixels to target buffer */ + ret = SDL_ConvertPixels(rect->w, rect->h, target->format, + src_image + rect->y * tdata->cbuf.surface.pitch + rect->x * 4, + tdata->cbuf.surface.pitch, + format, pixels, pitch); + + GX2RUnlockSurfaceEx(&tdata->cbuf.surface, 0, GX2R_RESOURCE_LOCKED_READ_ONLY); + + return ret; +} + + +SDL_RenderDriver WIIU_RenderDriver = +{ + .CreateRenderer = WIIU_SDL_CreateRenderer, + .info = { + .name = "WiiU GX2", + .flags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE, + .num_texture_formats = 13, //21, + .texture_formats = { + /* TODO: Alpha-less (X) formats */ + SDL_PIXELFORMAT_RGBA8888, +// SDL_PIXELFORMAT_RGBX8888, + +// SDL_PIXELFORMAT_RGB444, + SDL_PIXELFORMAT_ARGB4444, + SDL_PIXELFORMAT_RGBA4444, + SDL_PIXELFORMAT_ABGR4444, + SDL_PIXELFORMAT_BGRA4444, + +// SDL_PIXELFORMAT_RGB555, + SDL_PIXELFORMAT_ARGB1555, +// SDL_PIXELFORMAT_BGR555, + SDL_PIXELFORMAT_ABGR1555, + SDL_PIXELFORMAT_RGBA5551, + SDL_PIXELFORMAT_BGRA5551, + + /* TODO: RGB565 doesn't seem to work right, endian issue? */ +// SDL_PIXELFORMAT_RGB565, +// SDL_PIXELFORMAT_BGR565, + + SDL_PIXELFORMAT_ARGB8888, + SDL_PIXELFORMAT_BGRA8888, +// SDL_PIXELFORMAT_BGRX8888, + SDL_PIXELFORMAT_ABGR8888, +// SDL_PIXELFORMAT_BGR888, + + SDL_PIXELFORMAT_ARGB2101010, + }, + .max_texture_width = 0, + .max_texture_height = 0, + }, +}; + +#endif /* SDL_VIDEO_RENDER_WIIU */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/render/wiiu/SDL_render_wiiu.h b/src/render/wiiu/SDL_render_wiiu.h new file mode 100644 index 000000000..68f9ff910 --- /dev/null +++ b/src/render/wiiu/SDL_render_wiiu.h @@ -0,0 +1,322 @@ +/* + Simple DirectMedia Layer + Copyright (C) 2018-2019 Ash Logan + Copyright (C) 2018-2019 Roberto Van Eeden + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifndef SDL_render_wiiu_h +#define SDL_render_wiiu_h + +#include "../SDL_sysrender.h" +#include "SDL_pixels.h" +#include +#include +#include +#include +#include +#include + +/* Driver internal data structures */ +typedef struct WIIUVec2 WIIUVec2; +typedef struct WIIUVec3 WIIUVec3; +typedef struct WIIUVec4 WIIUVec4; +typedef struct WIIUPixFmt WIIUPixFmt; +typedef struct WIIU_RenderAllocData WIIU_RenderAllocData; +typedef struct WIIU_TextureDrawData WIIU_TextureDrawData; +typedef struct WIIU_RenderData WIIU_RenderData; +typedef struct WIIU_TextureData WIIU_TextureData; + +struct WIIUVec2 +{ + union { float x, r; }; + union { float y, g; }; +}; + +struct WIIUVec3 +{ + union { float x, r; }; + union { float y, g; }; + union { float z, b; }; +}; + +struct WIIUVec4 +{ + union { float x, r; }; + union { float y, g; }; + union { float z, b; }; + union { float w, a; }; +}; + +struct WIIUPixFmt +{ + GX2SurfaceFormat fmt; + uint32_t compMap; +}; + +struct WIIU_RenderAllocData +{ + void *next; + GX2RBuffer buffer; +}; + +struct WIIU_TextureDrawData +{ + void *next; + WIIU_TextureData *texdata; +}; + +struct WIIU_RenderData +{ + GX2ContextState *ctx; + WIIU_RenderAllocData *listfree; + WIIU_TextureDrawData *listdraw; + WIIUVec4 u_viewSize; + SDL_Texture windowTex; +}; + +struct WIIU_TextureData +{ + GX2Sampler sampler; + GX2Texture texture; + GX2ColorBuffer cbuf; + WIIUVec4 u_texSize; + WIIUVec4 u_mod; + int isRendering; +}; + +/* Ask texture driver to allocate texture's memory from MEM1 */ +#define WIIU_TEXTURE_MEM1_MAGIC (void *)0xCAFE0001 + +/* SDL_render API implementation */ +SDL_Renderer *WIIU_SDL_CreateRenderer(SDL_Window * window, Uint32 flags); +void WIIU_SDL_WindowEvent(SDL_Renderer * renderer, + const SDL_WindowEvent *event); +int WIIU_SDL_GetOutputSize(SDL_Renderer * renderer, int *w, int *h); +int WIIU_SDL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); +int WIIU_SDL_SetTextureColorMod(SDL_Renderer * renderer, + SDL_Texture * texture); +int WIIU_SDL_SetTextureAlphaMod(SDL_Renderer * renderer, + SDL_Texture * texture); +int WIIU_SDL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * rect, const void *pixels, + int pitch); +int WIIU_SDL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * rect, void **pixels, int *pitch); +void WIIU_SDL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture); +int WIIU_SDL_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture); +int WIIU_SDL_UpdateViewport(SDL_Renderer * renderer); +int WIIU_SDL_UpdateClipRect(SDL_Renderer * renderer); +int WIIU_SDL_RenderClear(SDL_Renderer * renderer); +int WIIU_SDL_RenderDrawPoints(SDL_Renderer * renderer, + const SDL_FPoint * points, int count); +int WIIU_SDL_RenderDrawLines(SDL_Renderer * renderer, + const SDL_FPoint * points, int count); +int WIIU_SDL_RenderFillRects(SDL_Renderer * renderer, + const SDL_FRect * rects, int count); +int WIIU_SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_FRect * dstrect); +int WIIU_SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * srcrect, const SDL_FRect * dstrect, + const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip); +int WIIU_SDL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, + Uint32 format, void * pixels, int pitch); +void WIIU_SDL_RenderPresent(SDL_Renderer * renderer); +void WIIU_SDL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture); +void WIIU_SDL_DestroyRenderer(SDL_Renderer * renderer); + +/* Driver internal functions */ +void WIIU_SDL_CreateWindowTex(SDL_Renderer * renderer, SDL_Window * window); + +/* Utility/helper functions */ +static inline GX2RBuffer * WIIU_AllocRenderData(WIIU_RenderData *r, GX2RBuffer buffer) +{ + WIIU_RenderAllocData *rdata = SDL_malloc(sizeof(WIIU_RenderAllocData)); + + rdata->buffer = buffer; + if (!GX2RCreateBuffer(&rdata->buffer)) { + SDL_free(rdata); + return 0; + } + + rdata->next = r->listfree; + r->listfree = rdata; + return &rdata->buffer; +} + +static inline void WIIU_FreeRenderData(WIIU_RenderData *r) +{ + while (r->listfree) { + WIIU_RenderAllocData *ptr = r->listfree; + r->listfree = r->listfree->next; + GX2RDestroyBufferEx(&ptr->buffer, 0); + SDL_free(ptr); + } +} + +static inline void WIIU_TextureStartRendering(WIIU_RenderData *r, WIIU_TextureData *t) +{ + WIIU_TextureDrawData *d = SDL_malloc(sizeof(WIIU_TextureDrawData)); + t->isRendering = 1; + d->texdata = t; + d->next = r->listdraw; + r->listdraw = d; +} + +static inline void WIIU_TextureDoneRendering(WIIU_RenderData *r) +{ + while (r->listdraw) { + WIIU_TextureDrawData *d = r->listdraw; + r->listdraw = r->listdraw->next; + d->texdata->isRendering = 0; + SDL_free(d); + } +} + +/* If the texture is currently being rendered and we change the content + before the rendering is finished, the GPU will end up partially drawing + the new data, so we wait for the GPU to finish rendering before + updating the texture */ +static inline void WIIU_TextureCheckWaitRendering(WIIU_RenderData *r, WIIU_TextureData *t) +{ + if (t->isRendering) { + GX2DrawDone(); + WIIU_TextureDoneRendering(r); + WIIU_FreeRenderData(r); + } +} + +static inline SDL_Texture * WIIU_GetRenderTarget(SDL_Renderer* renderer) +{ + WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata; + + if (renderer->target) { + return renderer->target; + } + + return &data->windowTex; +} + +static inline WIIUPixFmt SDLFormatToWIIUFormat(Uint32 format) +{ + WIIUPixFmt outFmt = { /* sane defaults? */ + .fmt = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8, + .compMap = 0x00010203, + }; + + switch (format) { + /* packed16 formats: 4 bits/channel */ + case SDL_PIXELFORMAT_RGB444: /* aka XRGB4444 */ + case SDL_PIXELFORMAT_ARGB4444: { + outFmt.fmt = GX2_SURFACE_FORMAT_UNORM_R4_G4_B4_A4; + outFmt.compMap = 0x01020300; + break; + } + case SDL_PIXELFORMAT_RGBA4444: { + outFmt.fmt = GX2_SURFACE_FORMAT_UNORM_R4_G4_B4_A4; + outFmt.compMap = 0x00010203; + break; + } + case SDL_PIXELFORMAT_ABGR4444: { + outFmt.fmt = GX2_SURFACE_FORMAT_UNORM_R4_G4_B4_A4; + outFmt.compMap = 0x03020100; + break; + } + case SDL_PIXELFORMAT_BGRA4444: { + outFmt.fmt = GX2_SURFACE_FORMAT_UNORM_R4_G4_B4_A4; + outFmt.compMap = 0x02010003; + break; + } + + /* packed16 formats: 5 bits/channel */ + case SDL_PIXELFORMAT_RGB555: /* aka XRGB1555 */ + case SDL_PIXELFORMAT_ARGB1555: { + outFmt.fmt = GX2_SURFACE_FORMAT_UNORM_R5_G5_B5_A1; + outFmt.compMap = 0x01020300; + break; + } + case SDL_PIXELFORMAT_BGR555: /* aka XRGB1555 */ + case SDL_PIXELFORMAT_ABGR1555: { + outFmt.fmt = GX2_SURFACE_FORMAT_UNORM_R5_G5_B5_A1; + outFmt.compMap = 0x03020100; + break; + } + case SDL_PIXELFORMAT_RGBA5551: { + outFmt.fmt = GX2_SURFACE_FORMAT_UNORM_R5_G5_B5_A1; + outFmt.compMap = 0x00010203; + break; + } + case SDL_PIXELFORMAT_BGRA5551: { + outFmt.fmt = GX2_SURFACE_FORMAT_UNORM_R5_G5_B5_A1; + outFmt.compMap = 0x02010003; + break; + } + + /* packed16 formats: 565 */ + case SDL_PIXELFORMAT_RGB565: { + outFmt.fmt = GX2_SURFACE_FORMAT_UNORM_R5_G6_B5; + outFmt.compMap = 0x00010203; + break; + } + case SDL_PIXELFORMAT_BGR565: { + outFmt.fmt = GX2_SURFACE_FORMAT_UNORM_R5_G6_B5; + outFmt.compMap = 0x02010003; + break; + } + + /* packed32 formats */ + case SDL_PIXELFORMAT_RGBA8888: + case SDL_PIXELFORMAT_RGBX8888: { + outFmt.fmt = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8; + outFmt.compMap = 0x00010203; + break; + } + case SDL_PIXELFORMAT_ARGB8888: { + outFmt.fmt = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8; + outFmt.compMap = 0x01020300; + break; + } + case SDL_PIXELFORMAT_BGRA8888: + case SDL_PIXELFORMAT_BGRX8888: { + outFmt.fmt = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8; + outFmt.compMap = 0x02010003; + break; + } + case SDL_PIXELFORMAT_ABGR8888: + case SDL_PIXELFORMAT_BGR888: { + outFmt.fmt = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8; + outFmt.compMap = 0x03020100; + break; + } + case SDL_PIXELFORMAT_ARGB2101010: { + outFmt.fmt = GX2_SURFACE_FORMAT_UNORM_R10_G10_B10_A2; + outFmt.compMap = 0x01020300; + break; + } + default: { + /* TODO return an error */ + printf("SDL: WiiU format not recognised (SDL: %08X)\n", format); + break; + } + } + + return outFmt; +} + +#endif //SDL_render_wiiu_h diff --git a/src/render/wiiu/SDL_rpresent_wiiu.c b/src/render/wiiu/SDL_rpresent_wiiu.c new file mode 100644 index 000000000..18adae8e1 --- /dev/null +++ b/src/render/wiiu/SDL_rpresent_wiiu.c @@ -0,0 +1,157 @@ +/* + Simple DirectMedia Layer + Copyright (C) 2018-2019 Ash Logan + Copyright (C) 2018-2019 Roberto Van Eeden + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_RENDER_WIIU + +#include "../../video/wiiu/wiiu_shaders.h" +#include "../SDL_sysrender.h" +#include "SDL_render_wiiu.h" + +#include +#include +#include +#include +#include +#include + +#define SCREEN_WIDTH 1280 +#define SCREEN_HEIGHT 720 + +static const WIIUVec4 u_viewSize = {.x = (float)SCREEN_WIDTH, .y = (float)SCREEN_HEIGHT}; + +static void render_scene(SDL_Renderer * renderer) +{ + WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata; + WIIU_TextureData *tdata = (WIIU_TextureData *) data->windowTex.driverdata; + + float tex_w = tdata->u_texSize.x; + float tex_h = tdata->u_texSize.y; + int win_x, win_y, win_w, win_h; + GX2RBuffer *a_position, *a_texCoord; + WIIUVec2 *a_position_vals, *a_texCoord_vals; + + /* Allocate attribute buffers */ + a_position = WIIU_AllocRenderData(data, (GX2RBuffer) { + .flags = + GX2R_RESOURCE_BIND_VERTEX_BUFFER | + GX2R_RESOURCE_USAGE_CPU_WRITE, + .elemSize = sizeof(WIIUVec2), /* float x/y for each corner */ + .elemCount = 4, /* 4 corners */ + }); + a_texCoord = WIIU_AllocRenderData(data, (GX2RBuffer) { + .flags = + GX2R_RESOURCE_BIND_VERTEX_BUFFER | + GX2R_RESOURCE_USAGE_CPU_WRITE, + .elemSize = sizeof(WIIUVec2), // float x/y for each corner + .elemCount = 4, // 4 corners + }); + + /* Calculate and save positions */ + if (SDL_GetWindowFlags(renderer->window) & SDL_WINDOW_FULLSCREEN) { + win_x = 0; + win_y = 0; + win_w = SCREEN_WIDTH; + win_h = SCREEN_HEIGHT; + } else { + /* Center */ + SDL_GetWindowSize(renderer->window, &win_w, &win_h); + win_x = (SCREEN_WIDTH - win_w) / 2; + win_y = (SCREEN_HEIGHT - win_h) / 2; + } + + a_position_vals = GX2RLockBufferEx(a_position, 0); + a_position_vals[0] = (WIIUVec2) { + .x = win_x, .y = win_y + }; + a_position_vals[1] = (WIIUVec2) { + .x = win_x + win_w, .y = win_y + }; + a_position_vals[2] = (WIIUVec2) { + .x = win_x + win_w, .y = win_y + win_h + }; + a_position_vals[3] = (WIIUVec2) { + .x = win_x, .y = win_y + win_h + }; + GX2RUnlockBufferEx(a_position, 0); + + /* Compute texture coords */ + a_texCoord_vals = GX2RLockBufferEx(a_texCoord, 0); + a_texCoord_vals[0] = (WIIUVec2) {.x = 0.0f, .y = tex_h}; + a_texCoord_vals[1] = (WIIUVec2) {.x = tex_w, .y = tex_h}; + a_texCoord_vals[2] = (WIIUVec2) {.x = tex_w, .y = 0.0f}; + a_texCoord_vals[3] = (WIIUVec2) {.x = 0.0f, .y = 0.0f}; + GX2RUnlockBufferEx(a_texCoord, 0); + + /* Render the window */ + WHBGfxClearColor(0.0f, 0.0f, 0.0f, 1.0f); + wiiuSetTextureShader(); + + GX2SetVertexUniformReg(wiiuTextureShader.vertexShader->uniformVars[0].offset, 4, (uint32_t *)&u_viewSize); + GX2SetVertexUniformReg(wiiuTextureShader.vertexShader->uniformVars[1].offset, 4, (uint32_t *)&tdata->u_texSize); + GX2SetPixelUniformReg(wiiuTextureShader.pixelShader->uniformVars[0].offset, 4, (uint32_t*)&tdata->u_mod); + + GX2RSetAttributeBuffer(a_position, 0, a_position->elemSize, 0); + GX2RSetAttributeBuffer(a_texCoord, 1, a_texCoord->elemSize, 0); + + GX2SetPixelTexture(&tdata->texture, wiiuTextureShader.pixelShader->samplerVars[0].location); + GX2SetPixelSampler(&tdata->sampler, wiiuTextureShader.pixelShader->samplerVars[0].location); + + GX2SetColorControl(GX2_LOGIC_OP_COPY, 0x00, FALSE, TRUE); + + GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1); +} + +void WIIU_SDL_RenderPresent(SDL_Renderer * renderer) +{ + WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata; + Uint32 flags = SDL_GetWindowFlags(renderer->window); + + if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) { + /* NOTE watch libwhb's source to ensure this call only does vsync */ + WHBGfxBeginRender(); + } + + /* Only render to TV if the window is *not* drc-only */ + if (!(flags & SDL_WINDOW_WIIU_GAMEPAD_ONLY)) { + WHBGfxBeginRenderTV(); + render_scene(renderer); + WHBGfxFinishRenderTV(); + } + + if (!(flags & SDL_WINDOW_WIIU_TV_ONLY)) { + WHBGfxBeginRenderDRC(); + render_scene(renderer); + WHBGfxFinishRenderDRC(); + } + + WHBGfxFinishRender(); + + /* Free the list of render and draw data */ + WIIU_FreeRenderData(data); + WIIU_TextureDoneRendering(data); + + /* Restore SDL context state */ + GX2SetContextState(data->ctx); +} + +#endif /* SDL_VIDEO_RENDER_WIIU */ diff --git a/src/render/wiiu/SDL_rtexture_wiiu.c b/src/render/wiiu/SDL_rtexture_wiiu.c new file mode 100644 index 000000000..7aae30b0d --- /dev/null +++ b/src/render/wiiu/SDL_rtexture_wiiu.c @@ -0,0 +1,229 @@ +/* + Simple DirectMedia Layer + Copyright (C) 2018-2019 Ash Logan + Copyright (C) 2018-2019 Roberto Van Eeden + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_RENDER_WIIU + +#include "../SDL_sysrender.h" +#include "SDL_render_wiiu.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +int WIIU_SDL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) +{ + BOOL res; + WIIUPixFmt gx2_fmt; + GX2RResourceFlags surface_flags; + WIIU_TextureData *tdata = (WIIU_TextureData *) SDL_calloc(1, sizeof(*tdata)); + if (!tdata) { + return SDL_OutOfMemory(); + } + + /* Setup sampler */ + if (texture->scaleMode == SDL_ScaleModeNearest) { + GX2InitSampler(&tdata->sampler, GX2_TEX_CLAMP_MODE_CLAMP, GX2_TEX_XY_FILTER_MODE_POINT); + } else { + GX2InitSampler(&tdata->sampler, GX2_TEX_CLAMP_MODE_CLAMP, GX2_TEX_XY_FILTER_MODE_LINEAR); + } + + + gx2_fmt = SDLFormatToWIIUFormat(texture->format); + + /* Setup GX2Texture */ + tdata->texture.surface.width = texture->w; + tdata->texture.surface.height = texture->h; + tdata->texture.surface.format = gx2_fmt.fmt; + tdata->texture.surface.depth = 1; + tdata->texture.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D; + tdata->texture.surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED; + tdata->texture.surface.mipLevels = 1; + tdata->texture.viewNumMips = 1; + tdata->texture.viewNumSlices = 1; + tdata->texture.compMap = gx2_fmt.compMap; + GX2CalcSurfaceSizeAndAlignment(&tdata->texture.surface); + GX2InitTextureRegs(&tdata->texture); + + /* Setup GX2ColorBuffer */ + tdata->cbuf.surface = tdata->texture.surface; + tdata->cbuf.viewNumSlices = 1; + GX2InitColorBufferRegs(&tdata->cbuf); + + /* Texture's surface flags */ + surface_flags = GX2R_RESOURCE_BIND_TEXTURE | GX2R_RESOURCE_BIND_COLOR_BUFFER | + GX2R_RESOURCE_USAGE_CPU_WRITE | GX2R_RESOURCE_USAGE_CPU_READ | + GX2R_RESOURCE_USAGE_GPU_WRITE | GX2R_RESOURCE_USAGE_GPU_READ; + + /* Allocate normal textures from MEM2 */ + if (texture->driverdata != WIIU_TEXTURE_MEM1_MAGIC) + surface_flags |= GX2R_RESOURCE_USAGE_FORCE_MEM2; + + /* Allocate the texture's surface */ + res = GX2RCreateSurface( + &tdata->texture.surface, + surface_flags + ); + if (!res) { + SDL_free(tdata); + return SDL_OutOfMemory(); + } + + /* Allocate a colour buffer, using the same backing buffer */ + res = GX2RCreateSurfaceUserMemory( + &tdata->cbuf.surface, + tdata->texture.surface.image, + tdata->texture.surface.mipmaps, + tdata->texture.surface.resourceFlags + ); + if (!res) { + GX2RDestroySurfaceEx(&tdata->texture.surface, 0); + SDL_free(tdata); + return SDL_OutOfMemory(); + } + + /* Initialize texture size uniform */ + tdata->u_texSize = (WIIUVec4) { + .x = texture->w, + .y = texture->h, + }; + + /* Initialize color modifier uniform */ + tdata->u_mod = (WIIUVec4) { + .r = (float)texture->r / 255.0f, + .g = (float)texture->g / 255.0f, + .b = (float)texture->b / 255.0f, + .a = (float)texture->a / 255.0f, + }; + + /* Setup texture driver data */ + texture->driverdata = tdata; + + return 0; +} + +/* Somewhat adapted from SDL_render.c: SDL_LockTextureNative + The app basically wants a pointer to a particular rectangle as well as + write access to it. Easy GX2R! */ +int WIIU_SDL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * rect, void **pixels, int *pitch) +{ + WIIU_RenderData *data = (WIIU_RenderData *) renderer->driverdata; + WIIU_TextureData *tdata = (WIIU_TextureData *) texture->driverdata; + Uint32 BytesPerPixel = SDL_BYTESPERPIXEL(texture->format); + void* pixel_buffer; + + /* Wait for the texture rendering to finish */ + WIIU_TextureCheckWaitRendering(data, tdata); + + pixel_buffer = GX2RLockSurfaceEx(&tdata->texture.surface, 0, 0); + + /* Calculate pointer to first pixel in rect */ + *pixels = (void *) ((Uint8 *) pixel_buffer + + rect->y * (tdata->texture.surface.pitch * BytesPerPixel) + + rect->x * BytesPerPixel); + *pitch = (tdata->texture.surface.pitch * BytesPerPixel); + + /* Not sure we even need to bother keeping track of this */ + texture->locked_rect = *rect; + + return 0; +} + +void WIIU_SDL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) +{ + WIIU_TextureData *tdata = (WIIU_TextureData *) texture->driverdata; + GX2RUnlockSurfaceEx(&tdata->texture.surface, 0, 0); +} + +int WIIU_SDL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, + const SDL_Rect * rect, const void *pixels, int pitch) +{ + Uint32 BytesPerPixel = SDL_BYTESPERPIXEL(texture->format); + size_t length = rect->w * BytesPerPixel; + Uint8 *src = (Uint8 *) pixels, *dst; + int row, dst_pitch; + + /* We write the rules, and we say all textures are streaming */ + WIIU_SDL_LockTexture(renderer, texture, rect, (void**)&dst, &dst_pitch); + + for (row = 0; row < rect->h; ++row) { + SDL_memcpy(dst, src, length); + src += pitch; + dst += dst_pitch; + } + + WIIU_SDL_UnlockTexture(renderer, texture); + + return 0; +} + +int WIIU_SDL_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture) +{ + WIIU_TextureData *tdata = (WIIU_TextureData *) texture->driverdata; + + /* Compute color mod */ + tdata->u_mod.r = (float)texture->r / 255.0f; + tdata->u_mod.g = (float)texture->g / 255.0f; + tdata->u_mod.b = (float)texture->b / 255.0f; + + return 0; +} + +int WIIU_SDL_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture) +{ + WIIU_TextureData *tdata = (WIIU_TextureData *) texture->driverdata; + + /* Compute alpha mod */ + tdata->u_mod.a = (float)texture->a / 255.0f; + + return 0; +} + +void WIIU_SDL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) +{ + WIIU_RenderData *data; + WIIU_TextureData *tdata; + + if (texture == NULL || texture->driverdata == NULL) { + return; + } + + data = (WIIU_RenderData *) renderer->driverdata; + tdata = (WIIU_TextureData *) texture->driverdata; + + /* Wait for the texture rendering to finish */ + WIIU_TextureCheckWaitRendering(data, tdata); + + GX2RDestroySurfaceEx(&tdata->cbuf.surface, 0); + GX2RDestroySurfaceEx(&tdata->texture.surface, 0); + + SDL_free(tdata); +} + +#endif //SDL_VIDEO_RENDER_WIIU diff --git a/src/render/wiiu/SDL_rwindow_wiiu.c b/src/render/wiiu/SDL_rwindow_wiiu.c new file mode 100644 index 000000000..fff15be94 --- /dev/null +++ b/src/render/wiiu/SDL_rwindow_wiiu.c @@ -0,0 +1,63 @@ +/* + Simple DirectMedia Layer + Copyright (C) 2018-2019 Ash Logan + Copyright (C) 2018-2019 Roberto Van Eeden + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_VIDEO_RENDER_WIIU + +#include "../SDL_sysrender.h" +#include "SDL_render_wiiu.h" + +void WIIU_SDL_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event) +{ + if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) { + /* Re-init the colour buffer etc. for new window size + TODO check: what if we're rendering to a texture when this happens? + SDL may handle this already, see SDL_render.c: SDL_RendererEventWatch */ + WIIU_SDL_CreateWindowTex(renderer, renderer->window); + WIIU_SDL_SetRenderTarget(renderer, NULL); + } +} + +/* We always output at whatever res the window is. + This may need to change if SDL_wiiuvideo is ever folded into SDL_render - + see SDL_*WindowTexture from SDL_video.c for how this could be done */ +int WIIU_SDL_GetOutputSize(SDL_Renderer * renderer, int *w, int *h) +{ + SDL_GetWindowSize(renderer->window, w, h); + return 0; +} + +/* We handle all viewport changes in the render functions and shaders, so we + don't actually have to do anything here. SDL still requires we implement it. */ +int WIIU_SDL_UpdateViewport(SDL_Renderer * renderer) +{ + return 0; +} + +/* Ideally this should change the GX2SetScissor values, but SetRenderTarget + needs refactoring first or these get overwritten. */ +int WIIU_SDL_UpdateClipRect(SDL_Renderer * renderer) +{ + return 0; +} + +#endif //SDL_VIDEO_RENDER_WIIU diff --git a/src/stdlib/SDL_malloc.c b/src/stdlib/SDL_malloc.c index c1aa44414..8c796fba7 100644 --- a/src/stdlib/SDL_malloc.c +++ b/src/stdlib/SDL_malloc.c @@ -512,6 +512,12 @@ DEFAULT_MMAP_THRESHOLD default: 256K #define LACKS_SYS_MMAN_H #endif /* __OS2__ */ +#ifdef __WIIU__ +#define HAVE_MMAP 0 +#define LACKS_SYS_MMAN_H +#define USE_LOCKS 0 // TODO: use locks +#endif /* __WIIU__ */ + #if defined(DARWIN) || defined(_DARWIN) /* Mac OSX docs advise not to use sbrk; it seems better to use mmap */ #ifndef HAVE_MORECORE diff --git a/src/thread/SDL_thread_c.h b/src/thread/SDL_thread_c.h index 278a68026..754c43718 100644 --- a/src/thread/SDL_thread_c.h +++ b/src/thread/SDL_thread_c.h @@ -46,6 +46,8 @@ #include "os2/SDL_systhread_c.h" #elif SDL_THREAD_NGAGE #include "ngage/SDL_systhread_c.h" +#elif SDL_THREAD_WIIU +#include "wiiu/SDL_systhread_c.h" #else #error Need thread implementation for this platform #include "generic/SDL_systhread_c.h" diff --git a/src/thread/wiiu/SDL_syscond.c b/src/thread/wiiu/SDL_syscond.c new file mode 100644 index 000000000..318a50050 --- /dev/null +++ b/src/thread/wiiu/SDL_syscond.c @@ -0,0 +1,146 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_THREAD_WIIU + +#include "SDL_thread.h" + +#include +#include +#include +#include + +typedef struct +{ + OSCondition *cond; + bool timed_out; +} WIIU_CondWaitTimeoutData; + +/* Create a condition variable */ +SDL_cond * +SDL_CreateCond(void) +{ + OSCondition *cond; + + cond = (OSCondition *) SDL_malloc(sizeof(OSCondition)); + if (cond) { + OSInitCond(cond); + } else { + SDL_OutOfMemory(); + } + return (SDL_cond *)cond; +} + +/* Destroy a condition variable */ +void +SDL_DestroyCond(SDL_cond * cond) +{ + if (cond) { + SDL_free(cond); + } +} + +/* Restart one of the threads that are waiting on the condition variable */ +int +SDL_CondSignal(SDL_cond * cond) +{ + return SDL_CondBroadcast(cond); +} + +/* Restart all threads that are waiting on the condition variable */ +int +SDL_CondBroadcast(SDL_cond * cond) +{ + if (!cond) { + return SDL_SetError("Passed a NULL condition variable"); + } + + OSSignalCond((OSCondition *)cond); + return 0; +} + +/* Wait on the condition variable for at most 'ms' milliseconds. + The mutex must be locked before entering this function! + The mutex is unlocked during the wait, and locked again after the wait. + +Typical use: + +Thread A: + SDL_LockMutex(lock); + while ( ! condition ) { + SDL_CondWait(cond, lock); + } + SDL_UnlockMutex(lock); + +Thread B: + SDL_LockMutex(lock); + ... + condition = true; + ... + SDL_CondSignal(cond); + SDL_UnlockMutex(lock); + */ + +static void +SDL_CondWaitTimeoutCallback(OSAlarm *alarm, OSContext *context) +{ + WIIU_CondWaitTimeoutData *data = (WIIU_CondWaitTimeoutData *)OSGetAlarmUserData(alarm); + data->timed_out = true; + OSSignalCond(data->cond); +} + +int +SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms) +{ + WIIU_CondWaitTimeoutData data; + OSAlarm alarm; + + data.timed_out = false; + data.cond = (OSCondition *)cond; + + // Timeout is zero + if (!ms) + return SDL_MUTEX_TIMEDOUT; + + // Set an alarm + OSCreateAlarm(&alarm); + OSSetAlarmUserData(&alarm, &data); + OSSetAlarm(&alarm, OSMillisecondsToTicks(ms), &SDL_CondWaitTimeoutCallback); + + // Wait on the condition + OSWaitCond((OSCondition *)cond, (OSMutex *)mutex); + + OSCancelAlarm(&alarm); + return data.timed_out ? SDL_MUTEX_TIMEDOUT : 0; +} + +/* Wait on the condition variable forever */ +int +SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex) +{ + OSWaitCond((OSCondition *)cond, (OSMutex *)mutex); + return 0; +} + +#endif /* SDL_THREAD_WIIU */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/thread/wiiu/SDL_sysmutex.c b/src/thread/wiiu/SDL_sysmutex.c new file mode 100644 index 000000000..f0c81699a --- /dev/null +++ b/src/thread/wiiu/SDL_sysmutex.c @@ -0,0 +1,72 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_THREAD_WIIU + +#include +#include +#include "SDL_thread.h" + + +SDL_mutex * +SDL_CreateMutex(void) +{ + OSMutex *mutex; + + /* Allocate the structure */ + mutex = (OSMutex *) SDL_calloc(1, sizeof(OSMutex)); + OSInitMutex(mutex); + return (SDL_mutex *)mutex; +} + +void +SDL_DestroyMutex(SDL_mutex * mutex) +{ + if (mutex) { + SDL_free(mutex); + } +} + +/* Lock the mutex */ +int +SDL_LockMutex(SDL_mutex * mutex) +{ + OSLockMutex((OSMutex *)mutex); + return 0; +} + +int +SDL_TryLockMutex(SDL_mutex * mutex) +{ + return OSTryLockMutex((OSMutex *)mutex) ? 0 : SDL_MUTEX_TIMEDOUT; +} + +int +SDL_UnlockMutex(SDL_mutex * mutex) +{ + OSUnlockMutex((OSMutex *)mutex); + return 0; +} + +#endif /* SDL_THREAD_WIIU */ + +/* vi: set ts=4 sw=4 expandtab: */ \ No newline at end of file diff --git a/src/thread/wiiu/SDL_sysmutex_c.h b/src/thread/wiiu/SDL_sysmutex_c.h new file mode 100644 index 000000000..2979437b5 --- /dev/null +++ b/src/thread/wiiu/SDL_sysmutex_c.h @@ -0,0 +1,22 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/thread/wiiu/SDL_syssem.c b/src/thread/wiiu/SDL_syssem.c new file mode 100644 index 000000000..a0038aa87 --- /dev/null +++ b/src/thread/wiiu/SDL_syssem.c @@ -0,0 +1,145 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_THREAD_WIIU + +#include "SDL_timer.h" +#include "SDL_thread.h" +#include "SDL_systhread_c.h" + +#include +#include +#include +#include +#include + +#include + +typedef struct +{ + OSCondition *cond; + bool timed_out; +} WIIU_SemWaitTimeoutData; + +struct SDL_semaphore +{ + OSMutex mtx; + OSSemaphore sem; + OSCondition cond; +}; + +SDL_sem * +SDL_CreateSemaphore(Uint32 initial_value) +{ + SDL_sem *sem; + + sem = (SDL_sem *) SDL_malloc(sizeof(*sem)); + if (sem) { + OSInitSemaphore(&sem->sem, initial_value); + OSInitMutex(&sem->mtx); + OSInitCond(&sem->cond); + } else { + SDL_OutOfMemory(); + } + + return sem; +} + +void +SDL_DestroySemaphore(SDL_sem * sem) +{ + if (sem) { + SDL_free(sem); + } +} + +int +SDL_SemTryWait(SDL_sem * sem) +{ + return (OSTryWaitSemaphore(&sem->sem) > 0) ? 0 : SDL_MUTEX_TIMEDOUT; +} + +static void +SDL_SemWaitTimeoutCallback(OSAlarm *alarm, OSContext *context) +{ + WIIU_SemWaitTimeoutData *data = (WIIU_SemWaitTimeoutData *)OSGetAlarmUserData(alarm); + data->timed_out = true; + OSSignalCond(data->cond); +} + +int +SDL_SemWaitTimeout(SDL_sem * sem, Uint32 ms) +{ + WIIU_SemWaitTimeoutData data; + OSAlarm alarm; + + // timeout is zero + if (!ms) + SDL_SemTryWait(sem); + + OSLockMutex(&sem->mtx); + + // setup callback data + data.timed_out = false; + data.cond = &sem->cond; + + // set an alarm + OSCreateAlarm(&alarm); + OSSetAlarmUserData(&alarm, &data); + OSSetAlarm(&alarm, OSMillisecondsToTicks(ms), &SDL_SemWaitTimeoutCallback); + + // try to acquire the semaphore + while((OSTryWaitSemaphore(&sem->sem) <= 0) && (data.timed_out == false)) { + OSWaitCond(&sem->cond, &sem->mtx); + } + + OSCancelAlarm(&alarm); + + OSUnlockMutex(&sem->mtx); + + return (data.timed_out == false) ? 0 : SDL_MUTEX_TIMEDOUT; +} + +int +SDL_SemWait(SDL_sem * sem) +{ + OSWaitSemaphore(&sem->sem); + return 0; +} + +Uint32 +SDL_SemValue(SDL_sem * sem) +{ + return OSGetSemaphoreCount(&sem->sem); +} + +int +SDL_SemPost(SDL_sem * sem) +{ + OSSignalSemaphore(&sem->sem); + OSSignalCond(&sem->cond); + return 0; +} + +#endif /* SDL_THREAD_WIIU */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/thread/wiiu/SDL_systhread.c b/src/thread/wiiu/SDL_systhread.c new file mode 100644 index 000000000..364255339 --- /dev/null +++ b/src/thread/wiiu/SDL_systhread.c @@ -0,0 +1,121 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#if SDL_THREAD_WIIU + +/* WiiU thread management routines for SDL */ + +#include +#include + +#include "SDL_error.h" +#include "SDL_thread.h" +#include "../SDL_systhread.h" +#include "../SDL_thread_c.h" +#include +#include + +static void +thread_deallocator(OSThread *thread, void *stack) +{ + free(thread); + free(stack); +} + +static void +thread_cleanup(OSThread *thread, void *stack) +{ +} + +int SDL_SYS_CreateThread(SDL_Thread *thread, void *args) +{ + OSThread *handle = (OSThread *)memalign(16, sizeof(OSThread)); + unsigned int stackSize = thread->stacksize ? thread->stacksize : 0x8000; + void *stackTop = memalign(16, stackSize) + stackSize; + int priority = OSGetThreadPriority(OSGetCurrentThread()); + + if (!OSCreateThread(handle, + (OSThreadEntryPointFn)SDL_RunThread, + (int32_t)args, + NULL, + stackTop, + stackSize, + priority, + OS_THREAD_ATTRIB_AFFINITY_ANY)) + { + return SDL_SetError("OSCreateThread() failed"); + } + + OSSetThreadDeallocator(handle, &thread_deallocator); + OSSetThreadCleanupCallback(handle, &thread_cleanup); + OSResumeThread(handle); + thread->handle = handle; + return 0; +} + +void SDL_SYS_SetupThread(const char *name) +{ + /* Do nothing. */ +} + +SDL_threadID SDL_ThreadID(void) +{ + return (SDL_threadID) OSGetCurrentThread(); +} + +void SDL_SYS_WaitThread(SDL_Thread *thread) +{ + OSJoinThread(thread->handle, NULL); +} + +void SDL_SYS_DetachThread(SDL_Thread *thread) +{ + OSDetachThread(thread->handle); +} + +void SDL_SYS_KillThread(SDL_Thread *thread) +{ + OSCancelThread(thread->handle); +} + +int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority) +{ + int value; + + if (priority == SDL_THREAD_PRIORITY_LOW) { + value = 17; + } else if (priority == SDL_THREAD_PRIORITY_HIGH) { + value = 15; + } else if (priority == SDL_THREAD_PRIORITY_TIME_CRITICAL) { + value = 14; + } else { + value = 16; + } + + return OSSetThreadPriority(OSGetCurrentThread(), value); + +} + +#endif /* SDL_THREAD_WIIU */ + +/* vim: ts=4 sw=4 + */ \ No newline at end of file diff --git a/src/thread/wiiu/SDL_systhread_c.h b/src/thread/wiiu/SDL_systhread_c.h new file mode 100644 index 000000000..ca0626101 --- /dev/null +++ b/src/thread/wiiu/SDL_systhread_c.h @@ -0,0 +1,27 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#include + +typedef OSThread *SYS_ThreadHandle; + +/* vi: set ts=4 sw=4 expandtab: */ \ No newline at end of file diff --git a/src/thread/wiiu/SDL_systls.c b/src/thread/wiiu/SDL_systls.c new file mode 100644 index 000000000..241862e83 --- /dev/null +++ b/src/thread/wiiu/SDL_systls.c @@ -0,0 +1,38 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "../../SDL_internal.h" +#include "../SDL_thread_c.h" + + +SDL_TLSData * +SDL_SYS_GetTLSData(void) +{ + return SDL_Generic_GetTLSData(); +} + +int +SDL_SYS_SetTLSData(SDL_TLSData *data) +{ + return SDL_Generic_SetTLSData(data); +} + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/timer/wiiu/SDL_systimer.c b/src/timer/wiiu/SDL_systimer.c new file mode 100644 index 000000000..6c95e1eff --- /dev/null +++ b/src/timer/wiiu/SDL_systimer.c @@ -0,0 +1,86 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#ifdef SDL_TIMER_WIIU + +#include "SDL_thread.h" +#include "SDL_timer.h" +#include "SDL_error.h" +#include "../SDL_timer_c.h" +#include +#include +#include + +static OSTime start; +static SDL_bool ticks_started = SDL_FALSE; + +void +SDL_TicksInit(void) +{ + if (ticks_started) { + return; + } + ticks_started = SDL_TRUE; + start = OSGetSystemTime(); +} + +void +SDL_TicksQuit(void) +{ + ticks_started = SDL_FALSE; +} + +Uint32 +SDL_GetTicks(void) +{ + OSTime now; + + if (!ticks_started) { + SDL_TicksInit(); + } + + now = OSGetSystemTime(); + return (Uint32)OSTicksToMilliseconds(now - start); +} + +Uint64 +SDL_GetPerformanceCounter(void) +{ + return OSGetTime(); +} + +Uint64 +SDL_GetPerformanceFrequency(void) +{ + return OSTimerClockSpeed; +} + +void +SDL_Delay(Uint32 ms) +{ + OSSleepTicks(OSMillisecondsToTicks(ms)); +} + +#endif /* SDL_TIMER_WIIU */ + +/* vim: ts=4 sw=4 + */ diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index d7a42cc64..0d88ea5e6 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -482,6 +482,7 @@ extern VideoBootStrap OFFSCREEN_bootstrap; extern VideoBootStrap NGAGE_bootstrap; extern VideoBootStrap OS2DIVE_bootstrap; extern VideoBootStrap OS2VMAN_bootstrap; +extern VideoBootStrap WIIU_bootstrap; /* Use SDL_OnVideoThread() sparingly, to avoid regressions in use cases that currently happen to work */ extern SDL_bool SDL_OnVideoThread(void); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 8065a0b8c..a22eb1be0 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -138,6 +138,9 @@ static VideoBootStrap *bootstrap[] = { #if SDL_VIDEO_DRIVER_OFFSCREEN &OFFSCREEN_bootstrap, #endif +#if SDL_VIDEO_DRIVER_WIIU + &WIIU_bootstrap, +#endif #if SDL_VIDEO_DRIVER_DUMMY &DUMMY_bootstrap, #if SDL_INPUT_LINUXEV diff --git a/src/video/wiiu/SDL_wiiuvideo.c b/src/video/wiiu/SDL_wiiuvideo.c new file mode 100644 index 000000000..4efd4e72e --- /dev/null +++ b/src/video/wiiu/SDL_wiiuvideo.c @@ -0,0 +1,147 @@ +/* + Simple DirectMedia Layer + Copyright (C) 2018-2018 Ash Logan + Copyright (C) 2018-2018 rw-r-r-0644 + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/* This is basically just a stub at this point - all the magic happens in + * SDL_Render, and the textureframebuffer stuff in SDL_video.c. + * Potentially more could/should be done here, video modes and things. + * Some design work will need to go into the responsibilities of render + * vs video. + */ + +#include "../../SDL_internal.h" + +#if SDL_VIDEO_DRIVER_WIIU + +/* SDL internals */ +#include "../SDL_sysvideo.h" +#include "SDL_version.h" +#include "SDL_syswm.h" +#include "SDL_loadso.h" +#include "SDL_events.h" +#include "../../events/SDL_mouse_c.h" +#include "../../events/SDL_keyboard_c.h" +#include "SDL_wiiuvideo.h" + +#include +#include +#include +#include + +#include + +#include "wiiu_shaders.h" + +static int WIIU_VideoInit(_THIS); +static int WIIU_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode); +static void WIIU_VideoQuit(_THIS); +static void WIIU_PumpEvents(_THIS); + +static int using_whb_proc = 0; + +#define SCREEN_WIDTH 1280 +#define SCREEN_HEIGHT 720 + +static int WIIU_VideoInit(_THIS) +{ + SDL_DisplayMode mode; + + if (!ProcUIIsRunning()) { + WHBProcInit(); + using_whb_proc = 1; + } + WHBGfxInit(); + + // setup shader + wiiuInitTextureShader(); + + // add default mode (1280x720) + mode.format = SDL_PIXELFORMAT_RGBA8888; + mode.w = SCREEN_WIDTH; + mode.h = SCREEN_HEIGHT; + mode.refresh_rate = 60; + mode.driverdata = NULL; + if (SDL_AddBasicVideoDisplay(&mode) < 0) { + return -1; + } + SDL_AddDisplayMode(&_this->displays[0], &mode); + + return 0; +} + +static void WIIU_VideoQuit(_THIS) +{ + wiiuFreeTextureShader(); + WHBGfxShutdown(); + if (using_whb_proc) WHBProcShutdown(); +} + +static int WIIU_CreateSDLWindow(_THIS, SDL_Window *window) { + SDL_SetKeyboardFocus(window); + return 0; +} + +static int WIIU_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode) +{ + return 0; +} + +static void WIIU_PumpEvents(_THIS) +{ +} + +static int WIIU_Available(void) +{ + return 1; +} + +static void WIIU_DeleteDevice(SDL_VideoDevice *device) +{ + SDL_free(device); +} + +static SDL_VideoDevice *WIIU_CreateDevice(int devindex) +{ + SDL_VideoDevice *device; + + device = (SDL_VideoDevice*) SDL_calloc(1, sizeof(SDL_VideoDevice)); + if(!device) { + SDL_OutOfMemory(); + return NULL; + } + + device->VideoInit = WIIU_VideoInit; + device->VideoQuit = WIIU_VideoQuit; + device->SetDisplayMode = WIIU_SetDisplayMode; + device->PumpEvents = WIIU_PumpEvents; + device->CreateSDLWindow = WIIU_CreateSDLWindow; + + device->free = WIIU_DeleteDevice; + + return device; +} + +VideoBootStrap WIIU_bootstrap = { + "WiiU", "Video driver for Nintendo WiiU", + WIIU_Available, WIIU_CreateDevice +}; + +#endif /* SDL_VIDEO_DRIVER_WIIU */ diff --git a/src/video/wiiu/SDL_wiiuvideo.h b/src/video/wiiu/SDL_wiiuvideo.h new file mode 100644 index 000000000..3cbf3df4c --- /dev/null +++ b/src/video/wiiu/SDL_wiiuvideo.h @@ -0,0 +1,45 @@ +/* + Simple DirectMedia Layer + Copyright (C) 2018-2018 Ash Logan + Copyright (C) 2018-2018 Roberto Van Eeden + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "../../SDL_internal.h" + +#ifndef SDL_wiiuvideo_h +#define SDL_wiiuvideo_h + +#include +#include "SDL_surface.h" + +#define WIIU_WINDOW_DATA "_SDL_WiiUData" +typedef struct +{ + SDL_Surface *surface; + GX2Texture texture; +} WIIU_WindowData; + +typedef struct +{ + SDL_bool tv_window_exists; + SDL_bool drc_window_exists; + SDL_bool mirrored_window_exists; +} WIIU_VideoDeviceData; + +#endif //SDL_wiiuvideo_h diff --git a/src/video/wiiu/shaders/build_shaders.sh b/src/video/wiiu/shaders/build_shaders.sh new file mode 100755 index 000000000..490f82fb9 --- /dev/null +++ b/src/video/wiiu/shaders/build_shaders.sh @@ -0,0 +1,14 @@ +#!/bin/bash +cd "${0%/*}" +echo "Regenerating wiiu_shaders.c ..." +latte-assembler compile colorShader.gsh --vsh colorShader.vsh --psh colorShader.psh +latte-assembler compile textureShader.gsh --vsh textureShader.vsh --psh textureShader.psh +xxd -i colorShader.gsh > colorShader.gsh.h +xxd -i textureShader.gsh > textureShader.gsh.h +sed -i '/_gsh_len/d' colorShader.gsh.h textureShader.gsh.h +sed -i 's/colorShader_gsh/wiiuColorShaderData/g' colorShader.gsh.h +sed -i 's/textureShader_gsh/wiiuTextureShaderData/g' textureShader.gsh.h +cp wiiu_shaders.c.in ../wiiu_shaders.c +cat colorShader.gsh.h textureShader.gsh.h >> ../wiiu_shaders.c +rm -rf colorShader.gsh textureShader.gsh colorShader.gsh.h textureShader.gsh.h +echo "Done!" diff --git a/src/video/wiiu/shaders/colorShader.frag b/src/video/wiiu/shaders/colorShader.frag new file mode 100644 index 000000000..651c31e11 --- /dev/null +++ b/src/video/wiiu/shaders/colorShader.frag @@ -0,0 +1,10 @@ +/* colorShader: fragment (pixel) shader (GLSL) */ +/* compile with ShaderAnalyzer (rv770) + fix latte-assembler messages */ + +layout(location = 0) uniform vec4 u_color; /* color */ + +void main() +{ + /* Set fragment color */ + gl_FragColor = u_color; +} diff --git a/src/video/wiiu/shaders/colorShader.psh b/src/video/wiiu/shaders/colorShader.psh new file mode 100644 index 000000000..5f821dc95 --- /dev/null +++ b/src/video/wiiu/shaders/colorShader.psh @@ -0,0 +1,14 @@ +; $MODE = "UniformRegister" +; $UNIFORM_VARS[0].name = "u_color" +; $UNIFORM_VARS[0].type = "float4" +; $UNIFORM_VARS[0].count = 1 +; $UNIFORM_VARS[0].offset = 0 +; $UNIFORM_VARS[0].block = -1 + +00 ALU: ADDR(32) CNT(4) + 0 x: MOV R0.x, C0.x + y: MOV R0.y, C0.y + z: MOV R0.z, C0.z + w: MOV R0.w, C0.w +01 EXP_DONE: PIX0, R0 +END_OF_PROGRAM diff --git a/src/video/wiiu/shaders/colorShader.vert b/src/video/wiiu/shaders/colorShader.vert new file mode 100644 index 000000000..62dbe66c3 --- /dev/null +++ b/src/video/wiiu/shaders/colorShader.vert @@ -0,0 +1,16 @@ +/* colorShader: vertex shader (GLSL) */ +/* compile with ShaderAnalyzer (rv770) + fix latte-assembler messages */ + +layout(location = 0) uniform vec2 u_viewSize; /* viewport size */ +layout(location = 0) in vec2 a_position; /* vertex position */ + +void main() +{ + /* Compute relative vertex position */ + a_position.y = u_viewSize.y - a_position.y; + a_position.x = ((a_position.x / u_viewSize.x) * 2.0f) - 1.0f; + a_position.y = ((a_position.y / u_viewSize.y) * 2.0f) - 1.0f; + + /* Set vertex position */ + gl_Position = vec4(a_position, 0.0, 1.0); +} diff --git a/src/video/wiiu/shaders/colorShader.vsh b/src/video/wiiu/shaders/colorShader.vsh new file mode 100644 index 000000000..d8239b94e --- /dev/null +++ b/src/video/wiiu/shaders/colorShader.vsh @@ -0,0 +1,27 @@ +; $MODE = "UniformRegister" +; $UNIFORM_VARS[0].name = "u_viewSize" +; $UNIFORM_VARS[0].type = "float2" +; $UNIFORM_VARS[0].count = 1 +; $UNIFORM_VARS[0].offset = 0 +; $UNIFORM_VARS[0].block = -1 +; $ATTRIB_VARS[0].name = "a_position" +; $ATTRIB_VARS[0].type = "float2" +; $ATTRIB_VARS[0].location = 0 + +00 CALL_FS NO_BARRIER +01 ALU: ADDR(32) CNT(9) + 0 x: ADD R0.x, -R1.y, C0.y + z: MOV R2.z, 0.0f + w: MOV R2.w, (0x3F800000, 1.0f).x + t: RCP_e ____, C0.x + 1 z: MUL_e*2 ____, R1.x, PS0 + t: RCP_e ____, C0.y + 2 x: MUL_e*2 ____, R0.x, PS1 + t: ADD R2.x, PV1.z, -1.0f + 3 y: ADD R2.y, PV2.x, -1.0f +02 EXP_DONE: POS0, R2 +03 EXP_DONE: PARAM0, R0.____ +04 ALU: ADDR(41) CNT(1) + 4 x: NOP ____ +05 NOP NO_BARRIER +END_OF_PROGRAM diff --git a/src/video/wiiu/shaders/textureShader.frag b/src/video/wiiu/shaders/textureShader.frag new file mode 100644 index 000000000..502f7aafa --- /dev/null +++ b/src/video/wiiu/shaders/textureShader.frag @@ -0,0 +1,13 @@ +/* textureShader: fragment (pixel) shader (GLSL) */ +/* compile with ShaderAnalyzer (rv770) + fix latte-assembler messages */ +/* NOTE: Ash knows R600 but not GLSL, so the .psh may have changes not in this + file. */ + +layout(location = 0) uniform sampler2D s_texture; /* texture sampler */ +in vec2 texCoord; /* relative texture postion passed from vertex shader */ + +void main() +{ + /* Compute fragment color for texture/position */ + gl_FragColor = texture2D(s_texture, texCoord); +} diff --git a/src/video/wiiu/shaders/textureShader.psh b/src/video/wiiu/shaders/textureShader.psh new file mode 100644 index 000000000..faca2f53e --- /dev/null +++ b/src/video/wiiu/shaders/textureShader.psh @@ -0,0 +1,22 @@ +; $MODE = "UniformRegister" +; $SAMPLER_VARS[0].name= "s_texture" +; $SAMPLER_VARS[0].type= "sampler2D" +; $SAMPLER_VARS[0].location = 0 +; $NUM_SPI_PS_INPUT_CNTL = 1 +; $SPI_PS_INPUT_CNTL[0].semantic = 0 +; $SPI_PS_INPUT_CNTL[0].default_val = 1 +; $UNIFORM_VARS[0].name = "u_mod" +; $UNIFORM_VARS[0].type = "float4" +; $UNIFORM_VARS[0].count = 1 +; $UNIFORM_VARS[0].offset = 0 +; $UNIFORM_VARS[0].block = -1 + +00 TEX: ADDR(48) CNT(1) VALID_PIX + 0 SAMPLE R0, R0.xy0x, t0, s0 +01 ALU: ADDR(32) CNT(4) + 1 x: MUL R0.x, R0.x, C0.x + y: MUL R0.y, R0.y, C0.y + z: MUL R0.z, R0.z, C0.z + w: MUL R0.w, R0.w, C0.w +02 EXP_DONE: PIX0, R0 +END_OF_PROGRAM diff --git a/src/video/wiiu/shaders/textureShader.vert b/src/video/wiiu/shaders/textureShader.vert new file mode 100644 index 000000000..d559ca533 --- /dev/null +++ b/src/video/wiiu/shaders/textureShader.vert @@ -0,0 +1,27 @@ +/* textureShader: vertex shader (GLSL) */ +/* compile with ShaderAnalyzer (rv770) + fix latte-assembler messages */ + +layout(location = 0) uniform vec2 u_viewSize; /* viewport size */ +layout(location = 1) uniform vec2 u_texSize; /* texture size */ +layout(location = 0) in vec2 a_position; /* vertex position */ +layout(location = 1) in vec2 a_texCoordIn; /* texture position */ +out vec2 texCoord; /* relative texture postion passed to pixel shader */ + +void main() +{ + /* Compute relative vertex position */ + a_position.y = u_viewSize.y - a_position.y; + a_position.x = ((a_position.x / u_viewSize.x) * 2.0f) - 1.0f; + a_position.y = ((a_position.y / u_viewSize.y) * 2.0f) - 1.0f; + + /* Set vertex position */ + gl_Position = vec4(a_position, 0.0, 1.0); + + /* Compute relative coordinate position */ + a_texCoordIn.y = u_texSize.y - a_texCoordIn.y; + a_texCoordIn.x = a_texCoordIn.x / u_texSize.x; + a_texCoordIn.y = a_texCoordIn.y / u_texSize.y; + + /* Pass texture coordinate to pixel shader */ + texCoord = a_texCoordIn; +} diff --git a/src/video/wiiu/shaders/textureShader.vsh b/src/video/wiiu/shaders/textureShader.vsh new file mode 100644 index 000000000..84f047e3e --- /dev/null +++ b/src/video/wiiu/shaders/textureShader.vsh @@ -0,0 +1,44 @@ +; $MODE = "UniformRegister" +; $UNIFORM_VARS[0].name = "u_viewSize" +; $UNIFORM_VARS[0].type = "float2" +; $UNIFORM_VARS[0].count = 1 +; $UNIFORM_VARS[0].offset = 4 +; $UNIFORM_VARS[0].block = -1 +; $UNIFORM_VARS[1].name = "u_texSize" +; $UNIFORM_VARS[1].type = "float2" +; $UNIFORM_VARS[1].count = 1 +; $UNIFORM_VARS[1].offset = 0 +; $UNIFORM_VARS[1].block = -1 +; $ATTRIB_VARS[0].name = "a_position" +; $ATTRIB_VARS[0].type = "float2" +; $ATTRIB_VARS[0].location = 0 +; $ATTRIB_VARS[1].name = "a_texCoordIn" +; $ATTRIB_VARS[1].type = "float2" +; $ATTRIB_VARS[1].location = 1 +; $NUM_SPI_VS_OUT_ID = 1 +; $SPI_VS_OUT_ID[0].semantic_0 = 0 + +00 CALL_FS NO_BARRIER +01 ALU: ADDR(32) CNT(16) + 0 x: ADD R127.x, -R2.y, C0.y + z: MOV R0.z, 0.0f + w: ADD R127.w, -R1.y, C1.y VEC_120 + t: RCP_e ____, C1.x + 1 y: MUL_e*2 ____, R1.x, PS0 + w: MOV R0.w, (0x3F800000, 1.0f).x + t: RCP_e ____, C1.y + 2 x: MUL_e*2 ____, R127.w, PS1 + t: ADD R0.x, PV1.y, -1.0f + 3 y: ADD R0.y, PV2.x, -1.0f + t: RCP_e ____, C0.x + 4 x: MUL_e ____, R2.x, PS3 + t: RCP_e ____, C0.y + 5 x: MOV R2.x, PV4.x + z: MUL_e ____, R127.x, PS4 + 6 y: MOV R2.y, PV5.z +02 EXP_DONE: POS0, R0 +03 EXP_DONE: PARAM0, R2.xyzz NO_BARRIER +04 ALU: ADDR(48) CNT(1) + 7 x: NOP ____ +05 NOP NO_BARRIER +END_OF_PROGRAM diff --git a/src/video/wiiu/shaders/wiiu_shaders.c.in b/src/video/wiiu/shaders/wiiu_shaders.c.in new file mode 100644 index 000000000..de2901e32 --- /dev/null +++ b/src/video/wiiu/shaders/wiiu_shaders.c.in @@ -0,0 +1,8 @@ +#include + +WHBGfxShaderGroup wiiuTextureShader; +int wiiuTextureShaderInit = 0; + +WHBGfxShaderGroup wiiuColorShader; +int wiiuColorShaderInit = 0; + diff --git a/src/video/wiiu/wiiu_shaders.c b/src/video/wiiu/wiiu_shaders.c new file mode 100644 index 000000000..341cb01f2 --- /dev/null +++ b/src/video/wiiu/wiiu_shaders.c @@ -0,0 +1,293 @@ +#include + +WHBGfxShaderGroup wiiuTextureShader; +int wiiuTextureShaderInit = 0; + +WHBGfxShaderGroup wiiuColorShader; +int wiiuColorShaderInit = 0; + +unsigned char wiiuColorShaderData[] = { + 0x47, 0x66, 0x78, 0x32, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x4c, 0x4b, 0x7b, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0xa8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x50, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd0, 0x60, 0x01, 0x34, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xd0, 0x60, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xca, 0x70, 0x01, 0x58, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0x70, 0x01, 0x64, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x75, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x53, 0x69, 0x7a, 0x65, 0x00, 0x00, + 0x61, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, + 0xd0, 0x60, 0x00, 0xe8, 0xd0, 0x60, 0x01, 0x08, 0xca, 0x70, 0x01, 0x34, + 0xca, 0x70, 0x01, 0x48, 0x7d, 0x42, 0x4c, 0x4b, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x70, 0xd0, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x18, 0xd0, 0x60, 0x01, 0x58, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0xd0, 0x60, 0x01, 0x70, 0x42, 0x4c, 0x4b, 0x7b, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x09, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xa0, 0x3c, 0x20, 0x01, 0x00, + 0x88, 0x06, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x94, + 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x14, 0xa0, 0x00, + 0x10, 0x00, 0x00, 0x00, 0xf8, 0x08, 0x00, 0x00, 0x90, 0x0c, 0x40, 0x40, + 0xf9, 0x00, 0x00, 0x00, 0x90, 0x0c, 0x40, 0x60, 0x00, 0x01, 0x00, 0x80, + 0x00, 0x33, 0x00, 0x00, 0x01, 0xe0, 0x1f, 0x01, 0x20, 0x01, 0x00, 0x40, + 0x00, 0x05, 0x00, 0x80, 0x00, 0x33, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, + 0x20, 0x01, 0x00, 0x00, 0xfe, 0x28, 0x1f, 0x82, 0x10, 0x00, 0x40, 0x00, + 0xfe, 0x20, 0x9f, 0x82, 0x10, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x0d, 0x00, 0x00, 0x42, 0x4c, 0x4b, 0x7b, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x01, 0x34, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd0, 0x60, 0x00, 0xe8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xca, 0x70, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x0b, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x75, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0xd0, 0x60, 0x00, 0xbc, + 0xca, 0x70, 0x00, 0xe8, 0x7d, 0x42, 0x4c, 0x4b, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0xd0, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0xd0, 0x60, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0xd0, 0x60, 0x01, 0x04, 0x42, 0x4c, 0x4b, 0x7b, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xa0, + 0x00, 0x00, 0x00, 0x00, 0x88, 0x06, 0x20, 0x94, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x90, 0x0c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x90, 0x0c, 0x00, 0x20, + 0x00, 0x09, 0x00, 0x00, 0x90, 0x0c, 0x00, 0x40, 0x00, 0x0d, 0x00, 0x80, + 0x90, 0x0c, 0x00, 0x60, 0x42, 0x4c, 0x4b, 0x7b, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00 +}; +unsigned char wiiuTextureShaderData[] = { + 0x47, 0x66, 0x78, 0x32, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x4c, 0x4b, 0x7b, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x01, 0x88, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xd0, 0x60, 0x01, 0x34, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0xd0, 0x60, 0x01, 0x5c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xca, 0x70, 0x01, 0x7c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xca, 0x70, 0x01, 0x88, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xca, 0x70, 0x01, 0x94, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0x70, 0x01, 0xa0, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x75, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x53, 0x69, 0x7a, 0x65, 0x00, 0x00, + 0x75, 0x5f, 0x74, 0x65, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x00, 0x00, 0x00, + 0x61, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, + 0x61, 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x49, 0x6e, + 0x00, 0x00, 0x00, 0x00, 0xd0, 0x60, 0x00, 0xe8, 0xd0, 0x60, 0x01, 0x08, + 0xca, 0x70, 0x01, 0x34, 0xca, 0x70, 0x01, 0x48, 0xca, 0x70, 0x01, 0x5c, + 0xca, 0x70, 0x01, 0x6c, 0x7d, 0x42, 0x4c, 0x4b, 0x00, 0x00, 0x00, 0x28, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xb0, 0xd0, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x34, 0xd0, 0x60, 0x01, 0x7c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x06, 0xd0, 0x60, 0x01, 0xb0, 0x42, 0x4c, 0x4b, 0x7b, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x01, 0x88, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x09, + 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xa0, 0x3c, 0x20, 0x00, 0x00, + 0x88, 0x06, 0x00, 0x94, 0x00, 0x40, 0x01, 0x00, 0x88, 0x04, 0x00, 0x14, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0xa0, 0x00, + 0x10, 0x00, 0xe0, 0x0f, 0xf8, 0x08, 0x00, 0x00, 0x90, 0x0c, 0x00, 0x40, + 0x01, 0x34, 0xa0, 0x00, 0x10, 0x00, 0xe8, 0x6f, 0x01, 0x01, 0x00, 0x80, + 0x00, 0x33, 0x00, 0x00, 0x01, 0xe0, 0x9f, 0x00, 0x20, 0x01, 0x00, 0x20, + 0xf9, 0x00, 0x00, 0x00, 0x90, 0x0c, 0x00, 0x60, 0x01, 0x05, 0x00, 0x80, + 0x00, 0x33, 0x00, 0x00, 0x7f, 0xec, 0x1f, 0x00, 0x20, 0x01, 0x00, 0x00, + 0xfe, 0x24, 0x1f, 0x82, 0x10, 0x00, 0x00, 0x00, 0xfe, 0x20, 0x9f, 0x02, + 0x10, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x80, 0x00, 0x33, 0x00, 0x00, + 0x02, 0xe0, 0x1f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x80, + 0x00, 0x33, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x90, 0x0c, 0x40, 0x00, + 0x7f, 0xe0, 0x1f, 0x81, 0x00, 0x01, 0x00, 0x40, 0xfe, 0x08, 0x00, 0x80, + 0x90, 0x0c, 0x40, 0x20, 0x00, 0x00, 0x00, 0x80, 0x00, 0x0d, 0x00, 0x00, + 0x42, 0x4c, 0x4b, 0x7b, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x01, 0x54, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x90, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xd0, 0x60, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xd0, 0x60, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xca, 0x70, 0x01, 0x08, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xca, 0x70, 0x01, 0x10, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x75, 0x5f, 0x6d, 0x6f, + 0x64, 0x00, 0x00, 0x00, 0x73, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, + 0x65, 0x00, 0x00, 0x00, 0xd0, 0x60, 0x00, 0xbc, 0xd0, 0x60, 0x00, 0xd4, + 0xca, 0x70, 0x00, 0xe8, 0xca, 0x70, 0x00, 0xfc, 0x7d, 0x42, 0x4c, 0x4b, + 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, + 0xd0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xd0, 0x60, 0x01, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xd0, 0x60, 0x01, 0x1c, + 0x42, 0x4c, 0x4b, 0x7b, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x90, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc0, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xa0, + 0x00, 0x00, 0x00, 0x00, 0x88, 0x06, 0x20, 0x94, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x04, 0xa0, 0x00, + 0x90, 0x00, 0x00, 0x20, 0x00, 0x08, 0x20, 0x01, 0x90, 0x00, 0x00, 0x40, + 0x00, 0x0c, 0xa0, 0x81, 0x90, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x0d, 0xf0, 0x00, 0x00, 0x80, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x42, 0x4c, 0x4b, 0x7b, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00 +}; diff --git a/src/video/wiiu/wiiu_shaders.h b/src/video/wiiu/wiiu_shaders.h new file mode 100644 index 000000000..0f9b98ca9 --- /dev/null +++ b/src/video/wiiu/wiiu_shaders.h @@ -0,0 +1,83 @@ +/* + Simple DirectMedia Layer + Copyright (C) 2018-2018 Ash Logan + Copyright (C) 2018-2018 Roberto Van Eeden + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "../../SDL_internal.h" + +#ifndef _WIIU_shaders_h +#define _WIIU_shaders_h + +#include +#include + +extern unsigned char wiiuTextureShaderData[]; +extern unsigned char wiiuColorShaderData[]; + +extern WHBGfxShaderGroup wiiuTextureShader; +extern int wiiuTextureShaderInit; + +static inline void wiiuInitTextureShader() { + if (!wiiuTextureShaderInit) { + WHBGfxLoadGFDShaderGroup(&wiiuTextureShader, 0, wiiuTextureShaderData); + WHBGfxInitShaderAttribute(&wiiuTextureShader, "a_position", 0, 0, GX2_ATTRIB_FORMAT_FLOAT_32_32); + WHBGfxInitShaderAttribute(&wiiuTextureShader, "a_texCoordIn", 1, 0, GX2_ATTRIB_FORMAT_FLOAT_32_32); + WHBGfxInitFetchShader(&wiiuTextureShader); + } + wiiuTextureShaderInit++; +} + +static inline void wiiuFreeTextureShader() { + if (wiiuTextureShaderInit) + if (!--wiiuTextureShaderInit) + WHBGfxFreeShaderGroup(&wiiuTextureShader); +} + +static inline void wiiuSetTextureShader() { + GX2SetFetchShader(&wiiuTextureShader.fetchShader); + GX2SetVertexShader(wiiuTextureShader.vertexShader); + GX2SetPixelShader(wiiuTextureShader.pixelShader); +} + +extern WHBGfxShaderGroup wiiuColorShader; +extern int wiiuColorShaderInit; + +static inline void wiiuInitColorShader() { + if (!wiiuColorShaderInit) { + WHBGfxLoadGFDShaderGroup(&wiiuColorShader, 0, wiiuColorShaderData); + WHBGfxInitShaderAttribute(&wiiuColorShader, "a_position", 0, 0, GX2_ATTRIB_FORMAT_FLOAT_32_32); + WHBGfxInitFetchShader(&wiiuColorShader); + } + wiiuColorShaderInit++; +} + +static inline void wiiuFreeColorShader() { + if (wiiuColorShaderInit) + if (!--wiiuColorShaderInit) + WHBGfxFreeShaderGroup(&wiiuColorShader); +} + +static inline void wiiuSetColorShader() { + GX2SetFetchShader(&wiiuColorShader.fetchShader); + GX2SetVertexShader(wiiuColorShader.vertexShader); + GX2SetPixelShader(wiiuColorShader.pixelShader); +} + +#endif //_WIIU_shaders_h