diff --git a/Makefile.wiiu b/Makefile.wiiu new file mode 100644 index 000000000..47f77bf26 --- /dev/null +++ b/Makefile.wiiu @@ -0,0 +1,83 @@ +#--------------------------------------------------------------------------------- +# Setup compile environment +#--------------------------------------------------------------------------------- +$(call assert,$(call seq,$(strip $(DEVKITPPC)),),Please set DEVKITPPC in your environment.) +$(call assert,$(call seq,$(strip $(WUT_ROOT)),),Please set WUT_ROOT in your environment.) +export PORTLIBS := $(DEVKITPRO)/portlibs/ppc +export PATH := $(WUT_ROOT)/bin:$(DEVKITPPC)/bin:$(PORTLIBS)/bin:$(PATH) +AS = powerpc-eabi-as +CC = powerpc-eabi-gcc +CXX = powerpc-eabi-g++ +AR = powerpc-eabi-ar + + +#--------------------------------------------------------------------------------- +# Build options +#--------------------------------------------------------------------------------- +TARGET = libSDL2.a +SOURCES = \ + src/*.c \ + src/atomic/*.c \ + src/audio/*.c \ + src/audio/dummy/*.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/software/*.c \ + src/stdlib/*.c \ + src/thread/*.c \ + src/thread/wiiu/*.c \ + src/thread/generic/*.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 -I$(WUT_ROOT)/include -I$(PORTLIBS)/include + + +#--------------------------------------------------------------------------------- +# Compile flags +#--------------------------------------------------------------------------------- +CFLAGS := -O3 -D__WIIU__ -D__WUT__ -mcpu=750 -meabi -mhard-float $(INCLUDE) +CXXFLAGS := $(CFLAGS) +ASFLAGS := -g + + +#--------------------------------------------------------------------------------- +# Build rules +#--------------------------------------------------------------------------------- +.PHONY: clean install +$(TARGET): $(OBJECTS) + rm -f $@ + $(AR) rcs $@ $^ +%.o: %.cpp + $(CXX) $(CXXFLAGS) -c $< -o $@ +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ +%.o: %.m + $(CC) $(OBJCFLAGS) -c $< -o $@ +%.o: %.s + $(CC) -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ +%.o: %.S + $(CC) -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ +install: $(TARGET) + mkdir -p $(PORTLIBS)/lib + mkdir -p $(PORTLIBS)/include/SDL2 + cp $(TARGET) $(PORTLIBS)/lib/ + cp -f ./include/*.h $(PORTLIBS)/include/SDL2/ +clean: + rm -rf $(OBJECTS) $(TARGET) \ No newline at end of file diff --git a/include/SDL_config.h b/include/SDL_config.h index 7d62d3e2e..827788b85 100644 --- a/include/SDL_config.h +++ b/include/SDL_config.h @@ -43,6 +43,8 @@ #include "SDL_config_psp.h" #elif defined(__OS2__) #include "SDL_config_os2.h" +#elif defined(__WIIU__) +#include "SDL_config_wiiu.h" #else /* This is a minimal configuration just to get SDL running on new platforms. */ #include "SDL_config_minimal.h" diff --git a/include/SDL_config_wiiu.h b/include/SDL_config_wiiu.h new file mode 100644 index 000000000..ed75c979f --- /dev/null +++ b/include/SDL_config_wiiu.h @@ -0,0 +1,157 @@ +/* + 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_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 + +/* 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 stub audio driver (src/audio/dummy/\*.c) */ +#define SDL_AUDIO_DRIVER_DUMMY 1 + +/* Wii U video dirver */ +#define SDL_VIDEO_DRIVER_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 + + +#endif /* SDL_config_wiiu_h_ */ diff --git a/include/SDL_platform.h b/include/SDL_platform.h index c2cbc6b4e..724dba4de 100644 --- a/include/SDL_platform.h +++ b/include/SDL_platform.h @@ -158,6 +158,10 @@ #undef __PSP__ #define __PSP__ 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 c34d0d103..3be1663b3 100644 --- a/include/SDL_test_common.h +++ b/include/SDL_test_common.h @@ -37,6 +37,9 @@ #if defined(__PSP__) #define DEFAULT_WINDOW_WIDTH 480 #define DEFAULT_WINDOW_HEIGHT 272 +#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 6e8017810..349c5faf9 100644 --- a/src/SDL.c +++ b/src/SDL.c @@ -474,6 +474,8 @@ SDL_GetPlatform() return "iOS"; #elif __PSP__ return "PlayStation Portable"; +#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 121deb2f8..828671b3e 100644 --- a/src/SDL_log.c +++ b/src/SDL_log.c @@ -37,6 +37,10 @@ #include #endif +#if defined(__WIIU__) +#include +#endif + #define DEFAULT_PRIORITY SDL_LOG_PRIORITY_CRITICAL #define DEFAULT_ASSERT_PRIORITY SDL_LOG_PRIORITY_WARN #define DEFAULT_APPLICATION_PRIORITY SDL_LOG_PRIORITY_INFO @@ -327,7 +331,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority, #if !defined(HAVE_STDIO_H) && !defined(__WINRT__) BOOL attachResult; DWORD attachError; - unsigned long charsWritten; + unsigned long charsWritten; DWORD consoleMode; /* Maybe attach console and get stderr handle */ @@ -342,7 +346,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority, } else if (attachError == ERROR_GEN_FAILURE) { OutputDebugString(TEXT("Could not attach to console of parent process\r\n")); consoleAttached = -1; - } else if (attachError == ERROR_ACCESS_DENIED) { + } else if (attachError == ERROR_ACCESS_DENIED) { /* Already attached */ consoleAttached = 1; } else { @@ -369,10 +373,10 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority, output = SDL_small_alloc(char, length, &isstack); SDL_snprintf(output, length, "%s: %s\r\n", SDL_priority_prefixes[priority], message); tstr = WIN_UTF8ToString(output); - + /* Output to debugger */ OutputDebugString(tstr); - + #if !defined(HAVE_STDIO_H) && !defined(__WINRT__) /* Screen output to stderr, if console was attached. */ if (consoleAttached == 1) { @@ -415,6 +419,10 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority, return; } } +#elif defined(__WIIU__) + { + OSReport("SDL: %s: %s\n", SDL_priority_prefixes[priority], message); + } #elif defined(__PSP__) { FILE* pFile; diff --git a/src/atomic/SDL_spinlock.c b/src/atomic/SDL_spinlock.c index f39a2e01b..c6e1e61da 100644 --- a/src/atomic/SDL_spinlock.c +++ b/src/atomic/SDL_spinlock.c @@ -32,6 +32,10 @@ #include #endif +#if defined(__WIIU__) +#include +#endif + #if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)) #include #endif @@ -114,6 +118,10 @@ SDL_AtomicTryLock(SDL_SpinLock *lock) /* Used for Solaris with non-gcc compilers. */ return (SDL_bool) ((int) atomic_cas_32((volatile uint32_t*)lock, 0, 1) == 0); +#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/dynapi/SDL_dynapi.h b/src/dynapi/SDL_dynapi.h index 0d2cf713c..a11b97162 100644 --- a/src/dynapi/SDL_dynapi.h +++ b/src/dynapi/SDL_dynapi.h @@ -53,6 +53,8 @@ #define SDL_DYNAMIC_API 0 #elif defined(__PSP__) && __PSP__ #define SDL_DYNAMIC_API 0 +#elif defined(__WIIU__) && __WIIU__ +#define SDL_DYNAMIC_API 0 #elif defined(__clang_analyzer__) #define SDL_DYNAMIC_API 0 /* Turn off for static analysis, so reports are more clear. */ #endif diff --git a/src/joystick/wiiu/SDL_sysjoystick.c b/src/joystick/wiiu/SDL_sysjoystick.c new file mode 100644 index 000000000..0d2db2a03 --- /dev/null +++ b/src/joystick/wiiu/SDL_sysjoystick.c @@ -0,0 +1,166 @@ +/* + 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_JOYSTICK_WIIU + +#include +#include + +#include "../SDL_sysjoystick.h" +#include "../SDL_joystick_c.h" + +#include "SDL_assert.h" +#include "SDL_events.h" + +static VPADButtons 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 +}; + +/* Function to scan the system for joysticks. + * Joystick 0 should be the system default joystick. + * This function should return the number of available joysticks, or -1 + * on an unrecoverable fatal error. + */ +int SDL_SYS_JoystickInit(void) { + return 1; +} + +/* Function to return the number of joystick devices plugged in right now */ +int SDL_SYS_NumJoysticks(void) { + return 1; +} + +/* Function to cause any queued joystick insertions to be processed */ +void SDL_SYS_JoystickDetect(void) { } + +/* Function to get the device-dependent name of a joystick */ +const char *SDL_SYS_JoystickNameForDeviceIndex(int device_index) { + return "Nintendo Wii U Gamepad"; +} + +/* Function to get the current instance id of the joystick located at device_index */ +SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index) { + return 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. + */ +int SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index) { + joystick->nbuttons = sizeof(button_map) / sizeof(VPADButtons); + joystick->naxes = 4; + joystick->nhats = 0; + return 0; +} + +/* Function to query if the joystick is currently attached + * It returns SDL_TRUE if attached, SDL_FALSE otherwise. + */ +SDL_bool SDL_SYS_JoystickAttached(SDL_Joystick * joystick) { + return SDL_TRUE; +} + + +/* 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. + */ +void SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) { + 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; + VPADRead(0, &vpad, 1, &error); + + int16_t x1 = (int16_t) ((vpad.leftStick.x) * 0x7ff0); + int16_t y1 = (int16_t) ((vpad.leftStick.y) * 0x7ff0); + int16_t x2 = (int16_t) ((vpad.rightStick.x) * 0x7ff0); + int16_t 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; + } + + int i; + for(i = 0; i < joystick->nbuttons; i++) { + SDL_PrivateJoystickButton( + joystick, i, + (vpad.hold & button_map[i]) ? + SDL_PRESSED : SDL_RELEASED + ); + } +} + +/* Function to return the stable GUID for a plugged in device */ +SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index ) { + SDL_JoystickGUID guid; + /* the GUID is just the first 16 chars of the name for now */ + const char *name = SDL_SYS_JoystickNameForDeviceIndex( device_index ); + SDL_zero( guid ); + SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) ); + return guid; +} + +/* Function to return the stable GUID for a plugged in device */ +SDL_JoystickGUID SDL_SYS_JoystickGetGUID(SDL_Joystick * joystick) { + SDL_JoystickGUID guid; + /* the GUID is just the first 16 chars of the name for now */ + const char *name = joystick->name; + SDL_zero( guid ); + SDL_memcpy( &guid, name, SDL_min( sizeof(guid), SDL_strlen( name ) ) ); + return guid; +} + +/* Function to close a joystick after use */ +void SDL_SYS_JoystickClose(SDL_Joystick * joystick) { } + +/* Function to perform any system-specific joystick related cleanup */ +void SDL_SYS_JoystickQuit(void) { } + +#endif diff --git a/src/libm/math_private.h b/src/libm/math_private.h index d0ef66a6d..cb52b3e3b 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) -#ifndef __HAIKU__ /* already defined in a system header. */ +#if !defined(__HAIKU__) && !defined(__WIIU__) /* already defined in a system header. */ typedef unsigned int u_int32_t; #endif diff --git a/src/stdlib/SDL_malloc.c b/src/stdlib/SDL_malloc.c index 915ca6a19..da94c839f 100644 --- a/src/stdlib/SDL_malloc.c +++ b/src/stdlib/SDL_malloc.c @@ -510,6 +510,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 7aa89f126..608d07e95 100644 --- a/src/thread/SDL_thread_c.h +++ b/src/thread/SDL_thread_c.h @@ -36,6 +36,8 @@ #include "psp/SDL_systhread_c.h" #elif SDL_THREAD_STDCPP #include "stdcpp/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..acb94532e --- /dev/null +++ b/src/thread/wiiu/SDL_syscond.c @@ -0,0 +1,110 @@ +/* + 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 + +/* 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); + */ + +int +SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms) +{ + return -1; +} + +/* 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: */ \ No newline at end of file diff --git a/src/thread/wiiu/SDL_sysmutex.c b/src/thread/wiiu/SDL_sysmutex.c new file mode 100644 index 000000000..c7eaa9340 --- /dev/null +++ b/src/thread/wiiu/SDL_sysmutex.c @@ -0,0 +1,76 @@ +/* + 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 +#include +#include "SDL_thread.h" + +struct SDL_mutex +{ + pthread_mutex_t id; +#if FAKE_RECURSIVE_MUTEX + int recursive; + pthread_t owner; +#endif +}; + +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; +} + +/* vi: set ts=4 sw=4 expandtab: */ \ No newline at end of file diff --git a/src/thread/wiiu/SDL_systhread.c b/src/thread/wiiu/SDL_systhread.c new file mode 100644 index 000000000..5a07a4904 --- /dev/null +++ b/src/thread/wiiu/SDL_systhread.c @@ -0,0 +1,122 @@ +/* + 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) +{ + unsigned int stackSize = thread->stacksize ? thread->stacksize : 0x8000; + int priority = OSGetThreadPriority(OSGetCurrentThread()); + OSThread *handle = (OSThread *)memalign(16, sizeof(OSThread)); + char *stack = (char *)memalign(16, stackSize); + memset(handle, 0, sizeof(OSThread)); + + if (!OSCreateThread(handle, + (OSThreadEntryPointFn)SDL_RunThread, + (int32_t)args, + NULL, + stack, + 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/timer/wiiu/SDL_systimer.c b/src/timer/wiiu/SDL_systimer.c new file mode 100644 index 000000000..ad348460b --- /dev/null +++ b/src/timer/wiiu/SDL_systimer.c @@ -0,0 +1,84 @@ +/* + 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) +{ + if (!ticks_started) { + SDL_TicksInit(); + } + + OSTime 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 + */ \ No newline at end of file diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index e88a8b60e..5ffb74f3f 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -380,11 +380,11 @@ struct SDL_VideoDevice /* Data private to this driver */ void *driverdata; struct SDL_GLDriverData *gl_data; - + #if SDL_VIDEO_OPENGL_EGL struct SDL_EGL_VideoData *egl_data; #endif - + #if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2 struct SDL_PrivateGLESData *gles_data; #endif @@ -421,6 +421,7 @@ extern VideoBootStrap NACL_bootstrap; extern VideoBootStrap VIVANTE_bootstrap; extern VideoBootStrap Emscripten_bootstrap; extern VideoBootStrap QNX_bootstrap; +extern VideoBootStrap WIIU_bootstrap; extern SDL_VideoDevice *SDL_GetVideoDevice(void); extern int SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode); diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index c63f74631..d40c41e68 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -109,6 +109,9 @@ static VideoBootStrap *bootstrap[] = { #if SDL_VIDEO_DRIVER_QNX &QNX_bootstrap, #endif +#if SDL_VIDEO_DRIVER_WIIU + &WIIU_bootstrap, +#endif #if SDL_VIDEO_DRIVER_DUMMY &DUMMY_bootstrap, #endif @@ -277,7 +280,7 @@ SDL_CreateWindowTexture(SDL_VideoDevice *unused, SDL_Window * window, Uint32 * f } } } - + if (!renderer) { for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) { SDL_RendererInfo info; @@ -1199,7 +1202,7 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen) if (SDL_strcmp(_this->name, "cocoa") == 0) { /* don't do this for X11, etc */ if (window->is_destroying && (window->last_fullscreen_flags & FULLSCREEN_MASK) == SDL_WINDOW_FULLSCREEN_DESKTOP) return 0; - + /* If we're switching between a fullscreen Space and "normal" fullscreen, we need to get back to normal first. */ if (fullscreen && ((window->last_fullscreen_flags & FULLSCREEN_MASK) == SDL_WINDOW_FULLSCREEN_DESKTOP) && ((window->flags & FULLSCREEN_MASK) == SDL_WINDOW_FULLSCREEN)) { if (!Cocoa_SetWindowFullscreenSpace(window, SDL_FALSE)) { @@ -1912,7 +1915,7 @@ SDL_GetWindowPosition(SDL_Window * window, int *x, int *y) /* Fullscreen windows are always at their display's origin */ if (window->flags & SDL_WINDOW_FULLSCREEN) { int displayIndex; - + if (x) { *x = 0; } @@ -2275,7 +2278,7 @@ SDL_SetWindowFullscreen(SDL_Window * window, Uint32 flags) if (SDL_UpdateFullscreenMode(window, FULLSCREEN_VISIBLE(window)) == 0) { return 0; } - + window->flags &= ~FULLSCREEN_MASK; window->flags |= oldflags; return -1; @@ -2420,11 +2423,11 @@ SDL_SetWindowModalFor(SDL_Window * modal_window, SDL_Window * parent_window) if (!_this->SetWindowModalFor) { return SDL_Unsupported(); } - + return _this->SetWindowModalFor(_this, modal_window, parent_window); } -int +int SDL_SetWindowInputFocus(SDL_Window * window) { CHECK_WINDOW_MAGIC(window, -1); @@ -2432,7 +2435,7 @@ SDL_SetWindowInputFocus(SDL_Window * window) if (!_this->SetWindowInputFocus) { return SDL_Unsupported(); } - + return _this->SetWindowInputFocus(_this, window); } @@ -3036,7 +3039,7 @@ SDL_GL_ExtensionSupported(const char *extension) /* Deduce supported ES profile versions from the supported ARB_ES*_compatibility extensions. There is no direct query. - + This is normally only called when the OpenGL driver supports {GLX,WGL}_EXT_create_context_es2_profile. */ diff --git a/src/video/wiiu/SDL_wiiuvideo.c b/src/video/wiiu/SDL_wiiuvideo.c new file mode 100644 index 000000000..9c36f899e --- /dev/null +++ b/src/video/wiiu/SDL_wiiuvideo.c @@ -0,0 +1,227 @@ +#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 +#include +#include +#include +#include + +#define FRAME_HEAP_TAG (0x000DECAF) + +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 WIIU_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format, void **pixels, int *pitch); +static int WIIU_UpdateWindowFramebuffer(_THIS, SDL_Window *window, const SDL_Rect *rects, int numrects); +static void WIIU_DestroyWindowFramebuffer(_THIS, SDL_Window *window); + +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(); + if(device) { + SDL_free(device); + } + return NULL; + } + + device->VideoInit = WIIU_VideoInit; + device->VideoQuit = WIIU_VideoQuit; + device->SetDisplayMode = WIIU_SetDisplayMode; + device->PumpEvents = WIIU_PumpEvents; + device->CreateWindowFramebuffer = WIIU_CreateWindowFramebuffer; + device->UpdateWindowFramebuffer = WIIU_UpdateWindowFramebuffer; + device->DestroyWindowFramebuffer = WIIU_DestroyWindowFramebuffer; + + device->free = WIIU_DeleteDevice; + + return device; +} + +VideoBootStrap WIIU_bootstrap = { + "WiiU", "Video driver for Nintendo WiiU", + WIIU_Available, WIIU_CreateDevice +}; + +static int WIIU_VideoInit(_THIS) { + SDL_DisplayMode mode; + + OSScreenInit(); + + mode.format = SDL_PIXELFORMAT_RGBA8888; + mode.w = 1280; + mode.h = 720; + 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) { + OSScreenShutdown(); +} + +static int WIIU_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode) { + return 0; +} + +static void WIIU_PumpEvents(_THIS) { + // TODO +} + +#define WIIU_DATA "_SDL_WiiUData" + +typedef struct { + SDL_Surface *sdl_surface; + void *wiiu_surface; + int wiiu_work_fb; +} WIIU_WindowData; + +static int WIIU_CreateWindowFramebuffer(_THIS, SDL_Window *window, Uint32 *format, void **pixels, int *pitch) { + SDL_Surface *surface; + const Uint32 surface_format = SDL_PIXELFORMAT_RGBA8888; + int w, h; + int bpp; + Uint32 Rmask, Gmask, Bmask, Amask; + + SDL_PixelFormatEnumToMasks(surface_format, &bpp, &Rmask, &Gmask, &Bmask, &Amask); + SDL_GetWindowSize(window, &w, &h); + surface = SDL_CreateRGBSurface(0, w, h, bpp, Rmask, Gmask, Bmask, Amask); + if(!surface) { + return -1; + } + + WIIU_WindowData *data = SDL_calloc(1, sizeof(WIIU_WindowData)); + data->sdl_surface = surface; + + // Allocate the framebuffers + MEMHeapHandle heap = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1); + MEMRecordStateForFrmHeap(heap, FRAME_HEAP_TAG); + + // Write "Look at the TV Screen" on the gamepad + void *sBufferDRC = MEMAllocFromFrmHeapEx(heap, OSScreenGetBufferSizeEx(SCREEN_DRC), 4); + OSScreenSetBufferEx(SCREEN_DRC, sBufferDRC); + OSScreenClearBufferEx(SCREEN_DRC, 0); + OSScreenPutFontEx(SCREEN_DRC, 0, 0, "Look at the TV Screen."); + DCFlushRange(sBufferDRC, OSScreenGetBufferSizeEx(SCREEN_DRC)); + OSScreenFlipBuffersEx(SCREEN_DRC); + OSScreenEnableEx(SCREEN_DRC, 1); + + // Allocate the framebuffer (TV will be used) + data->wiiu_work_fb = 1; + data->wiiu_surface = MEMAllocFromFrmHeapEx(heap, OSScreenGetBufferSizeEx(SCREEN_TV), 4); + OSScreenSetBufferEx(SCREEN_TV, data->wiiu_surface); + + // Prepare the framebuffer + OSScreenClearBufferEx(SCREEN_TV, 0); + + // Flush framebuffer + DCFlushRange(data->wiiu_surface, OSScreenGetBufferSizeEx(SCREEN_TV)); + OSScreenFlipBuffersEx(SCREEN_TV); + data->wiiu_work_fb = !data->wiiu_work_fb; + + // Enable the framebuffer + OSScreenEnableEx(SCREEN_TV, 1); + + // Set surface data + SDL_SetWindowData(window, WIIU_DATA, data); + *format = surface_format; + *pixels = surface->pixels; + *pitch = surface->pitch; + + // *hack*: if the window is not in focus joystick events will be + // ignored, so set the focus for the keyboard (actually the wiiu + // just doesn't have windows, so the focus concept doesn't really + // apply) + SDL_SetKeyboardFocus(window); + + return 0; +} + +static void WIIU_FBCopy(uint32_t *_dst, uint32_t *_src, uint32_t _w, uint32_t _h) { + register uint32_t *src = _src, *dst = _dst; + register uint32_t w = _w, h = _h; + register uint32_t a, b, c, d; + register uint32_t y, *xf; + + for(y = 0; y < h; y++) { + xf = dst + w; + do { + a = src[0]; + b = src[1]; + c = src[2]; + d = src[3]; + dst[0] = a; + dst[1] = b; + dst[2] = c; + dst[3] = d; + src += 4; + dst += 4; + } while(dst != xf); + dst += 1280 - w; + } +} + +static int WIIU_UpdateWindowFramebuffer(_THIS, SDL_Window *window, const SDL_Rect *rects, int numrects) { + WIIU_WindowData *data; + + data = (WIIU_WindowData*) SDL_GetWindowData(window, WIIU_DATA); + if(!data) { + return SDL_SetError("Couldn't find wiiu data for window"); + } + + SDL_Surface *sdl_surface = data->sdl_surface; + + // Get buffers + uint32_t *src_buffer = (uint32_t *)sdl_surface->pixels; + uint32_t *dst_buffer = (uint32_t *)(data->wiiu_surface + (data->wiiu_work_fb * 1280 * 720 * 4)); + WIIU_FBCopy(dst_buffer, src_buffer, sdl_surface->w, sdl_surface->h); + + // Flush framebuffer + DCFlushRange(data->wiiu_surface, OSScreenGetBufferSizeEx(SCREEN_TV)); + OSScreenFlipBuffersEx(SCREEN_TV); + data->wiiu_work_fb = !data->wiiu_work_fb; + + return 0; +} + +static void WIIU_DestroyWindowFramebuffer(_THIS, SDL_Window *window) { + WIIU_WindowData *data; + + data = (WIIU_WindowData*) SDL_GetWindowData(window, WIIU_DATA); + SDL_FreeSurface(data->sdl_surface); + SDL_free(data); + + MEMHeapHandle heap = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1); + OSScreenEnableEx(SCREEN_DRC, 0); + OSScreenEnableEx(SCREEN_TV, 0); + MEMFreeByStateToFrmHeap(heap, FRAME_HEAP_TAG); +} + +#endif /* SDL_VIDEO_DRIVER_WIIU */