From 6d53668beda9b8e88ee6c74230e1e70a2cc0061b Mon Sep 17 00:00:00 2001 From: Clownacy Date: Tue, 14 Apr 2020 00:31:13 +0100 Subject: [PATCH] Add Wii U platform backend With this backend, CSE2 can run on the Wii U. It's not ideal - it doesn't have its own renderer yet, so it just uses the software renderer, and it only displays on the gamepad, because drawing to the TV as well makes the game lag. Also there's no sound. Also the lack of input rebinding is annoying. --- CMakeLists.txt | 9 +- src/Backends/WiiU/Controller.cpp | 77 +++++++++++++++++ src/Backends/WiiU/Misc.cpp | 114 ++++++++++++++++++++++++++ src/Backends/WiiU/Window-Software.cpp | 107 ++++++++++++++++++++++++ 4 files changed, 306 insertions(+), 1 deletion(-) create mode 100644 src/Backends/WiiU/Controller.cpp create mode 100644 src/Backends/WiiU/Misc.cpp create mode 100644 src/Backends/WiiU/Window-Software.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d7c7c25e..c2499008 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,7 @@ option(BUILD_DOCONFIG "Compile a DoConfig clone tool - not useful for console po set(BACKEND_RENDERER "SDLTexture" CACHE STRING "Which renderer the game should use: 'OpenGL3' for an OpenGL 3.2 renderer, 'OpenGLES2' for an OpenGL ES 2.0 renderer, 'SDLTexture' for SDL2's hardware-accelerated Texture API, 'SDLSurface' for SDL2's software-rendered Surface API, or 'Software' for a handwritten software renderer") set(BACKEND_AUDIO "SDL2" CACHE STRING "Which audio backend the game should use: 'SDL2', 'miniaudio', or 'Null'") -set(BACKEND_PLATFORM "SDL2" CACHE STRING "Which platform backend the game should use: 'SDL2', 'GLFW3', or 'Null'") +set(BACKEND_PLATFORM "SDL2" CACHE STRING "Which platform backend the game should use: 'SDL2', 'GLFW3', 'WiiU', or 'Null'") option(LTO "Enable link-time optimisation" OFF) option(PKG_CONFIG_STATIC_LIBS "On platforms with pkg-config, static-link the dependencies (good for Windows builds, so you don't need to bundle DLL files)" OFF) @@ -351,6 +351,11 @@ elseif(BACKEND_PLATFORM MATCHES "GLFW3") "src/Backends/GLFW3/Misc.cpp" "src/Backends/GLFW3/Window.h" ) +elseif(BACKEND_PLATFORM MATCHES "WiiU") + target_sources(CSE2 PRIVATE + "src/Backends/WiiU/Controller.cpp" + "src/Backends/WiiU/Misc.cpp" + ) elseif(BACKEND_PLATFORM MATCHES "Null") target_sources(CSE2 PRIVATE "src/Backends/Null/Controller.cpp" @@ -372,6 +377,8 @@ elseif(BACKEND_PLATFORM MATCHES "GLFW3" AND BACKEND_RENDERER MATCHES "OpenGLES2" target_sources(CSE2 PRIVATE "src/Backends/GLFW3/Window-OpenGLES2.cpp") elseif(BACKEND_PLATFORM MATCHES "GLFW3" AND BACKEND_RENDERER MATCHES "Software") target_sources(CSE2 PRIVATE "src/Backends/GLFW3/Window-Software.cpp") +elseif(BACKEND_PLATFORM MATCHES "WiiU" AND BACKEND_RENDERER MATCHES "Software") + target_sources(CSE2 PRIVATE "src/Backends/WiiU/Window-Software.cpp") elseif(BACKEND_PLATFORM MATCHES "Null" AND BACKEND_RENDERER MATCHES "Software") target_sources(CSE2 PRIVATE "src/Backends/Null/Window-Software.cpp") else() diff --git a/src/Backends/WiiU/Controller.cpp b/src/Backends/WiiU/Controller.cpp new file mode 100644 index 00000000..ffeacb33 --- /dev/null +++ b/src/Backends/WiiU/Controller.cpp @@ -0,0 +1,77 @@ +#include "../Controller.h" + +#include + +#define DEADZONE (10000.0f / 32767.0f) + +bool ControllerBackend_Init(void) +{ + VPADInit(); + + return true; +} + +void ControllerBackend_Deinit(void) +{ + VPADShutdown(); +} + +bool ControllerBackend_GetJoystickStatus(bool **buttons, unsigned int *button_count, short **axes, unsigned int *axis_count) +{ + VPADReadError vpad_error; + VPADStatus vpad_status; + VPADRead(VPAD_CHAN_0, &vpad_status, 1, &vpad_error); + + static bool button_buffer[27]; + static short axis_buffer[4]; + + *button_count = sizeof(button_buffer) / sizeof(button_buffer[0]); + *axis_count = sizeof(axis_buffer) / sizeof(axis_buffer[0]); + + ////////////////////////// + // Handle button inputs // + ////////////////////////// + + button_buffer[0] = vpad_status.hold & VPAD_BUTTON_Y; // Shoot + button_buffer[1] = vpad_status.hold & VPAD_BUTTON_B; // Jump + button_buffer[2] = vpad_status.hold & VPAD_BUTTON_X; // Map + button_buffer[3] = vpad_status.hold & VPAD_BUTTON_L; // Weapon left + button_buffer[4] = vpad_status.hold & VPAD_BUTTON_R; // Weapon right + button_buffer[5] = vpad_status.hold & VPAD_BUTTON_A; // Inventory + button_buffer[6] = vpad_status.hold & VPAD_BUTTON_ZL; // Weapon left + button_buffer[7] = vpad_status.hold & VPAD_BUTTON_ZR; // Weapon right + button_buffer[8] = vpad_status.hold & VPAD_BUTTON_LEFT; + button_buffer[9] = vpad_status.hold & VPAD_BUTTON_RIGHT; + button_buffer[10] = vpad_status.hold & VPAD_BUTTON_UP; + button_buffer[11] = vpad_status.hold & VPAD_BUTTON_DOWN; + button_buffer[12] = vpad_status.hold & VPAD_BUTTON_PLUS; + button_buffer[13] = vpad_status.hold & VPAD_BUTTON_MINUS; + button_buffer[14] = vpad_status.hold & VPAD_BUTTON_HOME; + button_buffer[15] = vpad_status.hold & VPAD_BUTTON_SYNC; + button_buffer[16] = vpad_status.hold & VPAD_BUTTON_STICK_R; + button_buffer[17] = vpad_status.hold & VPAD_BUTTON_STICK_L; + button_buffer[18] = vpad_status.hold & VPAD_BUTTON_TV; + button_buffer[19] = vpad_status.hold & VPAD_STICK_R_EMULATION_LEFT; + button_buffer[20] = vpad_status.hold & VPAD_STICK_R_EMULATION_RIGHT; + button_buffer[21] = vpad_status.hold & VPAD_STICK_R_EMULATION_UP; + button_buffer[22] = vpad_status.hold & VPAD_STICK_R_EMULATION_DOWN; + button_buffer[23] = vpad_status.hold & VPAD_STICK_L_EMULATION_LEFT; + button_buffer[24] = vpad_status.hold & VPAD_STICK_L_EMULATION_RIGHT; + button_buffer[25] = vpad_status.hold & VPAD_STICK_L_EMULATION_UP; + button_buffer[26] = vpad_status.hold & VPAD_STICK_L_EMULATION_DOWN; + + *buttons = button_buffer; + + //////////////////////// + // Handle axis inputs // + //////////////////////// + + axis_buffer[0] = (short)(vpad_status.leftStick.x * 0x7FFF); + axis_buffer[1] = (short)(vpad_status.leftStick.y * -0x7FFF); + axis_buffer[2] = (short)(vpad_status.rightStick.x * 0x7FFF); + axis_buffer[3] = (short)(vpad_status.rightStick.y * -0x7FFF); + + *axes = axis_buffer; + + return true; +} diff --git a/src/Backends/WiiU/Misc.cpp b/src/Backends/WiiU/Misc.cpp new file mode 100644 index 00000000..c8f50561 --- /dev/null +++ b/src/Backends/WiiU/Misc.cpp @@ -0,0 +1,114 @@ +#include "../Misc.h" + +#include + +#include + +#include +#include + +static unsigned long tick_delta; + +bool Backend_Init(void) +{ + WHBProcInit(); + + if (!WHBMountSdCard()) + return FALSE; + + tick_delta = OSGetSystemInfo()->busClockSpeed / 4; + + return true; +} + +void Backend_Deinit(void) +{ + WHBUnmountSdCard(); + + WHBProcShutdown(); +} + +void Backend_PostWindowCreation(void) +{ + +} + +bool Backend_GetBasePath(char *string_buffer) +{ + strcpy(string_buffer, WHBGetSdCardMountPath()); + strcat(string_buffer, "/CSE2"); + + return true; +} + +void Backend_HideMouse(void) +{ + +} + +void Backend_SetWindowIcon(const unsigned char *rgb_pixels, unsigned int width, unsigned int height) +{ + (void)rgb_pixels; + (void)width; + (void)height; +} + +void Backend_SetCursor(const unsigned char *rgb_pixels, unsigned int width, unsigned int height) +{ + (void)rgb_pixels; + (void)width; + (void)height; +} + +void PlaybackBackend_EnableDragAndDrop(void) +{ + +} + +bool Backend_SystemTask(bool active) +{ + (void)active; + + return WHBProcIsRunning(); +} + +void Backend_GetKeyboardState(bool *keyboard_state) +{ + memset(keyboard_state, 0, sizeof(bool) * BACKEND_KEYBOARD_TOTAL); +} + +void Backend_ShowMessageBox(const char *title, const char *message) +{ + (void)title; + (void)message; +} + +ATTRIBUTE_FORMAT_PRINTF(1, 2) void Backend_PrintError(const char *format, ...) +{ + (void)format; +} + +ATTRIBUTE_FORMAT_PRINTF(1, 2) void Backend_PrintInfo(const char *format, ...) +{ + (void)format; +} + +unsigned long Backend_GetTicks(void) +{ + static uint64_t accumulator; + + static unsigned long last_tick; + + unsigned long current_tick = OSGetTick(); + + accumulator += current_tick - last_tick; + + last_tick = current_tick; + + return (accumulator * 1000) / tick_delta; +} + +void Backend_Delay(unsigned int ticks) +{ + OSSleepTicks((ticks * tick_delta) / 1000); +} diff --git a/src/Backends/WiiU/Window-Software.cpp b/src/Backends/WiiU/Window-Software.cpp new file mode 100644 index 00000000..182dd673 --- /dev/null +++ b/src/Backends/WiiU/Window-Software.cpp @@ -0,0 +1,107 @@ +#include "../Window-Software.h" + +#include + +#include +#include + +static unsigned char *fake_framebuffer; + +//static unsigned char *tv_framebuffer; +static unsigned char *drc_framebuffer; + +static size_t framebuffer_width; +static size_t framebuffer_height; + +//static uint32_t tv_buffer_size; +static uint32_t drc_buffer_size; + +unsigned char* WindowBackend_Software_CreateWindow(const char *window_title, int screen_width, int screen_height, bool fullscreen, size_t *pitch) +{ + (void)window_title; + (void)fullscreen; + + framebuffer_width = screen_width; + framebuffer_height = screen_height; + + OSScreenInit(); + + OSScreenEnableEx(SCREEN_TV, FALSE); + OSScreenEnableEx(SCREEN_DRC, TRUE); + +// tv_buffer_size = OSScreenGetBufferSizeEx(SCREEN_TV); + drc_buffer_size = OSScreenGetBufferSizeEx(SCREEN_DRC); + +// tv_framebuffer = (unsigned char*)aligned_alloc(0x100, tv_buffer_size); // C11 fun + drc_framebuffer = (unsigned char*)aligned_alloc(0x100, drc_buffer_size); // C11 fun + +// OSScreenSetBufferEx(SCREEN_TV, tv_framebuffer); + OSScreenSetBufferEx(SCREEN_DRC, drc_framebuffer); + + fake_framebuffer = (unsigned char*)malloc(screen_width * screen_height * 3); + + *pitch = screen_width * 3; + + return fake_framebuffer; +} + +void WindowBackend_Software_DestroyWindow(void) +{ + free(fake_framebuffer); + free(drc_framebuffer); +// free(tv_framebuffer); + OSScreenShutdown(); +} + +void WindowBackend_Software_Display(void) +{ + const size_t line_size = (drc_buffer_size / 480) / 2; + + static bool flipflop; + + unsigned char *in_pointer = fake_framebuffer; + + for (size_t y = 0; y < framebuffer_height; ++y) + { + unsigned char *out_pointer = &drc_framebuffer[line_size * y]; + + if (!flipflop) + out_pointer += drc_buffer_size / 2; + + out_pointer += ((854 - framebuffer_width) * 4) / 2; + + for (size_t x = 0; x < framebuffer_width; ++x) + { + *out_pointer++ = *in_pointer++; + *out_pointer++ = *in_pointer++; + *out_pointer++ = *in_pointer++; + *out_pointer++ = 0; +/* uint32_t colour = 0; + colour |= *in_pointer++ << 24; + colour |= *in_pointer++ << 16; + colour |= *in_pointer++ << 8; + OSScreenPutPixelEx(SCREEN_DRC, x, y, colour); + */ } + } + + flipflop = !flipflop; + +// static unsigned char accumulator = 0; + +// accumulator += 0x10; + +// for (size_t i = 0; i < buffer_size; ++i) +// real_framebuffer[i] = accumulator; + +// DCFlushRange(tv_framebuffer, tv_buffer_size); +// DCFlushRange(drc_framebuffer, drc_buffer_size); + +// OSScreenFlipBuffersEx(SCREEN_TV); + OSScreenFlipBuffersEx(SCREEN_DRC); +} + +void WindowBackend_Software_HandleWindowResize(unsigned int width, unsigned int height) +{ + (void)width; + (void)height; +}