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.
This commit is contained in:
Clownacy 2020-04-14 00:31:13 +01:00
parent bcbb06f092
commit 6d53668bed
4 changed files with 306 additions and 1 deletions

View file

@ -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()

View file

@ -0,0 +1,77 @@
#include "../Controller.h"
#include <vpad/input.h>
#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;
}

114
src/Backends/WiiU/Misc.cpp Normal file
View file

@ -0,0 +1,114 @@
#include "../Misc.h"
#include <string.h>
#include <coreinit/thread.h>
#include <whb/proc.h>
#include <whb/sdcard.h>
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);
}

View file

@ -0,0 +1,107 @@
#include "../Window-Software.h"
#include <stdlib.h>
#include <coreinit/cache.h>
#include <coreinit/screen.h>
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;
}