Wii U: Several fixes and improvements (#1608)

* WiiU: fix more scaling issues

* Wii U: batch depth reads

* Wii U: remove file buffering
Doesn't seem to to do much anymore

* Remove "missing_gcc_functions.c" to avoid conflicts

* Wii U: Fix random_device usage
random_device will always be seeded with a constant seed and will return the same number sequence every time

* Wii U: Improve software keyboard

* Wii U: Fix console input text width
This commit is contained in:
GaryOderNichts 2022-09-28 01:29:55 +02:00 committed by GitHub
parent 7fb8902e7f
commit 677c4845f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 147 additions and 89 deletions

View File

@ -229,7 +229,11 @@ namespace Ship {
// Renders input textfield
constexpr ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackEdit |
ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory;
ImGui::PushItemWidth(-53);
#ifdef __WIIU__
ImGui::PushItemWidth(-53.0f * 2.0f);
#else
ImGui::PushItemWidth(-53.0f);
#endif
if (ImGui::InputTextWithHint("##CMDInput", ">", this->inputBuffer, MAX_BUFFER_SIZE, flags, &Console::CallbackStub, this)) {
input_focus = true;
if (this->inputBuffer[0] != '\0' && this->inputBuffer[0] != ' ')
@ -250,7 +254,11 @@ namespace Ship {
}
ImGui::SameLine();
#ifdef __WIIU__
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 50 * 2.0f);
#else
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 50);
#endif
if (ImGui::Button("Submit") && !input_focus && this->inputBuffer[0] != '\0' && this->inputBuffer[0] != ' ') {
this->Dispatch(std::string(this->inputBuffer));
memset(this->inputBuffer, 0, MAX_BUFFER_SIZE);

View File

@ -220,9 +220,15 @@ namespace Ship {
const float duration = overlay->duration / overlay->fadeTime;
const ImVec4 color = ImVec4(1.0f, 1.0f, 1.0f, duration);
#ifdef __WIIU__
const float textWidth = this->GetStringWidth(overlay->value) * 2.0f;
const float textOffset = 40.0f * 2.0f;
#else
const float textWidth = this->GetStringWidth(overlay->value);
const float textOffset = 40.0f;
#endif
this->TextDraw(GetScreenWidth() - textWidth - 40, GetScreenHeight() - 40 - notY, true, color, text);
this->TextDraw(GetScreenWidth() - textWidth - textOffset, GetScreenHeight() - textOffset - notY, true, color, text);
notY += 30;
overlay->duration -= .05f;
}

View File

@ -660,7 +660,12 @@ namespace SohImGui {
ImGui::End();
#ifdef __WIIU__
const float scale = CVar_GetFloat("gInputScale", 1.0f) * 2.0f;
#else
const float scale = CVar_GetFloat("gInputScale", 1.0f);
#endif
ImVec2 BtnPos = ImVec2(160 * scale, 85 * scale);
if (CVar_GetS32("gInputEnabled", 0)) {

View File

@ -1,3 +1,7 @@
/* gfx_gx2.cpp - Fast3D GX2 backend for libultraship
Created in 2022 by GaryOderNichts
*/
#ifdef __WIIU__
#include "../../Window.h"
@ -444,7 +448,7 @@ static void gfx_gx2_init(void) {
memcpy(&depthReadBuffer, &main_framebuffer.depth_buffer, sizeof(GX2DepthBuffer));
depthReadBuffer.surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED;
depthReadBuffer.surface.width = 1;
depthReadBuffer.surface.width = 32;
depthReadBuffer.surface.height = 1;
GX2CalcSurfaceSizeAndAlignment(&depthReadBuffer.surface);
@ -734,35 +738,55 @@ static std::unordered_map<std::pair<float, float>, uint16_t, hash_pair_ff> gfx_g
}
std::unordered_map<std::pair<float, float>, uint16_t, hash_pair_ff> res;
if (!coordinates.size()) {
return res;
}
for (const auto& c : coordinates) {
// bug? coordinates sometimes read from oob
if ((c.first < 0.0f) || (c.first > (float) buffer->depth_buffer.surface.width)
|| (c.second < 0.0f) || (c.second > (float) buffer->depth_buffer.surface.height)) {
res.emplace(c, 0);
continue;
GX2Rect srcRects[32];
GX2Point dstPoints[32];
size_t num_coordinates = coordinates.size();
while (num_coordinates > 0) {
size_t numRects = 32;
if (num_coordinates < numRects) {
numRects = num_coordinates;
}
num_coordinates -= numRects;
// initialize rects and points
for (size_t i = 0; i < numRects; ++i) {
const auto& c = *std::next(coordinates.begin(), num_coordinates + i);
const int32_t x = (int32_t) std::clamp(c.first, 0.0f, (float) buffer->depth_buffer.surface.width - 1);
const int32_t y = (int32_t) std::clamp(c.second, 0.0f, (float) buffer->depth_buffer.surface.height - 1);
srcRects[i] = GX2Rect{
x,
(int32_t) buffer->depth_buffer.surface.height - y,
x + 1,
(int32_t) (buffer->depth_buffer.surface.height - y) + 1
};
// dst points will be spread over the x-axis of the buffer
dstPoints[i] = GX2Point{ i, 0 };
}
// Invalidate the buffer first
GX2Invalidate(GX2_INVALIDATE_MODE_CPU | GX2_INVALIDATE_MODE_DEPTH_BUFFER, depthReadBuffer.surface.image, depthReadBuffer.surface.imageSize);
// copy the pixel to the depthReadBuffer
GX2Rect srcRect = {
(int32_t) c.first,
(int32_t) buffer->depth_buffer.surface.height - (int32_t) c.second,
(int32_t) c.first + 1,
(int32_t) (buffer->depth_buffer.surface.height - (int32_t) c.second) + 1
};
GX2Point dstPoint = { 0, 0 };
GX2CopySurfaceEx(&buffer->depth_buffer.surface, 0, 0, &depthReadBuffer.surface, 0, 0, 1, &srcRect, &dstPoint);
GX2DrawDone();
// Perform the copy
GX2CopySurfaceEx(&buffer->depth_buffer.surface, 0, 0, &depthReadBuffer.surface, 0, 0, numRects, srcRects, dstPoints);
// Wait for draws to be done and restore context, in case GPU was used
GX2DrawDone();
gfx_wiiu_set_context_state();
// read the pixel from the depthReadBuffer
uint32_t tmp = __builtin_bswap32(*(uint32_t *)depthReadBuffer.surface.image);
float val = *(float *)&tmp;
// read the pixels from the depthReadBuffer
for (size_t i = 0; i < numRects; ++i) {
uint32_t tmp = __builtin_bswap32(*((uint32_t *)depthReadBuffer.surface.image + i));
float val = *(float *)&tmp;
res.emplace(c, val * 65532.0f);
const auto& c = *std::next(coordinates.begin(), num_coordinates + i);
res.emplace(c, val * 65532.0f);
}
}
return res;

View File

@ -1,3 +1,7 @@
/* gfx_gx2.h - Fast3D GX2 backend for libultraship
Created in 2022 by GaryOderNichts
*/
#ifndef GFX_GX2_H
#define GFX_GX2_H

View File

@ -1,3 +1,7 @@
/* gx2_shader_gen.c - Fast3D GX2 shader generator for libultraship
Created in 2022 by GaryOderNichts
*/
#ifdef __WIIU__
#include "gx2_shader_gen.h"
@ -597,7 +601,7 @@ static int generatePixelShader(GX2PixelShader *psh, struct CCFeatures *cc_featur
psh->regs.spi_ps_input_cntls[0] = 0 | (1 << 8);
// inputs
for (int i = 0; i < num_ps_inputs; i++) {
for (uint32_t i = 0; i < num_ps_inputs; i++) {
psh->regs.spi_ps_input_cntls[i + 1] = i | (1 << 8);
}
@ -656,7 +660,7 @@ static int generateVertexShader(GX2VertexShader *vsh, struct CCFeatures *cc_feat
);
// params
for (int i = 0; i < num_ps_inputs - 1; i++) {
for (uint32_t i = 0; i < num_ps_inputs - 1; i++) {
ADD_INSTR(
EXP(PARAM(i), _R(i + 2), _x, _y, _z, _w) NO_BARRIER,
);

View File

@ -1,3 +1,7 @@
/* gx2_shader_gen.h - Fast3D GX2 shader generator for libultraship
Created in 2022 by GaryOderNichts
*/
#pragma once
#include "gfx_cc.h"

View File

@ -1,5 +1,6 @@
// dear imgui: Platform Backend for the Wii U
#include "imgui.h"
#include "imgui_internal.h"
#include "imgui_impl_wiiu.h"
#include <stdlib.h> // malloc/free
@ -86,8 +87,12 @@ void ImGui_ImplWiiU_Shutdown()
static void ImGui_ImplWiiU_UpdateKeyboardInput(ImGui_ImplWiiU_ControllerInput* input)
{
ImGuiIO& io = ImGui::GetIO();
ImGuiInputTextState* state = ImGui::GetInputTextState(ImGui::GetActiveID());
if (!state)
return;
VPADGetTPCalibratedPoint(VPAD_CHAN_0, &input->vpad->tpNormal, &input->vpad->tpNormal);
if (input->vpad)
VPADGetTPCalibratedPoint(VPAD_CHAN_0, &input->vpad->tpNormal, &input->vpad->tpNormal);
nn::swkbd::ControllerInfo controllerInfo;
controllerInfo.vpad = input->vpad;
@ -104,6 +109,8 @@ static void ImGui_ImplWiiU_UpdateKeyboardInput(ImGui_ImplWiiU_ControllerInput* i
if (nn::swkbd::IsDecideOkButton(NULL))
{
state->ClearText();
// Add entered text
const char16_t* string = nn::swkbd::GetInputFormString();
for (int i = 0; *string; string++)
@ -248,6 +255,21 @@ bool ImGui_ImplWiiU_ProcessInput(ImGui_ImplWiiU_ControllerInput* input)
// Show keyboard if wanted
if (io.WantTextInput && !bd->WantedTextInput)
{
ImGuiInputTextState* state = ImGui::GetInputTextState(ImGui::GetActiveID());
if (state)
{
if (!(state->Flags & ImGuiInputTextFlags_AlwaysOverwrite))
bd->AppearArg.inputFormArg.initialText = (char16_t*) state->TextW.Data;
bd->AppearArg.inputFormArg.maxTextLength = state->BufCapacityA;
bd->AppearArg.inputFormArg.higlightInitialText = !!(state->Flags & ImGuiInputTextFlags_AutoSelectAll);
if (state->Flags & ImGuiInputTextFlags_Password)
bd->AppearArg.inputFormArg.passwordMode = nn::swkbd::PasswordMode::Fade;
else
bd->AppearArg.inputFormArg.passwordMode = nn::swkbd::PasswordMode::Clear;
}
// Open the keyboard for the controller which requested the text input
bd->AppearArg.keyboardArg.configArg.controllerType = bd->LastController;

View File

@ -4590,8 +4590,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
}
}
// Not sure why these are being cleared here, but we need the flags for the software keyboard in the wiiu backend
#ifndef __WIIU__
// Clear temporary user storage
state->Flags = ImGuiInputTextFlags_None;
#endif
}
// Copy result to user buffer. This can currently only happen when (g.ActiveId == id)

View File

@ -112,11 +112,6 @@ void Mercury::reload() {
}
std::ifstream ifs(this->path_);
#ifdef __WIIU__
alignas(0x40) char buffer[8192];
ifs.rdbuf()->pubsetbuf(buffer, sizeof(buffer));
#endif
try {
this->rjson = json::parse(ifs);
this->vjson = this->rjson.flatten();
@ -128,11 +123,5 @@ void Mercury::reload() {
void Mercury::save() const {
std::ofstream file(this->path_);
#ifdef __WIIU__
alignas(0x40) char buffer[8192];
file.rdbuf()->pubsetbuf(buffer, sizeof(buffer));
#endif
file << this->vjson.unflatten().dump(4);
}

View File

@ -385,7 +385,6 @@ set(Source_Files__src__boot
"src/boot/idle.c"
"src/boot/is_debug.c"
"src/boot/logutils.c"
"src/boot/missing_gcc_functions.c"
"src/boot/stackcheck.c"
"src/boot/viconfig.c"
"src/boot/yaz0.c"

View File

@ -40,13 +40,13 @@ const char* MarginCvarList[] {
ImVec4 GetRandomValue(int MaximumPossible){
ImVec4 NewColor;
unsigned long range = 255 - 0;
#ifndef __SWITCH__
#if !defined(__SWITCH__) && !defined(__WIIU__)
std::random_device rd;
std::mt19937 rng(rd());
#else
#else
size_t seed = std::hash<std::string>{}(std::to_string(rand()));
std::mt19937_64 rng(seed);
#endif
#endif
std::uniform_int_distribution<int> dist(0, 255 - 1);
NewColor.x = (float)(dist(rng)) / 255;
@ -55,9 +55,9 @@ ImVec4 GetRandomValue(int MaximumPossible){
return NewColor;
}
void GetRandomColorRGB(CosmeticsColorSection* ColorSection, int SectionSize){
#ifdef __SWITCH__
#if defined(__SWITCH__) || defined(__WIIU__)
srand(time(NULL));
#endif
#endif
for (int i = 0; i < SectionSize; i++){
CosmeticsColorIndividual* Element = ColorSection[i].Element;
ImVec4 colors = Element->ModifiedColor;
@ -343,7 +343,11 @@ void DrawRandomizeResetButton(const std::string Identifier, CosmeticsColorSectio
ImGui::TableSetupColumn(Col1Name.c_str(), FlagsCell, TablesCellsWidth/2);
ImGui::TableSetupColumn(Col2Name.c_str(), FlagsCell, TablesCellsWidth/2);
Table_InitHeader(false);
#ifdef __WIIU__
if(ImGui::Button(RNG_BtnText.c_str(), ImVec2( ImGui::GetContentRegionAvail().x, 20.0f * 2.0f))){
#else
if(ImGui::Button(RNG_BtnText.c_str(), ImVec2( ImGui::GetContentRegionAvail().x, 20.0f))){
#endif
CVar_SetS32("gHudColors", 2);
CVar_SetS32("gUseNaviCol", 1);
CVar_SetS32("gUseKeeseCol", 1);
@ -358,7 +362,11 @@ void DrawRandomizeResetButton(const std::string Identifier, CosmeticsColorSectio
}
UIWidgets::Tooltip(Tooltip_RNG.c_str());
Table_NextCol();
#ifdef __WIIU__
if(ImGui::Button(Reset_BtnText.c_str(), ImVec2( ImGui::GetContentRegionAvail().x, 20.0f * 2.0f))){
#else
if(ImGui::Button(Reset_BtnText.c_str(), ImVec2( ImGui::GetContentRegionAvail().x, 20.0f))){
#endif
GetDefaultColorRGB(ColorSection, SectionSize);
}
UIWidgets::Tooltip("Enable/Disable custom Link's tunics colors\nIf disabled you will have original colors for Link's tunics.");

View File

@ -15,7 +15,11 @@ void Random_Init(uint32_t seed) {
uint32_t Random(int min, int max) {
if (!init) {
//No seed given, get a random number from device to seed
#if !defined(__SWITCH__) && !defined(__WIIU__)
const auto seed = static_cast<uint32_t>(std::random_device{}());
#else
uint32_t seed = static_cast<uint32_t>(std::hash<std::string>{}(std::to_string(rand())));
#endif
Random_Init(seed);
}
std::uniform_int_distribution<uint32_t> distribution(min, max-1);

View File

@ -704,8 +704,13 @@ void LabeledComboBoxRightAligned(const char* label, const char* cvar, std::vecto
s32 currentValue = CVar_GetS32(cvar, defaultValue);
std::string hiddenLabel = "##" + std::string(cvar);
ImGui::Text(label);
#ifdef __WIIU__
ImGui::SameLine(ImGui::GetContentRegionAvail().x - (ImGui::CalcTextSize(options[currentValue].c_str()).x * 1.0f + 40.0f));
ImGui::PushItemWidth((ImGui::CalcTextSize(options[currentValue].c_str()).x * 1.0f) + 60.0f);
#else
ImGui::SameLine(ImGui::GetContentRegionAvail().x - (ImGui::CalcTextSize(options[currentValue].c_str()).x * 1.0f + 20.0f));
ImGui::PushItemWidth((ImGui::CalcTextSize(options[currentValue].c_str()).x * 1.0f) + 30.0f);
#endif
if (ImGui::BeginCombo(hiddenLabel.c_str(), options[currentValue].c_str())) {
for (int i = 0; i < options.size(); i++) {
if (ImGui::Selectable(options[i].c_str())) {

View File

@ -600,7 +600,7 @@ namespace GameMenuBar {
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
#ifdef __SWITCH__
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 110.0f);
#elif __WIIU__
#elif defined(__WIIU__)
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f * 2);
#else
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f);
@ -1106,7 +1106,11 @@ namespace GameMenuBar {
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f));
#ifdef __WIIU__
static ImVec2 buttonSize(200.0f * 2.0f, 0.0f);
#else
static ImVec2 buttonSize(200.0f, 0.0f);
#endif
if (ImGui::Button(GetWindowButtonText("Cosmetics Editor", CVar_GetS32("gCosmeticsEditorEnabled", 0)).c_str(), buttonSize))
{
bool currentValue = CVar_GetS32("gCosmeticsEditorEnabled", 0);
@ -1164,7 +1168,7 @@ namespace GameMenuBar {
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
#ifdef __SWITCH__
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 110.0f);
#elif __WIIU__
#elif defined(__WIIU__)
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f * 2);
#else
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f);
@ -1398,7 +1402,11 @@ namespace GameMenuBar {
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0,0));
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f));
#ifdef __WIIU__
static ImVec2 buttonSize(160.0f * 2.0f, 0.0f);
#else
static ImVec2 buttonSize(160.0f, 0.0f);
#endif
if (ImGui::Button(GetWindowButtonText("Stats", CVar_GetS32("gStatsEnabled", 0)).c_str(), buttonSize))
{
bool currentValue = CVar_GetS32("gStatsEnabled", 0);
@ -1454,7 +1462,11 @@ namespace GameMenuBar {
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.0f);
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.22f, 0.38f, 0.56f, 1.0f));
#ifdef __WIIU__
static ImVec2 buttonSize(200.0f * 2.0f, 0.0f);
#else
static ImVec2 buttonSize(200.0f, 0.0f);
#endif
if (ImGui::Button(GetWindowButtonText("Randomizer Settings", CVar_GetS32("gRandomizerSettingsEnabled", 0)).c_str(), buttonSize))
{
bool currentValue = CVar_GetS32("gRandomizerSettingsEnabled", 0);

View File

@ -196,11 +196,6 @@ void SaveManager::Init() {
if (std::filesystem::exists(sGlobalPath)) {
std::ifstream input(sGlobalPath);
#ifdef __WIIU__
alignas(0x40) char buffer[8192];
input.rdbuf()->pubsetbuf(buffer, sizeof(buffer));
#endif
nlohmann::json globalBlock;
input >> globalBlock;
@ -522,19 +517,13 @@ void SaveManager::SaveFile(int fileNum) {
section.second.second();
}
#ifdef __SWITCH__
#if defined(__SWITCH__) || defined(__WIIU__)
FILE* w = fopen(GetFileName(fileNum).c_str(), "w");
std::string json_string = baseBlock.dump(4);
fwrite(json_string.c_str(), sizeof(char), json_string.length(), w);
fclose(w);
#else
std::ofstream output(GetFileName(fileNum));
#ifdef __WIIU__
alignas(0x40) char buffer[8192];
output.rdbuf()->pubsetbuf(buffer, sizeof(buffer));
#endif
output << std::setw(4) << baseBlock << std::endl;
#endif
@ -547,13 +536,8 @@ void SaveManager::SaveGlobal() {
globalBlock["audioSetting"] = gSaveContext.audioSetting;
globalBlock["zTargetSetting"] = gSaveContext.zTargetSetting;
globalBlock["language"] = gSaveContext.language;
std::ofstream output("Save/global.sav");
#ifdef __WIIU__
alignas(0x40) char buffer[8192];
output.rdbuf()->pubsetbuf(buffer, sizeof(buffer));
#endif
output << std::setw(4) << globalBlock << std::endl;
}
@ -563,11 +547,6 @@ void SaveManager::LoadFile(int fileNum) {
std::ifstream input(GetFileName(fileNum));
#ifdef __WIIU__
alignas(0x40) char buffer[8192];
input.rdbuf()->pubsetbuf(buffer, sizeof(buffer));
#endif
nlohmann::json saveBlock;
input >> saveBlock;
if (!saveBlock.contains("version")) {
@ -1558,11 +1537,6 @@ void SaveManager::ConvertFromUnversioned() {
std::ifstream input("oot_save.sav", std::ios::binary);
#ifdef __WIIU__
alignas(0x40) char buffer[8192];
input.rdbuf()->pubsetbuf(buffer, sizeof(buffer));
#endif
std::vector<char> data(std::istreambuf_iterator<char>(input), {});
input.close();

View File

@ -325,7 +325,7 @@ namespace UIWidgets {
if (PlusMinusButton) {
#ifdef __SWITCH__
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 110.0f);
#elif __WIIU__
#elif defined(__WIIU__)
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f * 2);
#else
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f);
@ -439,9 +439,9 @@ namespace UIWidgets {
std::string FullName = "Random";
FullName += MakeInvisible;
if (ImGui::Button(FullName.c_str())) {
#ifdef __SWITCH__
#if defined(__SWITCH__) || defined(__WIIU__)
srand(time(NULL));
#endif
#endif
ImVec4 color = GetRandomValue(255);
colors->x = color.x;
colors->y = color.y;

View File

@ -1,13 +0,0 @@
#include "global.h"
// Define functions needed for the GCC build here.
f32 __floatundisf(u32 c) {
return (f32)c;
}
f64 __floatundidf(u32 c) {
return (f64)c;
}