mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-11-22 01:12:19 -05:00
Wii U support (#1097)
* Wii U support * [WiiU] Combined Dockerfile * [WiiU] Combined Dockerfile * [WiiU] Combined Dockerfile * Add Jenkins support * wiiu: fix scissor clamp * wiiu: improve button remapping * wiiu: fix scaling issues * Update Dockerfile after merge * Pull assets before build * Only stop container once * Adjust logging sinks * wiiu: Change button mapping to match PC version * wiiu: Implement controller changes * wiiu: Update BUILDING.md Co-authored-by: qurious-pixel <62252937+qurious-pixel@users.noreply.github.com> Co-authored-by: David Chavez <david@dcvz.io>
This commit is contained in:
parent
b989ef4f7f
commit
68e7f2e6c1
21
BUILDING.md
21
BUILDING.md
@ -167,6 +167,27 @@ cmake --build build-switch --target soh_nro
|
|||||||
# To develop the project open the repository in VSCode (or your preferred editor)
|
# To develop the project open the repository in VSCode (or your preferred editor)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Wii U
|
||||||
|
1. Requires that your build machine is setup with the tools necessary for your platform above
|
||||||
|
2. Requires that you have the Wii U build tools installed
|
||||||
|
3. Clone the Ship of Harkinian repository
|
||||||
|
4. Place one or more [compatible](#compatible-roms) roms in the `OTRExporter` directory with namings of your choice
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd Shipwright
|
||||||
|
# Setup cmake project for your host machine
|
||||||
|
cmake -H. -Bbuild-cmake -GNinja
|
||||||
|
# Extract assets & generate OTR (run this anytime you need to regenerate OTR)
|
||||||
|
cmake --build build-cmake --target ExtractAssets
|
||||||
|
# Setup cmake project for building for Wii U
|
||||||
|
cmake -H. -Bbuild-wiiu -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/WiiU.cmake # -DCMAKE_BUILD_TYPE:STRING=Release (if you're packaging)
|
||||||
|
# Build project and generate rpx
|
||||||
|
cmake --build build-wiiu --target soh
|
||||||
|
|
||||||
|
# Now you can run the executable in ./build-wiiu/soh/soh.rpx
|
||||||
|
# To develop the project open the repository in VSCode (or your preferred editor)
|
||||||
|
```
|
||||||
|
|
||||||
# Compatible Roms
|
# Compatible Roms
|
||||||
```
|
```
|
||||||
OOT_PAL_GC checksum 0x09465AC3
|
OOT_PAL_GC checksum 0x09465AC3
|
||||||
|
@ -122,7 +122,7 @@ add_subdirectory(ZAPDTR/ZAPD ${CMAKE_BINARY_DIR}/ZAPD)
|
|||||||
add_subdirectory(ZAPDTR/ZAPDUtils ${CMAKE_BINARY_DIR}/ZAPDUtils)
|
add_subdirectory(ZAPDTR/ZAPDUtils ${CMAKE_BINARY_DIR}/ZAPDUtils)
|
||||||
add_subdirectory(OTRExporter)
|
add_subdirectory(OTRExporter)
|
||||||
add_subdirectory(soh)
|
add_subdirectory(soh)
|
||||||
if(NOT CMAKE_SYSTEM_NAME MATCHES "Darwin|NintendoSwitch")
|
if(NOT CMAKE_SYSTEM_NAME MATCHES "Darwin|NintendoSwitch|CafeOS")
|
||||||
add_subdirectory(OTRGui)
|
add_subdirectory(OTRGui)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -179,13 +179,13 @@ add_custom_target(CreateOSXIcons
|
|||||||
add_dependencies(soh CreateOSXIcons)
|
add_dependencies(soh CreateOSXIcons)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME MATCHES "Windows|NintendoSwitch")
|
if(CMAKE_SYSTEM_NAME MATCHES "Windows|NintendoSwitch|CafeOS")
|
||||||
INSTALL(FILES ${CMAKE_SOURCE_DIR}/README.md DESTINATION . COMPONENT ship RENAME readme.txt )
|
INSTALL(FILES ${CMAKE_SOURCE_DIR}/README.md DESTINATION . COMPONENT ship RENAME readme.txt )
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||||
set(CPACK_GENERATOR "External")
|
set(CPACK_GENERATOR "External")
|
||||||
elseif(CMAKE_SYSTEM_NAME MATCHES "Windows|NintendoSwitch")
|
elseif(CMAKE_SYSTEM_NAME MATCHES "Windows|NintendoSwitch|CafeOS")
|
||||||
set(CPACK_GENERATOR "ZIP")
|
set(CPACK_GENERATOR "ZIP")
|
||||||
elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||||
set(CPACK_GENERATOR "Bundle")
|
set(CPACK_GENERATOR "Bundle")
|
||||||
|
@ -56,12 +56,13 @@ RUN \
|
|||||||
echo "deb [signed-by=/usr/local/share/keyring/devkitpro-pub.gpg] https://apt.devkitpro.org stable main" > /etc/apt/sources.list.d/devkitpro.list && \
|
echo "deb [signed-by=/usr/local/share/keyring/devkitpro-pub.gpg] https://apt.devkitpro.org stable main" > /etc/apt/sources.list.d/devkitpro.list && \
|
||||||
apt-get update -y && \
|
apt-get update -y && \
|
||||||
apt-get install -y devkitpro-pacman && \
|
apt-get install -y devkitpro-pacman && \
|
||||||
yes | dkp-pacman -Syu switch-dev switch-portlibs --noconfirm
|
yes | dkp-pacman -Syu switch-dev switch-portlibs wiiu-dev wiiu-portlibs --noconfirm
|
||||||
|
|
||||||
ENV DEVKITPRO=/opt/devkitpro
|
ENV DEVKITPRO=/opt/devkitpro
|
||||||
ENV DEVKITARM=/opt/devkitpro/devkitARM
|
ENV DEVKITARM=/opt/devkitpro/devkitARM
|
||||||
ENV DEVKITPPC=/opt/devkitpro/devkitPPC
|
ENV DEVKITPPC=/opt/devkitpro/devkitPPC
|
||||||
ENV PATH=$PATH:/opt/devkitpro/portlibs/switch/bin/
|
ENV PATH=$PATH:/opt/devkitpro/portlibs/switch/bin/:$DEVKITPPC/bin
|
||||||
|
ENV WUT_ROOT=$DEVKITPRO/wut
|
||||||
|
|
||||||
RUN mkdir /soh
|
RUN mkdir /soh
|
||||||
WORKDIR /soh
|
WORKDIR /soh
|
||||||
|
37
Jenkinsfile
vendored
37
Jenkinsfile
vendored
@ -185,6 +185,43 @@ pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
stage ('Build Wii U') {
|
||||||
|
agent {
|
||||||
|
label "SoH-Linux-Builders"
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
checkout([
|
||||||
|
$class: 'GitSCM',
|
||||||
|
branches: scm.branches,
|
||||||
|
doGenerateSubmoduleConfigurations: scm.doGenerateSubmoduleConfigurations,
|
||||||
|
extensions: scm.extensions,
|
||||||
|
userRemoteConfigs: scm.userRemoteConfigs
|
||||||
|
])
|
||||||
|
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
|
||||||
|
unstash 'assets'
|
||||||
|
sh '''
|
||||||
|
if docker ps -aq --filter "name=sohwiiucont" | grep -q .; then docker rm -f sohwiiucont; fi
|
||||||
|
docker build . -t sohwiiu
|
||||||
|
docker run --name sohwiiucont -dit --rm -v $(pwd):/soh sohwiiu /bin/bash
|
||||||
|
docker exec sohwiiucont scripts/wiiu/build.sh
|
||||||
|
|
||||||
|
mv build-wiiu/soh/*.rpx soh.rpx
|
||||||
|
mv README.md readme.txt
|
||||||
|
|
||||||
|
7z a soh-wiiu.7z soh.rpx readme.txt
|
||||||
|
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
archiveArtifacts artifacts: 'soh-wiiu.7z', followSymlinks: false, onlyIfSuccessful: true
|
||||||
|
}
|
||||||
|
post {
|
||||||
|
always {
|
||||||
|
sh 'sudo docker container stop sohwiiucont'
|
||||||
|
sh 'docker images --quiet --filter=dangling=true | xargs --no-run-if-empty docker rmi' // Clean dangling docker images
|
||||||
|
step([$class: 'WsCleanup']) // Clean workspace
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,12 @@
|
|||||||
// Local functions - platform-specific functions
|
// Local functions - platform-specific functions
|
||||||
|
|
||||||
#ifndef STORMLIB_WINDOWS
|
#ifndef STORMLIB_WINDOWS
|
||||||
|
|
||||||
|
#ifndef STORMLIB_WIIU // WIIU doesn't support thread_local
|
||||||
static thread_local DWORD dwLastError = ERROR_SUCCESS;
|
static thread_local DWORD dwLastError = ERROR_SUCCESS;
|
||||||
|
#else
|
||||||
|
static DWORD dwLastError = ERROR_SUCCESS;
|
||||||
|
#endif
|
||||||
|
|
||||||
DWORD GetLastError()
|
DWORD GetLastError()
|
||||||
{
|
{
|
||||||
|
@ -2005,7 +2005,7 @@ void ConvertTMPQHeader(void *header, uint16_t version)
|
|||||||
TMPQHeader * theHeader = (TMPQHeader *)header;
|
TMPQHeader * theHeader = (TMPQHeader *)header;
|
||||||
|
|
||||||
// Swap header part version 1
|
// Swap header part version 1
|
||||||
if(version == MPQ_FORMAT_VERSION_1)
|
if(version >= MPQ_FORMAT_VERSION_1)
|
||||||
{
|
{
|
||||||
theHeader->dwID = SwapUInt32(theHeader->dwID);
|
theHeader->dwID = SwapUInt32(theHeader->dwID);
|
||||||
theHeader->dwHeaderSize = SwapUInt32(theHeader->dwHeaderSize);
|
theHeader->dwHeaderSize = SwapUInt32(theHeader->dwHeaderSize);
|
||||||
@ -2018,21 +2018,21 @@ void ConvertTMPQHeader(void *header, uint16_t version)
|
|||||||
theHeader->dwBlockTableSize = SwapUInt32(theHeader->dwBlockTableSize);
|
theHeader->dwBlockTableSize = SwapUInt32(theHeader->dwBlockTableSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(version == MPQ_FORMAT_VERSION_2)
|
if(version >= MPQ_FORMAT_VERSION_2)
|
||||||
{
|
{
|
||||||
theHeader->HiBlockTablePos64 = SwapUInt64(theHeader->HiBlockTablePos64);
|
theHeader->HiBlockTablePos64 = SwapUInt64(theHeader->HiBlockTablePos64);
|
||||||
theHeader->wHashTablePosHi = SwapUInt16(theHeader->wHashTablePosHi);
|
theHeader->wHashTablePosHi = SwapUInt16(theHeader->wHashTablePosHi);
|
||||||
theHeader->wBlockTablePosHi = SwapUInt16(theHeader->wBlockTablePosHi);
|
theHeader->wBlockTablePosHi = SwapUInt16(theHeader->wBlockTablePosHi);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(version == MPQ_FORMAT_VERSION_3)
|
if(version >= MPQ_FORMAT_VERSION_3)
|
||||||
{
|
{
|
||||||
theHeader->ArchiveSize64 = SwapUInt64(theHeader->ArchiveSize64);
|
theHeader->ArchiveSize64 = SwapUInt64(theHeader->ArchiveSize64);
|
||||||
theHeader->BetTablePos64 = SwapUInt64(theHeader->BetTablePos64);
|
theHeader->BetTablePos64 = SwapUInt64(theHeader->BetTablePos64);
|
||||||
theHeader->HetTablePos64 = SwapUInt64(theHeader->HetTablePos64);
|
theHeader->HetTablePos64 = SwapUInt64(theHeader->HetTablePos64);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(version == MPQ_FORMAT_VERSION_4)
|
if(version >= MPQ_FORMAT_VERSION_4)
|
||||||
{
|
{
|
||||||
theHeader->HashTableSize64 = SwapUInt64(theHeader->HashTableSize64);
|
theHeader->HashTableSize64 = SwapUInt64(theHeader->HashTableSize64);
|
||||||
theHeader->BlockTableSize64 = SwapUInt64(theHeader->BlockTableSize64);
|
theHeader->BlockTableSize64 = SwapUInt64(theHeader->BlockTableSize64);
|
||||||
|
@ -180,7 +180,7 @@ static DWORD LoadAttributesFile(TMPQArchive * ha, LPBYTE pbAttrFile, DWORD cbAtt
|
|||||||
if((pbAttrPtr + cbArraySize) > pbAttrFileEnd)
|
if((pbAttrPtr + cbArraySize) > pbAttrFileEnd)
|
||||||
return ERROR_FILE_CORRUPT;
|
return ERROR_FILE_CORRUPT;
|
||||||
|
|
||||||
BSWAP_ARRAY32_UNSIGNED(ArrayCRC32, cbCRC32Size);
|
BSWAP_ARRAY32_UNSIGNED(ArrayCRC32, cbArraySize);
|
||||||
for(i = 0; i < dwAttributesEntries; i++)
|
for(i = 0; i < dwAttributesEntries; i++)
|
||||||
ha->pFileTable[i].dwCrc32 = ArrayCRC32[i];
|
ha->pFileTable[i].dwCrc32 = ArrayCRC32[i];
|
||||||
pbAttrPtr += cbArraySize;
|
pbAttrPtr += cbArraySize;
|
||||||
@ -196,7 +196,7 @@ static DWORD LoadAttributesFile(TMPQArchive * ha, LPBYTE pbAttrFile, DWORD cbAtt
|
|||||||
if((pbAttrPtr + cbArraySize) > pbAttrFileEnd)
|
if((pbAttrPtr + cbArraySize) > pbAttrFileEnd)
|
||||||
return ERROR_FILE_CORRUPT;
|
return ERROR_FILE_CORRUPT;
|
||||||
|
|
||||||
BSWAP_ARRAY64_UNSIGNED(ArrayFileTime, cbFileTimeSize);
|
BSWAP_ARRAY64_UNSIGNED(ArrayFileTime, cbArraySize);
|
||||||
for(i = 0; i < dwAttributesEntries; i++)
|
for(i = 0; i < dwAttributesEntries; i++)
|
||||||
ha->pFileTable[i].FileTime = ArrayFileTime[i];
|
ha->pFileTable[i].FileTime = ArrayFileTime[i];
|
||||||
pbAttrPtr += cbArraySize;
|
pbAttrPtr += cbArraySize;
|
||||||
|
@ -480,7 +480,7 @@ static bool IsMatchingPatchFile(
|
|||||||
{
|
{
|
||||||
// Load the patch header
|
// Load the patch header
|
||||||
SFileReadFile(hFile, &PatchHeader, sizeof(MPQ_PATCH_HEADER), &dwTransferred, NULL);
|
SFileReadFile(hFile, &PatchHeader, sizeof(MPQ_PATCH_HEADER), &dwTransferred, NULL);
|
||||||
BSWAP_ARRAY32_UNSIGNED(pPatchHeader, sizeof(DWORD) * 6);
|
BSWAP_ARRAY32_UNSIGNED(&PatchHeader, sizeof(DWORD) * 6);
|
||||||
|
|
||||||
// If the file contains an incremental patch,
|
// If the file contains an incremental patch,
|
||||||
// compare the "MD5 before patching" with the base file MD5
|
// compare the "MD5 before patching" with the base file MD5
|
||||||
|
@ -631,8 +631,8 @@ typedef struct _TMPQHash
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
BYTE Platform;
|
|
||||||
BYTE Reserved;
|
BYTE Reserved;
|
||||||
|
BYTE Platform;
|
||||||
USHORT lcLocale;
|
USHORT lcLocale;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -254,6 +254,34 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Defines for Wii U platform
|
||||||
|
|
||||||
|
#if !defined(STORMLIB_PLATFORM_DEFINED) && defined(__WIIU__)
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
#undef STORMLIB_LITTLE_ENDIAN // Wii U is always big endian
|
||||||
|
|
||||||
|
#define STORMLIB_MAC // Use Mac compatible code
|
||||||
|
#define STORMLIB_WIIU
|
||||||
|
#define STORMLIB_PLATFORM_DEFINED
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Assumption: If the platform is not defined, assume a Linux-like platform
|
// Assumption: If the platform is not defined, assume a Linux-like platform
|
||||||
|
|
||||||
|
@ -465,6 +465,12 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "NintendoSwitch")
|
|||||||
PNG::PNG
|
PNG::PNG
|
||||||
Threads::Threads
|
Threads::Threads
|
||||||
)
|
)
|
||||||
|
elseif(CMAKE_SYSTEM_NAME STREQUAL "CafeOS")
|
||||||
|
set(ADDITIONAL_LIBRARY_DEPENDENCIES
|
||||||
|
"ZAPDUtils;"
|
||||||
|
"libultraship;"
|
||||||
|
PNG::PNG
|
||||||
|
)
|
||||||
else()
|
else()
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
@ -478,7 +484,7 @@ else()
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME STREQUAL "NintendoSwitch")
|
if(CMAKE_SYSTEM_NAME MATCHES "NintendoSwitch|CafeOS")
|
||||||
add_library(pathconf OBJECT pathconf.c)
|
add_library(pathconf OBJECT pathconf.c)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE "${ADDITIONAL_LIBRARY_DEPENDENCIES}" $<TARGET_OBJECTS:pathconf> )
|
target_link_libraries(${PROJECT_NAME} PRIVATE "${ADDITIONAL_LIBRARY_DEPENDENCIES}" $<TARGET_OBJECTS:pathconf> )
|
||||||
else()
|
else()
|
||||||
|
@ -130,7 +130,13 @@ float BinaryReader::ReadSingle()
|
|||||||
stream->Read((char*)&result, sizeof(float));
|
stream->Read((char*)&result, sizeof(float));
|
||||||
|
|
||||||
if (endianness != Endianness::Native)
|
if (endianness != Endianness::Native)
|
||||||
result = BitConverter::ToFloatBE((uint8_t*)&result, 0);
|
{
|
||||||
|
float tmp;
|
||||||
|
char* dst = (char*)&tmp;
|
||||||
|
char* src = (char*)&result;
|
||||||
|
dst[3] = src[0]; dst[2] = src[1]; dst[1] = src[2]; dst[0] = src[3];
|
||||||
|
result = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
if (std::isnan(result))
|
if (std::isnan(result))
|
||||||
throw std::runtime_error("BinaryReader::ReadSingle(): Error reading stream");
|
throw std::runtime_error("BinaryReader::ReadSingle(): Error reading stream");
|
||||||
@ -145,7 +151,14 @@ double BinaryReader::ReadDouble()
|
|||||||
stream->Read((char*)&result, sizeof(double));
|
stream->Read((char*)&result, sizeof(double));
|
||||||
|
|
||||||
if (endianness != Endianness::Native)
|
if (endianness != Endianness::Native)
|
||||||
result = BitConverter::ToDoubleBE((uint8_t*)&result, 0);
|
{
|
||||||
|
double tmp;
|
||||||
|
char* dst = (char*)&tmp;
|
||||||
|
char* src = (char*)&result;
|
||||||
|
dst[7] = src[0]; dst[6] = src[1]; dst[5] = src[2]; dst[4] = src[3];
|
||||||
|
dst[3] = src[4]; dst[2] = src[5]; dst[1] = src[6]; dst[0] = src[7];
|
||||||
|
result = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
if (std::isnan(result))
|
if (std::isnan(result))
|
||||||
throw std::runtime_error("BinaryReader::ReadDouble(): Error reading stream");
|
throw std::runtime_error("BinaryReader::ReadDouble(): Error reading stream");
|
||||||
|
@ -107,7 +107,13 @@ void BinaryWriter::Write(uint64_t value)
|
|||||||
void BinaryWriter::Write(float value)
|
void BinaryWriter::Write(float value)
|
||||||
{
|
{
|
||||||
if (endianness != Endianness::Native)
|
if (endianness != Endianness::Native)
|
||||||
value = BitConverter::ToFloatBE((uint8_t*)&value, 0);
|
{
|
||||||
|
float tmp;
|
||||||
|
char* dst = (char*)&tmp;
|
||||||
|
char* src = (char*)&value;
|
||||||
|
dst[3] = src[0]; dst[2] = src[1]; dst[1] = src[2]; dst[0] = src[3];
|
||||||
|
value = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
stream->Write((char*)&value, sizeof(float));
|
stream->Write((char*)&value, sizeof(float));
|
||||||
}
|
}
|
||||||
@ -115,7 +121,14 @@ void BinaryWriter::Write(float value)
|
|||||||
void BinaryWriter::Write(double value)
|
void BinaryWriter::Write(double value)
|
||||||
{
|
{
|
||||||
if (endianness != Endianness::Native)
|
if (endianness != Endianness::Native)
|
||||||
value = BitConverter::ToDoubleBE((uint8_t*)&value, 0);
|
{
|
||||||
|
double tmp;
|
||||||
|
char* dst = (char*)&tmp;
|
||||||
|
char* src = (char*)&value;
|
||||||
|
dst[7] = src[0]; dst[6] = src[1]; dst[5] = src[2]; dst[4] = src[3];
|
||||||
|
dst[3] = src[4]; dst[2] = src[5]; dst[1] = src[6]; dst[0] = src[7];
|
||||||
|
value = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
stream->Write((char*)&value, sizeof(double));
|
stream->Write((char*)&value, sizeof(double));
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,11 @@ void StringHelper::ReplaceOriginal(std::string& str, const std::string& from, co
|
|||||||
|
|
||||||
bool StringHelper::StartsWith(const std::string& s, const std::string& input)
|
bool StringHelper::StartsWith(const std::string& s, const std::string& input)
|
||||||
{
|
{
|
||||||
|
#if __cplusplus >= 202002L
|
||||||
|
return s.starts_with(input.c_str());
|
||||||
|
#else
|
||||||
return s.rfind(input, 0) == 0;
|
return s.rfind(input, 0) == 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StringHelper::Contains(const std::string& s, const std::string& input)
|
bool StringHelper::Contains(const std::string& s, const std::string& input)
|
||||||
|
@ -86,11 +86,17 @@ set(Source_Files__Controller
|
|||||||
"InputEditor.h"
|
"InputEditor.h"
|
||||||
"KeyboardController.cpp"
|
"KeyboardController.cpp"
|
||||||
"KeyboardController.h"
|
"KeyboardController.h"
|
||||||
"SDLController.cpp"
|
|
||||||
"SDLController.h"
|
|
||||||
"UltraController.h"
|
"UltraController.h"
|
||||||
"DummyController.h"
|
"DummyController.h"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (NOT CMAKE_SYSTEM_NAME STREQUAL "CafeOS")
|
||||||
|
list(APPEND Source_Files__Controller
|
||||||
|
"SDLController.cpp"
|
||||||
|
"SDLController.h"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
source_group("Source Files\\Controller" FILES ${Source_Files__Controller})
|
source_group("Source Files\\Controller" FILES ${Source_Files__Controller})
|
||||||
|
|
||||||
set(Source_Files__Controller__Attachment
|
set(Source_Files__Controller__Attachment
|
||||||
@ -150,16 +156,21 @@ source_group("Source Files\\Lib" FILES ${Source_Files__Lib})
|
|||||||
set(Source_Files__Lib__Fast3D
|
set(Source_Files__Lib__Fast3D
|
||||||
"Lib/Fast3D/gfx_cc.cpp"
|
"Lib/Fast3D/gfx_cc.cpp"
|
||||||
"Lib/Fast3D/gfx_cc.h"
|
"Lib/Fast3D/gfx_cc.h"
|
||||||
"Lib/Fast3D/gfx_opengl.cpp"
|
|
||||||
"Lib/Fast3D/gfx_opengl.h"
|
|
||||||
"Lib/Fast3D/gfx_pc.cpp"
|
"Lib/Fast3D/gfx_pc.cpp"
|
||||||
"Lib/Fast3D/gfx_pc.h"
|
"Lib/Fast3D/gfx_pc.h"
|
||||||
"Lib/Fast3D/gfx_rendering_api.h"
|
"Lib/Fast3D/gfx_rendering_api.h"
|
||||||
"Lib/Fast3D/gfx_screen_config.h"
|
"Lib/Fast3D/gfx_screen_config.h"
|
||||||
"Lib/Fast3D/gfx_sdl.h"
|
|
||||||
"Lib/Fast3D/gfx_sdl2.cpp"
|
|
||||||
"Lib/Fast3D/gfx_window_manager_api.h"
|
"Lib/Fast3D/gfx_window_manager_api.h"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (NOT CMAKE_SYSTEM_NAME STREQUAL "CafeOS")
|
||||||
|
list(APPEND Source_Files__Lib__Fast3D
|
||||||
|
"Lib/Fast3D/gfx_opengl.cpp"
|
||||||
|
"Lib/Fast3D/gfx_opengl.h"
|
||||||
|
"Lib/Fast3D/gfx_sdl.h"
|
||||||
|
"Lib/Fast3D/gfx_sdl2.cpp"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
source_group("Source Files\\Lib\\Fast3D" FILES ${Source_Files__Lib__Fast3D})
|
source_group("Source Files\\Lib\\Fast3D" FILES ${Source_Files__Lib__Fast3D})
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
@ -179,14 +190,19 @@ set(Source_Files__Lib__Fast3D__extra
|
|||||||
"Lib/Fast3D/gfx_glx.cpp"
|
"Lib/Fast3D/gfx_glx.cpp"
|
||||||
"Lib/Fast3D/gfx_glx.h"
|
"Lib/Fast3D/gfx_glx.h"
|
||||||
)
|
)
|
||||||
|
elseif (CMAKE_SYSTEM_NAME STREQUAL "CafeOS")
|
||||||
|
set(Source_Files__Lib__Fast3D__extra
|
||||||
|
"Lib/Fast3D/gfx_wiiu.cpp"
|
||||||
|
"Lib/Fast3D/gfx_wiiu.h"
|
||||||
|
"Lib/Fast3D/gfx_gx2.cpp"
|
||||||
|
"Lib/Fast3D/gfx_gx2.h"
|
||||||
|
"Lib/Fast3D/gx2_shader_gen.c"
|
||||||
|
"Lib/Fast3D/gx2_shader_gen.h"
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
source_group("Source Files\\Lib\\Fast3D\\extra" FILES ${Source_Files__Lib__Fast3D__extra})
|
source_group("Source Files\\Lib\\Fast3D\\extra" FILES ${Source_Files__Lib__Fast3D__extra})
|
||||||
|
|
||||||
set(Source_Files__Lib__ImGui
|
set(Source_Files__Lib__ImGui
|
||||||
"Lib/ImGui/backends/imgui_impl_opengl3.cpp"
|
|
||||||
"Lib/ImGui/backends/imgui_impl_opengl3.h"
|
|
||||||
"Lib/ImGui/backends/imgui_impl_sdl.cpp"
|
|
||||||
"Lib/ImGui/backends/imgui_impl_sdl.h"
|
|
||||||
"Lib/ImGui/imconfig.h"
|
"Lib/ImGui/imconfig.h"
|
||||||
"Lib/ImGui/imgui.cpp"
|
"Lib/ImGui/imgui.cpp"
|
||||||
"Lib/ImGui/imgui.h"
|
"Lib/ImGui/imgui.h"
|
||||||
@ -199,6 +215,16 @@ set(Source_Files__Lib__ImGui
|
|||||||
"Lib/ImGui/imstb_textedit.h"
|
"Lib/ImGui/imstb_textedit.h"
|
||||||
"Lib/ImGui/imstb_truetype.h"
|
"Lib/ImGui/imstb_truetype.h"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (NOT CMAKE_SYSTEM_NAME STREQUAL "CafeOS")
|
||||||
|
list(APPEND Source_Files__Lib__ImGui
|
||||||
|
"Lib/ImGui/backends/imgui_impl_opengl3.cpp"
|
||||||
|
"Lib/ImGui/backends/imgui_impl_opengl3.h"
|
||||||
|
"Lib/ImGui/backends/imgui_impl_sdl.cpp"
|
||||||
|
"Lib/ImGui/backends/imgui_impl_sdl.h"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
set(Source_Files__Lib__ImGui__Windows
|
set(Source_Files__Lib__ImGui__Windows
|
||||||
"Lib/ImGui/backends/imgui_impl_dx11.cpp"
|
"Lib/ImGui/backends/imgui_impl_dx11.cpp"
|
||||||
@ -206,8 +232,19 @@ set(Source_Files__Lib__ImGui__Windows
|
|||||||
"Lib/ImGui/backends/imgui_impl_win32.cpp"
|
"Lib/ImGui/backends/imgui_impl_win32.cpp"
|
||||||
"Lib/ImGui/backends/imgui_impl_win32.h"
|
"Lib/ImGui/backends/imgui_impl_win32.h"
|
||||||
)
|
)
|
||||||
|
elseif (CMAKE_SYSTEM_NAME STREQUAL "CafeOS")
|
||||||
|
set(Source_Files__Lib__ImGui__WiiU
|
||||||
|
"Lib/ImGui/backends/wiiu/imgui_impl_wiiu.cpp"
|
||||||
|
"Lib/ImGui/backends/wiiu/imgui_impl_wiiu.h"
|
||||||
|
"Lib/ImGui/backends/wiiu/imgui_impl_gx2.cpp"
|
||||||
|
"Lib/ImGui/backends/wiiu/imgui_impl_gx2.h"
|
||||||
|
)
|
||||||
endif ()
|
endif ()
|
||||||
source_group("Source Files\\Lib\\ImGui" FILES ${Source_Files__Lib__ImGui} ${Source_Files__Lib__ImGui__Windows})
|
source_group("Source Files\\Lib\\ImGui" FILES
|
||||||
|
${Source_Files__Lib__ImGui}
|
||||||
|
${Source_Files__Lib__ImGui__Windows}
|
||||||
|
${Source_Files__Lib__ImGui__WiiU}
|
||||||
|
)
|
||||||
|
|
||||||
set(Source_Files__Lib__Mercury
|
set(Source_Files__Lib__Mercury
|
||||||
"Lib/Mercury/Mercury.cpp"
|
"Lib/Mercury/Mercury.cpp"
|
||||||
@ -316,6 +353,18 @@ set(Source_Files__NintendoSwitch
|
|||||||
source_group("Source Files\\NintendoSwitch" FILES ${Source_Files__NintendoSwitch})
|
source_group("Source Files\\NintendoSwitch" FILES ${Source_Files__NintendoSwitch})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (CMAKE_SYSTEM_NAME STREQUAL "CafeOS")
|
||||||
|
set(Source_Files__CafeOS
|
||||||
|
"WiiUController.cpp"
|
||||||
|
"WiiUController.h"
|
||||||
|
"WiiUGamepad.cpp"
|
||||||
|
"WiiUGamepad.h"
|
||||||
|
"WiiUImpl.cpp"
|
||||||
|
"WiiUImpl.h"
|
||||||
|
)
|
||||||
|
source_group("Source Files\\CafeOS" FILES ${Source_Files__CafeOS})
|
||||||
|
endif()
|
||||||
|
|
||||||
set(ALL_FILES
|
set(ALL_FILES
|
||||||
${Header_Files__Resources__Factories}
|
${Header_Files__Resources__Factories}
|
||||||
${Header_Files__Resources__Files}
|
${Header_Files__Resources__Files}
|
||||||
@ -332,6 +381,7 @@ set(ALL_FILES
|
|||||||
${Source_Files__Lib__Fast3D__extra}
|
${Source_Files__Lib__Fast3D__extra}
|
||||||
${Source_Files__Lib__ImGui}
|
${Source_Files__Lib__ImGui}
|
||||||
${Source_Files__Lib__ImGui__Windows}
|
${Source_Files__Lib__ImGui__Windows}
|
||||||
|
${Source_Files__Lib__ImGui__WiiU}
|
||||||
${Source_Files__Lib__Mercury}
|
${Source_Files__Lib__Mercury}
|
||||||
${Source_Files__Lib__stb}
|
${Source_Files__Lib__stb}
|
||||||
${Source_Files__Lib__dr_libs}
|
${Source_Files__Lib__dr_libs}
|
||||||
@ -343,6 +393,7 @@ set(ALL_FILES
|
|||||||
${Source_Files__Resources__mpq}
|
${Source_Files__Resources__mpq}
|
||||||
${Source_Files__Darwin}
|
${Source_Files__Darwin}
|
||||||
${Source_Files__NintendoSwitch}
|
${Source_Files__NintendoSwitch}
|
||||||
|
${Source_Files__CafeOS}
|
||||||
)
|
)
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
@ -445,9 +496,21 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
|||||||
STORMLIB_NO_AUTO_LINK
|
STORMLIB_NO_AUTO_LINK
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
|
||||||
|
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|Clang|AppleClang")
|
elseif (CMAKE_SYSTEM_NAME STREQUAL "CafeOS")
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
||||||
|
"$<$<CONFIG:Debug>:"
|
||||||
|
"_DEBUG"
|
||||||
|
">"
|
||||||
|
"$<$<CONFIG:Release>:"
|
||||||
|
"NDEBUG"
|
||||||
|
">"
|
||||||
|
"SPDLOG_ACTIVE_LEVEL=3;"
|
||||||
|
"SPDLOG_NO_THREAD_ID;"
|
||||||
|
"SPDLOG_NO_TLS;"
|
||||||
|
"STBI_NO_THREAD_LOCALS;"
|
||||||
|
)
|
||||||
|
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|Clang|AppleClang")
|
||||||
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
||||||
"$<$<CONFIG:Debug>:"
|
"$<$<CONFIG:Debug>:"
|
||||||
"_DEBUG"
|
"_DEBUG"
|
||||||
@ -462,7 +525,7 @@ endif()
|
|||||||
################################################################################
|
################################################################################
|
||||||
# Compile and link options
|
# Compile and link options
|
||||||
################################################################################
|
################################################################################
|
||||||
if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows|NintendoSwitch")
|
if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows|NintendoSwitch|CafeOS")
|
||||||
find_package(SDL2)
|
find_package(SDL2)
|
||||||
find_package(GLEW)
|
find_package(GLEW)
|
||||||
find_package(X11)
|
find_package(X11)
|
||||||
@ -485,7 +548,7 @@ if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows|NintendoSwitch")
|
|||||||
set(GLEW-INCLUDE ${GLEW_INCLUDE_DIRS})
|
set(GLEW-INCLUDE ${GLEW_INCLUDE_DIRS})
|
||||||
endif()
|
endif()
|
||||||
set(SDL2-INCLUDE ${SDL2_INCLUDE_DIRS})
|
set(SDL2-INCLUDE ${SDL2_INCLUDE_DIRS})
|
||||||
elseif (CMAKE_SYSTEM_NAME MATCHES "NintendoSwitch")
|
elseif (CMAKE_SYSTEM_NAME MATCHES "NintendoSwitch|CafeOS")
|
||||||
find_package(SDL2)
|
find_package(SDL2)
|
||||||
else()
|
else()
|
||||||
set(GLEW-INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/Lib/GLEW/)
|
set(GLEW-INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/Lib/GLEW/)
|
||||||
@ -627,6 +690,15 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "NintendoSwitch")
|
|||||||
SDL2::SDL2
|
SDL2::SDL2
|
||||||
Threads::Threads
|
Threads::Threads
|
||||||
)
|
)
|
||||||
|
elseif(CMAKE_SYSTEM_NAME STREQUAL "CafeOS")
|
||||||
|
find_package(SDL2 REQUIRED)
|
||||||
|
target_link_libraries(${PROJECT_NAME}
|
||||||
|
storm
|
||||||
|
SDL2::SDL2-static
|
||||||
|
)
|
||||||
|
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||||
|
${DEVKITPRO}/portlibs/wiiu/include/
|
||||||
|
)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(${PROJECT_NAME}
|
target_link_libraries(${PROJECT_NAME}
|
||||||
SDL2::SDL2
|
SDL2::SDL2
|
||||||
|
@ -3,11 +3,17 @@
|
|||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
#include "Controller.h"
|
#include "Controller.h"
|
||||||
#include "DummyController.h"
|
#include "DummyController.h"
|
||||||
#include "KeyboardController.h"
|
|
||||||
#include "SDLController.h"
|
|
||||||
#include <Utils/StringHelper.h>
|
#include <Utils/StringHelper.h>
|
||||||
#include "Cvar.h"
|
#include "Cvar.h"
|
||||||
|
|
||||||
|
#ifndef __WIIU__
|
||||||
|
#include "KeyboardController.h"
|
||||||
|
#include "SDLController.h"
|
||||||
|
#else
|
||||||
|
#include "WiiUGamepad.h"
|
||||||
|
#include "WiiUController.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Ship {
|
namespace Ship {
|
||||||
|
|
||||||
void ControlDeck::Init(uint8_t* bits) {
|
void ControlDeck::Init(uint8_t* bits) {
|
||||||
@ -20,6 +26,7 @@ namespace Ship {
|
|||||||
virtualDevices.clear();
|
virtualDevices.clear();
|
||||||
physicalDevices.clear();
|
physicalDevices.clear();
|
||||||
|
|
||||||
|
#ifndef __WIIU__
|
||||||
for (int i = 0; i < SDL_NumJoysticks(); i++) {
|
for (int i = 0; i < SDL_NumJoysticks(); i++) {
|
||||||
if (SDL_IsGameController(i)) {
|
if (SDL_IsGameController(i)) {
|
||||||
auto sdl = std::make_shared<SDLController>(i);
|
auto sdl = std::make_shared<SDLController>(i);
|
||||||
@ -30,6 +37,20 @@ namespace Ship {
|
|||||||
|
|
||||||
physicalDevices.push_back(std::make_shared<DummyController>("Auto", "Auto", true));
|
physicalDevices.push_back(std::make_shared<DummyController>("Auto", "Auto", true));
|
||||||
physicalDevices.push_back(std::make_shared<KeyboardController>());
|
physicalDevices.push_back(std::make_shared<KeyboardController>());
|
||||||
|
#else
|
||||||
|
physicalDevices.push_back(std::make_shared<DummyController>("Auto", "Auto", true));
|
||||||
|
|
||||||
|
auto gamepad = std::make_shared<Ship::WiiUGamepad>();
|
||||||
|
gamepad->Open();
|
||||||
|
physicalDevices.push_back(gamepad);
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
auto controller = std::make_shared<Ship::WiiUController>((WPADChan) i);
|
||||||
|
controller->Open();
|
||||||
|
physicalDevices.push_back(controller);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
physicalDevices.push_back(std::make_shared<DummyController>("Disconnected", "None", false));
|
physicalDevices.push_back(std::make_shared<DummyController>("Disconnected", "None", false));
|
||||||
|
|
||||||
for (const auto& device : physicalDevices) {
|
for (const auto& device : physicalDevices) {
|
||||||
|
@ -21,7 +21,9 @@ namespace Ship {
|
|||||||
void Controller::Read(OSContPad* pad, int32_t virtualSlot) {
|
void Controller::Read(OSContPad* pad, int32_t virtualSlot) {
|
||||||
ReadFromSource(virtualSlot);
|
ReadFromSource(virtualSlot);
|
||||||
|
|
||||||
|
#ifndef __WIIU__
|
||||||
SDL_PumpEvents();
|
SDL_PumpEvents();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Button Inputs
|
// Button Inputs
|
||||||
pad->button |= getPressedButtons(virtualSlot) & 0xFFFF;
|
pad->button |= getPressedButtons(virtualSlot) & 0xFFFF;
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
#include "OSXFolderManager.h"
|
#include "OSXFolderManager.h"
|
||||||
#elif defined(__SWITCH__)
|
#elif defined(__SWITCH__)
|
||||||
#include "SwitchImpl.h"
|
#include "SwitchImpl.h"
|
||||||
|
#elif defined(__WIIU__)
|
||||||
|
#include "WiiUImpl.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Ship {
|
namespace Ship {
|
||||||
@ -59,7 +61,6 @@ namespace Ship {
|
|||||||
void GlobalCtx2::InitWindow() {
|
void GlobalCtx2::InitWindow() {
|
||||||
InitLogging();
|
InitLogging();
|
||||||
Config = std::make_shared<Mercury>(GetPathRelativeToAppDirectory("shipofharkinian.json"));
|
Config = std::make_shared<Mercury>(GetPathRelativeToAppDirectory("shipofharkinian.json"));
|
||||||
Config->reload();
|
|
||||||
|
|
||||||
MainPath = Config->getString("Game.Main Archive", GetPathRelativeToAppDirectory("oot.otr"));
|
MainPath = Config->getString("Game.Main Archive", GetPathRelativeToAppDirectory("oot.otr"));
|
||||||
PatchesPath = Config->getString("Game.Patches Archive", GetAppDirectoryPath() + "/mods");
|
PatchesPath = Config->getString("Game.Patches Archive", GetAppDirectoryPath() + "/mods");
|
||||||
@ -73,6 +74,8 @@ namespace Ship {
|
|||||||
MessageBox(nullptr, L"Main OTR file not found!", L"Uh oh", MB_OK);
|
MessageBox(nullptr, L"Main OTR file not found!", L"Uh oh", MB_OK);
|
||||||
#elif defined(__SWITCH__)
|
#elif defined(__SWITCH__)
|
||||||
printf("Main OTR file not found!\n");
|
printf("Main OTR file not found!\n");
|
||||||
|
#elif defined(__WIIU__)
|
||||||
|
Ship::WiiU::ThrowMissingOTR(MainPath.c_str());
|
||||||
#else
|
#else
|
||||||
SPDLOG_ERROR("Main OTR file not found!");
|
SPDLOG_ERROR("Main OTR file not found!");
|
||||||
#endif
|
#endif
|
||||||
@ -85,28 +88,36 @@ namespace Ship {
|
|||||||
|
|
||||||
void GlobalCtx2::InitLogging() {
|
void GlobalCtx2::InitLogging() {
|
||||||
try {
|
try {
|
||||||
auto logPath = GetPathRelativeToAppDirectory(("logs/" + GetName() + ".log").c_str());
|
|
||||||
|
|
||||||
// Setup Logging
|
// Setup Logging
|
||||||
spdlog::init_thread_pool(8192, 1);
|
spdlog::init_thread_pool(8192, 1);
|
||||||
|
std::vector<spdlog::sink_ptr> Sinks;
|
||||||
|
|
||||||
auto SohConsoleSink = std::make_shared<spdlog::sinks::soh_sink_mt>();
|
auto SohConsoleSink = std::make_shared<spdlog::sinks::soh_sink_mt>();
|
||||||
SohConsoleSink->set_level(spdlog::level::trace);
|
SohConsoleSink->set_level(spdlog::level::trace);
|
||||||
#if defined(__linux__)
|
Sinks.push_back(SohConsoleSink);
|
||||||
|
|
||||||
|
#if (!defined(_WIN32) && !defined(__WIIU__)) || defined(_DEBUG)
|
||||||
auto ConsoleSink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
|
auto ConsoleSink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
|
||||||
ConsoleSink->set_level(spdlog::level::trace);
|
ConsoleSink->set_level(spdlog::level::trace);
|
||||||
|
Sinks.push_back(ConsoleSink);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __WIIU__
|
||||||
|
auto logPath = GetPathRelativeToAppDirectory(("logs/" + GetName() + ".log").c_str());
|
||||||
auto FileSink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(logPath, 1024 * 1024 * 10, 10);
|
auto FileSink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(logPath, 1024 * 1024 * 10, 10);
|
||||||
FileSink->set_level(spdlog::level::trace);
|
FileSink->set_level(spdlog::level::trace);
|
||||||
std::vector<spdlog::sink_ptr> Sinks{
|
Sinks.push_back(FileSink);
|
||||||
#if defined(__linux__)
|
|
||||||
ConsoleSink,
|
|
||||||
#endif
|
#endif
|
||||||
FileSink,
|
|
||||||
SohConsoleSink
|
|
||||||
};
|
|
||||||
Logger = std::make_shared<spdlog::async_logger>(GetName(), Sinks.begin(), Sinks.end(), spdlog::thread_pool(), spdlog::async_overflow_policy::block);
|
Logger = std::make_shared<spdlog::async_logger>(GetName(), Sinks.begin(), Sinks.end(), spdlog::thread_pool(), spdlog::async_overflow_policy::block);
|
||||||
GetLogger()->set_level(spdlog::level::trace);
|
GetLogger()->set_level(spdlog::level::trace);
|
||||||
|
|
||||||
|
#ifndef __WIIU__
|
||||||
GetLogger()->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%@] [%l] %v");
|
GetLogger()->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%@] [%l] %v");
|
||||||
|
#else
|
||||||
|
GetLogger()->set_pattern("[%s:%#] [%l] %v");
|
||||||
|
#endif
|
||||||
|
|
||||||
spdlog::register_logger(GetLogger());
|
spdlog::register_logger(GetLogger());
|
||||||
spdlog::set_default_logger(GetLogger());
|
spdlog::set_default_logger(GetLogger());
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,16 @@
|
|||||||
#include "Lib/spdlog/include/spdlog/common.h"
|
#include "Lib/spdlog/include/spdlog/common.h"
|
||||||
#include "UltraController.h"
|
#include "UltraController.h"
|
||||||
|
|
||||||
|
#ifdef __WIIU__
|
||||||
|
#include <gx2/registers.h> // GX2SetViewport / GX2SetScissor
|
||||||
|
|
||||||
|
#include "Lib/ImGui/backends/wiiu/imgui_impl_gx2.h"
|
||||||
|
#include "Lib/ImGui/backends/wiiu/imgui_impl_wiiu.h"
|
||||||
|
|
||||||
|
#include "Lib/Fast3D/gfx_wiiu.h"
|
||||||
|
#include "Lib/Fast3D/gfx_gx2.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if __APPLE__
|
#if __APPLE__
|
||||||
#include <SDL_hints.h>
|
#include <SDL_hints.h>
|
||||||
#else
|
#else
|
||||||
@ -101,7 +111,11 @@ namespace SohImGui {
|
|||||||
bool statsWindowOpen;
|
bool statsWindowOpen;
|
||||||
|
|
||||||
const char* filters[3] = {
|
const char* filters[3] = {
|
||||||
|
#ifdef __WIIU__
|
||||||
|
"",
|
||||||
|
#else
|
||||||
"Three-Point",
|
"Three-Point",
|
||||||
|
#endif
|
||||||
"Linear",
|
"Linear",
|
||||||
"None"
|
"None"
|
||||||
};
|
};
|
||||||
@ -110,7 +124,11 @@ namespace SohImGui {
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
{ "dx11", "DirectX" },
|
{ "dx11", "DirectX" },
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef __WIIU__
|
||||||
{ "sdl", "OpenGL" }
|
{ "sdl", "OpenGL" }
|
||||||
|
#else
|
||||||
|
{ "wiiu", "GX2" }
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -178,10 +196,16 @@ namespace SohImGui {
|
|||||||
|
|
||||||
void ImGuiWMInit() {
|
void ImGuiWMInit() {
|
||||||
switch (impl.backend) {
|
switch (impl.backend) {
|
||||||
|
#ifdef __WIIU__
|
||||||
|
case Backend::GX2:
|
||||||
|
ImGui_ImplWiiU_Init();
|
||||||
|
break;
|
||||||
|
#else
|
||||||
case Backend::SDL:
|
case Backend::SDL:
|
||||||
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "1");
|
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "1");
|
||||||
ImGui_ImplSDL2_InitForOpenGL(static_cast<SDL_Window*>(impl.sdl.window), impl.sdl.context);
|
ImGui_ImplSDL2_InitForOpenGL(static_cast<SDL_Window*>(impl.sdl.window), impl.sdl.context);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
#if defined(ENABLE_DX11) || defined(ENABLE_DX12)
|
#if defined(ENABLE_DX11) || defined(ENABLE_DX12)
|
||||||
case Backend::DX11:
|
case Backend::DX11:
|
||||||
ImGui_ImplWin32_Init(impl.dx11.window);
|
ImGui_ImplWin32_Init(impl.dx11.window);
|
||||||
@ -195,6 +219,11 @@ namespace SohImGui {
|
|||||||
|
|
||||||
void ImGuiBackendInit() {
|
void ImGuiBackendInit() {
|
||||||
switch (impl.backend) {
|
switch (impl.backend) {
|
||||||
|
#ifdef __WIIU__
|
||||||
|
case Backend::GX2:
|
||||||
|
ImGui_ImplGX2_Init();
|
||||||
|
break;
|
||||||
|
#else
|
||||||
case Backend::SDL:
|
case Backend::SDL:
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
ImGui_ImplOpenGL3_Init("#version 410 core");
|
ImGui_ImplOpenGL3_Init("#version 410 core");
|
||||||
@ -202,6 +231,7 @@ namespace SohImGui {
|
|||||||
ImGui_ImplOpenGL3_Init("#version 120");
|
ImGui_ImplOpenGL3_Init("#version 120");
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(ENABLE_DX11) || defined(ENABLE_DX12)
|
#if defined(ENABLE_DX11) || defined(ENABLE_DX12)
|
||||||
case Backend::DX11:
|
case Backend::DX11:
|
||||||
@ -215,9 +245,17 @@ namespace SohImGui {
|
|||||||
|
|
||||||
void ImGuiProcessEvent(EventImpl event) {
|
void ImGuiProcessEvent(EventImpl event) {
|
||||||
switch (impl.backend) {
|
switch (impl.backend) {
|
||||||
|
#ifdef __WIIU__
|
||||||
|
case Backend::GX2:
|
||||||
|
if (!ImGui_ImplWiiU_ProcessInput((ImGui_ImplWiiU_ControllerInput*)event.gx2.input)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#else
|
||||||
case Backend::SDL:
|
case Backend::SDL:
|
||||||
ImGui_ImplSDL2_ProcessEvent(static_cast<const SDL_Event*>(event.sdl.event));
|
ImGui_ImplSDL2_ProcessEvent(static_cast<const SDL_Event*>(event.sdl.event));
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
#if defined(ENABLE_DX11) || defined(ENABLE_DX12)
|
#if defined(ENABLE_DX11) || defined(ENABLE_DX12)
|
||||||
case Backend::DX11:
|
case Backend::DX11:
|
||||||
ImGui_ImplWin32_WndProcHandler(static_cast<HWND>(event.win32.handle), event.win32.msg, event.win32.wparam, event.win32.lparam);
|
ImGui_ImplWin32_WndProcHandler(static_cast<HWND>(event.win32.handle), event.win32.msg, event.win32.wparam, event.win32.lparam);
|
||||||
@ -230,9 +268,14 @@ namespace SohImGui {
|
|||||||
|
|
||||||
void ImGuiWMNewFrame() {
|
void ImGuiWMNewFrame() {
|
||||||
switch (impl.backend) {
|
switch (impl.backend) {
|
||||||
|
#ifdef __WIIU__
|
||||||
|
case Backend::GX2:
|
||||||
|
break;
|
||||||
|
#else
|
||||||
case Backend::SDL:
|
case Backend::SDL:
|
||||||
ImGui_ImplSDL2_NewFrame(static_cast<SDL_Window*>(impl.sdl.window));
|
ImGui_ImplSDL2_NewFrame(static_cast<SDL_Window*>(impl.sdl.window));
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
#if defined(ENABLE_DX11) || defined(ENABLE_DX12)
|
#if defined(ENABLE_DX11) || defined(ENABLE_DX12)
|
||||||
case Backend::DX11:
|
case Backend::DX11:
|
||||||
ImGui_ImplWin32_NewFrame();
|
ImGui_ImplWin32_NewFrame();
|
||||||
@ -245,9 +288,16 @@ namespace SohImGui {
|
|||||||
|
|
||||||
void ImGuiBackendNewFrame() {
|
void ImGuiBackendNewFrame() {
|
||||||
switch (impl.backend) {
|
switch (impl.backend) {
|
||||||
|
#ifdef __WIIU__
|
||||||
|
case Backend::GX2:
|
||||||
|
io->DeltaTime = (float) frametime / 1000.0f / 1000.0f;
|
||||||
|
ImGui_ImplGX2_NewFrame();
|
||||||
|
break;
|
||||||
|
#else
|
||||||
case Backend::SDL:
|
case Backend::SDL:
|
||||||
ImGui_ImplOpenGL3_NewFrame();
|
ImGui_ImplOpenGL3_NewFrame();
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
#if defined(ENABLE_DX11) || defined(ENABLE_DX12)
|
#if defined(ENABLE_DX11) || defined(ENABLE_DX12)
|
||||||
case Backend::DX11:
|
case Backend::DX11:
|
||||||
ImGui_ImplDX11_NewFrame();
|
ImGui_ImplDX11_NewFrame();
|
||||||
@ -260,9 +310,20 @@ namespace SohImGui {
|
|||||||
|
|
||||||
void ImGuiRenderDrawData(ImDrawData* data) {
|
void ImGuiRenderDrawData(ImDrawData* data) {
|
||||||
switch (impl.backend) {
|
switch (impl.backend) {
|
||||||
|
#ifdef __WIIU__
|
||||||
|
case Backend::GX2:
|
||||||
|
ImGui_ImplGX2_RenderDrawData(data);
|
||||||
|
|
||||||
|
// Reset viewport and scissor for drawing the keyboard
|
||||||
|
GX2SetViewport(0.0f, 0.0f, io->DisplaySize.x, io->DisplaySize.y, 0.0f, 1.0f);
|
||||||
|
GX2SetScissor(0, 0, io->DisplaySize.x, io->DisplaySize.y);
|
||||||
|
ImGui_ImplWiiU_DrawKeyboardOverlay();
|
||||||
|
break;
|
||||||
|
#else
|
||||||
case Backend::SDL:
|
case Backend::SDL:
|
||||||
ImGui_ImplOpenGL3_RenderDrawData(data);
|
ImGui_ImplOpenGL3_RenderDrawData(data);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
#if defined(ENABLE_DX11) || defined(ENABLE_DX12)
|
#if defined(ENABLE_DX11) || defined(ENABLE_DX12)
|
||||||
case Backend::DX11:
|
case Backend::DX11:
|
||||||
ImGui_ImplDX11_RenderDrawData(data);
|
ImGui_ImplDX11_RenderDrawData(data);
|
||||||
@ -395,9 +456,19 @@ namespace SohImGui {
|
|||||||
Ship::Switch::SetupFont(io->Fonts);
|
Ship::Switch::SetupFont(io->Fonts);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __WIIU__
|
||||||
|
// Scale everything by 2 for the Wii U
|
||||||
|
ImGui::GetStyle().ScaleAllSizes(2.0f);
|
||||||
|
io->FontGlobalScale = 2.0f;
|
||||||
|
|
||||||
|
// Setup display sizes
|
||||||
|
io->DisplaySize.x = window_impl.gx2.width;
|
||||||
|
io->DisplaySize.y = window_impl.gx2.height;
|
||||||
|
#endif
|
||||||
|
|
||||||
lastBackendID = GetBackendID(GlobalCtx2::GetInstance()->GetConfig());
|
lastBackendID = GetBackendID(GlobalCtx2::GetInstance()->GetConfig());
|
||||||
if (CVar_GetS32("gOpenMenuBar", 0) != 1) {
|
if (CVar_GetS32("gOpenMenuBar", 0) != 1) {
|
||||||
#ifdef __SWITCH__
|
#if defined(__SWITCH__) || defined(__WIIU__)
|
||||||
SohImGui::overlay->TextDrawNotification(30.0f, true, "Press - to access enhancements menu");
|
SohImGui::overlay->TextDrawNotification(30.0f, true, "Press - to access enhancements menu");
|
||||||
#else
|
#else
|
||||||
SohImGui::overlay->TextDrawNotification(30.0f, true, "Press F1 to access enhancements menu");
|
SohImGui::overlay->TextDrawNotification(30.0f, true, "Press F1 to access enhancements menu");
|
||||||
@ -412,6 +483,18 @@ namespace SohImGui {
|
|||||||
if (UseViewports()) {
|
if (UseViewports()) {
|
||||||
io->ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
|
io->ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __SWITCH__
|
||||||
|
bool enableControllerNavigation = true;
|
||||||
|
#else
|
||||||
|
bool enableControllerNavigation = CVar_GetS32("gControlNav", 0);
|
||||||
|
#endif
|
||||||
|
if (enableControllerNavigation && CVar_GetS32("gOpenMenuBar", 0)) {
|
||||||
|
io->ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad | ImGuiConfigFlags_NavEnableKeyboard;
|
||||||
|
} else {
|
||||||
|
io->ConfigFlags &= ~ImGuiConfigFlags_NavEnableGamepad;
|
||||||
|
}
|
||||||
|
|
||||||
console->Init();
|
console->Init();
|
||||||
overlay->Init();
|
overlay->Init();
|
||||||
controller->Init();
|
controller->Init();
|
||||||
@ -616,7 +699,11 @@ namespace SohImGui {
|
|||||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
|
||||||
}
|
}
|
||||||
if (PlusMinusButton) {
|
if (PlusMinusButton) {
|
||||||
|
#ifdef __WIIU__
|
||||||
|
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f * 2);
|
||||||
|
#else
|
||||||
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f);
|
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (ImGui::SliderFloat(id, &val, min, max, format))
|
if (ImGui::SliderFloat(id, &val, min, max, format))
|
||||||
{
|
{
|
||||||
@ -846,15 +933,11 @@ namespace SohImGui {
|
|||||||
#else
|
#else
|
||||||
bool enableControllerNavigation = CVar_GetS32("gControlNav", 0);
|
bool enableControllerNavigation = CVar_GetS32("gControlNav", 0);
|
||||||
#endif
|
#endif
|
||||||
if (enableControllerNavigation) {
|
if (enableControllerNavigation && CVar_GetS32("gOpenMenuBar", 0)) {
|
||||||
if (CVar_GetS32("gOpenMenuBar", 0)) {
|
|
||||||
io->ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad | ImGuiConfigFlags_NavEnableKeyboard;
|
io->ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad | ImGuiConfigFlags_NavEnableKeyboard;
|
||||||
} else {
|
} else {
|
||||||
io->ConfigFlags &= ~ImGuiConfigFlags_NavEnableGamepad;
|
io->ConfigFlags &= ~ImGuiConfigFlags_NavEnableGamepad;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
io->ConfigFlags &= ~ImGuiConfigFlags_NavEnableGamepad;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if __APPLE__
|
#if __APPLE__
|
||||||
@ -875,13 +958,18 @@ namespace SohImGui {
|
|||||||
if (DefaultAssets.contains("Game_Icon")) {
|
if (DefaultAssets.contains("Game_Icon")) {
|
||||||
#ifdef __SWITCH__
|
#ifdef __SWITCH__
|
||||||
ImVec2 iconSize = ImVec2(20.0f, 20.0f);
|
ImVec2 iconSize = ImVec2(20.0f, 20.0f);
|
||||||
|
float posScale = 1.0f;
|
||||||
|
#elif defined(__WIIU__)
|
||||||
|
ImVec2 iconSize = ImVec2(16.0f * 2, 16.0f * 2);
|
||||||
|
float posScale = 2.0f;
|
||||||
#else
|
#else
|
||||||
ImVec2 iconSize = ImVec2(16.0f, 16.0f);
|
ImVec2 iconSize = ImVec2(16.0f, 16.0f);
|
||||||
|
float posScale = 1.0f;
|
||||||
#endif
|
#endif
|
||||||
ImGui::SetCursorPos(ImVec2(5, 2.5f));
|
ImGui::SetCursorPos(ImVec2(5, 2.5f) * posScale);
|
||||||
ImGui::Image(GetTextureByID(DefaultAssets["Game_Icon"]->textureId), iconSize);
|
ImGui::Image(GetTextureByID(DefaultAssets["Game_Icon"]->textureId), iconSize);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetCursorPos(ImVec2(25, 0));
|
ImGui::SetCursorPos(ImVec2(25, 0) * posScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ImVec2 windowPadding(8.0f, 8.0f);
|
static ImVec2 windowPadding(8.0f, 8.0f);
|
||||||
@ -957,9 +1045,11 @@ namespace SohImGui {
|
|||||||
Tooltip("Multiplies your output resolution by the value inputted, as a more intensive but effective form of anti-aliasing");
|
Tooltip("Multiplies your output resolution by the value inputted, as a more intensive but effective form of anti-aliasing");
|
||||||
gfx_current_dimensions.internal_mul = CVar_GetFloat("gInternalResolution", 1);
|
gfx_current_dimensions.internal_mul = CVar_GetFloat("gInternalResolution", 1);
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef __WIIU__
|
||||||
PaddedEnhancementSliderInt("MSAA: %d", "##IMSAA", "gMSAAValue", 1, 8, "", 1, false, true, false);
|
PaddedEnhancementSliderInt("MSAA: %d", "##IMSAA", "gMSAAValue", 1, 8, "", 1, false, true, false);
|
||||||
Tooltip("Activates multi-sample anti-aliasing when above 1x up to 8x for 8 samples for every pixel");
|
Tooltip("Activates multi-sample anti-aliasing when above 1x up to 8x for 8 samples for every pixel");
|
||||||
gfx_msaa_level = CVar_GetS32("gMSAAValue", 1);
|
gfx_msaa_level = CVar_GetS32("gMSAAValue", 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (impl.backend == Backend::DX11)
|
if (impl.backend == Backend::DX11)
|
||||||
{
|
{
|
||||||
@ -1434,7 +1524,7 @@ namespace SohImGui {
|
|||||||
|
|
||||||
const char* fps_cvar = "gInterpolationFPS";
|
const char* fps_cvar = "gInterpolationFPS";
|
||||||
{
|
{
|
||||||
#ifdef __SWITCH__
|
#if defined(__SWITCH__) || defined(__WIIU__)
|
||||||
int minFps = 20;
|
int minFps = 20;
|
||||||
int maxFps = 60;
|
int maxFps = 60;
|
||||||
#else
|
#else
|
||||||
@ -1444,6 +1534,12 @@ namespace SohImGui {
|
|||||||
|
|
||||||
int val = CVar_GetS32(fps_cvar, minFps);
|
int val = CVar_GetS32(fps_cvar, minFps);
|
||||||
val = MAX(MIN(val, maxFps), 20);
|
val = MAX(MIN(val, maxFps), 20);
|
||||||
|
|
||||||
|
#ifdef __WIIU__
|
||||||
|
// only support divisors of 60 on the Wii U
|
||||||
|
val = 60 / (60 / val);
|
||||||
|
#endif
|
||||||
|
|
||||||
int fps = val;
|
int fps = val;
|
||||||
|
|
||||||
if (fps == 20)
|
if (fps == 20)
|
||||||
@ -1458,15 +1554,28 @@ namespace SohImGui {
|
|||||||
std::string MinusBTNFPSI = " - ##FPSInterpolation";
|
std::string MinusBTNFPSI = " - ##FPSInterpolation";
|
||||||
std::string PlusBTNFPSI = " + ##FPSInterpolation";
|
std::string PlusBTNFPSI = " + ##FPSInterpolation";
|
||||||
if (ImGui::Button(MinusBTNFPSI.c_str())) {
|
if (ImGui::Button(MinusBTNFPSI.c_str())) {
|
||||||
|
#ifdef __WIIU__
|
||||||
|
if (val >= 60) val = 30;
|
||||||
|
else val = 20;
|
||||||
|
#else
|
||||||
val--;
|
val--;
|
||||||
|
#endif
|
||||||
CVar_SetS32(fps_cvar, val);
|
CVar_SetS32(fps_cvar, val);
|
||||||
needs_save = true;
|
needs_save = true;
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
|
||||||
|
#ifdef __WIIU__
|
||||||
|
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f * 2);
|
||||||
|
#else
|
||||||
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f);
|
ImGui::PushItemWidth(ImGui::GetWindowSize().x - 79.0f);
|
||||||
|
#endif
|
||||||
if (ImGui::SliderInt("##FPSInterpolation", &val, minFps, maxFps, "", ImGuiSliderFlags_AlwaysClamp))
|
if (ImGui::SliderInt("##FPSInterpolation", &val, minFps, maxFps, "", ImGuiSliderFlags_AlwaysClamp))
|
||||||
{
|
{
|
||||||
|
#ifdef __WIIU__
|
||||||
|
// only support divisors of 60 on the Wii U
|
||||||
|
val = 60 / (60 / val);
|
||||||
|
#endif
|
||||||
if (val > 360)
|
if (val > 360)
|
||||||
{
|
{
|
||||||
val = 360;
|
val = 360;
|
||||||
@ -1490,7 +1599,12 @@ namespace SohImGui {
|
|||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 7.0f);
|
||||||
if (ImGui::Button(PlusBTNFPSI.c_str())) {
|
if (ImGui::Button(PlusBTNFPSI.c_str())) {
|
||||||
|
#ifdef __WIIU__
|
||||||
|
if (val <= 20) val = 30;
|
||||||
|
else val = 60;
|
||||||
|
#else
|
||||||
val++;
|
val++;
|
||||||
|
#endif
|
||||||
CVar_SetS32(fps_cvar, val);
|
CVar_SetS32(fps_cvar, val);
|
||||||
needs_save = true;
|
needs_save = true;
|
||||||
}
|
}
|
||||||
@ -1791,14 +1905,18 @@ namespace SohImGui {
|
|||||||
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0));
|
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0));
|
||||||
ImGui::Begin("Debug Stats", &statsWindowOpen, ImGuiWindowFlags_NoFocusOnAppearing);
|
ImGui::Begin("Debug Stats", &statsWindowOpen, ImGuiWindowFlags_NoFocusOnAppearing);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#if defined(_WIN32)
|
||||||
ImGui::Text("Platform: Windows");
|
ImGui::Text("Platform: Windows");
|
||||||
#elif __APPLE__
|
#elif defined(__APPLE__)
|
||||||
ImGui::Text("Platform: macOS");
|
ImGui::Text("Platform: macOS");
|
||||||
#elif defined(__SWITCH__)
|
#elif defined(__SWITCH__)
|
||||||
ImGui::Text("Platform: Nintendo Switch");
|
ImGui::Text("Platform: Nintendo Switch");
|
||||||
#else
|
#elif defined(__WIIU__)
|
||||||
|
ImGui::Text("Platform: Nintendo Wii U");
|
||||||
|
#elif defined(__linux__)
|
||||||
ImGui::Text("Platform: Linux");
|
ImGui::Text("Platform: Linux");
|
||||||
|
#else
|
||||||
|
ImGui::Text("Platform: Unknown");
|
||||||
#endif
|
#endif
|
||||||
ImGui::Text("Status: %.3f ms/frame (%.1f FPS)", 1000.0f / framerate, framerate);
|
ImGui::Text("Status: %.3f ms/frame (%.1f FPS)", 1000.0f / framerate, framerate);
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
@ -2281,6 +2399,13 @@ namespace SohImGui {
|
|||||||
return gfx_d3d11_get_texture_by_id(id);
|
return gfx_d3d11_get_texture_by_id(id);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef __WIIU__
|
||||||
|
if (impl.backend == Backend::GX2)
|
||||||
|
{
|
||||||
|
return gfx_gx2_texture_for_imgui(id);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return reinterpret_cast<ImTextureID>(id);
|
return reinterpret_cast<ImTextureID>(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,8 @@ struct GameAsset {
|
|||||||
namespace SohImGui {
|
namespace SohImGui {
|
||||||
enum class Backend {
|
enum class Backend {
|
||||||
DX11,
|
DX11,
|
||||||
SDL
|
SDL,
|
||||||
|
GX2,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Dialogues {
|
enum class Dialogues {
|
||||||
@ -45,6 +46,10 @@ namespace SohImGui {
|
|||||||
void* window;
|
void* window;
|
||||||
void* context;
|
void* context;
|
||||||
} sdl;
|
} sdl;
|
||||||
|
struct {
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
} gx2;
|
||||||
};
|
};
|
||||||
} WindowImpl;
|
} WindowImpl;
|
||||||
|
|
||||||
@ -58,6 +63,9 @@ namespace SohImGui {
|
|||||||
struct {
|
struct {
|
||||||
void* event;
|
void* event;
|
||||||
} sdl;
|
} sdl;
|
||||||
|
struct {
|
||||||
|
void* input;
|
||||||
|
} gx2;
|
||||||
} EventImpl;
|
} EventImpl;
|
||||||
|
|
||||||
extern WindowImpl impl;
|
extern WindowImpl impl;
|
||||||
|
@ -45,6 +45,9 @@ namespace Ship {
|
|||||||
if(btn != -1) {
|
if(btn != -1) {
|
||||||
backend->SetButtonMapping(CurrentPort, n64Btn, btn);
|
backend->SetButtonMapping(CurrentPort, n64Btn, btn);
|
||||||
BtnReading = -1;
|
BtnReading = -1;
|
||||||
|
|
||||||
|
// avoid immediately triggering another button during gamepad nav
|
||||||
|
ImGui::SetKeyboardFocusHere(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,9 +148,17 @@ namespace Ship {
|
|||||||
|
|
||||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
|
||||||
|
|
||||||
|
#ifdef __WIIU__
|
||||||
|
ImGui::BeginChild("##MSInput", ImVec2(90 * 2, 50 * 2), false);
|
||||||
|
#else
|
||||||
ImGui::BeginChild("##MSInput", ImVec2(90 , 50), false);
|
ImGui::BeginChild("##MSInput", ImVec2(90 , 50), false);
|
||||||
|
#endif
|
||||||
ImGui::Text("Deadzone");
|
ImGui::Text("Deadzone");
|
||||||
|
#ifdef __WIIU__
|
||||||
|
ImGui::PushItemWidth(80 * 2);
|
||||||
|
#else
|
||||||
ImGui::PushItemWidth(80);
|
ImGui::PushItemWidth(80);
|
||||||
|
#endif
|
||||||
ImGui::InputFloat("##MDZone", &profile->AxisDeadzones[0] /* This is the SDL value for left stick X axis */, 1.0f, 0.0f, "%.0f");
|
ImGui::InputFloat("##MDZone", &profile->AxisDeadzones[0] /* This is the SDL value for left stick X axis */, 1.0f, 0.0f, "%.0f");
|
||||||
ImGui::PopItemWidth();
|
ImGui::PopItemWidth();
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
@ -176,13 +187,25 @@ namespace Ship {
|
|||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
|
||||||
|
#ifdef __WIIU__
|
||||||
|
ImGui::BeginChild("##CSInput", ImVec2(90 * 2, 85 * 2), false);
|
||||||
|
#else
|
||||||
ImGui::BeginChild("##CSInput", ImVec2(90, 85), false);
|
ImGui::BeginChild("##CSInput", ImVec2(90, 85), false);
|
||||||
|
#endif
|
||||||
ImGui::Text("Deadzone");
|
ImGui::Text("Deadzone");
|
||||||
|
#ifdef __WIIU__
|
||||||
|
ImGui::PushItemWidth(80 * 2);
|
||||||
|
#else
|
||||||
ImGui::PushItemWidth(80);
|
ImGui::PushItemWidth(80);
|
||||||
ImGui::InputFloat("##MDZone", &profile->AxisDeadzones[2] /* This is the SDL value for left stick X axis */, 1.0f, 0.0f, "%.0f");
|
#endif
|
||||||
|
ImGui::InputFloat("##MDZone", &profile->AxisDeadzones[2] /* This is the SDL value for right stick X axis */, 1.0f, 0.0f, "%.0f");
|
||||||
ImGui::PopItemWidth();
|
ImGui::PopItemWidth();
|
||||||
ImGui::Text("Sensitivity");
|
ImGui::Text("Sensitivity");
|
||||||
|
#ifdef __WIIU__
|
||||||
|
ImGui::PushItemWidth(80 * 2);
|
||||||
|
#else
|
||||||
ImGui::PushItemWidth(80);
|
ImGui::PushItemWidth(80);
|
||||||
|
#endif
|
||||||
ImGui::InputFloat("##MSensitivity", &profile->AxisSensitivities[2] /* This is the SDL value for right stick X axis */, 1.0f, 0.0f, "%.0f");
|
ImGui::InputFloat("##MSensitivity", &profile->AxisSensitivities[2] /* This is the SDL value for right stick X axis */, 1.0f, 0.0f, "%.0f");
|
||||||
profile->AxisSensitivities[3] = profile->AxisSensitivities[2];
|
profile->AxisSensitivities[3] = profile->AxisSensitivities[2];
|
||||||
ImGui::PopItemWidth();
|
ImGui::PopItemWidth();
|
||||||
@ -195,15 +218,20 @@ namespace Ship {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(Backend->CanGyro()) {
|
if(Backend->CanGyro()) {
|
||||||
|
#ifndef __WIIU__
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
#endif
|
||||||
SohImGui::BeginGroupPanel("Gyro Options", ImVec2(175, 20));
|
SohImGui::BeginGroupPanel("Gyro Options", ImVec2(175, 20));
|
||||||
float cursorX = ImGui::GetCursorPosX() + 5;
|
float cursorX = ImGui::GetCursorPosX() + 5;
|
||||||
ImGui::SetCursorPosX(cursorX);
|
ImGui::SetCursorPosX(cursorX);
|
||||||
ImGui::Checkbox("Enable Gyro", &profile->UseGyro);
|
ImGui::Checkbox("Enable Gyro", &profile->UseGyro);
|
||||||
ImGui::SetCursorPosX(cursorX);
|
ImGui::SetCursorPosX(cursorX);
|
||||||
ImGui::Text("Gyro Sensitivity: %d%%", static_cast<int>(100.0f * profile->GyroData[GYRO_SENSITIVITY]));
|
ImGui::Text("Gyro Sensitivity: %d%%", static_cast<int>(100.0f * profile->GyroData[GYRO_SENSITIVITY]));
|
||||||
|
#ifdef __WIIU__
|
||||||
|
ImGui::PushItemWidth(135.0f * 2);
|
||||||
|
#else
|
||||||
ImGui::PushItemWidth(135.0f);
|
ImGui::PushItemWidth(135.0f);
|
||||||
|
#endif
|
||||||
ImGui::SetCursorPosX(cursorX);
|
ImGui::SetCursorPosX(cursorX);
|
||||||
ImGui::SliderFloat("##GSensitivity", &profile->GyroData[GYRO_SENSITIVITY], 0.0f, 1.0f, "");
|
ImGui::SliderFloat("##GSensitivity", &profile->GyroData[GYRO_SENSITIVITY], 0.0f, 1.0f, "");
|
||||||
ImGui::PopItemWidth();
|
ImGui::PopItemWidth();
|
||||||
@ -218,13 +246,25 @@ namespace Ship {
|
|||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 5);
|
||||||
|
#ifdef __WIIU__
|
||||||
|
ImGui::BeginChild("##GyInput", ImVec2(90 * 2, 85 * 2), false);
|
||||||
|
#else
|
||||||
ImGui::BeginChild("##GyInput", ImVec2(90, 85), false);
|
ImGui::BeginChild("##GyInput", ImVec2(90, 85), false);
|
||||||
|
#endif
|
||||||
ImGui::Text("Drift X");
|
ImGui::Text("Drift X");
|
||||||
|
#ifdef __WIIU__
|
||||||
|
ImGui::PushItemWidth(80 * 2);
|
||||||
|
#else
|
||||||
ImGui::PushItemWidth(80);
|
ImGui::PushItemWidth(80);
|
||||||
|
#endif
|
||||||
ImGui::InputFloat("##GDriftX", &profile->GyroData[DRIFT_X], 1.0f, 0.0f, "%.1f");
|
ImGui::InputFloat("##GDriftX", &profile->GyroData[DRIFT_X], 1.0f, 0.0f, "%.1f");
|
||||||
ImGui::PopItemWidth();
|
ImGui::PopItemWidth();
|
||||||
ImGui::Text("Drift Y");
|
ImGui::Text("Drift Y");
|
||||||
|
#ifdef __WIIU__
|
||||||
|
ImGui::PushItemWidth(80 * 2);
|
||||||
|
#else
|
||||||
ImGui::PushItemWidth(80);
|
ImGui::PushItemWidth(80);
|
||||||
|
#endif
|
||||||
ImGui::InputFloat("##GDriftY", &profile->GyroData[DRIFT_Y], 1.0f, 0.0f, "%.1f");
|
ImGui::InputFloat("##GDriftY", &profile->GyroData[DRIFT_Y], 1.0f, 0.0f, "%.1f");
|
||||||
ImGui::PopItemWidth();
|
ImGui::PopItemWidth();
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
@ -250,6 +290,8 @@ namespace Ship {
|
|||||||
ImGui::SetCursorPosX(cursor.x);
|
ImGui::SetCursorPosX(cursor.x);
|
||||||
#ifdef __SWITCH__
|
#ifdef __SWITCH__
|
||||||
ImGui::SetCursorPosY(cursor.y + 167);
|
ImGui::SetCursorPosY(cursor.y + 167);
|
||||||
|
#elif defined(__WIIU__)
|
||||||
|
ImGui::SetCursorPosY(cursor.y + 120 * 2);
|
||||||
#else
|
#else
|
||||||
ImGui::SetCursorPosY(cursor.y + 120);
|
ImGui::SetCursorPosY(cursor.y + 120);
|
||||||
#endif
|
#endif
|
||||||
@ -261,7 +303,11 @@ namespace Ship {
|
|||||||
ImGui::SetCursorPosX(cursorX);
|
ImGui::SetCursorPosX(cursorX);
|
||||||
ImGui::Text("Rumble Force: %d%%", static_cast<int>(100.0f * profile->RumbleStrength));
|
ImGui::Text("Rumble Force: %d%%", static_cast<int>(100.0f * profile->RumbleStrength));
|
||||||
ImGui::SetCursorPosX(cursorX);
|
ImGui::SetCursorPosX(cursorX);
|
||||||
|
#ifdef __WIIU__
|
||||||
|
ImGui::PushItemWidth(135.0f * 2);
|
||||||
|
#else
|
||||||
ImGui::PushItemWidth(135.0f);
|
ImGui::PushItemWidth(135.0f);
|
||||||
|
#endif
|
||||||
ImGui::SliderFloat("##RStrength", &profile->RumbleStrength, 0.0f, 1.0f, "");
|
ImGui::SliderFloat("##RStrength", &profile->RumbleStrength, 0.0f, 1.0f, "");
|
||||||
ImGui::PopItemWidth();
|
ImGui::PopItemWidth();
|
||||||
}
|
}
|
||||||
@ -279,6 +325,9 @@ namespace Ship {
|
|||||||
#ifdef __SWITCH__
|
#ifdef __SWITCH__
|
||||||
ImVec2 minSize = ImVec2(641, 250);
|
ImVec2 minSize = ImVec2(641, 250);
|
||||||
ImVec2 maxSize = ImVec2(2200, 505);
|
ImVec2 maxSize = ImVec2(2200, 505);
|
||||||
|
#elif defined(__WIIU__)
|
||||||
|
ImVec2 minSize = ImVec2(641 * 2, 250 * 2);
|
||||||
|
ImVec2 maxSize = ImVec2(1200 * 2, 290 * 2);
|
||||||
#else
|
#else
|
||||||
ImVec2 minSize = ImVec2(641, 250);
|
ImVec2 minSize = ImVec2(641, 250);
|
||||||
ImVec2 maxSize = ImVec2(1200, 290);
|
ImVec2 maxSize = ImVec2(1200, 290);
|
||||||
|
826
libultraship/libultraship/Lib/Fast3D/gfx_gx2.cpp
Normal file
826
libultraship/libultraship/Lib/Fast3D/gfx_gx2.cpp
Normal file
@ -0,0 +1,826 @@
|
|||||||
|
#ifdef __WIIU__
|
||||||
|
|
||||||
|
#include "../../Window.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#ifndef _LANGUAGE_C
|
||||||
|
#define _LANGUAGE_C
|
||||||
|
#endif
|
||||||
|
#include "PR/ultra64/gbi.h"
|
||||||
|
|
||||||
|
#include "gfx_cc.h"
|
||||||
|
#include "gfx_rendering_api.h"
|
||||||
|
#include "../../GlobalCtx2.h"
|
||||||
|
#include "gfx_pc.h"
|
||||||
|
#include "gfx_wiiu.h"
|
||||||
|
|
||||||
|
#include <gx2/texture.h>
|
||||||
|
#include <gx2/draw.h>
|
||||||
|
#include <gx2/clear.h>
|
||||||
|
#include <gx2/state.h>
|
||||||
|
#include <gx2/swap.h>
|
||||||
|
#include <gx2/event.h>
|
||||||
|
#include <gx2/utils.h>
|
||||||
|
#include <gx2/mem.h>
|
||||||
|
#include <gx2/registers.h>
|
||||||
|
#include <gx2/display.h>
|
||||||
|
#include "gx2_shader_gen.h"
|
||||||
|
|
||||||
|
#include <proc_ui/procui.h>
|
||||||
|
#include <coreinit/memory.h>
|
||||||
|
|
||||||
|
#include "../ImGui/backends/wiiu/imgui_impl_gx2.h"
|
||||||
|
|
||||||
|
#define ALIGN(x, align) (((x) + ((align) -1)) & ~((align) -1))
|
||||||
|
|
||||||
|
struct ShaderProgram {
|
||||||
|
struct ShaderGroup group;
|
||||||
|
uint8_t num_inputs;
|
||||||
|
bool used_textures[2];
|
||||||
|
bool used_noise;
|
||||||
|
uint32_t window_params_offset;
|
||||||
|
uint32_t samplers_location[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Texture {
|
||||||
|
GX2Texture texture;
|
||||||
|
bool texture_uploaded;
|
||||||
|
|
||||||
|
GX2Sampler sampler;
|
||||||
|
bool sampler_set;
|
||||||
|
|
||||||
|
// For ImGui rendering
|
||||||
|
ImGui_ImplGX2_Texture imtex;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Framebuffer {
|
||||||
|
GX2ColorBuffer color_buffer;
|
||||||
|
bool colorBufferMem1;
|
||||||
|
GX2DepthBuffer depth_buffer;
|
||||||
|
bool depthBufferMem1;
|
||||||
|
|
||||||
|
GX2Texture texture;
|
||||||
|
GX2Sampler sampler;
|
||||||
|
|
||||||
|
// For ImGui rendering
|
||||||
|
ImGui_ImplGX2_Texture imtex;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct Framebuffer main_framebuffer;
|
||||||
|
static GX2DepthBuffer depthReadBuffer;
|
||||||
|
static struct Framebuffer *current_framebuffer;
|
||||||
|
|
||||||
|
static std::map<std::pair<uint64_t, uint32_t>, struct ShaderProgram> shader_program_pool;
|
||||||
|
static struct ShaderProgram *current_shader_program;
|
||||||
|
|
||||||
|
static struct Texture *current_texture;
|
||||||
|
static int current_tile;
|
||||||
|
|
||||||
|
// 96 Mb (should be more than enough to draw everything without waiting for the GPU)
|
||||||
|
#define DRAW_BUFFER_SIZE 0x6000000
|
||||||
|
static uint8_t *draw_buffer = nullptr;
|
||||||
|
static uint8_t *draw_ptr = nullptr;
|
||||||
|
|
||||||
|
static uint32_t frame_count;
|
||||||
|
static float current_noise_scale;
|
||||||
|
static FilteringMode current_filter_mode = FILTER_LINEAR;
|
||||||
|
|
||||||
|
static BOOL current_depth_test = TRUE;
|
||||||
|
static BOOL current_depth_write = TRUE;
|
||||||
|
static GX2CompareFunction current_depth_compare_function = GX2_COMPARE_FUNC_LESS;
|
||||||
|
|
||||||
|
static float current_viewport_x = 0.0f;
|
||||||
|
static float current_viewport_y = 0.0f;
|
||||||
|
static float current_viewport_width = WIIU_DEFAULT_FB_WIDTH;
|
||||||
|
static float current_viewport_height = WIIU_DEFAULT_FB_HEIGHT;
|
||||||
|
|
||||||
|
static uint32_t current_scissor_x = 0;
|
||||||
|
static uint32_t current_scissor_y = 0;
|
||||||
|
static uint32_t current_scissor_width = WIIU_DEFAULT_FB_WIDTH;
|
||||||
|
static uint32_t current_scissor_height = WIIU_DEFAULT_FB_HEIGHT;
|
||||||
|
|
||||||
|
static bool current_zmode_decal = false;
|
||||||
|
static bool current_use_alpha = false;
|
||||||
|
|
||||||
|
static inline GX2SamplerVar *GX2GetPixelSamplerVar(const GX2PixelShader *shader, const char *name)
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < shader->samplerVarCount; ++i) {
|
||||||
|
if (strcmp(name, shader->samplerVars[i].name) == 0) {
|
||||||
|
return &shader->samplerVars[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int32_t GX2GetPixelSamplerVarLocation(const GX2PixelShader *shader, const char *name)
|
||||||
|
{
|
||||||
|
GX2SamplerVar *sampler = GX2GetPixelSamplerVar(shader, name);
|
||||||
|
return sampler ? sampler->location : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int32_t GX2GetPixelUniformVarOffset(const GX2PixelShader *shader, const char *name)
|
||||||
|
{
|
||||||
|
GX2UniformVar *uniform = GX2GetPixelUniformVar(shader, name);
|
||||||
|
return uniform ? uniform->offset : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_init_framebuffer(struct Framebuffer *buffer, uint32_t width, uint32_t height) {
|
||||||
|
memset(&buffer->color_buffer, 0, sizeof(GX2ColorBuffer));
|
||||||
|
buffer->color_buffer.surface.use = GX2_SURFACE_USE_TEXTURE_COLOR_BUFFER_TV;
|
||||||
|
buffer->color_buffer.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
|
||||||
|
buffer->color_buffer.surface.width = width;
|
||||||
|
buffer->color_buffer.surface.height = height;
|
||||||
|
buffer->color_buffer.surface.depth = 1;
|
||||||
|
buffer->color_buffer.surface.mipLevels = 1;
|
||||||
|
buffer->color_buffer.surface.format = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8;
|
||||||
|
buffer->color_buffer.surface.aa = GX2_AA_MODE1X;
|
||||||
|
buffer->color_buffer.surface.tileMode = GX2_TILE_MODE_DEFAULT;
|
||||||
|
buffer->color_buffer.viewNumSlices = 1;
|
||||||
|
|
||||||
|
memset(&buffer->depth_buffer, 0, sizeof(GX2DepthBuffer));
|
||||||
|
buffer->depth_buffer.surface.use = GX2_SURFACE_USE_DEPTH_BUFFER | GX2_SURFACE_USE_TEXTURE;
|
||||||
|
buffer->depth_buffer.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
|
||||||
|
buffer->depth_buffer.surface.width = width;
|
||||||
|
buffer->depth_buffer.surface.height = height;
|
||||||
|
buffer->depth_buffer.surface.depth = 1;
|
||||||
|
buffer->depth_buffer.surface.mipLevels = 1;
|
||||||
|
buffer->depth_buffer.surface.format = GX2_SURFACE_FORMAT_FLOAT_R32;
|
||||||
|
buffer->depth_buffer.surface.aa = GX2_AA_MODE1X;
|
||||||
|
buffer->depth_buffer.surface.tileMode = GX2_TILE_MODE_DEFAULT;
|
||||||
|
buffer->depth_buffer.viewNumSlices = 1;
|
||||||
|
buffer->depth_buffer.depthClear = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct GfxClipParameters gfx_gx2_get_clip_parameters(void) {
|
||||||
|
return { false, false };
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_set_uniforms(struct ShaderProgram *prg) {
|
||||||
|
if (prg->used_noise) {
|
||||||
|
float window_params_array[2] = { current_noise_scale, (float) frame_count };
|
||||||
|
|
||||||
|
GX2SetPixelUniformReg(prg->window_params_offset, 2, window_params_array);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_unload_shader(struct ShaderProgram *old_prg) {
|
||||||
|
current_shader_program = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_load_shader(struct ShaderProgram *new_prg) {
|
||||||
|
current_shader_program = new_prg;
|
||||||
|
|
||||||
|
GX2SetFetchShader(&new_prg->group.fetchShader);
|
||||||
|
GX2SetVertexShader(&new_prg->group.vertexShader);
|
||||||
|
GX2SetPixelShader(&new_prg->group.pixelShader);
|
||||||
|
|
||||||
|
gfx_gx2_set_uniforms(new_prg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ShaderProgram* gfx_gx2_create_and_load_new_shader(uint64_t shader_id0, uint32_t shader_id1) {
|
||||||
|
struct CCFeatures cc_features;
|
||||||
|
gfx_cc_get_features(shader_id0, shader_id1, &cc_features);
|
||||||
|
|
||||||
|
struct ShaderProgram* prg = &shader_program_pool[std::make_pair(shader_id0, shader_id1)];
|
||||||
|
|
||||||
|
printf("Generating shader: %016llx-%08x\n", shader_id0, shader_id1);
|
||||||
|
if (gx2GenerateShaderGroup(&prg->group, &cc_features) != 0) {
|
||||||
|
printf("Failed to generate shader\n");
|
||||||
|
current_shader_program = nullptr;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
prg->num_inputs = cc_features.num_inputs;
|
||||||
|
prg->used_textures[0] = cc_features.used_textures[0];
|
||||||
|
prg->used_textures[1] = cc_features.used_textures[1];
|
||||||
|
|
||||||
|
gfx_gx2_load_shader(prg);
|
||||||
|
|
||||||
|
prg->window_params_offset = GX2GetPixelUniformVarOffset(&prg->group.pixelShader, "window_params");
|
||||||
|
prg->samplers_location[0] = GX2GetPixelSamplerVarLocation(&prg->group.pixelShader, "uTex0");
|
||||||
|
prg->samplers_location[1] = GX2GetPixelSamplerVarLocation(&prg->group.pixelShader, "uTex1");
|
||||||
|
|
||||||
|
prg->used_noise = cc_features.opt_alpha && cc_features.opt_noise;
|
||||||
|
|
||||||
|
printf("Generated and loaded shader\n");
|
||||||
|
|
||||||
|
return prg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ShaderProgram *gfx_gx2_lookup_shader(uint64_t shader_id0, uint32_t shader_id1) {
|
||||||
|
auto it = shader_program_pool.find(std::make_pair(shader_id0, shader_id1));
|
||||||
|
return it == shader_program_pool.end() ? nullptr : &it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_shader_get_info(struct ShaderProgram *prg, uint8_t *num_inputs, bool used_textures[2]) {
|
||||||
|
*num_inputs = prg->num_inputs;
|
||||||
|
used_textures[0] = prg->used_textures[0];
|
||||||
|
used_textures[1] = prg->used_textures[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t gfx_gx2_new_texture(void) {
|
||||||
|
// some 32-bit trickery :P
|
||||||
|
struct Texture *tex = (struct Texture *) calloc(1, sizeof(struct Texture));
|
||||||
|
|
||||||
|
tex->imtex.Texture = &tex->texture;
|
||||||
|
tex->imtex.Sampler = &tex->sampler;
|
||||||
|
|
||||||
|
return (uint32_t) tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_delete_texture(uint32_t texture_id) {
|
||||||
|
struct Texture *tex = (struct Texture *) texture_id;
|
||||||
|
|
||||||
|
if (tex->texture.surface.image) {
|
||||||
|
free(tex->texture.surface.image);
|
||||||
|
}
|
||||||
|
|
||||||
|
free((void *) tex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_select_texture(int tile, uint32_t texture_id) {
|
||||||
|
struct Texture *tex = (struct Texture *) texture_id;
|
||||||
|
current_texture = tex;
|
||||||
|
current_tile = tile;
|
||||||
|
|
||||||
|
if (current_shader_program) {
|
||||||
|
uint32_t sampler_location = current_shader_program->samplers_location[tile];
|
||||||
|
|
||||||
|
if (tex->texture_uploaded) {
|
||||||
|
GX2SetPixelTexture(&tex->texture, sampler_location);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tex->sampler_set) {
|
||||||
|
GX2SetPixelSampler(&tex->sampler, sampler_location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_upload_texture(const uint8_t *rgba32_buf, uint32_t width, uint32_t height) {
|
||||||
|
struct Texture *tex = current_texture;
|
||||||
|
assert(tex);
|
||||||
|
|
||||||
|
if ((tex->texture.surface.width != width) ||
|
||||||
|
(tex->texture.surface.height != height) ||
|
||||||
|
!tex->texture.surface.image) {
|
||||||
|
|
||||||
|
if (tex->texture.surface.image) {
|
||||||
|
free(tex->texture.surface.image);
|
||||||
|
tex->texture.surface.image = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&tex->texture, 0, sizeof(GX2Texture));
|
||||||
|
tex->texture.surface.use = GX2_SURFACE_USE_TEXTURE;
|
||||||
|
tex->texture.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
|
||||||
|
tex->texture.surface.width = width;
|
||||||
|
tex->texture.surface.height = height;
|
||||||
|
tex->texture.surface.depth = 1;
|
||||||
|
tex->texture.surface.mipLevels = 1;
|
||||||
|
tex->texture.surface.format = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8;
|
||||||
|
tex->texture.surface.aa = GX2_AA_MODE1X;
|
||||||
|
tex->texture.surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED;
|
||||||
|
tex->texture.viewFirstMip = 0;
|
||||||
|
tex->texture.viewNumMips = 1;
|
||||||
|
tex->texture.viewFirstSlice = 0;
|
||||||
|
tex->texture.viewNumSlices = 1;
|
||||||
|
tex->texture.compMap = GX2_COMP_MAP(GX2_SQ_SEL_R, GX2_SQ_SEL_G, GX2_SQ_SEL_B, GX2_SQ_SEL_A);
|
||||||
|
|
||||||
|
GX2CalcSurfaceSizeAndAlignment(&tex->texture.surface);
|
||||||
|
GX2InitTextureRegs(&tex->texture);
|
||||||
|
|
||||||
|
tex->texture.surface.image = memalign(tex->texture.surface.alignment, tex->texture.surface.imageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* buf = (uint8_t *) tex->texture.surface.image;
|
||||||
|
assert(buf);
|
||||||
|
|
||||||
|
for (uint32_t y = 0; y < height; ++y) {
|
||||||
|
memcpy(buf + (y * tex->texture.surface.pitch * 4), rgba32_buf + (y * width * 4), width * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, tex->texture.surface.image, tex->texture.surface.imageSize);
|
||||||
|
|
||||||
|
if (current_shader_program) {
|
||||||
|
GX2SetPixelTexture(&tex->texture, current_shader_program->samplers_location[current_tile]);
|
||||||
|
}
|
||||||
|
|
||||||
|
tex->texture_uploaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GX2TexClampMode gfx_cm_to_gx2(uint32_t val) {
|
||||||
|
switch (val) {
|
||||||
|
case G_TX_NOMIRROR | G_TX_CLAMP:
|
||||||
|
return GX2_TEX_CLAMP_MODE_CLAMP;
|
||||||
|
case G_TX_MIRROR | G_TX_WRAP:
|
||||||
|
return GX2_TEX_CLAMP_MODE_MIRROR;
|
||||||
|
case G_TX_MIRROR | G_TX_CLAMP:
|
||||||
|
return GX2_TEX_CLAMP_MODE_MIRROR_ONCE;
|
||||||
|
case G_TX_NOMIRROR | G_TX_WRAP:
|
||||||
|
return GX2_TEX_CLAMP_MODE_WRAP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GX2_TEX_CLAMP_MODE_WRAP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_set_sampler_parameters(int tile, bool linear_filter, uint32_t cms, uint32_t cmt) {
|
||||||
|
struct Texture *tex = current_texture;
|
||||||
|
assert(tex);
|
||||||
|
|
||||||
|
current_tile = tile;
|
||||||
|
|
||||||
|
GX2InitSampler(&tex->sampler, GX2_TEX_CLAMP_MODE_CLAMP,
|
||||||
|
(linear_filter && current_filter_mode == FILTER_LINEAR) ?
|
||||||
|
GX2_TEX_XY_FILTER_MODE_LINEAR : GX2_TEX_XY_FILTER_MODE_POINT);
|
||||||
|
|
||||||
|
GX2InitSamplerClamping(&tex->sampler, gfx_cm_to_gx2(cms), gfx_cm_to_gx2(cmt), GX2_TEX_CLAMP_MODE_WRAP);
|
||||||
|
|
||||||
|
if (current_shader_program) {
|
||||||
|
GX2SetPixelSampler(&tex->sampler, current_shader_program->samplers_location[tile]);
|
||||||
|
}
|
||||||
|
|
||||||
|
tex->sampler_set = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_set_depth_test_and_mask(bool depth_test, bool z_upd) {
|
||||||
|
current_depth_test = depth_test || z_upd;
|
||||||
|
current_depth_write = z_upd;
|
||||||
|
current_depth_compare_function = depth_test ? GX2_COMPARE_FUNC_LEQUAL : GX2_COMPARE_FUNC_ALWAYS;
|
||||||
|
|
||||||
|
GX2SetDepthOnlyControl(current_depth_test, current_depth_write, current_depth_compare_function);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_set_zmode_decal(bool zmode_decal) {
|
||||||
|
current_zmode_decal = zmode_decal;
|
||||||
|
if (zmode_decal) {
|
||||||
|
GX2SetPolygonControl(GX2_FRONT_FACE_CCW, FALSE, FALSE, TRUE,
|
||||||
|
GX2_POLYGON_MODE_TRIANGLE, GX2_POLYGON_MODE_TRIANGLE,
|
||||||
|
TRUE, TRUE, FALSE);
|
||||||
|
GX2SetPolygonOffset(-2.0f, -2.0f, -2.0f, -2.0f, 0.0f);
|
||||||
|
} else {
|
||||||
|
GX2SetPolygonControl(GX2_FRONT_FACE_CCW, FALSE, FALSE, FALSE,
|
||||||
|
GX2_POLYGON_MODE_TRIANGLE, GX2_POLYGON_MODE_TRIANGLE,
|
||||||
|
FALSE, FALSE, FALSE);
|
||||||
|
GX2SetPolygonOffset(0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_set_viewport(int x, int y, int width, int height) {
|
||||||
|
uint32_t buffer_height = current_framebuffer->color_buffer.surface.height;
|
||||||
|
|
||||||
|
current_viewport_x = x;
|
||||||
|
current_viewport_y = buffer_height - y - height;
|
||||||
|
current_viewport_width = width;
|
||||||
|
current_viewport_height = height;
|
||||||
|
|
||||||
|
GX2SetViewport(current_viewport_x, current_viewport_y, current_viewport_width, current_viewport_height, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_set_scissor(int x, int y, int width, int height) {
|
||||||
|
uint32_t buffer_height = current_framebuffer->color_buffer.surface.height;
|
||||||
|
uint32_t buffer_width = current_framebuffer->color_buffer.surface.width;
|
||||||
|
|
||||||
|
current_scissor_x = std::min((uint32_t) width, (uint32_t) x);
|
||||||
|
current_scissor_y = std::min((uint32_t) height, buffer_height - y - height);
|
||||||
|
current_scissor_width = std::min((uint32_t) width, buffer_width);
|
||||||
|
current_scissor_height = std::min((uint32_t) height, buffer_height);
|
||||||
|
|
||||||
|
GX2SetScissor(current_scissor_x, current_scissor_y, current_scissor_width, current_scissor_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_set_use_alpha(bool use_alpha) {
|
||||||
|
current_use_alpha = use_alpha;
|
||||||
|
GX2SetColorControl(GX2_LOGIC_OP_COPY, use_alpha ? 0xff : 0, FALSE, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_draw_triangles(float buf_vbo[], size_t buf_vbo_len, size_t buf_vbo_num_tris) {
|
||||||
|
if (!current_shader_program) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t vbo_len = sizeof(float) * buf_vbo_len;
|
||||||
|
|
||||||
|
if (draw_ptr + vbo_len >= draw_buffer + DRAW_BUFFER_SIZE) {
|
||||||
|
printf("Waiting on GPU!!!\n");
|
||||||
|
GX2DrawDone();
|
||||||
|
draw_ptr = draw_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
float* new_vbo = (float *) draw_ptr;
|
||||||
|
draw_ptr += ALIGN(vbo_len, GX2_VERTEX_BUFFER_ALIGNMENT);
|
||||||
|
|
||||||
|
OSBlockMove(new_vbo, buf_vbo, vbo_len, FALSE);
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, new_vbo, vbo_len);
|
||||||
|
|
||||||
|
GX2SetAttribBuffer(0, vbo_len, current_shader_program->group.stride, new_vbo);
|
||||||
|
GX2DrawEx(GX2_PRIMITIVE_MODE_TRIANGLES, 3 * buf_vbo_num_tris, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_init(void) {
|
||||||
|
// Init the default framebuffer
|
||||||
|
gfx_gx2_init_framebuffer(&main_framebuffer, WIIU_DEFAULT_FB_WIDTH, WIIU_DEFAULT_FB_HEIGHT);
|
||||||
|
|
||||||
|
GX2CalcSurfaceSizeAndAlignment(&main_framebuffer.color_buffer.surface);
|
||||||
|
GX2InitColorBufferRegs(&main_framebuffer.color_buffer);
|
||||||
|
|
||||||
|
main_framebuffer.color_buffer.surface.image = gfx_wiiu_alloc_mem1(main_framebuffer.color_buffer.surface.imageSize, main_framebuffer.color_buffer.surface.alignment);
|
||||||
|
assert(main_framebuffer.color_buffer.surface.image);
|
||||||
|
|
||||||
|
GX2CalcSurfaceSizeAndAlignment(&main_framebuffer.depth_buffer.surface);
|
||||||
|
GX2InitDepthBufferRegs(&main_framebuffer.depth_buffer);
|
||||||
|
|
||||||
|
main_framebuffer.depth_buffer.surface.image = gfx_wiiu_alloc_mem1(main_framebuffer.depth_buffer.surface.imageSize, main_framebuffer.depth_buffer.surface.alignment);
|
||||||
|
assert(main_framebuffer.depth_buffer.surface.image);
|
||||||
|
|
||||||
|
main_framebuffer.imtex.Texture = &main_framebuffer.texture;
|
||||||
|
main_framebuffer.imtex.Sampler = &main_framebuffer.sampler;
|
||||||
|
|
||||||
|
// create a linear aligned copy of the depth buffer to read pixels to
|
||||||
|
memcpy(&depthReadBuffer, &main_framebuffer.depth_buffer, sizeof(GX2DepthBuffer));
|
||||||
|
|
||||||
|
depthReadBuffer.surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED;
|
||||||
|
depthReadBuffer.surface.width = 1;
|
||||||
|
depthReadBuffer.surface.height = 1;
|
||||||
|
|
||||||
|
GX2CalcSurfaceSizeAndAlignment(&depthReadBuffer.surface);
|
||||||
|
|
||||||
|
depthReadBuffer.surface.image = gfx_wiiu_alloc_mem1(depthReadBuffer.surface.alignment, depthReadBuffer.surface.imageSize);
|
||||||
|
assert(depthReadBuffer.surface.image);
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_MODE_CPU | GX2_INVALIDATE_MODE_DEPTH_BUFFER, depthReadBuffer.surface.image, depthReadBuffer.surface.imageSize);
|
||||||
|
|
||||||
|
GX2SetColorBuffer(&main_framebuffer.color_buffer, GX2_RENDER_TARGET_0);
|
||||||
|
GX2SetDepthBuffer(&main_framebuffer.depth_buffer);
|
||||||
|
|
||||||
|
current_framebuffer = &main_framebuffer;
|
||||||
|
|
||||||
|
// allocate draw buffer
|
||||||
|
draw_buffer = (uint8_t *) memalign(GX2_VERTEX_BUFFER_ALIGNMENT, DRAW_BUFFER_SIZE);
|
||||||
|
assert(draw_buffer);
|
||||||
|
draw_ptr = draw_buffer;
|
||||||
|
|
||||||
|
GX2SetRasterizerClipControl(TRUE, FALSE);
|
||||||
|
|
||||||
|
GX2SetBlendControl(GX2_RENDER_TARGET_0,
|
||||||
|
GX2_BLEND_MODE_SRC_ALPHA,
|
||||||
|
GX2_BLEND_MODE_INV_SRC_ALPHA,
|
||||||
|
GX2_BLEND_COMBINE_MODE_ADD,
|
||||||
|
FALSE,
|
||||||
|
GX2_BLEND_MODE_ZERO,
|
||||||
|
GX2_BLEND_MODE_ZERO,
|
||||||
|
GX2_BLEND_COMBINE_MODE_ADD);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfx_gx2_shutdown(void) {
|
||||||
|
if (has_foreground) {
|
||||||
|
GX2DrawDone();
|
||||||
|
|
||||||
|
if (depthReadBuffer.surface.image) {
|
||||||
|
gfx_wiiu_free_mem1(depthReadBuffer.surface.image);
|
||||||
|
depthReadBuffer.surface.image = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (main_framebuffer.color_buffer.surface.image) {
|
||||||
|
gfx_wiiu_free_mem1(main_framebuffer.color_buffer.surface.image);
|
||||||
|
main_framebuffer.color_buffer.surface.image = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (main_framebuffer.depth_buffer.surface.image) {
|
||||||
|
gfx_wiiu_free_mem1(main_framebuffer.depth_buffer.surface.image);
|
||||||
|
main_framebuffer.depth_buffer.surface.image = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (draw_buffer) {
|
||||||
|
free(draw_buffer);
|
||||||
|
draw_buffer = nullptr;
|
||||||
|
draw_ptr = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_on_resize(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_start_frame(void) {
|
||||||
|
// Restore state since ImGui modified it when rendering
|
||||||
|
GX2SetViewport(current_viewport_x, current_viewport_y, current_viewport_width, current_viewport_height, 0.0f, 1.0f);
|
||||||
|
GX2SetScissor(current_scissor_x, current_scissor_y, current_scissor_width, current_scissor_height);
|
||||||
|
|
||||||
|
GX2SetColorControl(GX2_LOGIC_OP_COPY, current_use_alpha ? 0xff : 0, FALSE, TRUE);
|
||||||
|
|
||||||
|
GX2SetBlendControl(GX2_RENDER_TARGET_0,
|
||||||
|
GX2_BLEND_MODE_SRC_ALPHA,
|
||||||
|
GX2_BLEND_MODE_INV_SRC_ALPHA,
|
||||||
|
GX2_BLEND_COMBINE_MODE_ADD,
|
||||||
|
FALSE,
|
||||||
|
GX2_BLEND_MODE_ZERO,
|
||||||
|
GX2_BLEND_MODE_ZERO,
|
||||||
|
GX2_BLEND_COMBINE_MODE_ADD);
|
||||||
|
|
||||||
|
GX2SetDepthOnlyControl(current_depth_test, current_depth_write, current_depth_compare_function);
|
||||||
|
|
||||||
|
if (current_zmode_decal) {
|
||||||
|
GX2SetPolygonControl(GX2_FRONT_FACE_CCW, FALSE, FALSE, TRUE,
|
||||||
|
GX2_POLYGON_MODE_TRIANGLE, GX2_POLYGON_MODE_TRIANGLE,
|
||||||
|
TRUE, TRUE, FALSE);
|
||||||
|
GX2SetPolygonOffset(-2.0f, -2.0f, -2.0f, -2.0f, 0.0f);
|
||||||
|
} else {
|
||||||
|
GX2SetPolygonControl(GX2_FRONT_FACE_CCW, FALSE, FALSE, FALSE,
|
||||||
|
GX2_POLYGON_MODE_TRIANGLE, GX2_POLYGON_MODE_TRIANGLE,
|
||||||
|
FALSE, FALSE, FALSE);
|
||||||
|
GX2SetPolygonOffset(0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
frame_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_end_frame(void) {
|
||||||
|
draw_ptr = draw_buffer;
|
||||||
|
|
||||||
|
GX2CopyColorBufferToScanBuffer(&main_framebuffer.color_buffer, GX2_SCAN_TARGET_TV);
|
||||||
|
GX2CopyColorBufferToScanBuffer(&main_framebuffer.color_buffer, GX2_SCAN_TARGET_DRC);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_finish_render(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gfx_gx2_create_framebuffer(void) {
|
||||||
|
struct Framebuffer *buffer = (struct Framebuffer *) calloc(1, sizeof(struct Framebuffer));
|
||||||
|
assert(buffer);
|
||||||
|
|
||||||
|
GX2InitSampler(&buffer->sampler, GX2_TEX_CLAMP_MODE_WRAP, GX2_TEX_XY_FILTER_MODE_LINEAR);
|
||||||
|
|
||||||
|
buffer->imtex.Texture = &buffer->texture;
|
||||||
|
buffer->imtex.Sampler = &buffer->sampler;
|
||||||
|
|
||||||
|
// some more 32-bit shenanigans :D
|
||||||
|
return (int) buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_gx2_update_framebuffer_parameters(int fb, uint32_t width, uint32_t height, uint32_t msaa_level, bool opengl_invert_y, bool render_target, bool has_depth_buffer, bool can_extract_depth) {
|
||||||
|
struct Framebuffer *buffer = (struct Framebuffer *) fb;
|
||||||
|
|
||||||
|
// we don't support updating the main buffer (fb 0)
|
||||||
|
if (!buffer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer->texture.surface.width == width &&
|
||||||
|
buffer->texture.surface.height == height) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the GPU no longer writes to the buffer
|
||||||
|
GX2DrawDone();
|
||||||
|
|
||||||
|
if (buffer->texture.surface.image) {
|
||||||
|
if (buffer->colorBufferMem1) {
|
||||||
|
gfx_wiiu_free_mem1(buffer->texture.surface.image);
|
||||||
|
} else {
|
||||||
|
free(buffer->texture.surface.image);
|
||||||
|
}
|
||||||
|
buffer->texture.surface.image = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer->depth_buffer.surface.image) {
|
||||||
|
if (buffer->depthBufferMem1) {
|
||||||
|
gfx_wiiu_free_mem1(buffer->depth_buffer.surface.image);
|
||||||
|
} else {
|
||||||
|
free(buffer->depth_buffer.surface.image);
|
||||||
|
}
|
||||||
|
buffer->depth_buffer.surface.image = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx_gx2_init_framebuffer(buffer, width, height);
|
||||||
|
|
||||||
|
GX2CalcSurfaceSizeAndAlignment(&buffer->depth_buffer.surface);
|
||||||
|
GX2InitDepthBufferRegs(&buffer->depth_buffer);
|
||||||
|
|
||||||
|
buffer->depth_buffer.surface.image = gfx_wiiu_alloc_mem1(buffer->depth_buffer.surface.imageSize, buffer->depth_buffer.surface.alignment);
|
||||||
|
// fall back to mem2
|
||||||
|
if (!buffer->depth_buffer.surface.image) {
|
||||||
|
buffer->depth_buffer.surface.image = memalign(buffer->depth_buffer.surface.alignment, buffer->depth_buffer.surface.imageSize);
|
||||||
|
buffer->depthBufferMem1 = false;
|
||||||
|
} else {
|
||||||
|
buffer->depthBufferMem1 = true;
|
||||||
|
}
|
||||||
|
assert(buffer->depth_buffer.surface.image);
|
||||||
|
|
||||||
|
GX2CalcSurfaceSizeAndAlignment(&buffer->color_buffer.surface);
|
||||||
|
GX2InitColorBufferRegs(&buffer->color_buffer);
|
||||||
|
|
||||||
|
memset(&buffer->texture, 0, sizeof(GX2Texture));
|
||||||
|
buffer->texture.surface.use = GX2_SURFACE_USE_TEXTURE;
|
||||||
|
buffer->texture.surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
|
||||||
|
buffer->texture.surface.width = width;
|
||||||
|
buffer->texture.surface.height = height;
|
||||||
|
buffer->texture.surface.depth = 1;
|
||||||
|
buffer->texture.surface.mipLevels = 1;
|
||||||
|
buffer->texture.surface.format = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8;
|
||||||
|
buffer->texture.surface.aa = GX2_AA_MODE1X;
|
||||||
|
buffer->texture.surface.tileMode = GX2_TILE_MODE_DEFAULT;
|
||||||
|
buffer->texture.viewFirstMip = 0;
|
||||||
|
buffer->texture.viewNumMips = 1;
|
||||||
|
buffer->texture.viewFirstSlice = 0;
|
||||||
|
buffer->texture.viewNumSlices = 1;
|
||||||
|
buffer->texture.compMap = GX2_COMP_MAP(GX2_SQ_SEL_R, GX2_SQ_SEL_G, GX2_SQ_SEL_B, GX2_SQ_SEL_A);
|
||||||
|
|
||||||
|
GX2CalcSurfaceSizeAndAlignment(&buffer->texture.surface);
|
||||||
|
GX2InitTextureRegs(&buffer->texture);
|
||||||
|
|
||||||
|
// the texture and color buffer share a buffer
|
||||||
|
assert(buffer->color_buffer.surface.imageSize == buffer->texture.surface.imageSize);
|
||||||
|
|
||||||
|
buffer->texture.surface.image = gfx_wiiu_alloc_mem1(buffer->texture.surface.imageSize, buffer->texture.surface.alignment);
|
||||||
|
// fall back to mem2
|
||||||
|
if (!buffer->texture.surface.image) {
|
||||||
|
buffer->texture.surface.image = memalign(buffer->texture.surface.alignment, buffer->texture.surface.imageSize);
|
||||||
|
buffer->colorBufferMem1 = false;
|
||||||
|
} else {
|
||||||
|
buffer->colorBufferMem1 = true;
|
||||||
|
}
|
||||||
|
assert(buffer->texture.surface.image);
|
||||||
|
|
||||||
|
buffer->color_buffer.surface.image = buffer->texture.surface.image;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfx_gx2_start_draw_to_framebuffer(int fb, float noise_scale) {
|
||||||
|
struct Framebuffer *buffer = (struct Framebuffer *) fb;
|
||||||
|
|
||||||
|
// fb 0 = main buffer
|
||||||
|
if (!buffer) {
|
||||||
|
buffer = &main_framebuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (noise_scale != 0.0f) {
|
||||||
|
current_noise_scale = 1.0f / noise_scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
GX2SetColorBuffer(&buffer->color_buffer, GX2_RENDER_TARGET_0);
|
||||||
|
GX2SetDepthBuffer(&buffer->depth_buffer);
|
||||||
|
|
||||||
|
current_framebuffer = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfx_gx2_clear_framebuffer(void) {
|
||||||
|
struct Framebuffer *buffer = current_framebuffer;
|
||||||
|
|
||||||
|
GX2ClearColor(&buffer->color_buffer, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
GX2ClearDepthStencilEx(&buffer->depth_buffer,
|
||||||
|
buffer->depth_buffer.depthClear,
|
||||||
|
buffer->depth_buffer.stencilClear, GX2_CLEAR_FLAGS_BOTH);
|
||||||
|
|
||||||
|
gfx_wiiu_set_context_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfx_gx2_resolve_msaa_color_buffer(int fb_id_target, int fb_id_source) {
|
||||||
|
struct Framebuffer *src_buffer = (struct Framebuffer *) fb_id_source;
|
||||||
|
struct Framebuffer *target_buffer = (struct Framebuffer *) fb_id_target;
|
||||||
|
|
||||||
|
// fb 0 = main buffer
|
||||||
|
if (!src_buffer) {
|
||||||
|
src_buffer = &main_framebuffer;
|
||||||
|
}
|
||||||
|
if (!target_buffer) {
|
||||||
|
target_buffer = &main_framebuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src_buffer->color_buffer.surface.aa == GX2_AA_MODE1X) {
|
||||||
|
GX2CopySurface(&src_buffer->color_buffer.surface,
|
||||||
|
src_buffer->color_buffer.viewMip,
|
||||||
|
src_buffer->color_buffer.viewFirstSlice,
|
||||||
|
&target_buffer->color_buffer.surface,
|
||||||
|
target_buffer->color_buffer.viewMip,
|
||||||
|
target_buffer->color_buffer.viewFirstSlice);
|
||||||
|
} else {
|
||||||
|
GX2ResolveAAColorBuffer(&src_buffer->color_buffer,
|
||||||
|
&target_buffer->color_buffer.surface,
|
||||||
|
target_buffer->color_buffer.viewMip,
|
||||||
|
target_buffer->color_buffer.viewFirstSlice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *gfx_gx2_get_framebuffer_texture_id(int fb_id) {
|
||||||
|
struct Framebuffer *buffer = (struct Framebuffer *) fb_id;
|
||||||
|
|
||||||
|
// fb 0 = main buffer
|
||||||
|
if (!buffer) {
|
||||||
|
buffer = &main_framebuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &buffer->imtex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfx_gx2_select_texture_fb(int fb) {
|
||||||
|
struct Framebuffer *buffer = (struct Framebuffer *) fb;
|
||||||
|
assert(buffer);
|
||||||
|
|
||||||
|
assert(current_shader_program);
|
||||||
|
uint32_t location = current_shader_program->samplers_location[0];
|
||||||
|
GX2SetPixelTexture(&buffer->texture, location);
|
||||||
|
GX2SetPixelSampler(&buffer->sampler, location);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::unordered_map<std::pair<float, float>, uint16_t, hash_pair_ff> gfx_gx2_get_pixel_depth(int fb_id, const std::set<std::pair<float, float>>& coordinates) {
|
||||||
|
struct Framebuffer *buffer = (struct Framebuffer *) fb_id;
|
||||||
|
|
||||||
|
// fb 0 = main buffer
|
||||||
|
if (!buffer) {
|
||||||
|
buffer = &main_framebuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_map<std::pair<float, float>, uint16_t, hash_pair_ff> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
res.emplace(c, val * 65532.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfx_gx2_set_texture_filter(FilteringMode mode) {
|
||||||
|
// three-point is not implemented in the shaders yet
|
||||||
|
if (mode == FILTER_THREE_POINT) {
|
||||||
|
mode = FILTER_LINEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_filter_mode = mode;
|
||||||
|
gfx_texture_cache_clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
FilteringMode gfx_gx2_get_texture_filter(void) {
|
||||||
|
return current_filter_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui_ImplGX2_Texture* gfx_gx2_texture_for_imgui(uint32_t texture_id) {
|
||||||
|
struct Texture *tex = (struct Texture *) texture_id;
|
||||||
|
return &tex->imtex;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GfxRenderingAPI gfx_gx2_api = {
|
||||||
|
gfx_gx2_get_clip_parameters,
|
||||||
|
gfx_gx2_unload_shader,
|
||||||
|
gfx_gx2_load_shader,
|
||||||
|
gfx_gx2_create_and_load_new_shader,
|
||||||
|
gfx_gx2_lookup_shader,
|
||||||
|
gfx_gx2_shader_get_info,
|
||||||
|
gfx_gx2_new_texture,
|
||||||
|
gfx_gx2_select_texture,
|
||||||
|
gfx_gx2_upload_texture,
|
||||||
|
gfx_gx2_set_sampler_parameters,
|
||||||
|
gfx_gx2_set_depth_test_and_mask,
|
||||||
|
gfx_gx2_set_zmode_decal,
|
||||||
|
gfx_gx2_set_viewport,
|
||||||
|
gfx_gx2_set_scissor,
|
||||||
|
gfx_gx2_set_use_alpha,
|
||||||
|
gfx_gx2_draw_triangles,
|
||||||
|
gfx_gx2_init,
|
||||||
|
gfx_gx2_on_resize,
|
||||||
|
gfx_gx2_start_frame,
|
||||||
|
gfx_gx2_end_frame,
|
||||||
|
gfx_gx2_finish_render,
|
||||||
|
gfx_gx2_create_framebuffer,
|
||||||
|
gfx_gx2_update_framebuffer_parameters,
|
||||||
|
gfx_gx2_start_draw_to_framebuffer,
|
||||||
|
gfx_gx2_clear_framebuffer,
|
||||||
|
gfx_gx2_resolve_msaa_color_buffer,
|
||||||
|
gfx_gx2_get_pixel_depth,
|
||||||
|
gfx_gx2_get_framebuffer_texture_id,
|
||||||
|
gfx_gx2_select_texture_fb,
|
||||||
|
gfx_gx2_delete_texture,
|
||||||
|
gfx_gx2_set_texture_filter,
|
||||||
|
gfx_gx2_get_texture_filter
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
12
libultraship/libultraship/Lib/Fast3D/gfx_gx2.h
Normal file
12
libultraship/libultraship/Lib/Fast3D/gfx_gx2.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef GFX_GX2_H
|
||||||
|
#define GFX_GX2_H
|
||||||
|
|
||||||
|
#include "gfx_rendering_api.h"
|
||||||
|
|
||||||
|
void gfx_gx2_shutdown(void);
|
||||||
|
|
||||||
|
struct ImGui_ImplGX2_Texture* gfx_gx2_texture_for_imgui(uint32_t texture_id);
|
||||||
|
|
||||||
|
extern struct GfxRenderingAPI gfx_gx2_api;
|
||||||
|
|
||||||
|
#endif
|
@ -1382,12 +1382,25 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo
|
|||||||
buf_vbo[buf_vbo_len++] = u / tex_width[t];
|
buf_vbo[buf_vbo_len++] = u / tex_width[t];
|
||||||
buf_vbo[buf_vbo_len++] = v / tex_height[t];
|
buf_vbo[buf_vbo_len++] = v / tex_height[t];
|
||||||
|
|
||||||
if (tm & (1 << 2 * t)) {
|
bool clampS = tm & (1 << 2 * t);
|
||||||
|
bool clampT = tm & (1 << 2 * t + 1);
|
||||||
|
|
||||||
|
if (clampS) {
|
||||||
buf_vbo[buf_vbo_len++] = (tex_width2[t] - 0.5f) / tex_width[t];
|
buf_vbo[buf_vbo_len++] = (tex_width2[t] - 0.5f) / tex_width[t];
|
||||||
}
|
}
|
||||||
if (tm & (1 << 2 * t + 1)) {
|
#ifdef __WIIU__
|
||||||
|
else {
|
||||||
|
buf_vbo[buf_vbo_len++] = 0.0f;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (clampT) {
|
||||||
buf_vbo[buf_vbo_len++] = (tex_height2[t] - 0.5f) / tex_height[t];
|
buf_vbo[buf_vbo_len++] = (tex_height2[t] - 0.5f) / tex_height[t];
|
||||||
}
|
}
|
||||||
|
#ifdef __WIIU__
|
||||||
|
else {
|
||||||
|
buf_vbo[buf_vbo_len++] = 0.0f;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_fog) {
|
if (use_fog) {
|
||||||
@ -1464,6 +1477,12 @@ static void gfx_sp_tri1(uint8_t vtx1_idx, uint8_t vtx2_idx, uint8_t vtx3_idx, bo
|
|||||||
buf_vbo[buf_vbo_len++] = color->r / 255.0f;
|
buf_vbo[buf_vbo_len++] = color->r / 255.0f;
|
||||||
buf_vbo[buf_vbo_len++] = color->g / 255.0f;
|
buf_vbo[buf_vbo_len++] = color->g / 255.0f;
|
||||||
buf_vbo[buf_vbo_len++] = color->b / 255.0f;
|
buf_vbo[buf_vbo_len++] = color->b / 255.0f;
|
||||||
|
#ifdef __WIIU__
|
||||||
|
// padding
|
||||||
|
if (!use_alpha) {
|
||||||
|
buf_vbo[buf_vbo_len++] = 1.0f;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (use_fog && color == &v_arr[i]->color) {
|
if (use_fog && color == &v_arr[i]->color) {
|
||||||
@ -2658,8 +2677,10 @@ void gfx_init(struct GfxWindowManagerAPI *wapi, struct GfxRenderingAPI *rapi, co
|
|||||||
gfx_current_dimensions.internal_mul = CVar_GetFloat("gInternalResolution", 1);
|
gfx_current_dimensions.internal_mul = CVar_GetFloat("gInternalResolution", 1);
|
||||||
#endif
|
#endif
|
||||||
gfx_msaa_level = CVar_GetS32("gMSAAValue", 1);
|
gfx_msaa_level = CVar_GetS32("gMSAAValue", 1);
|
||||||
|
#ifndef __WIIU__ // Wii U overrides dimentions in gfx_wapi->init to match framebuffer size
|
||||||
gfx_current_dimensions.width = width;
|
gfx_current_dimensions.width = width;
|
||||||
gfx_current_dimensions.height = height;
|
gfx_current_dimensions.height = height;
|
||||||
|
#endif
|
||||||
game_framebuffer = gfx_rapi->create_framebuffer();
|
game_framebuffer = gfx_rapi->create_framebuffer();
|
||||||
game_framebuffer_msaa_resolved = gfx_rapi->create_framebuffer();
|
game_framebuffer_msaa_resolved = gfx_rapi->create_framebuffer();
|
||||||
|
|
||||||
|
467
libultraship/libultraship/Lib/Fast3D/gfx_wiiu.cpp
Normal file
467
libultraship/libultraship/Lib/Fast3D/gfx_wiiu.cpp
Normal file
@ -0,0 +1,467 @@
|
|||||||
|
#ifdef __WIIU__
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
|
#include <coreinit/time.h>
|
||||||
|
#include <coreinit/thread.h>
|
||||||
|
#include <coreinit/foreground.h>
|
||||||
|
#include <coreinit/memory.h>
|
||||||
|
#include <coreinit/memheap.h>
|
||||||
|
#include <coreinit/memdefaultheap.h>
|
||||||
|
#include <coreinit/memexpheap.h>
|
||||||
|
#include <coreinit/memfrmheap.h>
|
||||||
|
|
||||||
|
#include <gx2/state.h>
|
||||||
|
#include <gx2/context.h>
|
||||||
|
#include <gx2/display.h>
|
||||||
|
#include <gx2/event.h>
|
||||||
|
#include <gx2/swap.h>
|
||||||
|
#include <gx2/mem.h>
|
||||||
|
#include <gx2r/mem.h>
|
||||||
|
|
||||||
|
#include <whb/proc.h>
|
||||||
|
#include <proc_ui/procui.h>
|
||||||
|
#include <proc_ui/memory.h>
|
||||||
|
|
||||||
|
#include <vpad/input.h>
|
||||||
|
#include <padscore/kpad.h>
|
||||||
|
|
||||||
|
#ifndef _LANGUAGE_C
|
||||||
|
#define _LANGUAGE_C
|
||||||
|
#endif
|
||||||
|
#include "PR/ultra64/gbi.h"
|
||||||
|
|
||||||
|
#include "gfx_window_manager_api.h"
|
||||||
|
#include "gfx_pc.h"
|
||||||
|
#include "gfx_gx2.h"
|
||||||
|
#include "gfx_wiiu.h"
|
||||||
|
|
||||||
|
#include "Lib/ImGui/backends/wiiu/imgui_impl_wiiu.h"
|
||||||
|
#include "../../WiiUImpl.h"
|
||||||
|
#include "../../ImGuiImpl.h"
|
||||||
|
#include "../../Hooks.h"
|
||||||
|
|
||||||
|
static MEMHeapHandle heap_MEM1 = nullptr;
|
||||||
|
static MEMHeapHandle heap_foreground = nullptr;
|
||||||
|
|
||||||
|
bool has_foreground = false;
|
||||||
|
static void *mem1_storage = nullptr;
|
||||||
|
static void *command_buffer_pool = nullptr;
|
||||||
|
GX2ContextState *context_state = nullptr;
|
||||||
|
|
||||||
|
static GX2TVRenderMode tv_render_mode;
|
||||||
|
static void *tv_scan_buffer = nullptr;
|
||||||
|
static uint32_t tv_scan_buffer_size = 0;
|
||||||
|
static uint32_t tv_width;
|
||||||
|
static uint32_t tv_height;
|
||||||
|
|
||||||
|
static GX2DrcRenderMode drc_render_mode;
|
||||||
|
static void *drc_scan_buffer = nullptr;
|
||||||
|
static uint32_t drc_scan_buffer_size = 0;
|
||||||
|
|
||||||
|
static int frame_divisor = 1;
|
||||||
|
|
||||||
|
// for ImGui DeltaTime
|
||||||
|
// (initialized to 1 to not trigger imguis assert on initial draw)
|
||||||
|
uint32_t frametime = 1;
|
||||||
|
|
||||||
|
bool gfx_wiiu_init_mem1(void) {
|
||||||
|
MEMHeapHandle heap = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1);
|
||||||
|
uint32_t size;
|
||||||
|
void *base;
|
||||||
|
|
||||||
|
size = MEMGetAllocatableSizeForFrmHeapEx(heap, 4);
|
||||||
|
if (!size) {
|
||||||
|
printf("%s: MEMGetAllocatableSizeForFrmHeapEx == 0", __FUNCTION__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
base = MEMAllocFromFrmHeapEx(heap, size, 4);
|
||||||
|
if (!base) {
|
||||||
|
printf("%s: MEMAllocFromFrmHeapEx(heap, 0x%X, 4) failed", __FUNCTION__, size);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
heap_MEM1 = MEMCreateExpHeapEx(base, size, 0);
|
||||||
|
if (!heap_MEM1) {
|
||||||
|
printf("%s: MEMCreateExpHeapEx(%p, 0x%X, 0) failed", __FUNCTION__, base, size);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfx_wiiu_destroy_mem1(void) {
|
||||||
|
MEMHeapHandle heap = MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM1);
|
||||||
|
|
||||||
|
if (heap_MEM1) {
|
||||||
|
MEMDestroyExpHeap(heap_MEM1);
|
||||||
|
heap_MEM1 = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gfx_wiiu_init_foreground(void) {
|
||||||
|
MEMHeapHandle heap = MEMGetBaseHeapHandle(MEM_BASE_HEAP_FG);
|
||||||
|
uint32_t size;
|
||||||
|
void *base;
|
||||||
|
|
||||||
|
size = MEMGetAllocatableSizeForFrmHeapEx(heap, 4);
|
||||||
|
if (!size) {
|
||||||
|
printf("%s: MEMAllocFromFrmHeapEx(heap, 0x%X, 4)", __FUNCTION__, size);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
base = MEMAllocFromFrmHeapEx(heap, size, 4);
|
||||||
|
if (!base) {
|
||||||
|
printf("%s: MEMGetAllocatableSizeForFrmHeapEx == 0", __FUNCTION__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
heap_foreground = MEMCreateExpHeapEx(base, size, 0);
|
||||||
|
if (!heap_foreground) {
|
||||||
|
printf("%s: MEMCreateExpHeapEx(%p, 0x%X, 0)", __FUNCTION__, base, size);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfx_wiiu_destroy_foreground(void) {
|
||||||
|
MEMHeapHandle foreground = MEMGetBaseHeapHandle(MEM_BASE_HEAP_FG);
|
||||||
|
|
||||||
|
if (heap_foreground) {
|
||||||
|
MEMDestroyExpHeap(heap_foreground);
|
||||||
|
heap_foreground = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEMFreeToFrmHeap(foreground, MEM_FRM_HEAP_FREE_ALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *gfx_wiiu_alloc_mem1(uint32_t size, uint32_t alignment) {
|
||||||
|
void *block;
|
||||||
|
|
||||||
|
if (!heap_MEM1) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alignment < 4) {
|
||||||
|
alignment = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
block = MEMAllocFromExpHeapEx(heap_MEM1, size, alignment);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfx_wiiu_free_mem1(void *block) {
|
||||||
|
if (!heap_MEM1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEMFreeToExpHeap(heap_MEM1, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *gfx_wiiu_alloc_foreground(uint32_t size, uint32_t alignment) {
|
||||||
|
void *block;
|
||||||
|
|
||||||
|
if (!heap_foreground) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alignment < 4) {
|
||||||
|
alignment = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
block = MEMAllocFromExpHeapEx(heap_foreground, size, alignment);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfx_wiiu_free_foreground(void *block) {
|
||||||
|
if (!heap_foreground) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MEMFreeToExpHeap(heap_foreground, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t gfx_wiiu_proc_callback_acquired(void *context) {
|
||||||
|
has_foreground = true;
|
||||||
|
|
||||||
|
bool result = gfx_wiiu_init_foreground();
|
||||||
|
assert(result);
|
||||||
|
|
||||||
|
tv_scan_buffer = gfx_wiiu_alloc_foreground(tv_scan_buffer_size, GX2_SCAN_BUFFER_ALIGNMENT);
|
||||||
|
assert(tv_scan_buffer);
|
||||||
|
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, tv_scan_buffer, tv_scan_buffer_size);
|
||||||
|
GX2SetTVBuffer(tv_scan_buffer, tv_scan_buffer_size, tv_render_mode, GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8, GX2_BUFFERING_MODE_DOUBLE);
|
||||||
|
|
||||||
|
drc_scan_buffer = gfx_wiiu_alloc_foreground(drc_scan_buffer_size, GX2_SCAN_BUFFER_ALIGNMENT);
|
||||||
|
assert(drc_scan_buffer);
|
||||||
|
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, drc_scan_buffer, drc_scan_buffer_size);
|
||||||
|
GX2SetDRCBuffer(drc_scan_buffer, drc_scan_buffer_size, drc_render_mode, GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8, GX2_BUFFERING_MODE_DOUBLE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t gfx_wiiu_proc_callback_released(void* context) {
|
||||||
|
if (tv_scan_buffer) {
|
||||||
|
gfx_wiiu_free_foreground(tv_scan_buffer);
|
||||||
|
tv_scan_buffer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drc_scan_buffer) {
|
||||||
|
gfx_wiiu_free_foreground(drc_scan_buffer);
|
||||||
|
drc_scan_buffer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx_wiiu_destroy_foreground();
|
||||||
|
|
||||||
|
has_foreground = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_wiiu_init(const char *game_name, bool start_in_fullscreen, uint32_t width, uint32_t height) {
|
||||||
|
WHBProcInit();
|
||||||
|
|
||||||
|
uint32_t mem1_addr, mem1_size;
|
||||||
|
OSGetMemBound(OS_MEM1, &mem1_addr, &mem1_size);
|
||||||
|
mem1_storage = memalign(0x40, mem1_size);
|
||||||
|
assert(mem1_storage);
|
||||||
|
|
||||||
|
ProcUISetMEM1Storage(mem1_storage, mem1_size);
|
||||||
|
|
||||||
|
bool result = gfx_wiiu_init_mem1();
|
||||||
|
assert(result);
|
||||||
|
|
||||||
|
command_buffer_pool = memalign(GX2_COMMAND_BUFFER_ALIGNMENT, 0x400000);
|
||||||
|
assert(command_buffer_pool);
|
||||||
|
|
||||||
|
uint32_t initAttribs[] = {
|
||||||
|
GX2_INIT_CMD_BUF_BASE, (uintptr_t) command_buffer_pool,
|
||||||
|
GX2_INIT_CMD_BUF_POOL_SIZE, 0x400000,
|
||||||
|
GX2_INIT_ARGC, 0,
|
||||||
|
GX2_INIT_ARGV, 0,
|
||||||
|
GX2_INIT_END
|
||||||
|
};
|
||||||
|
GX2Init(initAttribs);
|
||||||
|
|
||||||
|
switch(GX2GetSystemTVScanMode()) {
|
||||||
|
case GX2_TV_SCAN_MODE_480I:
|
||||||
|
case GX2_TV_SCAN_MODE_480P:
|
||||||
|
tv_render_mode = GX2_TV_RENDER_MODE_WIDE_480P;
|
||||||
|
tv_width = 854;
|
||||||
|
tv_height = 480;
|
||||||
|
break;
|
||||||
|
case GX2_TV_SCAN_MODE_1080I:
|
||||||
|
case GX2_TV_SCAN_MODE_1080P:
|
||||||
|
tv_render_mode = GX2_TV_RENDER_MODE_WIDE_1080P;
|
||||||
|
tv_width = 1920;
|
||||||
|
tv_height = 1080;
|
||||||
|
break;
|
||||||
|
case GX2_TV_SCAN_MODE_720P:
|
||||||
|
default:
|
||||||
|
tv_render_mode = GX2_TV_RENDER_MODE_WIDE_720P;
|
||||||
|
tv_width = 1280;
|
||||||
|
tv_height = 720;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
drc_render_mode = GX2GetSystemDRCScanMode();
|
||||||
|
|
||||||
|
uint32_t unk;
|
||||||
|
GX2CalcTVSize(tv_render_mode, GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8, GX2_BUFFERING_MODE_DOUBLE, &tv_scan_buffer_size, &unk);
|
||||||
|
GX2CalcDRCSize(drc_render_mode, GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8, GX2_BUFFERING_MODE_DOUBLE, &drc_scan_buffer_size, &unk);
|
||||||
|
|
||||||
|
ProcUIRegisterCallback(PROCUI_CALLBACK_ACQUIRE, gfx_wiiu_proc_callback_acquired, nullptr, 100);
|
||||||
|
ProcUIRegisterCallback(PROCUI_CALLBACK_RELEASE, gfx_wiiu_proc_callback_released, nullptr, 100);
|
||||||
|
|
||||||
|
gfx_wiiu_proc_callback_acquired(nullptr);
|
||||||
|
|
||||||
|
context_state = (GX2ContextState *) memalign(GX2_CONTEXT_STATE_ALIGNMENT, sizeof(GX2ContextState));
|
||||||
|
assert(context_state);
|
||||||
|
|
||||||
|
GX2SetupContextStateEx(context_state, TRUE);
|
||||||
|
GX2SetContextState(context_state);
|
||||||
|
|
||||||
|
GX2SetTVScale(WIIU_DEFAULT_FB_WIDTH, WIIU_DEFAULT_FB_HEIGHT);
|
||||||
|
GX2SetDRCScale(WIIU_DEFAULT_FB_WIDTH, WIIU_DEFAULT_FB_HEIGHT);
|
||||||
|
|
||||||
|
GX2SetSwapInterval(frame_divisor);
|
||||||
|
|
||||||
|
gfx_current_dimensions.width = gfx_current_game_window_viewport.width = WIIU_DEFAULT_FB_WIDTH;
|
||||||
|
gfx_current_dimensions.height = gfx_current_game_window_viewport.height = WIIU_DEFAULT_FB_HEIGHT;
|
||||||
|
|
||||||
|
SohImGui::WindowImpl window_impl;
|
||||||
|
window_impl.backend = SohImGui::Backend::GX2;
|
||||||
|
window_impl.gx2.width = WIIU_DEFAULT_FB_WIDTH;
|
||||||
|
window_impl.gx2.height = WIIU_DEFAULT_FB_HEIGHT;
|
||||||
|
SohImGui::Init(window_impl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_wiiu_shutdown(void) {
|
||||||
|
if (has_foreground) {
|
||||||
|
gfx_wiiu_proc_callback_released(nullptr);
|
||||||
|
gfx_wiiu_destroy_mem1();
|
||||||
|
}
|
||||||
|
|
||||||
|
GX2Shutdown();
|
||||||
|
|
||||||
|
if (context_state) {
|
||||||
|
free(context_state);
|
||||||
|
context_state = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command_buffer_pool) {
|
||||||
|
free(command_buffer_pool);
|
||||||
|
command_buffer_pool = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcUISetMEM1Storage(nullptr, 0);
|
||||||
|
free(mem1_storage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfx_wiiu_set_context_state(void) {
|
||||||
|
GX2SetContextState(context_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_wiiu_set_fullscreen_changed_callback(void (*on_fullscreen_changed)(bool is_now_fullscreen)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_wiiu_set_fullscreen(bool enable) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_wiiu_show_cursor(bool hide) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_wiiu_set_keyboard_callbacks(bool (*on_key_down)(int scancode), bool (*on_key_up)(int scancode), void (*on_all_keys_up)(void)) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_wiiu_main_loop(void (*run_one_game_iter)(void)) {
|
||||||
|
while (WHBProcIsRunning()) {
|
||||||
|
run_one_game_iter();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ship::ExecuteHooks<Ship::ExitGame>();
|
||||||
|
Ship::WiiU::Exit();
|
||||||
|
|
||||||
|
gfx_gx2_shutdown();
|
||||||
|
gfx_wiiu_shutdown();
|
||||||
|
WHBProcShutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_wiiu_get_dimensions(uint32_t *width, uint32_t *height) {
|
||||||
|
*width = WIIU_DEFAULT_FB_WIDTH;
|
||||||
|
*height = WIIU_DEFAULT_FB_HEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_wiiu_handle_events(void) {
|
||||||
|
Ship::WiiU::Update();
|
||||||
|
|
||||||
|
ImGui_ImplWiiU_ControllerInput input{};
|
||||||
|
|
||||||
|
VPADReadError vpad_error;
|
||||||
|
input.vpad = Ship::WiiU::GetVPADStatus(&vpad_error);
|
||||||
|
if (vpad_error != VPAD_READ_SUCCESS) {
|
||||||
|
input.vpad = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
KPADError kpad_error;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
input.kpad[i] = Ship::WiiU::GetKPADStatus((WPADChan) i, &kpad_error);
|
||||||
|
if (kpad_error != KPAD_ERROR_OK) {
|
||||||
|
input.kpad[i] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SohImGui::EventImpl event_impl;
|
||||||
|
event_impl.gx2.input = &input;
|
||||||
|
SohImGui::Update(event_impl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool gfx_wiiu_start_frame(void) {
|
||||||
|
uint32_t swap_count, flip_count;
|
||||||
|
OSTime last_flip, last_vsync;
|
||||||
|
uint32_t wait_count = 0;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
GX2GetSwapStatus(&swap_count, &flip_count, &last_flip, &last_vsync);
|
||||||
|
|
||||||
|
if (flip_count >= swap_count) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wait_count >= 10) {
|
||||||
|
// GPU timed out, drop frame
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wait_count++;
|
||||||
|
GX2WaitForVsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_wiiu_swap_buffers_begin(void) {
|
||||||
|
GX2SwapScanBuffers();
|
||||||
|
GX2Flush();
|
||||||
|
|
||||||
|
gfx_wiiu_set_context_state();
|
||||||
|
|
||||||
|
GX2SetTVEnable(TRUE);
|
||||||
|
GX2SetDRCEnable(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_wiiu_swap_buffers_end(void) {
|
||||||
|
static OSTick tick = 0;
|
||||||
|
frametime = OSTicksToMicroseconds(OSGetSystemTick() - tick);
|
||||||
|
tick = OSGetSystemTick();
|
||||||
|
}
|
||||||
|
|
||||||
|
static double gfx_wiiu_get_time(void) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_wiiu_set_target_fps(int fps) {
|
||||||
|
// use the nearest divisor
|
||||||
|
int divisor = 60 / fps;
|
||||||
|
if (divisor < 1) {
|
||||||
|
divisor = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame_divisor != divisor) {
|
||||||
|
GX2SetSwapInterval(divisor);
|
||||||
|
frame_divisor = divisor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gfx_wiiu_set_maximum_frame_latency(int latency) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static float gfx_wiiu_get_detected_hz(void) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GfxWindowManagerAPI gfx_wiiu = {
|
||||||
|
gfx_wiiu_init,
|
||||||
|
gfx_wiiu_set_keyboard_callbacks,
|
||||||
|
gfx_wiiu_set_fullscreen_changed_callback,
|
||||||
|
gfx_wiiu_set_fullscreen,
|
||||||
|
gfx_wiiu_show_cursor,
|
||||||
|
gfx_wiiu_main_loop,
|
||||||
|
gfx_wiiu_get_dimensions,
|
||||||
|
gfx_wiiu_handle_events,
|
||||||
|
gfx_wiiu_start_frame,
|
||||||
|
gfx_wiiu_swap_buffers_begin,
|
||||||
|
gfx_wiiu_swap_buffers_end,
|
||||||
|
gfx_wiiu_get_time,
|
||||||
|
gfx_wiiu_set_target_fps,
|
||||||
|
gfx_wiiu_set_maximum_frame_latency,
|
||||||
|
gfx_wiiu_get_detected_hz,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
38
libultraship/libultraship/Lib/Fast3D/gfx_wiiu.h
Normal file
38
libultraship/libultraship/Lib/Fast3D/gfx_wiiu.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#ifndef GFX_WIIU_H
|
||||||
|
#define GFX_WIIU_H
|
||||||
|
#ifdef __WIIU__
|
||||||
|
|
||||||
|
#include <vpad/input.h>
|
||||||
|
#include <padscore/kpad.h>
|
||||||
|
|
||||||
|
#include "gfx_window_manager_api.h"
|
||||||
|
|
||||||
|
// make the default fb always 1080p to not mess with scaling
|
||||||
|
#define WIIU_DEFAULT_FB_WIDTH 1920
|
||||||
|
#define WIIU_DEFAULT_FB_HEIGHT 1080
|
||||||
|
|
||||||
|
extern bool has_foreground;
|
||||||
|
extern uint32_t frametime;
|
||||||
|
|
||||||
|
bool gfx_wiiu_init_mem1(void);
|
||||||
|
|
||||||
|
void gfx_wiiu_destroy_mem1(void);
|
||||||
|
|
||||||
|
bool gfx_wiiu_init_foreground(void);
|
||||||
|
|
||||||
|
void gfx_wiiu_destroy_foreground(void);
|
||||||
|
|
||||||
|
void *gfx_wiiu_alloc_mem1(uint32_t size, uint32_t alignment);
|
||||||
|
|
||||||
|
void gfx_wiiu_free_mem1(void *block);
|
||||||
|
|
||||||
|
void *gfx_wiiu_alloc_foreground(uint32_t size, uint32_t alignment);
|
||||||
|
|
||||||
|
void gfx_wiiu_free_foreground(void *block);
|
||||||
|
|
||||||
|
void gfx_wiiu_set_context_state(void);
|
||||||
|
|
||||||
|
extern struct GfxWindowManagerAPI gfx_wiiu;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
810
libultraship/libultraship/Lib/Fast3D/gx2_shader_gen.c
Normal file
810
libultraship/libultraship/Lib/Fast3D/gx2_shader_gen.c
Normal file
@ -0,0 +1,810 @@
|
|||||||
|
#ifdef __WIIU__
|
||||||
|
|
||||||
|
#include "gx2_shader_gen.h"
|
||||||
|
#include "gx2_shader_inl.h"
|
||||||
|
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <gx2/mem.h>
|
||||||
|
|
||||||
|
#define ROUNDUP(x, align) (((x) + ((align) -1)) & ~((align) -1))
|
||||||
|
|
||||||
|
#define FRAG_COORD_REG _R0
|
||||||
|
#define TEXEL_REG _R1
|
||||||
|
#define FOG_REG _R3
|
||||||
|
#define GRAYSCALE_REG _R4
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SHADER_TEXINFO0 = SHADER_COMBINED + 1,
|
||||||
|
SHADER_TEXINFO1,
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint8_t get_reg(struct CCFeatures *cc_features, uint8_t c) {
|
||||||
|
if (c == SHADER_0) {
|
||||||
|
return ALU_SRC_0;
|
||||||
|
}
|
||||||
|
if (c == SHADER_1) {
|
||||||
|
return ALU_SRC_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == SHADER_COMBINED) {
|
||||||
|
return TEXEL_REG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c >= SHADER_INPUT_1 && c <= SHADER_INPUT_7) {
|
||||||
|
return _R(5 + (c - SHADER_INPUT_1));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t input_last = (cc_features->num_inputs + 5) - 1;
|
||||||
|
|
||||||
|
if (c == SHADER_TEXEL0 || c == SHADER_TEXEL0A) {
|
||||||
|
// reuse unused regs
|
||||||
|
if (!cc_features->opt_noise) {
|
||||||
|
return FRAG_COORD_REG;
|
||||||
|
} else if (!cc_features->opt_fog) {
|
||||||
|
return FOG_REG;
|
||||||
|
} else if (!cc_features->opt_grayscale) {
|
||||||
|
return GRAYSCALE_REG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _R(input_last + 1);
|
||||||
|
}
|
||||||
|
if (c == SHADER_TEXEL1 || c == SHADER_TEXEL1A) {
|
||||||
|
// if the shader doesn't use texture 0 we can reuse it for texture 1
|
||||||
|
if (!cc_features->used_textures[0]) {
|
||||||
|
return get_reg(cc_features, SHADER_TEXEL0);
|
||||||
|
}
|
||||||
|
// reuse unused regs which tex 0 doesn't use yet
|
||||||
|
else if (!cc_features->opt_fog && get_reg(cc_features, SHADER_TEXEL0) != FOG_REG) {
|
||||||
|
return FOG_REG;
|
||||||
|
} else if (!cc_features->opt_grayscale && get_reg(cc_features, SHADER_TEXEL0) != GRAYSCALE_REG) {
|
||||||
|
return GRAYSCALE_REG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _R(input_last + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reuse the regs above
|
||||||
|
if (c == SHADER_TEXINFO0) {
|
||||||
|
return get_reg(cc_features, SHADER_TEXEL0);
|
||||||
|
}
|
||||||
|
if (c == SHADER_TEXINFO1) {
|
||||||
|
return get_reg(cc_features, SHADER_TEXEL1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t get_num_regs(struct CCFeatures *cc_features) {
|
||||||
|
uint8_t input_count = cc_features->num_inputs + 5;
|
||||||
|
|
||||||
|
uint8_t last_tex_reg;
|
||||||
|
if (cc_features->used_textures[1]) {
|
||||||
|
last_tex_reg = get_reg(cc_features, SHADER_TEXEL1) + 1;
|
||||||
|
} else if (cc_features->used_textures[0]) {
|
||||||
|
last_tex_reg = get_reg(cc_features, SHADER_TEXEL0) + 1;
|
||||||
|
} else {
|
||||||
|
return input_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (last_tex_reg < input_count) ? input_count : last_tex_reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ADD_INSTR(...) \
|
||||||
|
uint64_t tmp[] = {__VA_ARGS__}; \
|
||||||
|
memcpy(*alu_ptr, tmp, sizeof(tmp)); \
|
||||||
|
*alu_ptr += sizeof(tmp) / sizeof(uint64_t)
|
||||||
|
|
||||||
|
static inline void add_tex_clamp_S_T(struct CCFeatures *cc_features, uint64_t **alu_ptr, uint8_t tex) {
|
||||||
|
uint8_t texinfo_reg = get_reg(cc_features, (tex == 0) ? SHADER_TEXINFO0 : SHADER_TEXINFO1);
|
||||||
|
uint8_t texcoord_reg = (tex == 0) ? _R1 : _R2;
|
||||||
|
|
||||||
|
ADD_INSTR(
|
||||||
|
/* R127.xy = (float) texinfo.xy */
|
||||||
|
ALU_INT_TO_FLT(_R127, _x, texinfo_reg, _x) SCL_210
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_INT_TO_FLT(_R127, _y, texinfo_reg, _y) SCL_210
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
/* R127.xy = 0.5f / texSize */
|
||||||
|
ALU_RECIP_IEEE(__, _x, _R127, _x) SCL_210
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_MUL_IEEE(_R127, _x, ALU_SRC_PS, _x, ALU_SRC_0_5, _x),
|
||||||
|
ALU_RECIP_IEEE(__, _y, _R127, _y) SCL_210
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_MUL_IEEE(_R127, _y, ALU_SRC_PS, _y, ALU_SRC_0_5, _x)
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
/* texCoord.xy = clamp(texCoord.xy, R127.xy, texClamp.xy) */
|
||||||
|
ALU_MAX(__, _x, texcoord_reg, _x, _R127, _x),
|
||||||
|
ALU_MAX(__, _y, texcoord_reg, _y, _R127, _y)
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_MIN(texcoord_reg, _x, ALU_SRC_PV, _x, texcoord_reg, _z),
|
||||||
|
ALU_MIN(texcoord_reg, _y, ALU_SRC_PV, _y, texcoord_reg, _w)
|
||||||
|
ALU_LAST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void add_tex_clamp_S(struct CCFeatures *cc_features, uint64_t **alu_ptr, uint8_t tex) {
|
||||||
|
uint8_t texinfo_reg = get_reg(cc_features, (tex == 0) ? SHADER_TEXINFO0 : SHADER_TEXINFO1);
|
||||||
|
uint8_t texcoord_reg = (tex == 0) ? _R1 : _R2;
|
||||||
|
|
||||||
|
ADD_INSTR(
|
||||||
|
/* R127.x = (float) texinfo.x */
|
||||||
|
ALU_INT_TO_FLT(_R127, _x, texinfo_reg, _x) SCL_210
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
/* R127.x = 0.5f / texSize */
|
||||||
|
ALU_RECIP_IEEE(__, _x, _R127, _x) SCL_210
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_MUL_IEEE(_R127, _x, ALU_SRC_PS, _x, ALU_SRC_0_5, _x)
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
/* texCoord.xy = clamp(texCoord.xy, R127.xy, texClamp.xy) */
|
||||||
|
ALU_MAX(__, _x, texcoord_reg, _x, _R127, _x)
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_MIN(texcoord_reg, _x, ALU_SRC_PV, _x, texcoord_reg, _z)
|
||||||
|
ALU_LAST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void add_tex_clamp_T(struct CCFeatures *cc_features, uint64_t **alu_ptr, uint8_t tex) {
|
||||||
|
uint8_t texinfo_reg = get_reg(cc_features, (tex == 0) ? SHADER_TEXINFO0 : SHADER_TEXINFO1);
|
||||||
|
uint8_t texcoord_reg = (tex == 0) ? _R1 : _R2;
|
||||||
|
|
||||||
|
ADD_INSTR(
|
||||||
|
/* R127.y = (float) texinfo.y */
|
||||||
|
ALU_INT_TO_FLT(_R127, _y, texinfo_reg, _y) SCL_210
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
/* R127.y = 0.5f / texSize */
|
||||||
|
ALU_RECIP_IEEE(__, _x, _R127, _y) SCL_210
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_MUL_IEEE(_R127, _y, ALU_SRC_PS, _x, ALU_SRC_0_5, _x)
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
/* texCoord.xy = clamp(texCoord.xy, R127.xy, texClamp.xy) */
|
||||||
|
ALU_MAX(__, _y, texcoord_reg, _y, _R127, _y)
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_MIN(texcoord_reg, _y, ALU_SRC_PV, _y, texcoord_reg, _w)
|
||||||
|
ALU_LAST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void add_mov(struct CCFeatures *cc_features, uint64_t **alu_ptr, uint8_t src, bool single) {
|
||||||
|
bool src_alpha = (src == SHADER_TEXEL0A) || (src == SHADER_TEXEL1A);
|
||||||
|
src = get_reg(cc_features, src);
|
||||||
|
|
||||||
|
/* texel = src */
|
||||||
|
if (single) {
|
||||||
|
ADD_INSTR(
|
||||||
|
ALU_MOV(TEXEL_REG, _w, src, _w)
|
||||||
|
ALU_LAST,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ADD_INSTR(
|
||||||
|
ALU_MOV(TEXEL_REG, _x, src, src_alpha ? _w :_x),
|
||||||
|
ALU_MOV(TEXEL_REG, _y, src, src_alpha ? _w :_y),
|
||||||
|
ALU_MOV(TEXEL_REG, _z, src, src_alpha ? _w :_z)
|
||||||
|
ALU_LAST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void add_mul(struct CCFeatures *cc_features, uint64_t **alu_ptr, uint8_t src0, uint8_t src1, bool single) {
|
||||||
|
bool src0_alpha = (src0 == SHADER_TEXEL0A) || (src0 == SHADER_TEXEL1A);
|
||||||
|
bool src1_alpha = (src1 == SHADER_TEXEL0A) || (src1 == SHADER_TEXEL1A);
|
||||||
|
src0 = get_reg(cc_features, src0);
|
||||||
|
src1 = get_reg(cc_features, src1);
|
||||||
|
|
||||||
|
/* texel = src0 * src1 */
|
||||||
|
if (single) {
|
||||||
|
ADD_INSTR(
|
||||||
|
ALU_MUL(TEXEL_REG, _w, src0, _w, src1, _w)
|
||||||
|
ALU_LAST,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ADD_INSTR(
|
||||||
|
ALU_MUL(TEXEL_REG, _x, src0, src0_alpha ? _w : _x, src1, src1_alpha ? _w : _x),
|
||||||
|
ALU_MUL(TEXEL_REG, _y, src0, src0_alpha ? _w : _y, src1, src1_alpha ? _w : _y),
|
||||||
|
ALU_MUL(TEXEL_REG, _z, src0, src0_alpha ? _w : _z, src1, src1_alpha ? _w : _z)
|
||||||
|
ALU_LAST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void add_mix(struct CCFeatures *cc_features, uint64_t **alu_ptr, uint8_t src0, uint8_t src1, uint8_t src2, uint8_t src3, bool single) {
|
||||||
|
bool src0_alpha = (src0 == SHADER_TEXEL0A) || (src0 == SHADER_TEXEL1A);
|
||||||
|
bool src1_alpha = (src1 == SHADER_TEXEL0A) || (src1 == SHADER_TEXEL1A);
|
||||||
|
bool src2_alpha = (src2 == SHADER_TEXEL0A) || (src2 == SHADER_TEXEL1A);
|
||||||
|
bool src3_alpha = (src3 == SHADER_TEXEL0A) || (src3 == SHADER_TEXEL1A);
|
||||||
|
src0 = get_reg(cc_features, src0);
|
||||||
|
src1 = get_reg(cc_features, src1);
|
||||||
|
src2 = get_reg(cc_features, src2);
|
||||||
|
src3 = get_reg(cc_features, src3);
|
||||||
|
|
||||||
|
/* texel = (src0 - src1) * src2 - src3 */
|
||||||
|
if (single) {
|
||||||
|
ADD_INSTR(
|
||||||
|
ALU_ADD(__, _w, src0, _w, src1 _NEG, _w)
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_MULADD(TEXEL_REG, _w, ALU_SRC_PV, _w, src2, _w, src3, _w)
|
||||||
|
ALU_LAST,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ADD_INSTR(
|
||||||
|
ALU_ADD(__, _x, src0, src0_alpha ? _w : _x, src1 _NEG, src1_alpha ? _w : _x),
|
||||||
|
ALU_ADD(__, _y, src0, src0_alpha ? _w : _y, src1 _NEG, src1_alpha ? _w : _y),
|
||||||
|
ALU_ADD(__, _z, src0, src0_alpha ? _w : _z, src1 _NEG, src1_alpha ? _w : _z)
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_MULADD(TEXEL_REG, _x, ALU_SRC_PV, _x, src2, src2_alpha ? _w : _x, src3, src3_alpha ? _w : _x),
|
||||||
|
ALU_MULADD(TEXEL_REG, _y, ALU_SRC_PV, _y, src2, src2_alpha ? _w : _y, src3, src3_alpha ? _w : _y),
|
||||||
|
ALU_MULADD(TEXEL_REG, _z, ALU_SRC_PV, _z, src2, src2_alpha ? _w : _z, src3, src3_alpha ? _w : _z)
|
||||||
|
ALU_LAST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#undef ADD_INSTR
|
||||||
|
|
||||||
|
static void append_tex_clamp(struct CCFeatures *cc_features, uint64_t **alu_ptr, uint8_t tex, bool s, bool t) {
|
||||||
|
if (s && t) {
|
||||||
|
add_tex_clamp_S_T(cc_features, alu_ptr, tex);
|
||||||
|
} else if (s) {
|
||||||
|
add_tex_clamp_S(cc_features, alu_ptr, tex);
|
||||||
|
} else {
|
||||||
|
add_tex_clamp_T(cc_features, alu_ptr, tex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void append_formula(struct CCFeatures *cc_features, uint64_t **alu_ptr, uint8_t c[2][4], bool do_single, bool do_multiply, bool do_mix, bool only_alpha) {
|
||||||
|
if (do_single) {
|
||||||
|
add_mov(cc_features, alu_ptr, c[only_alpha][3], only_alpha);
|
||||||
|
} else if (do_multiply) {
|
||||||
|
add_mul(cc_features, alu_ptr, c[only_alpha][0], c[only_alpha][2], only_alpha);
|
||||||
|
} else if (do_mix) {
|
||||||
|
add_mix(cc_features, alu_ptr, c[only_alpha][0], c[only_alpha][1], c[only_alpha][2], c[only_alpha][1], only_alpha);
|
||||||
|
} else {
|
||||||
|
add_mix(cc_features, alu_ptr, c[only_alpha][0], c[only_alpha][1], c[only_alpha][2], c[only_alpha][3], only_alpha);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const uint64_t noise_instructions[] = {
|
||||||
|
/* R127 = floor(gl_FragCoord.xy * window_params.x) */
|
||||||
|
ALU_MUL(__, _x, FRAG_COORD_REG, _x, _C(0), _x),
|
||||||
|
ALU_MUL(__, _y, FRAG_COORD_REG, _y, _C(0), _x)
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_FLOOR(_R127, _x, ALU_SRC_PV, _x),
|
||||||
|
ALU_FLOOR(_R127, _y, ALU_SRC_PV, _y)
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
/* R127 = sin(vec3(R127.x, R127.y, window_params.y)) */
|
||||||
|
ALU_MULADD(_R127, _x, _R127, _x, ALU_SRC_LITERAL, _x, ALU_SRC_0_5, _x),
|
||||||
|
ALU_MULADD(_R127, _y, _R127, _y, ALU_SRC_LITERAL, _x, ALU_SRC_0_5, _x),
|
||||||
|
ALU_MULADD(_R127, _z, _C(0), _y, ALU_SRC_LITERAL, _x, ALU_SRC_0_5, _x)
|
||||||
|
ALU_LAST,
|
||||||
|
ALU_LITERAL(0x3E22F983 /* 0.1591549367f (radians -> revolutions) */),
|
||||||
|
|
||||||
|
ALU_FRACT(__, _x, _R127, _x),
|
||||||
|
ALU_FRACT(__, _y, _R127, _y),
|
||||||
|
ALU_FRACT(__, _z, _R127, _z)
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_MULADD(_R127, _x, ALU_SRC_PV, _x, ALU_SRC_LITERAL, _x, ALU_SRC_LITERAL, _y),
|
||||||
|
ALU_MULADD(_R127, _y, ALU_SRC_PV, _y, ALU_SRC_LITERAL, _x, ALU_SRC_LITERAL, _y),
|
||||||
|
ALU_MULADD(_R127, _z, ALU_SRC_PV, _z, ALU_SRC_LITERAL, _x, ALU_SRC_LITERAL, _y)
|
||||||
|
ALU_LAST,
|
||||||
|
ALU_LITERAL2(0x40C90FDB /* 6.283185482f (tau) */, 0xC0490FDB /* -3.141592741f (-pi) */),
|
||||||
|
|
||||||
|
ALU_MUL(_R127, _x, ALU_SRC_PV, _x, ALU_SRC_LITERAL, _x),
|
||||||
|
ALU_MUL(_R127, _y, ALU_SRC_PV, _y, ALU_SRC_LITERAL, _x),
|
||||||
|
ALU_MUL(_R127, _z, ALU_SRC_PV, _z, ALU_SRC_LITERAL, _x)
|
||||||
|
ALU_LAST,
|
||||||
|
ALU_LITERAL(0x3E22F983 /* 0.1591549367f (radians -> revolutions) */),
|
||||||
|
|
||||||
|
ALU_SIN(_R127, _x, _R127, _x) SCL_210
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_SIN(_R127, _y, _R127, _y) SCL_210
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_SIN(_R127, _z, _R127, _z) SCL_210
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
/* R127.x = dot(R127.xyz, vec3(12.9898, 78.233, 37.719)); */
|
||||||
|
ALU_DOT4(_R127, _x, _R127, _x, ALU_SRC_LITERAL, _x),
|
||||||
|
ALU_DOT4(__, _y, _R127, _y, ALU_SRC_LITERAL, _y),
|
||||||
|
ALU_DOT4(__, _z, _R127, _z, ALU_SRC_LITERAL, _z),
|
||||||
|
ALU_DOT4(__, _w, ALU_SRC_LITERAL, _w, ALU_SRC_0, _x)
|
||||||
|
ALU_LAST,
|
||||||
|
ALU_LITERAL4(0x414FD639 /* 12.9898f */, 0x429C774C /* 78.233f */, 0x4216E042 /* 37.719f */, 0x80000000 /* -0.0f */),
|
||||||
|
|
||||||
|
/* R127.x = fract(sin(R127.x) * 143758.5453); */
|
||||||
|
ALU_MULADD(_R127, _x, _R127, _x, ALU_SRC_LITERAL, _x, ALU_SRC_0_5, _x)
|
||||||
|
ALU_LAST,
|
||||||
|
ALU_LITERAL(0x3E22F983 /* 0.1591549367f (radians -> revolutions) */),
|
||||||
|
|
||||||
|
ALU_FRACT(__, _x, _R127, _x)
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_MULADD(_R127, _x, ALU_SRC_PV, _x, ALU_SRC_LITERAL, _x, ALU_SRC_LITERAL, _y)
|
||||||
|
ALU_LAST,
|
||||||
|
ALU_LITERAL2(0x40C90FDB /* 6.283185482f (tau) */, 0xC0490FDB /* -3.141592741f (-pi) */),
|
||||||
|
|
||||||
|
ALU_SIN(_R127, _x, _R127, _x) SCL_210
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_MUL(__, _x, _R127, _x, ALU_SRC_LITERAL, _x)
|
||||||
|
ALU_LAST,
|
||||||
|
ALU_LITERAL(0x480C63A3 /* 143758.5453f */),
|
||||||
|
|
||||||
|
ALU_FRACT( _R127, _x, ALU_SRC_PV, _x)
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
/* texel.a *= floor(R127.x + 0.5); */
|
||||||
|
ALU_ADD(__, _x, _R127, _x, ALU_SRC_0_5, _x)
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_FLOOR(__, _x, ALU_SRC_PV, _x)
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_MUL(TEXEL_REG, _w, TEXEL_REG, _w, ALU_SRC_PV, _x)
|
||||||
|
ALU_LAST,
|
||||||
|
};
|
||||||
|
|
||||||
|
static GX2UniformVar uniformVars[] = {
|
||||||
|
{ "window_params", GX2_SHADER_VAR_TYPE_FLOAT2, 1, 0, -1, },
|
||||||
|
};
|
||||||
|
|
||||||
|
static GX2SamplerVar samplerVars[] = {
|
||||||
|
{ "uTex0", GX2_SAMPLER_VAR_TYPE_SAMPLER_2D, 0 },
|
||||||
|
{ "uTex1", GX2_SAMPLER_VAR_TYPE_SAMPLER_2D, 1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ADD_INSTR(...) \
|
||||||
|
do { \
|
||||||
|
uint64_t tmp[] = {__VA_ARGS__}; \
|
||||||
|
memcpy(cur_buf, tmp, sizeof(tmp)); \
|
||||||
|
cur_buf += sizeof(tmp) / sizeof(uint64_t); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static int generatePixelShader(GX2PixelShader *psh, struct CCFeatures *cc_features) {
|
||||||
|
static const size_t max_program_buf_size = 512 * sizeof(uint64_t);
|
||||||
|
uint64_t *program_buf = memalign(GX2_SHADER_PROGRAM_ALIGNMENT, max_program_buf_size);
|
||||||
|
if (!program_buf) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(program_buf, 0, max_program_buf_size);
|
||||||
|
|
||||||
|
// start placing alus at offset 32
|
||||||
|
static const uint32_t base_alu_offset = 32;
|
||||||
|
uint64_t *cur_buf = NULL;
|
||||||
|
|
||||||
|
// check if we need to clamp
|
||||||
|
bool texclamp[2] = { false, false };
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
if (cc_features->used_textures[i]) {
|
||||||
|
if (cc_features->clamp[i][0] || cc_features->clamp[i][1]) {
|
||||||
|
texclamp[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t texclamp_alu_offset = base_alu_offset;
|
||||||
|
uint32_t texclamp_alu_size = 0;
|
||||||
|
uint32_t texclamp_alu_cnt = 0;
|
||||||
|
|
||||||
|
if (texclamp[0] || texclamp[1]) {
|
||||||
|
// texclamp alu
|
||||||
|
cur_buf = program_buf + texclamp_alu_offset;
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
if (cc_features->used_textures[i] && texclamp[i]) {
|
||||||
|
append_tex_clamp(cc_features, &cur_buf, i, cc_features->clamp[i][0], cc_features->clamp[i][1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
texclamp_alu_size = (uintptr_t) cur_buf - ((uintptr_t) (program_buf + texclamp_alu_offset));
|
||||||
|
texclamp_alu_cnt = texclamp_alu_size / sizeof(uint64_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
// main alu0
|
||||||
|
uint32_t main_alu0_offset = texclamp_alu_offset + texclamp_alu_cnt;
|
||||||
|
cur_buf = program_buf + main_alu0_offset;
|
||||||
|
|
||||||
|
for (int c = 0; c < (cc_features->opt_2cyc ? 2 : 1); c++) {
|
||||||
|
append_formula(cc_features, &cur_buf, cc_features->c[c], cc_features->do_single[c][0], cc_features->do_multiply[c][0], cc_features->do_mix[c][0], false);
|
||||||
|
if (cc_features->opt_alpha) {
|
||||||
|
append_formula(cc_features, &cur_buf, cc_features->c[c], cc_features->do_single[c][1], cc_features->do_multiply[c][1], cc_features->do_mix[c][1], true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cc_features->opt_fog) {
|
||||||
|
ADD_INSTR(
|
||||||
|
/* texel.rgb = mix(texel.rgb, vFog.rgb, vFog.a); */
|
||||||
|
ALU_ADD(__, _x, FOG_REG, _x, _R1 _NEG, _x),
|
||||||
|
ALU_ADD(__, _y, FOG_REG, _y, _R1 _NEG, _y),
|
||||||
|
ALU_ADD(__, _z, FOG_REG, _z, _R1 _NEG, _z)
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_MULADD(TEXEL_REG, _x, ALU_SRC_PV, _x, FOG_REG, _w, TEXEL_REG, _x),
|
||||||
|
ALU_MULADD(TEXEL_REG, _y, ALU_SRC_PV, _y, FOG_REG, _w, TEXEL_REG, _y),
|
||||||
|
ALU_MULADD(TEXEL_REG, _z, ALU_SRC_PV, _z, FOG_REG, _w, TEXEL_REG, _z)
|
||||||
|
ALU_LAST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cc_features->opt_texture_edge && cc_features->opt_alpha) {
|
||||||
|
ADD_INSTR(
|
||||||
|
/* if (texel.a > 0.19) texel.a = 1.0; else discard; */
|
||||||
|
ALU_KILLGT(__, _x, ALU_SRC_LITERAL, _x, TEXEL_REG, _w),
|
||||||
|
ALU_MOV(TEXEL_REG, _w, ALU_SRC_1, _x)
|
||||||
|
ALU_LAST,
|
||||||
|
ALU_LITERAL(0x3e428f5c /*0.19f*/),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t main_alu0_size = (uintptr_t) cur_buf - ((uintptr_t) (program_buf + main_alu0_offset));
|
||||||
|
const uint32_t main_alu0_cnt = main_alu0_size / sizeof(uint64_t);
|
||||||
|
|
||||||
|
// main alu1
|
||||||
|
// place the following instructions into a new alu, in case the other alu uses KILL
|
||||||
|
const uint32_t main_alu1_offset = main_alu0_offset + main_alu0_cnt;
|
||||||
|
cur_buf = program_buf + main_alu1_offset;
|
||||||
|
|
||||||
|
if (cc_features->opt_alpha && cc_features->opt_noise) {
|
||||||
|
memcpy(cur_buf, noise_instructions, sizeof(noise_instructions));
|
||||||
|
cur_buf += sizeof(noise_instructions) / sizeof(uint64_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cc_features->opt_grayscale) {
|
||||||
|
ADD_INSTR(
|
||||||
|
/* texel.r + texel.g + texel.b */
|
||||||
|
ALU_ADD(__, _x, TEXEL_REG, _x, TEXEL_REG, _y)
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_ADD(__, _x, ALU_SRC_PV, _x, TEXEL_REG, _z)
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
/* PV.x / 3 */
|
||||||
|
ALU_MUL_IEEE(__, _x, ALU_SRC_PV, _x, ALU_SRC_LITERAL, _x)
|
||||||
|
ALU_LAST,
|
||||||
|
ALU_LITERAL(0x3eaaaaab /*0.3333333433f*/),
|
||||||
|
|
||||||
|
/* texel.rgb = mix(texel.rgb, vGrayscaleColor.rgb * intensity, vGrayscaleColor.a); */
|
||||||
|
ALU_MULADD(_R127, _x, GRAYSCALE_REG, _x, ALU_SRC_PV, _x, _R1 _NEG, _x),
|
||||||
|
ALU_MULADD(_R127, _y, GRAYSCALE_REG, _y, ALU_SRC_PV, _x, _R1 _NEG, _y),
|
||||||
|
ALU_MULADD(_R127, _z, GRAYSCALE_REG, _z, ALU_SRC_PV, _x, _R1 _NEG, _z)
|
||||||
|
ALU_LAST,
|
||||||
|
|
||||||
|
ALU_MULADD(TEXEL_REG, _x, ALU_SRC_PV, _x, GRAYSCALE_REG, _w, TEXEL_REG, _x),
|
||||||
|
ALU_MULADD(TEXEL_REG, _y, ALU_SRC_PV, _y, GRAYSCALE_REG, _w, TEXEL_REG, _y),
|
||||||
|
ALU_MULADD(TEXEL_REG, _z, ALU_SRC_PV, _z, GRAYSCALE_REG, _w, TEXEL_REG, _z)
|
||||||
|
ALU_LAST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cc_features->opt_alpha) {
|
||||||
|
if (cc_features->opt_alpha_threshold) {
|
||||||
|
ADD_INSTR(
|
||||||
|
/* if (texel.a < 8.0 / 256.0) discard; */
|
||||||
|
ALU_KILLGT(__, _x, ALU_SRC_LITERAL, _x, TEXEL_REG, _w)
|
||||||
|
ALU_LAST,
|
||||||
|
ALU_LITERAL(0x3d000000 /*0.03125f*/),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cc_features->opt_invisible) {
|
||||||
|
ADD_INSTR(
|
||||||
|
/* texel.a = 0.0; */
|
||||||
|
ALU_MOV(TEXEL_REG, _w, ALU_SRC_0, _x)
|
||||||
|
ALU_LAST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t main_alu1_size = (uintptr_t) cur_buf - ((uintptr_t) (program_buf + main_alu1_offset));
|
||||||
|
const uint32_t main_alu1_cnt = main_alu1_size / sizeof(uint64_t);
|
||||||
|
|
||||||
|
// tex
|
||||||
|
uint32_t num_textures = cc_features->used_textures[0] + cc_features->used_textures[1];
|
||||||
|
uint32_t num_texinfo = texclamp[0] + texclamp[1];
|
||||||
|
|
||||||
|
uint32_t texinfo_offset = ROUNDUP(main_alu1_offset + main_alu1_cnt, 16);
|
||||||
|
uint32_t cur_tex_offset = texinfo_offset;
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
if (cc_features->used_textures[i] && texclamp[i]) {
|
||||||
|
uint8_t dst_reg = get_reg(cc_features, (i == 0) ? SHADER_TEXINFO0 : SHADER_TEXINFO1);
|
||||||
|
|
||||||
|
uint64_t texinfo_buf[] = {
|
||||||
|
TEX_GET_TEXTURE_INFO(dst_reg, _x, _y, _m, _m, _R1, _0, _0, _0, _0, _t(i), _s(i))
|
||||||
|
};
|
||||||
|
|
||||||
|
memcpy(program_buf + cur_tex_offset, texinfo_buf, sizeof(texinfo_buf));
|
||||||
|
cur_tex_offset += sizeof(texinfo_buf) / sizeof(uint64_t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t texsample_offset = cur_tex_offset;
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
if (cc_features->used_textures[i]) {
|
||||||
|
uint8_t texcoord_reg = (i == 0) ? _R1 : _R2;
|
||||||
|
uint8_t dst_reg = get_reg(cc_features, (i == 0) ? SHADER_TEXEL0 : SHADER_TEXEL1);
|
||||||
|
|
||||||
|
uint64_t tex_buf[] = {
|
||||||
|
TEX_SAMPLE(dst_reg, _x, _y, _z, _w, texcoord_reg, _x, _y, _0, _x, _t(i), _s(i))
|
||||||
|
};
|
||||||
|
|
||||||
|
memcpy(program_buf + cur_tex_offset, tex_buf, sizeof(tex_buf));
|
||||||
|
cur_tex_offset += sizeof(tex_buf) / sizeof(uint64_t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure we didn't overflow the buffer
|
||||||
|
const uint32_t total_program_size = cur_tex_offset * sizeof(uint64_t);
|
||||||
|
assert(total_program_size <= max_program_buf_size);
|
||||||
|
|
||||||
|
// cf
|
||||||
|
uint32_t cur_cf_offset = 0;
|
||||||
|
|
||||||
|
// if we use texclamp place those alus first
|
||||||
|
if (texclamp[0] || texclamp[1]) {
|
||||||
|
program_buf[cur_cf_offset++] = TEX(texinfo_offset, num_texinfo);
|
||||||
|
program_buf[cur_cf_offset++] = ALU(texclamp_alu_offset, texclamp_alu_cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_textures > 0) {
|
||||||
|
program_buf[cur_cf_offset++] = TEX(texsample_offset, num_textures) VALID_PIX;
|
||||||
|
}
|
||||||
|
|
||||||
|
program_buf[cur_cf_offset++] = ALU(main_alu0_offset, main_alu0_cnt);
|
||||||
|
|
||||||
|
if (main_alu1_cnt > 0) {
|
||||||
|
program_buf[cur_cf_offset++] = ALU(main_alu1_offset, main_alu1_cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cc_features->opt_alpha) {
|
||||||
|
program_buf[cur_cf_offset++] = EXP_DONE(PIX0, TEXEL_REG, _x, _y, _z, _w) END_OF_PROGRAM;
|
||||||
|
} else {
|
||||||
|
program_buf[cur_cf_offset++] = EXP_DONE(PIX0, TEXEL_REG, _x, _y, _z, _1) END_OF_PROGRAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
// regs
|
||||||
|
const uint32_t num_ps_inputs = 4 + cc_features->num_inputs;
|
||||||
|
|
||||||
|
psh->regs.sq_pgm_resources_ps = get_num_regs(cc_features); // num_gprs
|
||||||
|
psh->regs.sq_pgm_exports_ps = 2; // export_mode
|
||||||
|
psh->regs.spi_ps_in_control_0 = (num_ps_inputs + 1) // num_interp
|
||||||
|
| (1 << 8) // position_ena
|
||||||
|
| (1 << 26) // persp_gradient_ena
|
||||||
|
| (1 << 28); // baryc_sample_cntl
|
||||||
|
|
||||||
|
psh->regs.num_spi_ps_input_cntl = num_ps_inputs + 1;
|
||||||
|
|
||||||
|
// frag pos
|
||||||
|
psh->regs.spi_ps_input_cntls[0] = 0 | (1 << 8);
|
||||||
|
|
||||||
|
// inputs
|
||||||
|
for (int i = 0; i < num_ps_inputs; i++) {
|
||||||
|
psh->regs.spi_ps_input_cntls[i + 1] = i | (1 << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
psh->regs.cb_shader_mask = 0xf; // output0_enable
|
||||||
|
psh->regs.cb_shader_control = 1; // rt0_enable
|
||||||
|
psh->regs.db_shader_control = (1 << 4) // z_order
|
||||||
|
| (1 << 6); // kill_enable
|
||||||
|
|
||||||
|
// program
|
||||||
|
psh->size = total_program_size;
|
||||||
|
psh->program = program_buf;
|
||||||
|
|
||||||
|
psh->mode = GX2_SHADER_MODE_UNIFORM_REGISTER;
|
||||||
|
|
||||||
|
// uniform vars
|
||||||
|
psh->uniformVars = uniformVars;
|
||||||
|
psh->uniformVarCount = sizeof(uniformVars) / sizeof(GX2UniformVar);
|
||||||
|
|
||||||
|
// samplers
|
||||||
|
psh->samplerVars = samplerVars;
|
||||||
|
psh->samplerVarCount = sizeof(samplerVars) / sizeof(GX2SamplerVar);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GX2AttribVar attribVars[] = {
|
||||||
|
{ "aVtxPos", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 0 },
|
||||||
|
{ "aTexCoord0", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 1 },
|
||||||
|
{ "aTexCoord1", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 2 },
|
||||||
|
{ "aFog", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 3 },
|
||||||
|
{ "aGrayscaleColor", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 4 },
|
||||||
|
{ "aInput1", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 5 },
|
||||||
|
{ "aInput2", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 6 },
|
||||||
|
{ "aInput3", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 7 },
|
||||||
|
{ "aInput4", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 8 },
|
||||||
|
{ "aInput5", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 9 },
|
||||||
|
{ "aInput6", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 10 },
|
||||||
|
{ "aInput7", GX2_SHADER_VAR_TYPE_FLOAT4, 0, 11 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static int generateVertexShader(GX2VertexShader *vsh, struct CCFeatures *cc_features) {
|
||||||
|
static const size_t max_program_buf_size = 16 * sizeof(uint64_t);
|
||||||
|
uint64_t *program_buf = memalign(GX2_SHADER_PROGRAM_ALIGNMENT, max_program_buf_size);
|
||||||
|
if (!program_buf) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t num_ps_inputs = 4 + cc_features->num_inputs;
|
||||||
|
|
||||||
|
uint64_t *cur_buf = program_buf;
|
||||||
|
|
||||||
|
// aVtxPos
|
||||||
|
ADD_INSTR(
|
||||||
|
CALL_FS NO_BARRIER,
|
||||||
|
EXP_DONE(POS0, _R1, _x, _y, _z, _w),
|
||||||
|
);
|
||||||
|
|
||||||
|
// params
|
||||||
|
for (int i = 0; i < num_ps_inputs - 1; i++) {
|
||||||
|
ADD_INSTR(
|
||||||
|
EXP(PARAM(i), _R(i + 2), _x, _y, _z, _w) NO_BARRIER,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// last param
|
||||||
|
ADD_INSTR(
|
||||||
|
(EXP_DONE(PARAM(num_ps_inputs - 1), _R(num_ps_inputs + 1), _x, _y, _z, _w) NO_BARRIER)
|
||||||
|
END_OF_PROGRAM,
|
||||||
|
);
|
||||||
|
|
||||||
|
const uint32_t program_size = (uintptr_t) cur_buf - ((uintptr_t) program_buf);
|
||||||
|
assert(program_size <= max_program_buf_size);
|
||||||
|
|
||||||
|
// regs
|
||||||
|
vsh->regs.sq_pgm_resources_vs = (num_ps_inputs + 2) // num_gprs
|
||||||
|
| (1 << 8); // stack_size
|
||||||
|
|
||||||
|
// num outputs minus 1
|
||||||
|
vsh->regs.spi_vs_out_config = ((num_ps_inputs - 1) << 1);
|
||||||
|
|
||||||
|
vsh->regs.num_spi_vs_out_id = 3;
|
||||||
|
memset(vsh->regs.spi_vs_out_id, 0xff, sizeof(vsh->regs.spi_vs_out_id));
|
||||||
|
vsh->regs.spi_vs_out_id[0] = (0) | (1 << 8) | (2 << 16) | (3 << 24);
|
||||||
|
vsh->regs.spi_vs_out_id[1] = (4) | (5 << 8) | (6 << 16) | (7 << 24);
|
||||||
|
vsh->regs.spi_vs_out_id[2] = (8) | (9 << 8) | (10 << 16) | (0xff << 24);
|
||||||
|
|
||||||
|
vsh->regs.sq_vtx_semantic_clear = ~((1 << 12) - 1);
|
||||||
|
vsh->regs.num_sq_vtx_semantic = 12;
|
||||||
|
memset(vsh->regs.sq_vtx_semantic, 0xff, sizeof(vsh->regs.sq_vtx_semantic));
|
||||||
|
// aVtxPos
|
||||||
|
vsh->regs.sq_vtx_semantic[0] = 0;
|
||||||
|
// aTexCoord0
|
||||||
|
vsh->regs.sq_vtx_semantic[1] = 1;
|
||||||
|
// aTexCoord1
|
||||||
|
vsh->regs.sq_vtx_semantic[2] = 2;
|
||||||
|
// aFog
|
||||||
|
vsh->regs.sq_vtx_semantic[3] = 3;
|
||||||
|
// aGrayscaleColor
|
||||||
|
vsh->regs.sq_vtx_semantic[4] = 4;
|
||||||
|
// aInput1
|
||||||
|
vsh->regs.sq_vtx_semantic[5] = 5;
|
||||||
|
// aInput2
|
||||||
|
vsh->regs.sq_vtx_semantic[6] = 6;
|
||||||
|
// aInput3
|
||||||
|
vsh->regs.sq_vtx_semantic[7] = 7;
|
||||||
|
// aInput4
|
||||||
|
vsh->regs.sq_vtx_semantic[8] = 8;
|
||||||
|
// aInput5
|
||||||
|
vsh->regs.sq_vtx_semantic[9] = 9;
|
||||||
|
// aInput6
|
||||||
|
vsh->regs.sq_vtx_semantic[10] = 10;
|
||||||
|
// aInput7
|
||||||
|
vsh->regs.sq_vtx_semantic[11] = 11;
|
||||||
|
|
||||||
|
vsh->regs.vgt_vertex_reuse_block_cntl = 14; // vtx_reuse_depth
|
||||||
|
vsh->regs.vgt_hos_reuse_depth = 16; // reuse_depth
|
||||||
|
|
||||||
|
// program
|
||||||
|
vsh->program = program_buf;
|
||||||
|
vsh->size = program_size;
|
||||||
|
|
||||||
|
vsh->mode = GX2_SHADER_MODE_UNIFORM_REGISTER;
|
||||||
|
|
||||||
|
// attribs
|
||||||
|
vsh->attribVarCount = sizeof(attribVars) / sizeof(GX2AttribVar);
|
||||||
|
vsh->attribVars = attribVars;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#undef ADD_INSTR
|
||||||
|
|
||||||
|
int gx2GenerateShaderGroup(struct ShaderGroup *group, struct CCFeatures *cc_features) {
|
||||||
|
memset(group, 0, sizeof(struct ShaderGroup));
|
||||||
|
|
||||||
|
// generate the pixel shader
|
||||||
|
if (generatePixelShader(&group->pixelShader, cc_features) != 0) {
|
||||||
|
gx2FreeShaderGroup(group);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate the vertex shader
|
||||||
|
if (generateVertexShader(&group->vertexShader, cc_features) != 0) {
|
||||||
|
gx2FreeShaderGroup(group);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t attribOffset = 0;
|
||||||
|
|
||||||
|
// aVtxPos
|
||||||
|
group->attributes[group->numAttributes++] =
|
||||||
|
(GX2AttribStream) { 0, 0, attribOffset, GX2_ATTRIB_FORMAT_FLOAT_32_32_32_32, GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _z, _w), GX2_ENDIAN_SWAP_DEFAULT };
|
||||||
|
attribOffset += 4 * sizeof(float);
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
if (cc_features->used_textures[i]) {
|
||||||
|
// aTexCoordX
|
||||||
|
group->attributes[group->numAttributes++] =
|
||||||
|
(GX2AttribStream) { 1 + i, 0, attribOffset, GX2_ATTRIB_FORMAT_FLOAT_32_32_32_32, GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _z, _w), GX2_ENDIAN_SWAP_DEFAULT };
|
||||||
|
attribOffset += 4 * sizeof(float);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// aFog
|
||||||
|
if (cc_features->opt_fog) {
|
||||||
|
group->attributes[group->numAttributes++] =
|
||||||
|
(GX2AttribStream) { 3, 0, attribOffset, GX2_ATTRIB_FORMAT_FLOAT_32_32_32_32, GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _z, _w), GX2_ENDIAN_SWAP_DEFAULT };
|
||||||
|
attribOffset += 4 * sizeof(float);
|
||||||
|
}
|
||||||
|
|
||||||
|
// aGrayscaleColor
|
||||||
|
if (cc_features->opt_grayscale) {
|
||||||
|
group->attributes[group->numAttributes++] =
|
||||||
|
(GX2AttribStream) { 4, 0, attribOffset, GX2_ATTRIB_FORMAT_FLOAT_32_32_32_32, GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _z, _w), GX2_ENDIAN_SWAP_DEFAULT };
|
||||||
|
attribOffset += 4 * sizeof(float);
|
||||||
|
}
|
||||||
|
|
||||||
|
// aInput
|
||||||
|
for (int i = 0; i < cc_features->num_inputs; i++) {
|
||||||
|
group->attributes[group->numAttributes++] =
|
||||||
|
(GX2AttribStream) { 5 + i, 0, attribOffset, GX2_ATTRIB_FORMAT_FLOAT_32_32_32_32, GX2_ATTRIB_INDEX_PER_VERTEX, 0, GX2_COMP_SEL(_x, _y, _z, _w), GX2_ENDIAN_SWAP_DEFAULT };
|
||||||
|
attribOffset += 4 * sizeof(float);
|
||||||
|
}
|
||||||
|
|
||||||
|
group->stride = attribOffset;
|
||||||
|
|
||||||
|
// init the fetch shader
|
||||||
|
group->fetchShader.size = GX2CalcFetchShaderSizeEx(group->numAttributes, GX2_FETCH_SHADER_TESSELLATION_NONE, GX2_TESSELLATION_MODE_DISCRETE);
|
||||||
|
group->fetchShader.program = memalign(GX2_SHADER_PROGRAM_ALIGNMENT, group->fetchShader.size);
|
||||||
|
if (!group->fetchShader.program) {
|
||||||
|
gx2FreeShaderGroup(group);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
GX2InitFetchShaderEx(&group->fetchShader, group->fetchShader.program, group->numAttributes, group->attributes, GX2_FETCH_SHADER_TESSELLATION_NONE, GX2_TESSELLATION_MODE_DISCRETE);
|
||||||
|
|
||||||
|
// invalidate all programs
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_SHADER, group->vertexShader.program, group->vertexShader.size);
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_SHADER, group->pixelShader.program, group->pixelShader.size);
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_SHADER, group->fetchShader.program, group->fetchShader.size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gx2FreeShaderGroup(struct ShaderGroup *group) {
|
||||||
|
free(group->vertexShader.program);
|
||||||
|
free(group->pixelShader.program);
|
||||||
|
free(group->fetchShader.program);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
27
libultraship/libultraship/Lib/Fast3D/gx2_shader_gen.h
Normal file
27
libultraship/libultraship/Lib/Fast3D/gx2_shader_gen.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gfx_cc.h"
|
||||||
|
#include <gx2/shaders.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct ShaderGroup {
|
||||||
|
GX2VertexShader vertexShader;
|
||||||
|
GX2PixelShader pixelShader;
|
||||||
|
GX2FetchShader fetchShader;
|
||||||
|
|
||||||
|
uint32_t stride;
|
||||||
|
|
||||||
|
uint32_t numAttributes;
|
||||||
|
GX2AttribStream attributes[13];
|
||||||
|
};
|
||||||
|
|
||||||
|
int gx2GenerateShaderGroup(struct ShaderGroup *group, struct CCFeatures *cc_features);
|
||||||
|
|
||||||
|
void gx2FreeShaderGroup(struct ShaderGroup *group);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
624
libultraship/libultraship/Lib/Fast3D/gx2_shader_inl.h
Normal file
624
libultraship/libultraship/Lib/Fast3D/gx2_shader_inl.h
Normal file
@ -0,0 +1,624 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014-2016 - Ali Bouhlel
|
||||||
|
* Copyright (C) 2022 - GaryOderNichts
|
||||||
|
*
|
||||||
|
* Licensed as MIT.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef GX2_SHADER_INL_H
|
||||||
|
#define GX2_SHADER_INL_H
|
||||||
|
|
||||||
|
#define to_QWORD(w0, w1) (((uint64_t)(w0) << 32ull) | (w1))
|
||||||
|
#define to_LE(x) (__builtin_bswap32(x))
|
||||||
|
|
||||||
|
/* CF */
|
||||||
|
#define CF_DWORD0(addr) to_LE(addr)
|
||||||
|
|
||||||
|
#define CF_DWORD1(popCount, cfConst, cond, count, callCount, inst) \
|
||||||
|
to_LE(popCount | (cfConst << 3) | (cond << 8) | (count << 10) | (callCount << 13) | (inst << 23) | (1 << 31))
|
||||||
|
|
||||||
|
#define CF_ALU_WORD0(addr, kcacheBank0, kcacheBank1, kcacheMode0) \
|
||||||
|
to_LE(addr | (kcacheBank0 << 22) | (kcacheBank1 << 26) | (kcacheMode0 << 30))
|
||||||
|
#define CF_ALU_WORD1(kcacheMode1, kcacheAddr0, kcacheAddr1, count, altConst, inst) \
|
||||||
|
to_LE(kcacheMode1 | (kcacheAddr0 << 2) | (kcacheAddr1 << 10) | (count << 18) | (altConst << 25) | (inst << 26) | (1 << 31))
|
||||||
|
|
||||||
|
#define CF_EXP_WORD0(dstReg_and_type, srcReg, srcRel, indexGpr, elemSize)\
|
||||||
|
to_LE(dstReg_and_type | (srcReg << 15) | (srcRel << 22) | (indexGpr << 23) | (elemSize << 30))
|
||||||
|
|
||||||
|
#define CF_EXP_WORD1(srcSelX, srcSelY, srcSelZ, srcSelW, validPixelMode, inst) \
|
||||||
|
to_LE(srcSelX | (srcSelY << 3) | (srcSelZ << 6) | (srcSelW << 9) | (validPixelMode << 22) | (inst << 23) | (1 << 31))
|
||||||
|
|
||||||
|
#define CF_ALLOC_EXPORT_WORD0(arrayBase, type, dstReg, dstRel, indexGpr, elemSize) \
|
||||||
|
to_LE(arrayBase | (type << 13) | (dstReg << 15) | (dstRel << 22) | (indexGpr << 23) | (elemSize << 30))
|
||||||
|
|
||||||
|
#define CF_ALLOC_EXPORT_WORD1_BUF(arraySize, writeMask, inst) \
|
||||||
|
to_LE(arraySize | (writeMask << 12) | (inst << 23) | (1 << 31))
|
||||||
|
|
||||||
|
#define ALU_SRC_KCACHE0_BASE 0x80
|
||||||
|
#define ALU_SRC_KCACHE1_BASE 0xA0
|
||||||
|
#define CF_KCACHE_BANK_LOCK_1 0x1
|
||||||
|
#define CB1 0x1
|
||||||
|
#define CB2 0x2
|
||||||
|
#define _0_15 CF_KCACHE_BANK_LOCK_1
|
||||||
|
|
||||||
|
#define KC0(x) (x + ALU_SRC_KCACHE0_BASE)
|
||||||
|
#define KC1(x) (x + ALU_SRC_KCACHE1_BASE)
|
||||||
|
|
||||||
|
#define NO_BARRIER & (~to_QWORD(0,to_LE(1 << 31)))
|
||||||
|
#define END_OF_PROGRAM | to_QWORD(0,to_LE(1 << 21))
|
||||||
|
#define VALID_PIX | to_QWORD(0,to_LE(1 << 22))
|
||||||
|
#define WHOLE_QUAD_MODE | to_QWORD(0,to_LE(1 << 30))
|
||||||
|
#define BURSTCNT(x) | to_QWORD(0,to_LE(x << 17))
|
||||||
|
#define WRITE(x) (x >> 2)
|
||||||
|
#define ARRAY_SIZE(x) x
|
||||||
|
#define ELEM_SIZE(x) x
|
||||||
|
#define KCACHE0(bank, mode) | to_QWORD(CF_ALU_WORD0(0, bank, 0, mode), 0)
|
||||||
|
#define KCACHE1(bank, mode) | to_QWORD(CF_ALU_WORD0(0, 0, bank, 0), CF_ALU_WORD1(mode,0, 0, 0, 0, 0))
|
||||||
|
|
||||||
|
#define DEACTIVATE 1
|
||||||
|
#define UPDATE_EXEC_MASK(mode) | to_QWORD(0, to_LE(mode << 2))
|
||||||
|
#define UPDATE_PRED | to_QWORD(0, to_LE(1ull << 3))
|
||||||
|
#define CLAMP | to_QWORD(0, to_LE(1ull << 31))
|
||||||
|
#define ALU_LAST | to_QWORD(to_LE(1ull << 31), 0)
|
||||||
|
|
||||||
|
/* ALU */
|
||||||
|
|
||||||
|
#define ALU_WORD0(src0Sel, src0Rel, src0Chan, src0Neg, src1Sel, src1Rel, src1Chan, src1Neg, indexMode, predSel) \
|
||||||
|
to_LE(src0Sel | ((src0Rel) << 9) | ((src0Chan) << 10) | ((src0Neg) << 12) | ((src1Sel) << 13) | ((src1Rel) << 22) \
|
||||||
|
| ((src1Chan) << 23) | ((src1Neg) << 25) | ((indexMode) << 26) | ((predSel) << 29))
|
||||||
|
|
||||||
|
#define ALU_WORD1_OP2(src0Abs, src1Abs, updateExecuteMask, updatePred, writeMask, omod, inst, encoding, bankSwizzle, dstGpr, dstRel, dstChan, clamp) \
|
||||||
|
to_LE(src0Abs | (src1Abs << 1) | (updateExecuteMask << 2) | (updatePred << 3) | (writeMask << 4) | (omod << 5) | (inst << 7) | \
|
||||||
|
(encoding << 15) | (bankSwizzle << 18) | ((dstGpr&0x7F) << 21) | (dstRel << 28) | ((dstChan&0x3) << 29) | (clamp << 31))
|
||||||
|
|
||||||
|
#define ALU_WORD1_OP3(src2Sel, src2Rel, src2Chan, src2Neg, inst, bankSwizzle, dstGpr, dstRel, dstChan, clamp) \
|
||||||
|
to_LE(src2Sel | (src2Rel << 9) | (src2Chan << 10) | (src2Neg << 12) | (inst << 13) | \
|
||||||
|
(bankSwizzle << 18) | ((dstGpr&0x7F) << 21) | (dstRel << 28) | ((dstChan&0x3) << 29) | (clamp << 31))
|
||||||
|
|
||||||
|
/* TEX */
|
||||||
|
#define TEX_WORD0(inst, bcFracMode, fetchWholeQuad, resourceID, srcReg, srcRel, altConst) \
|
||||||
|
to_LE(inst | (bcFracMode << 5) | (fetchWholeQuad << 7) | (resourceID << 8) | (srcReg << 16) | (srcRel << 23) | (altConst << 24))
|
||||||
|
|
||||||
|
#define TEX_WORD1(dstReg, dstRel, dstSelX, dstSelY, dstSelZ, dstSelW, lodBias, coordTypeX, coordTypeY, coordTypeZ, coordTypeW) \
|
||||||
|
to_LE(dstReg | (dstRel << 7) | (dstSelX << 9) | (dstSelY << 12) | (dstSelZ << 15) | (dstSelW << 18) | \
|
||||||
|
(lodBias << 21) | (coordTypeX << 28) | (coordTypeY << 29) | (coordTypeZ << 30) | (coordTypeW << 31))
|
||||||
|
|
||||||
|
#define TEX_WORD2(offsetX, offsetY, offsetZ, samplerID, srcSelX, srcSelY, srcSelZ, srcSelW) \
|
||||||
|
to_LE(offsetX | (offsetY << 5) | (offsetZ << 10) | (samplerID << 15) | (srcSelX << 20) | (srcSelY << 23) | (srcSelZ << 26) | (srcSelW << 29))
|
||||||
|
|
||||||
|
#define VTX_WORD0(inst, type, buffer_id, srcReg, srcSelX, mega) \
|
||||||
|
to_LE(inst | (type << 5) | (buffer_id << 8) | (srcReg << 16) | (srcSelX << 24) | (mega << 26))
|
||||||
|
|
||||||
|
#define VTX_WORD1(dstReg, dstSelX, dstSelY, dstSelZ, dstSelW) \
|
||||||
|
to_LE(dstReg | (dstSelX << 9) | (dstSelY << 12) | (dstSelZ << 15) | (dstSelW << 18) | (1 << 21))
|
||||||
|
|
||||||
|
#define VTX_WORD2(offset, ismega) \
|
||||||
|
to_LE(offset| (ismega << 19))
|
||||||
|
|
||||||
|
#define _x 0
|
||||||
|
#define _y 1
|
||||||
|
#define _z 2
|
||||||
|
#define _w 3
|
||||||
|
#define _0 4
|
||||||
|
#define _1 5
|
||||||
|
#define _m 7 /*mask*/
|
||||||
|
|
||||||
|
#define _xyzw 0b1111
|
||||||
|
#define _xy__ 0b0011
|
||||||
|
|
||||||
|
#define GX2_COMP_SEL(c0, c1, c2, c3) (((c0) << 24) | ((c1) << 16) | ((c2) << 8) | (c3))
|
||||||
|
|
||||||
|
#define ALU_LITERAL(v) to_QWORD(to_LE(v), 0)
|
||||||
|
#define ALU_LITERAL2(v0,v1) to_QWORD(to_LE(v0), to_LE(v1))
|
||||||
|
#define ALU_LITERAL3(v0,v1,v2) ALU_LITERAL2(v0,v1),ALU_LITERAL(v2)
|
||||||
|
#define ALU_LITERAL4(v0,v1,v2,v3) ALU_LITERAL2(v0,v1),ALU_LITERAL2(v2,v3)
|
||||||
|
#define ALU_LITERAL5(v0,v1,v2,v3,v5) ALU_LITERAL4(v0,v1,v2,v3),ALU_LITERAL(v4)
|
||||||
|
|
||||||
|
/* SRCx_SEL special constants */
|
||||||
|
#define ALU_SRC_1_DBL_L 0xF4
|
||||||
|
#define ALU_SRC_1_DBL_M 0xF5
|
||||||
|
#define ALU_SRC_0_5_DBL_L 0xF6
|
||||||
|
#define ALU_SRC_0_5_DBL_M 0xF7
|
||||||
|
#define ALU_SRC_0 0xF8
|
||||||
|
#define ALU_SRC_1 0xF9
|
||||||
|
#define ALU_SRC_1_INT 0xFA
|
||||||
|
#define ALU_SRC_M_1_INT 0xFB
|
||||||
|
#define ALU_SRC_0_5 0xFC
|
||||||
|
#define ALU_SRC_LITERAL 0xFD
|
||||||
|
#define ALU_SRC_PV 0xFE
|
||||||
|
#define ALU_SRC_PS 0xFF
|
||||||
|
|
||||||
|
#define _NEG | (1 << 12)
|
||||||
|
#define _ABS | (1 << 13)
|
||||||
|
|
||||||
|
#define ALU_OMOD_OFF 0x0
|
||||||
|
#define ALU_OMOD_M2 0x1
|
||||||
|
#define ALU_OMOD_M4 0x2
|
||||||
|
#define ALU_OMOD_D2 0x3
|
||||||
|
|
||||||
|
#define ALU_VEC_012 0x0
|
||||||
|
#define ALU_VEC_021 0x1
|
||||||
|
#define ALU_VEC_120 0x2
|
||||||
|
#define ALU_VEC_102 0x3
|
||||||
|
#define ALU_VEC_201 0x4
|
||||||
|
#define ALU_VEC_210 0x5
|
||||||
|
#define VEC_012 | to_QWORD(0, to_LE(ALU_VEC_012 << 18))
|
||||||
|
#define VEC_021 | to_QWORD(0, to_LE(ALU_VEC_021 << 18))
|
||||||
|
#define VEC_120 | to_QWORD(0, to_LE(ALU_VEC_120 << 18))
|
||||||
|
#define VEC_102 | to_QWORD(0, to_LE(ALU_VEC_102 << 18))
|
||||||
|
#define VEC_201 | to_QWORD(0, to_LE(ALU_VEC_201 << 18))
|
||||||
|
#define VEC_210 | to_QWORD(0, to_LE(ALU_VEC_210 << 18))
|
||||||
|
|
||||||
|
#define VALID_PIX | to_QWORD(0,to_LE(1 << 22))
|
||||||
|
|
||||||
|
#define ALU_SCL_210 0x0
|
||||||
|
#define ALU_SCL_122 0x1
|
||||||
|
#define ALU_SCL_212 0x2
|
||||||
|
#define ALU_SCL_221 0x3
|
||||||
|
|
||||||
|
#define SCL_210 | to_QWORD(0, to_LE(ALU_SCL_210 << 18))
|
||||||
|
#define SCL_122 | to_QWORD(0, to_LE(ALU_SCL_122 << 18))
|
||||||
|
#define SCL_212 | to_QWORD(0, to_LE(ALU_SCL_212 << 18))
|
||||||
|
#define SCL_221 | to_QWORD(0, to_LE(ALU_SCL_221 << 18))
|
||||||
|
|
||||||
|
#define FETCH_TYPE(x) x
|
||||||
|
#define MINI(x) ((x) - 1)
|
||||||
|
#define MEGA(x) (MINI(x) | 0x80000000)
|
||||||
|
#define OFFSET(x) x
|
||||||
|
|
||||||
|
#define VERTEX_DATA 0
|
||||||
|
#define INSTANCE_DATA 1
|
||||||
|
#define NO_INDEX_OFFSET 2
|
||||||
|
|
||||||
|
/* CF defines */
|
||||||
|
#define CF_COND_ACTIVE 0x0
|
||||||
|
#define CF_COND_FALSE 0x1
|
||||||
|
#define CF_COND_BOOL 0x2
|
||||||
|
#define CF_COND_NOT_BOOL 0x3
|
||||||
|
|
||||||
|
/* TEX defines */
|
||||||
|
#define TEX_UNNORMALIZED 0x0
|
||||||
|
#define TEX_NORMALIZED 0x1
|
||||||
|
|
||||||
|
/* instructions */
|
||||||
|
/* CF */
|
||||||
|
#define CF_INST_TEX 0x01
|
||||||
|
#define CF_INST_VTX 0x02
|
||||||
|
#define CF_INST_LOOP_END 0x05
|
||||||
|
#define CF_INST_LOOP_START_DX10 0x06
|
||||||
|
#define CF_INST_JUMP 0x0A
|
||||||
|
#define CF_INST_ELSE 0x0D
|
||||||
|
#define CF_INST_POP 0x0E
|
||||||
|
#define CF_INST_CALL_FS 0x13
|
||||||
|
#define CF_INST_EMIT_VERTEX 0x15
|
||||||
|
#define CF_INST_MEM_RING 0x26
|
||||||
|
|
||||||
|
#define CF_INST_ALU 0x08
|
||||||
|
#define CF_INST_ALU_PUSH_BEFORE 0x09
|
||||||
|
#define CF_INST_ALU_POP_AFTER 0x0A
|
||||||
|
#define CF_INST_ALU_POP2_AFTER 0x0B
|
||||||
|
#define CF_INST_ALU_BREAK 0x0E
|
||||||
|
#define CF_INST_ALU_ELSE_AFTER 0x0F
|
||||||
|
/* ALU */
|
||||||
|
#define OP2_INST_ADD 0x0
|
||||||
|
#define OP2_INST_MUL 0x1
|
||||||
|
#define OP2_INST_MUL_IEEE 0x2
|
||||||
|
#define OP2_INST_MIN 0x04
|
||||||
|
#define OP2_INST_MAX 0x03
|
||||||
|
#define OP2_INST_MAX_DX10 0x05
|
||||||
|
#define OP2_INST_FRACT 0x10
|
||||||
|
#define OP2_INST_SETGT 0x09
|
||||||
|
#define OP2_INST_SETE_DX10 0x0C
|
||||||
|
#define OP2_INST_SETGT_DX10 0x0D
|
||||||
|
#define OP2_INST_SETGE_DX10 0x0E
|
||||||
|
#define OP2_INST_FLOOR 0x14
|
||||||
|
#define OP2_INST_MOVA_INT 0x18
|
||||||
|
#define OP2_INST_MOV 0x19
|
||||||
|
#define OP2_INST_NOP 0x1A
|
||||||
|
#define OP2_INST_PRED_SETGT 0x21
|
||||||
|
#define OP2_INST_KILLGT 0x2D
|
||||||
|
#define OP2_INST_AND_INT 0x30
|
||||||
|
#define OP2_INST_OR_INT 0x31
|
||||||
|
#define OP2_INST_NOT_INT 0x33
|
||||||
|
#define OP2_INST_ADD_INT 0x34
|
||||||
|
#define OP2_INST_SETE_INT 0x3A
|
||||||
|
#define OP2_INST_SETGT_INT 0x3B
|
||||||
|
#define OP2_INST_SETGE_INT 0x3C
|
||||||
|
#define OP2_INST_SETNE_INT 0x3D
|
||||||
|
#define OP2_INST_PRED_SETE_INT 0x42
|
||||||
|
#define OP2_INST_PRED_SETGT_INT 0x43
|
||||||
|
#define OP2_INST_PRED_SETGE_INT 0x44
|
||||||
|
#define OP2_INST_PRED_SETNE_INT 0x45
|
||||||
|
#define OP2_INST_KILLE_INT 0x46
|
||||||
|
#define OP2_INST_KILLGT_INT 0x47
|
||||||
|
#define OP2_INST_KILLGE_INT 0x48
|
||||||
|
#define OP2_INST_KILLNE_INT 0x49
|
||||||
|
#define OP2_INST_DOT4 0x50
|
||||||
|
#define OP2_INST_DOT4_IEEE 0x51
|
||||||
|
#define OP2_INST_EXP_IEEE 0x61
|
||||||
|
#define OP2_INST_LOG_CLAMPED 0x62
|
||||||
|
#define OP2_INST_RECIP_IEEE 0x66
|
||||||
|
#define OP2_INST_RECIPSQRT_IEEE 0x69
|
||||||
|
#define OP2_INST_SQRT_IEEE 0x6A
|
||||||
|
#define OP2_INST_FLT_TO_INT 0x6B
|
||||||
|
#define OP2_INST_INT_TO_FLT 0x6C
|
||||||
|
#define OP2_INST_SIN 0x6E
|
||||||
|
#define OP2_INST_COS 0x6F
|
||||||
|
#define OP2_INST_LSHR_INT 0x71
|
||||||
|
#define OP2_INST_MULLO_INT 0x73
|
||||||
|
#define OP2_INST_LSHL_INT 0x72
|
||||||
|
#define OP2_INST_FLT_TO_UINT 0x79
|
||||||
|
|
||||||
|
#define OP3_INST_MULADD 0x10
|
||||||
|
#define OP3_INST_MULADD_D2 0x13
|
||||||
|
#define OP3_INST_CNDGT 0x19
|
||||||
|
#define OP3_INST_CNDE_INT 0x1C
|
||||||
|
/* EXP */
|
||||||
|
#define CF_INST_EXP 0x27
|
||||||
|
#define CF_INST_EXP_DONE 0x28
|
||||||
|
|
||||||
|
/* TEX */
|
||||||
|
#define TEX_INST_LD 0x3
|
||||||
|
#define TEX_INST_GET_TEXTURE_INFO 0x4
|
||||||
|
#define TEX_INST_GET_GRADIENTS_H 0x07
|
||||||
|
#define TEX_INST_GET_GRADIENTS_V 0x08
|
||||||
|
#define TEX_INST_SAMPLE 0x10
|
||||||
|
/* VTX */
|
||||||
|
#define VTX_INST_FETCH 0x0
|
||||||
|
|
||||||
|
/* EXPORT_TYPE */
|
||||||
|
#define EXPORT_TYPE_PIXEL 0x0
|
||||||
|
#define EXPORT_TYPE_POS 0x1
|
||||||
|
#define EXPORT_TYPE_PARAM 0x2
|
||||||
|
|
||||||
|
#define EXPORT_ARRAY_BASE_POS(id) (0x3C + id) /* [0, 3] */
|
||||||
|
#define EXPORT_ARRAY_BASE_PARAM(id) id /* [0, 31] */
|
||||||
|
#define EXPORT_ARRAY_BASE_PIX(id) id
|
||||||
|
|
||||||
|
/* exports */
|
||||||
|
#define POS(id) EXPORT_ARRAY_BASE_POS(id) | (EXPORT_TYPE_POS << 13)
|
||||||
|
#define PARAM(id) EXPORT_ARRAY_BASE_PARAM(id) | (EXPORT_TYPE_PARAM << 13)
|
||||||
|
#define PIX(id) EXPORT_ARRAY_BASE_PIX(id) | (EXPORT_TYPE_PIXEL << 13)
|
||||||
|
#define POS0 POS(0)
|
||||||
|
#define PARAM0 PARAM(0)
|
||||||
|
#define PARAM1 PARAM(1)
|
||||||
|
#define PARAM2 PARAM(2)
|
||||||
|
#define PARAM3 PARAM(3)
|
||||||
|
#define PARAM4 PARAM(4)
|
||||||
|
#define PARAM5 PARAM(5)
|
||||||
|
#define PARAM6 PARAM(6)
|
||||||
|
#define PARAM7 PARAM(7)
|
||||||
|
#define PARAM8 PARAM(8)
|
||||||
|
#define PARAM9 PARAM(9)
|
||||||
|
#define PARAM10 PARAM(10)
|
||||||
|
#define PARAM11 PARAM(11)
|
||||||
|
#define PIX0 PIX(0)
|
||||||
|
|
||||||
|
/* registers */
|
||||||
|
#define __ (0x80) /* invalid regitser (write mask off) */
|
||||||
|
#define _R(x) x
|
||||||
|
#define _R0 _R(0x0)
|
||||||
|
#define _R1 _R(0x1)
|
||||||
|
#define _R2 _R(0x2)
|
||||||
|
#define _R3 _R(0x3)
|
||||||
|
#define _R4 _R(0x4)
|
||||||
|
#define _R5 _R(0x5)
|
||||||
|
#define _R6 _R(0x6)
|
||||||
|
#define _R7 _R(0x7)
|
||||||
|
#define _R8 _R(0x8)
|
||||||
|
#define _R9 _R(0x9)
|
||||||
|
#define _R10 _R(0xA)
|
||||||
|
#define _R11 _R(0xB)
|
||||||
|
#define _R12 _R(0xC)
|
||||||
|
#define _R13 _R(0xD)
|
||||||
|
#define _R14 _R(0xE)
|
||||||
|
#define _R15 _R(0xF)
|
||||||
|
#define _R16 _R(0x10)
|
||||||
|
#define _R17 _R(0x11)
|
||||||
|
#define _R18 _R(0x12)
|
||||||
|
#define _R19 _R(0x13)
|
||||||
|
#define _R20 _R(0x14)
|
||||||
|
#define _R21 _R(0x15)
|
||||||
|
#define _R22 _R(0x16)
|
||||||
|
#define _R23 _R(0x17)
|
||||||
|
#define _R24 _R(0x18)
|
||||||
|
#define _R25 _R(0x19)
|
||||||
|
#define _R26 _R(0x1A)
|
||||||
|
#define _R27 _R(0x1B)
|
||||||
|
#define _R28 _R(0x1C)
|
||||||
|
#define _R29 _R(0x1D)
|
||||||
|
#define _R30 _R(0x1E)
|
||||||
|
#define _R31 _R(0x1F)
|
||||||
|
|
||||||
|
#define _R120 _R(0x78)
|
||||||
|
#define _R121 _R(0x79)
|
||||||
|
#define _R122 _R(0x7A)
|
||||||
|
#define _R123 _R(0x7B)
|
||||||
|
#define _R124 _R(0x7C)
|
||||||
|
#define _R125 _R(0x7D)
|
||||||
|
#define _R126 _R(0x7E)
|
||||||
|
#define _R127 _R(0x7F)
|
||||||
|
|
||||||
|
/* texture */
|
||||||
|
#define _t(x) x
|
||||||
|
#define _t0 _t(0x0)
|
||||||
|
#define _t1 _t(0x1)
|
||||||
|
|
||||||
|
/* sampler */
|
||||||
|
#define _s(x) x
|
||||||
|
#define _s0 _s(0x0)
|
||||||
|
#define _s1 _s(0x1)
|
||||||
|
|
||||||
|
#define _b(x) x
|
||||||
|
|
||||||
|
/* const files */
|
||||||
|
#define ALU_SRC_CONST_FILE_BASE 0x100
|
||||||
|
#define _C(x) (ALU_SRC_CONST_FILE_BASE + (x))
|
||||||
|
|
||||||
|
#define CALL_FS to_QWORD(CF_DWORD0(0), CF_DWORD1(0,0,0,0,0,CF_INST_CALL_FS))
|
||||||
|
|
||||||
|
#define TEX(addr, cnt) to_QWORD(CF_DWORD0(addr), CF_DWORD1(0x0, 0x0, CF_COND_ACTIVE, (cnt - 1), 0x0, CF_INST_TEX))
|
||||||
|
#define VTX(addr, cnt) to_QWORD(CF_DWORD0(addr), CF_DWORD1(0x0, 0x0, CF_COND_ACTIVE, (cnt - 1), 0x0, CF_INST_VTX))
|
||||||
|
#define LOOP_END(addr) to_QWORD(CF_DWORD0(addr), CF_DWORD1(0x0, 0x0, CF_COND_ACTIVE, 0x0, 0x0, CF_INST_LOOP_END))
|
||||||
|
#define LOOP_START_DX10(addr) to_QWORD(CF_DWORD0(addr), CF_DWORD1(0x0, 0x0, CF_COND_ACTIVE, 0x0, 0x0, CF_INST_LOOP_START_DX10))
|
||||||
|
#define JUMP(popCount, addr) to_QWORD(CF_DWORD0(addr), CF_DWORD1(popCount, 0x0, CF_COND_ACTIVE, 0x0, 0x0, CF_INST_JUMP))
|
||||||
|
#define ELSE(popCount, addr) to_QWORD(CF_DWORD0(addr), CF_DWORD1(popCount, 0x0, CF_COND_ACTIVE, 0x0, 0x0, CF_INST_ELSE))
|
||||||
|
#define POP(popCount, addr) to_QWORD(CF_DWORD0(addr), CF_DWORD1(popCount, 0x0, CF_COND_ACTIVE, 0x0, 0x0, CF_INST_POP))
|
||||||
|
|
||||||
|
#define ALU(addr, cnt) to_QWORD(CF_ALU_WORD0(addr, 0x0, 0x0, 0x0), CF_ALU_WORD1(0x0, 0x0, 0x0, (cnt - 1), 0x0, CF_INST_ALU))
|
||||||
|
#define ALU_PUSH_BEFORE(addr, cnt) to_QWORD(CF_ALU_WORD0(addr, 0x0, 0x0, 0x0), CF_ALU_WORD1(0x0, 0x0, 0x0, (cnt - 1), 0x0, CF_INST_ALU_PUSH_BEFORE))
|
||||||
|
#define ALU_POP_AFTER(addr, cnt) to_QWORD(CF_ALU_WORD0(addr, 0x0, 0x0, 0x0), CF_ALU_WORD1(0x0, 0x0, 0x0, (cnt - 1), 0x0, CF_INST_ALU_POP_AFTER))
|
||||||
|
#define ALU_POP2_AFTER(addr, cnt) to_QWORD(CF_ALU_WORD0(addr, 0x0, 0x0, 0x0), CF_ALU_WORD1(0x0, 0x0, 0x0, (cnt - 1), 0x0, CF_INST_ALU_POP2_AFTER))
|
||||||
|
#define ALU_BREAK(addr, cnt) to_QWORD(CF_ALU_WORD0(addr, 0x0, 0x0, 0x0), CF_ALU_WORD1(0x0, 0x0, 0x0, (cnt - 1), 0x0, CF_INST_ALU_BREAK))
|
||||||
|
#define ALU_ELSE_AFTER(addr, cnt) to_QWORD(CF_ALU_WORD0(addr, 0x0, 0x0, 0x0), CF_ALU_WORD1(0x0, 0x0, 0x0, (cnt - 1), 0x0, CF_INST_ALU_ELSE_AFTER))
|
||||||
|
|
||||||
|
#define EXP_DONE(dstReg_and_type, srcReg, srcSelX, srcSelY, srcSelZ, srcSelW) to_QWORD(CF_EXP_WORD0(dstReg_and_type, srcReg, 0x0, 0x0, 0x0), \
|
||||||
|
CF_EXP_WORD1(srcSelX, srcSelY, srcSelZ, srcSelW, 0x0, CF_INST_EXP_DONE))
|
||||||
|
|
||||||
|
#define EXP(dstReg_and_type, srcReg, srcSelX, srcSelY, srcSelZ, srcSelW) to_QWORD(CF_EXP_WORD0(dstReg_and_type, srcReg, 0x0, 0x0, 0x0), \
|
||||||
|
CF_EXP_WORD1(srcSelX, srcSelY, srcSelZ, srcSelW, 0x0, CF_INST_EXP))
|
||||||
|
|
||||||
|
#define MEM_RING(arrayBase, dstReg, writeMask, arraySize, elemSize) \
|
||||||
|
to_QWORD(CF_ALLOC_EXPORT_WORD0(arrayBase, 0x00, dstReg, 0x00, 0x00, elemSize), \
|
||||||
|
CF_ALLOC_EXPORT_WORD1_BUF(arraySize, writeMask, CF_INST_MEM_RING))
|
||||||
|
|
||||||
|
#define EMIT_VERTEX to_QWORD(0, CF_DWORD1(0, 0, 0, 0, 0, CF_INST_EMIT_VERTEX))
|
||||||
|
|
||||||
|
#define ALU_OP2(inst, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, omod) \
|
||||||
|
to_QWORD(ALU_WORD0(((src0Sel) & ((1 << 13) - 1)), 0x0, src0Chan, 0x0, ((src1Sel) & ((1 << 13) - 1)), 0x0, src1Chan, 0x0, 0x0, 0x0), \
|
||||||
|
ALU_WORD1_OP2(((src0Sel) >> 13), ((src1Sel) >> 13), 0x0, 0x0, (((dstGpr&__) >> 7) ^ 0x1), omod, inst, 0x0, 0x0, dstGpr, 0x0, dstChan, 0x0))
|
||||||
|
|
||||||
|
#define ALU_OP3(inst, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, src2Sel, src2Chan) \
|
||||||
|
to_QWORD(ALU_WORD0(src0Sel, 0x0, src0Chan, 0x0, src1Sel, 0x0, src1Chan, 0x0, 0x0, 0x0), \
|
||||||
|
ALU_WORD1_OP3(src2Sel, 0x0, src2Chan, 0x0, inst, 0x0, dstGpr, 0x0, dstChan, 0x0))
|
||||||
|
|
||||||
|
#define ALU_NOP(dstGpr, dstChan) \
|
||||||
|
ALU_OP2(OP2_INST_NOP, dstGpr, dstChan, ALU_SRC_PV, dstChan, ALU_SRC_PV, dstChan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_ADD(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_ADD, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_ADD_x2(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_ADD, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_M2)
|
||||||
|
|
||||||
|
#define ALU_ADD_D2(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_ADD, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_D2)
|
||||||
|
|
||||||
|
#define ALU_MUL(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_MUL, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_MUL_x2(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_MUL, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_M2)
|
||||||
|
|
||||||
|
#define ALU_MUL_x4(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_MUL, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_M4)
|
||||||
|
|
||||||
|
#define ALU_MUL_IEEE(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_MUL_IEEE, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_MUL_IEEE_x2(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_MUL_IEEE, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_M2)
|
||||||
|
|
||||||
|
#define ALU_MUL_IEEE_x4(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_MUL_IEEE, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_M4)
|
||||||
|
|
||||||
|
#define ALU_FRACT(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_FRACT, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_FLOOR(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_FLOOR, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_SQRT_IEEE(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_SQRT_IEEE, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_SQRT_IEEE_D2(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_SQRT_IEEE, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_D2)
|
||||||
|
|
||||||
|
#define ALU_MOVA_INT(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_MOVA_INT, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_MOV(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_MOV, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_MOV_D2(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_MOV, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_D2)
|
||||||
|
|
||||||
|
#define ALU_MOV_x2(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_MOV, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_M2)
|
||||||
|
|
||||||
|
#define ALU_MOV_x4(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_MOV, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_M4)
|
||||||
|
|
||||||
|
#define ALU_DOT4_IEEE(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_DOT4_IEEE, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_DOT4(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_DOT4, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_PRED_SETGT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_PRED_SETGT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_KILLGT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_KILLGT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_SETE_DX10(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_SETE_DX10, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_SETGT_DX10(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_SETGT_DX10, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_SETGE_DX10(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_SETGE_DX10, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_SETGT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_SETGT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_PRED_SETE_INT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_PRED_SETE_INT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_PRED_SETGT_INT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_PRED_SETGT_INT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_PRED_SETGE_INT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_PRED_SETGE_INT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_KILLGE_INT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_KILLGE_INT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_SETGT_INT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_SETGT_INT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_SETGE_INT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_SETGE_INT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_ADD_INT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_ADD_INT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_PRED_SETNE_INT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_PRED_SETNE_INT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_MIN(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_MIN, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_MAX(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_MAX, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_MAX_DX10(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_MAX_DX10, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_LSHR_INT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_LSHR_INT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_MULLO_INT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_MULLO_INT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_LSHL_INT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_LSHL_INT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_AND_INT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_AND_INT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_SETE_INT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_SETE_INT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_KILLE_INT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_KILLE_INT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_KILLGT_INT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_KILLGT_INT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_KILLNE_INT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_KILLNE_INT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_SETNE_INT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_SETNE_INT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_OR_INT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan) \
|
||||||
|
ALU_OP2(OP2_INST_OR_INT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_INT_TO_FLT(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_INT_TO_FLT, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_FLT_TO_UINT(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_FLT_TO_UINT, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_FLT_TO_INT(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_FLT_TO_INT, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_EXP_IEEE(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_EXP_IEEE, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_LOG_CLAMPED(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_LOG_CLAMPED, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_RECIP_IEEE(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_RECIP_IEEE, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_RECIPSQRT_IEEE(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_RECIPSQRT_IEEE, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_SIN(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_SIN, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_COS(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_COS, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
#define ALU_COS_D2(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_COS, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_D2)
|
||||||
|
|
||||||
|
#define ALU_NOT_INT(dstGpr, dstChan, src0Sel, src0Chan) \
|
||||||
|
ALU_OP2(OP2_INST_NOT_INT, dstGpr, dstChan, src0Sel, src0Chan, ALU_SRC_0, 0x0, ALU_OMOD_OFF)
|
||||||
|
|
||||||
|
|
||||||
|
#define ALU_MULADD(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, src2Sel, src2Chan) \
|
||||||
|
ALU_OP3(OP3_INST_MULADD, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, src2Sel, src2Chan)
|
||||||
|
|
||||||
|
#define ALU_MULADD_D2(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, src2Sel, src2Chan) \
|
||||||
|
ALU_OP3(OP3_INST_MULADD_D2, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, src2Sel, src2Chan)
|
||||||
|
|
||||||
|
#define ALU_CNDGT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, src2Sel, src2Chan) \
|
||||||
|
ALU_OP3(OP3_INST_CNDGT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, src2Sel, src2Chan)
|
||||||
|
|
||||||
|
#define ALU_CNDE_INT(dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, src2Sel, src2Chan) \
|
||||||
|
ALU_OP3(OP3_INST_CNDE_INT, dstGpr, dstChan, src0Sel, src0Chan, src1Sel, src1Chan, src2Sel, src2Chan)
|
||||||
|
|
||||||
|
#define TEX_LD(dstReg, dstSelX, dstSelY, dstSelZ, dstSelW, srcReg, srcSelX, srcSelY, srcSelZ, srcSelW, resourceID, samplerID)\
|
||||||
|
to_QWORD(TEX_WORD0(TEX_INST_LD, 0x0, 0x0, resourceID, srcReg, 0x0, 0x0), \
|
||||||
|
TEX_WORD1(dstReg, 0x0, dstSelX, dstSelY, dstSelZ, dstSelW, 0x0, TEX_UNNORMALIZED, TEX_UNNORMALIZED, TEX_UNNORMALIZED, TEX_UNNORMALIZED)), \
|
||||||
|
to_QWORD(TEX_WORD2(0x0, 0x0, 0x0, samplerID, srcSelX, srcSelY, srcSelZ, srcSelW), 0x00000000)
|
||||||
|
|
||||||
|
#define TEX_SAMPLE(dstReg, dstSelX, dstSelY, dstSelZ, dstSelW, srcReg, srcSelX, srcSelY, srcSelZ, srcSelW, resourceID, samplerID)\
|
||||||
|
to_QWORD(TEX_WORD0(TEX_INST_SAMPLE, 0x0, 0x0, resourceID, srcReg, 0x0, 0x0), \
|
||||||
|
TEX_WORD1(dstReg, 0x0, dstSelX, dstSelY, dstSelZ, dstSelW, 0x0, TEX_NORMALIZED, TEX_NORMALIZED, TEX_NORMALIZED, TEX_NORMALIZED)), \
|
||||||
|
to_QWORD(TEX_WORD2(0x0, 0x0, 0x0, samplerID, _x, _y, _0, _x), 0x00000000)
|
||||||
|
|
||||||
|
#define TEX_GET_GRADIENTS_H(dstReg, dstSelX, dstSelY, dstSelZ, dstSelW, srcReg, srcSelX, srcSelY, srcSelZ, srcSelW, resourceID, samplerID)\
|
||||||
|
to_QWORD(TEX_WORD0(TEX_INST_GET_GRADIENTS_H, 0x0, 0x0, resourceID, srcReg, 0x0, 0x0), \
|
||||||
|
TEX_WORD1(dstReg, 0x0, dstSelX, dstSelY, dstSelZ, dstSelW, 0x0, TEX_NORMALIZED, TEX_NORMALIZED, TEX_NORMALIZED, TEX_NORMALIZED)), \
|
||||||
|
to_QWORD(TEX_WORD2(0x0, 0x0, 0x0, samplerID, _x, _y, _z, _x), 0x00000000)
|
||||||
|
|
||||||
|
#define TEX_GET_GRADIENTS_V(dstReg, dstSelX, dstSelY, dstSelZ, dstSelW, srcReg, srcSelX, srcSelY, srcSelZ, srcSelW, resourceID, samplerID)\
|
||||||
|
to_QWORD(TEX_WORD0(TEX_INST_GET_GRADIENTS_V, 0x0, 0x0, resourceID, srcReg, 0x0, 0x0), \
|
||||||
|
TEX_WORD1(dstReg, 0x0, dstSelX, dstSelY, dstSelZ, dstSelW, 0x0, TEX_NORMALIZED, TEX_NORMALIZED, TEX_NORMALIZED, TEX_NORMALIZED)), \
|
||||||
|
to_QWORD(TEX_WORD2(0x0, 0x0, 0x0, samplerID, _x, _y, _z, _x), 0x00000000)
|
||||||
|
|
||||||
|
#define TEX_GET_TEXTURE_INFO(dstReg, dstSelX, dstSelY, dstSelZ, dstSelW, srcReg, srcSelX, srcSelY, srcSelZ, srcSelW, resourceID, samplerID)\
|
||||||
|
to_QWORD(TEX_WORD0(TEX_INST_GET_TEXTURE_INFO, 0x0, 0x0, resourceID, srcReg, 0x0, 0x0), \
|
||||||
|
TEX_WORD1(dstReg, 0x0, dstSelX, dstSelY, dstSelZ, dstSelW, 0x0, TEX_NORMALIZED, TEX_NORMALIZED, TEX_NORMALIZED, TEX_NORMALIZED)), \
|
||||||
|
to_QWORD(TEX_WORD2(0x0, 0x0, 0x0, samplerID, srcSelX, srcSelY, srcSelZ, srcSelW), 0x00000000)
|
||||||
|
|
||||||
|
|
||||||
|
#define VTX_FETCH(dstReg, dstSelX, dstSelY, dstSelZ, dstSelW, srcReg, srcSelX, buffer_id, type, mega, offset) \
|
||||||
|
to_QWORD(VTX_WORD0(VTX_INST_FETCH, type, buffer_id, srcReg, srcSelX, mega), VTX_WORD1(dstReg, dstSelX, dstSelY, dstSelZ, dstSelW)) , \
|
||||||
|
to_QWORD(VTX_WORD2(offset, (mega >> 31)), 0x00000000)
|
||||||
|
|
||||||
|
#define _x2(v) v, v
|
||||||
|
#define _x4(v) _x2(v), _x2(v)
|
||||||
|
#define _x8(v) _x4(v), _x4(v)
|
||||||
|
#define _x16(v) _x8(v), _x8(v)
|
||||||
|
|
||||||
|
#define _x9(v) _x8(v), v
|
||||||
|
#define _x30(v) _x16(v), _x8(v), _x4(v),_x2(v)
|
||||||
|
#define _x31(v) _x30(v), v
|
||||||
|
|
||||||
|
#endif /* GX2_SHADER_INL_H */
|
@ -0,0 +1,334 @@
|
|||||||
|
// dear imgui: Renderer Backend for the Nintendo Wii U using GX2
|
||||||
|
#include "imgui.h"
|
||||||
|
#include "imgui_impl_gx2.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h> // intptr_t
|
||||||
|
#include <malloc.h> // memalign
|
||||||
|
|
||||||
|
// GX2 includes
|
||||||
|
#include <whb/gfx.h>
|
||||||
|
#include <gx2/registers.h>
|
||||||
|
#include <gx2/draw.h>
|
||||||
|
#include <gx2/utils.h>
|
||||||
|
#include <gx2/mem.h>
|
||||||
|
#include <gx2r/surface.h>
|
||||||
|
|
||||||
|
// Include shader data
|
||||||
|
#include "shaders/shader.h"
|
||||||
|
|
||||||
|
// GX2 Data
|
||||||
|
struct ImGui_ImplGX2_Data
|
||||||
|
{
|
||||||
|
uint32_t VertexBufferSize;
|
||||||
|
void* VertexBuffer;
|
||||||
|
uint32_t IndexBufferSize;
|
||||||
|
void* IndexBuffer;
|
||||||
|
|
||||||
|
ImGui_ImplGX2_Texture* FontTexture;
|
||||||
|
|
||||||
|
WHBGfxShaderGroup* ShaderGroup;
|
||||||
|
|
||||||
|
ImGui_ImplGX2_Data() { memset(this, 0, sizeof(*this)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Backend data stored in io.BackendRendererUserData
|
||||||
|
static ImGui_ImplGX2_Data* ImGui_ImplGX2_GetBackendData()
|
||||||
|
{
|
||||||
|
return ImGui::GetCurrentContext() ? (ImGui_ImplGX2_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
bool ImGui_ImplGX2_Init()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
|
||||||
|
|
||||||
|
ImGui_ImplGX2_Data* bd = IM_NEW(ImGui_ImplGX2_Data)();
|
||||||
|
io.BackendRendererUserData = (void*)bd;
|
||||||
|
io.BackendRendererName = "imgui_impl_gx2";
|
||||||
|
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplGX2_Shutdown()
|
||||||
|
{
|
||||||
|
ImGui_ImplGX2_Data* bd = ImGui_ImplGX2_GetBackendData();
|
||||||
|
IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
ImGui_ImplGX2_DestroyDeviceObjects();
|
||||||
|
io.BackendRendererName = NULL;
|
||||||
|
io.BackendRendererUserData = NULL;
|
||||||
|
IM_DELETE(bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplGX2_NewFrame()
|
||||||
|
{
|
||||||
|
ImGui_ImplGX2_Data* bd = ImGui_ImplGX2_GetBackendData();
|
||||||
|
IM_ASSERT(bd != NULL && "Did you call ImGui_ImplGX2_Init()?");
|
||||||
|
|
||||||
|
if (!bd->ShaderGroup)
|
||||||
|
ImGui_ImplGX2_CreateDeviceObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplGX2_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height)
|
||||||
|
{
|
||||||
|
ImGui_ImplGX2_Data* bd = ImGui_ImplGX2_GetBackendData();
|
||||||
|
|
||||||
|
// Setup render state: alpha-blending enabled, no face culling, no depth testing
|
||||||
|
GX2SetColorControl(GX2_LOGIC_OP_COPY, 0xFF, FALSE, TRUE);
|
||||||
|
GX2SetBlendControl(GX2_RENDER_TARGET_0,
|
||||||
|
GX2_BLEND_MODE_SRC_ALPHA,
|
||||||
|
GX2_BLEND_MODE_INV_SRC_ALPHA,
|
||||||
|
GX2_BLEND_COMBINE_MODE_ADD,
|
||||||
|
TRUE,
|
||||||
|
GX2_BLEND_MODE_ONE,
|
||||||
|
GX2_BLEND_MODE_INV_SRC_ALPHA,
|
||||||
|
GX2_BLEND_COMBINE_MODE_ADD);
|
||||||
|
GX2SetCullOnlyControl(GX2_FRONT_FACE_CCW, FALSE, FALSE);
|
||||||
|
GX2SetDepthOnlyControl(FALSE, FALSE, GX2_COMPARE_FUNC_NEVER);
|
||||||
|
|
||||||
|
// Setup viewport, orthographic projection matrix
|
||||||
|
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
|
||||||
|
GX2SetViewport(0, 0, (float)fb_width, (float)fb_height, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
GX2SetFetchShader(&bd->ShaderGroup->fetchShader);
|
||||||
|
GX2SetVertexShader(bd->ShaderGroup->vertexShader);
|
||||||
|
GX2SetPixelShader(bd->ShaderGroup->pixelShader);
|
||||||
|
|
||||||
|
float L = draw_data->DisplayPos.x;
|
||||||
|
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
|
||||||
|
float T = draw_data->DisplayPos.y;
|
||||||
|
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
|
||||||
|
const float ortho_projection[4][4] =
|
||||||
|
{
|
||||||
|
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
|
||||||
|
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
|
||||||
|
{ 0.0f, 0.0f, -1.0f, 0.0f },
|
||||||
|
{ (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f },
|
||||||
|
};
|
||||||
|
|
||||||
|
GX2SetVertexUniformReg(0, sizeof(ortho_projection) / sizeof(float), &ortho_projection[0][0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplGX2_RenderDrawData(ImDrawData* draw_data)
|
||||||
|
{
|
||||||
|
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||||
|
int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
|
||||||
|
int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
|
||||||
|
if (fb_width <= 0 || fb_height <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ImGui_ImplGX2_Data* bd = ImGui_ImplGX2_GetBackendData();
|
||||||
|
|
||||||
|
ImGui_ImplGX2_SetupRenderState(draw_data, fb_width, fb_height);
|
||||||
|
|
||||||
|
// Will project scissor/clipping rectangles into framebuffer space
|
||||||
|
ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports
|
||||||
|
ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
|
||||||
|
|
||||||
|
// Create continuous vertex/index buffers
|
||||||
|
uint32_t vtx_buffer_size = (uint32_t)draw_data->TotalVtxCount * (int)sizeof(ImDrawVert);
|
||||||
|
uint32_t idx_buffer_size = (uint32_t)draw_data->TotalIdxCount * (int)sizeof(ImDrawIdx);
|
||||||
|
|
||||||
|
// Grow buffers if needed
|
||||||
|
if (bd->VertexBufferSize < vtx_buffer_size)
|
||||||
|
{
|
||||||
|
bd->VertexBufferSize = vtx_buffer_size;
|
||||||
|
free(bd->VertexBuffer);
|
||||||
|
bd->VertexBuffer = memalign(GX2_VERTEX_BUFFER_ALIGNMENT, vtx_buffer_size);
|
||||||
|
}
|
||||||
|
if (bd->IndexBufferSize < idx_buffer_size)
|
||||||
|
{
|
||||||
|
bd->IndexBufferSize = idx_buffer_size;
|
||||||
|
free(bd->IndexBuffer);
|
||||||
|
bd->IndexBuffer = memalign(GX2_INDEX_BUFFER_ALIGNMENT, idx_buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy data into continuous buffers
|
||||||
|
uint8_t* vtx_dst = (uint8_t*)bd->VertexBuffer;
|
||||||
|
uint8_t* idx_dst = (uint8_t*)bd->IndexBuffer;
|
||||||
|
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||||
|
{
|
||||||
|
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||||
|
|
||||||
|
memcpy(vtx_dst, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert));
|
||||||
|
vtx_dst += cmd_list->VtxBuffer.Size * sizeof(ImDrawVert);
|
||||||
|
|
||||||
|
memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||||
|
idx_dst += cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush memory
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_MODE_CPU_ATTRIBUTE_BUFFER, bd->VertexBuffer, vtx_buffer_size);
|
||||||
|
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, bd->IndexBuffer, idx_buffer_size);
|
||||||
|
|
||||||
|
GX2SetAttribBuffer(0, vtx_buffer_size, sizeof(ImDrawVert), bd->VertexBuffer);
|
||||||
|
|
||||||
|
// Render command lists
|
||||||
|
// (Because we merged all buffers into a single one, we maintain our own offset into them)
|
||||||
|
int global_vtx_offset = 0;
|
||||||
|
int global_idx_offset = 0;
|
||||||
|
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||||
|
{
|
||||||
|
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||||
|
|
||||||
|
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||||
|
{
|
||||||
|
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||||
|
if (pcmd->UserCallback != NULL)
|
||||||
|
{
|
||||||
|
// User callback, registered via ImDrawList::AddCallback()
|
||||||
|
// (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
|
||||||
|
if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
|
||||||
|
ImGui_ImplGX2_SetupRenderState(draw_data, fb_width, fb_height);
|
||||||
|
else
|
||||||
|
pcmd->UserCallback(cmd_list, pcmd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Project scissor/clipping rectangles into framebuffer space
|
||||||
|
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
|
||||||
|
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
|
||||||
|
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Discard invalid draws to avoid GPU crash
|
||||||
|
if (clip_min.x < 0.0f || clip_min.y < 0.0f || clip_max.x > fb_width || clip_max.y > fb_height || !pcmd->ElemCount)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Apply scissor/clipping rectangle
|
||||||
|
GX2SetScissor((uint32_t)clip_min.x, (uint32_t)clip_min.y, (uint32_t)(clip_max.x - clip_min.x), (uint32_t)(clip_max.y - clip_min.y));
|
||||||
|
|
||||||
|
// Bind texture, Draw
|
||||||
|
ImGui_ImplGX2_Texture* tex = (ImGui_ImplGX2_Texture*) pcmd->GetTexID();
|
||||||
|
IM_ASSERT(tex && "TextureID cannot be NULL");
|
||||||
|
|
||||||
|
GX2SetPixelTexture(tex->Texture, 0);
|
||||||
|
GX2SetPixelSampler(tex->Sampler, 0);
|
||||||
|
|
||||||
|
GX2DrawIndexedEx(GX2_PRIMITIVE_MODE_TRIANGLES, pcmd->ElemCount,
|
||||||
|
sizeof(ImDrawIdx) == 2 ? GX2_INDEX_TYPE_U16 : GX2_INDEX_TYPE_U32,
|
||||||
|
(uint8_t*) bd->IndexBuffer + (pcmd->IdxOffset + global_idx_offset) * sizeof(ImDrawIdx),
|
||||||
|
global_vtx_offset + pcmd->VtxOffset, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
global_idx_offset += cmd_list->IdxBuffer.Size;
|
||||||
|
global_vtx_offset += cmd_list->VtxBuffer.Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplGX2_CreateFontsTexture()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
ImGui_ImplGX2_Data* bd = ImGui_ImplGX2_GetBackendData();
|
||||||
|
|
||||||
|
if (bd->FontTexture)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build texture atlas
|
||||||
|
unsigned char* src_pixels;
|
||||||
|
int width, height;
|
||||||
|
io.Fonts->GetTexDataAsRGBA32(&src_pixels, &width, &height); // Load as RGBA 32-bit (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders.
|
||||||
|
|
||||||
|
bd->FontTexture = IM_NEW(ImGui_ImplGX2_Texture)();
|
||||||
|
|
||||||
|
GX2Texture* tex = IM_NEW(GX2Texture)();
|
||||||
|
memset(tex, 0, sizeof(GX2Texture));
|
||||||
|
bd->FontTexture->Texture = tex;
|
||||||
|
|
||||||
|
tex->surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
|
||||||
|
tex->surface.use = GX2_SURFACE_USE_TEXTURE;
|
||||||
|
tex->surface.width = width;
|
||||||
|
tex->surface.height = height;
|
||||||
|
tex->surface.depth = 1;
|
||||||
|
tex->surface.mipLevels = 1;
|
||||||
|
tex->surface.format = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8;
|
||||||
|
tex->surface.aa = GX2_AA_MODE1X;
|
||||||
|
tex->surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED;
|
||||||
|
tex->viewNumSlices = 1;
|
||||||
|
tex->viewNumMips = 1;
|
||||||
|
// swapped for endianness
|
||||||
|
tex->compMap = GX2_COMP_MAP(GX2_SQ_SEL_A, GX2_SQ_SEL_B, GX2_SQ_SEL_G, GX2_SQ_SEL_R);
|
||||||
|
|
||||||
|
GX2RCreateSurface(&tex->surface, GX2R_RESOURCE_BIND_TEXTURE | GX2R_RESOURCE_USAGE_CPU_WRITE | GX2R_RESOURCE_USAGE_GPU_READ);
|
||||||
|
GX2InitTextureRegs(tex);
|
||||||
|
|
||||||
|
unsigned char* dst_pixels = (unsigned char*) GX2RLockSurfaceEx(&tex->surface, 0, GX2R_RESOURCE_BIND_NONE);
|
||||||
|
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
memcpy(dst_pixels + (y * tex->surface.pitch * 4), src_pixels + (y * width * 4), width * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
GX2RUnlockSurfaceEx(&tex->surface, 0, GX2R_RESOURCE_BIND_NONE);
|
||||||
|
|
||||||
|
bd->FontTexture->Sampler = IM_NEW(GX2Sampler)();
|
||||||
|
GX2InitSampler(bd->FontTexture->Sampler, GX2_TEX_CLAMP_MODE_CLAMP, GX2_TEX_XY_FILTER_MODE_LINEAR);
|
||||||
|
|
||||||
|
// Store our identifier
|
||||||
|
io.Fonts->SetTexID((ImTextureID) bd->FontTexture);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplGX2_DestroyFontsTexture()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
ImGui_ImplGX2_Data* bd = ImGui_ImplGX2_GetBackendData();
|
||||||
|
if (bd->FontTexture)
|
||||||
|
{
|
||||||
|
GX2RDestroySurfaceEx(&bd->FontTexture->Texture->surface, GX2R_RESOURCE_BIND_NONE);
|
||||||
|
io.Fonts->SetTexID(0);
|
||||||
|
IM_DELETE(bd->FontTexture->Texture);
|
||||||
|
IM_DELETE(bd->FontTexture->Sampler);
|
||||||
|
IM_DELETE(bd->FontTexture);
|
||||||
|
bd->FontTexture = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplGX2_CreateDeviceObjects()
|
||||||
|
{
|
||||||
|
ImGui_ImplGX2_Data* bd = ImGui_ImplGX2_GetBackendData();
|
||||||
|
bd->ShaderGroup = IM_NEW(WHBGfxShaderGroup)();
|
||||||
|
|
||||||
|
if (!WHBGfxLoadGFDShaderGroup(bd->ShaderGroup, 0, shader_gsh))
|
||||||
|
{
|
||||||
|
IM_DELETE(bd->ShaderGroup);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
WHBGfxInitShaderAttribute(bd->ShaderGroup, "Position", 0, 0, GX2_ATTRIB_FORMAT_FLOAT_32_32);
|
||||||
|
WHBGfxInitShaderAttribute(bd->ShaderGroup, "UV", 0, 8, GX2_ATTRIB_FORMAT_FLOAT_32_32);
|
||||||
|
WHBGfxInitShaderAttribute(bd->ShaderGroup, "Color", 0, 16, GX2_ATTRIB_TYPE_8_8_8_8);
|
||||||
|
|
||||||
|
if (!WHBGfxInitFetchShader(bd->ShaderGroup))
|
||||||
|
{
|
||||||
|
IM_DELETE(bd->ShaderGroup);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui_ImplGX2_CreateFontsTexture();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplGX2_DestroyDeviceObjects()
|
||||||
|
{
|
||||||
|
ImGui_ImplGX2_Data* bd = ImGui_ImplGX2_GetBackendData();
|
||||||
|
|
||||||
|
free(bd->VertexBuffer);
|
||||||
|
bd->VertexBuffer = NULL;
|
||||||
|
|
||||||
|
free(bd->IndexBuffer);
|
||||||
|
bd->IndexBuffer = NULL;
|
||||||
|
|
||||||
|
WHBGfxFreeShaderGroup(bd->ShaderGroup);
|
||||||
|
IM_DELETE(bd->ShaderGroup);
|
||||||
|
bd->ShaderGroup = NULL;
|
||||||
|
|
||||||
|
ImGui_ImplGX2_DestroyFontsTexture();
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
// dear imgui: Renderer Backend for the Nintendo Wii U using GX2
|
||||||
|
#pragma once
|
||||||
|
#include "imgui.h" // IMGUI_IMPL_API
|
||||||
|
|
||||||
|
// GX2 Texture / contains a texture and sampler
|
||||||
|
// Can be used as a ImTextureID with the GX2 backend
|
||||||
|
struct ImGui_ImplGX2_Texture
|
||||||
|
{
|
||||||
|
struct GX2Texture* Texture;
|
||||||
|
struct GX2Sampler* Sampler;
|
||||||
|
|
||||||
|
ImGui_ImplGX2_Texture() { memset(this, 0, sizeof(*this)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Backend API
|
||||||
|
IMGUI_IMPL_API bool ImGui_ImplGX2_Init();
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplGX2_Shutdown();
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplGX2_NewFrame();
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplGX2_RenderDrawData(ImDrawData* draw_data);
|
||||||
|
|
||||||
|
// (Optional) Called by Init/NewFrame/Shutdown
|
||||||
|
IMGUI_IMPL_API bool ImGui_ImplGX2_CreateFontsTexture();
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplGX2_DestroyFontsTexture();
|
||||||
|
IMGUI_IMPL_API bool ImGui_ImplGX2_CreateDeviceObjects();
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplGX2_DestroyDeviceObjects();
|
@ -0,0 +1,294 @@
|
|||||||
|
// dear imgui: Platform Backend for the Wii U
|
||||||
|
#include "imgui.h"
|
||||||
|
#include "imgui_impl_wiiu.h"
|
||||||
|
#include <stdlib.h> // malloc/free
|
||||||
|
|
||||||
|
// Software keyboard
|
||||||
|
#include <nn/swkbd.h>
|
||||||
|
|
||||||
|
// Wii U Data
|
||||||
|
struct ImGui_ImplWiiU_Data
|
||||||
|
{
|
||||||
|
nn::swkbd::CreateArg CreateArg;
|
||||||
|
nn::swkbd::AppearArg AppearArg;
|
||||||
|
nn::swkbd::ControllerType LastController;
|
||||||
|
|
||||||
|
bool WantedTextInput;
|
||||||
|
bool WasTouched;
|
||||||
|
|
||||||
|
ImGui_ImplWiiU_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Backend data stored in io.BackendPlatformUserData
|
||||||
|
static ImGui_ImplWiiU_Data* ImGui_ImplWiiU_GetBackendData()
|
||||||
|
{
|
||||||
|
return ImGui::GetCurrentContext() ? (ImGui_ImplWiiU_Data*)ImGui::GetIO().BackendPlatformUserData : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplWiiU_Init()
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
IM_ASSERT(io.BackendPlatformUserData == NULL && "Already initialized a platform backend!");
|
||||||
|
|
||||||
|
// Setup backend data
|
||||||
|
ImGui_ImplWiiU_Data* bd = IM_NEW(ImGui_ImplWiiU_Data)();
|
||||||
|
io.BackendPlatformUserData = (void*)bd;
|
||||||
|
io.BackendPlatformName = "imgui_impl_wiiu";
|
||||||
|
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
|
||||||
|
|
||||||
|
// Initialize and create software keyboard
|
||||||
|
nn::swkbd::CreateArg createArg;
|
||||||
|
|
||||||
|
createArg.workMemory = malloc(nn::swkbd::GetWorkMemorySize(0));
|
||||||
|
createArg.fsClient = (FSClient*) malloc(sizeof(FSClient));
|
||||||
|
if (!createArg.workMemory || !createArg.fsClient)
|
||||||
|
{
|
||||||
|
free(createArg.workMemory);
|
||||||
|
free(createArg.fsClient);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSAddClient(createArg.fsClient, FS_ERROR_FLAG_NONE);
|
||||||
|
|
||||||
|
if (!nn::swkbd::Create(createArg))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
nn::swkbd::AppearArg appearArg;
|
||||||
|
bd->CreateArg = createArg;
|
||||||
|
bd->AppearArg = appearArg;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplWiiU_Shutdown()
|
||||||
|
{
|
||||||
|
ImGui_ImplWiiU_Data* bd = ImGui_ImplWiiU_GetBackendData();
|
||||||
|
IM_ASSERT(bd != NULL && "No platform backend to shutdown, or already shutdown?");
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
// Destroy software keyboard
|
||||||
|
nn::swkbd::Destroy();
|
||||||
|
free(bd->CreateArg.workMemory);
|
||||||
|
bd->CreateArg.workMemory = NULL;
|
||||||
|
|
||||||
|
if (bd->CreateArg.fsClient)
|
||||||
|
{
|
||||||
|
FSDelClient(bd->CreateArg.fsClient, FS_ERROR_FLAG_NONE);
|
||||||
|
free(bd->CreateArg.fsClient);
|
||||||
|
bd->CreateArg.fsClient = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
io.BackendPlatformName = NULL;
|
||||||
|
io.BackendPlatformUserData = NULL;
|
||||||
|
IM_DELETE(bd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplWiiU_UpdateKeyboardInput(ImGui_ImplWiiU_ControllerInput* input)
|
||||||
|
{
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
VPADGetTPCalibratedPoint(VPAD_CHAN_0, &input->vpad->tpNormal, &input->vpad->tpNormal);
|
||||||
|
|
||||||
|
nn::swkbd::ControllerInfo controllerInfo;
|
||||||
|
controllerInfo.vpad = input->vpad;
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
controllerInfo.kpad[i] = input->kpad[i];
|
||||||
|
|
||||||
|
nn::swkbd::Calc(controllerInfo);
|
||||||
|
|
||||||
|
if (nn::swkbd::IsNeedCalcSubThreadFont())
|
||||||
|
nn::swkbd::CalcSubThreadFont();
|
||||||
|
|
||||||
|
if (nn::swkbd::IsNeedCalcSubThreadPredict())
|
||||||
|
nn::swkbd::CalcSubThreadPredict();
|
||||||
|
|
||||||
|
if (nn::swkbd::IsDecideOkButton(NULL))
|
||||||
|
{
|
||||||
|
// Add entered text
|
||||||
|
const char16_t* string = nn::swkbd::GetInputFormString();
|
||||||
|
for (int i = 0; *string; string++)
|
||||||
|
io.AddInputCharacterUTF16(string[i]);
|
||||||
|
|
||||||
|
// close keyboard
|
||||||
|
nn::swkbd::DisappearInputForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nn::swkbd::IsDecideCancelButton(NULL))
|
||||||
|
nn::swkbd::DisappearInputForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ImGui_ImplWiiU_UpdateTouchInput(ImGui_ImplWiiU_ControllerInput* input)
|
||||||
|
{
|
||||||
|
if (!input->vpad)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ImGui_ImplWiiU_Data* bd = ImGui_ImplWiiU_GetBackendData();
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
VPADTouchData touch;
|
||||||
|
VPADGetTPCalibratedPoint(VPAD_CHAN_0, &touch, &input->vpad->tpNormal);
|
||||||
|
|
||||||
|
if (touch.touched)
|
||||||
|
{
|
||||||
|
float scale_x = (io.DisplaySize.x / io.DisplayFramebufferScale.x) / 1280.0f;
|
||||||
|
float scale_y = (io.DisplaySize.y / io.DisplayFramebufferScale.y) / 720.0f;
|
||||||
|
io.AddMousePosEvent(touch.x * scale_x, touch.y * scale_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (touch.touched != bd->WasTouched)
|
||||||
|
{
|
||||||
|
io.AddMouseButtonEvent(ImGuiMouseButton_Left, touch.touched);
|
||||||
|
bd->WasTouched = touch.touched;
|
||||||
|
bd->LastController = nn::swkbd::ControllerType::DrcGamepad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IM_CLAMP(V, MN, MX) ((V) < (MN) ? (MN) : (V) > (MX) ? (MX) : (V))
|
||||||
|
|
||||||
|
static void ImGui_ImplWiiU_UpdateControllerInput(ImGui_ImplWiiU_ControllerInput* input)
|
||||||
|
{
|
||||||
|
ImGui_ImplWiiU_Data* bd = ImGui_ImplWiiU_GetBackendData();
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
// SoH removal to make opening the menu easier
|
||||||
|
// if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
|
||||||
|
// return;
|
||||||
|
|
||||||
|
uint32_t vpad_buttons = input->vpad ? input->vpad->hold : 0;
|
||||||
|
uint32_t wpad_buttons = 0;
|
||||||
|
uint32_t classic_buttons = 0;
|
||||||
|
uint32_t pro_buttons = 0;
|
||||||
|
|
||||||
|
float stick_l_x = input->vpad ? input->vpad->leftStick.x : 0.0f;
|
||||||
|
float stick_l_y = input->vpad ? input->vpad->leftStick.y : 0.0f;
|
||||||
|
float stick_r_x = input->vpad ? input->vpad->rightStick.x : 0.0f;
|
||||||
|
float stick_r_y = input->vpad ? input->vpad->rightStick.y : 0.0f;
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
KPADStatus* kpad = input->kpad[i];
|
||||||
|
if (!kpad)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (kpad->extensionType)
|
||||||
|
{
|
||||||
|
case WPAD_EXT_CORE:
|
||||||
|
case WPAD_EXT_NUNCHUK:
|
||||||
|
case WPAD_EXT_MPLUS:
|
||||||
|
case WPAD_EXT_MPLUS_NUNCHUK:
|
||||||
|
wpad_buttons |= kpad->hold;
|
||||||
|
break;
|
||||||
|
case WPAD_EXT_CLASSIC:
|
||||||
|
case WPAD_EXT_MPLUS_CLASSIC:
|
||||||
|
classic_buttons |= kpad->classic.hold;
|
||||||
|
if (classic_buttons & WPAD_CLASSIC_BUTTON_Y)
|
||||||
|
bd->LastController = (nn::swkbd::ControllerType) i;
|
||||||
|
|
||||||
|
stick_l_x += kpad->classic.leftStick.x;
|
||||||
|
stick_l_y += kpad->classic.leftStick.y;
|
||||||
|
stick_r_x += kpad->classic.rightStick.x;
|
||||||
|
stick_r_y += kpad->classic.rightStick.y;
|
||||||
|
break;
|
||||||
|
case WPAD_EXT_PRO_CONTROLLER:
|
||||||
|
pro_buttons |= kpad->pro.hold;
|
||||||
|
if (pro_buttons & WPAD_PRO_BUTTON_Y)
|
||||||
|
bd->LastController = (nn::swkbd::ControllerType) i;
|
||||||
|
|
||||||
|
stick_l_x += kpad->pro.leftStick.x;
|
||||||
|
stick_l_y += kpad->pro.leftStick.y;
|
||||||
|
stick_r_x += kpad->pro.rightStick.x;
|
||||||
|
stick_r_y += kpad->pro.rightStick.y;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vpad_buttons & VPAD_BUTTON_Y)
|
||||||
|
bd->LastController = nn::swkbd::ControllerType::DrcGamepad;
|
||||||
|
|
||||||
|
io.AddKeyEvent(ImGuiKey_GamepadStart, (vpad_buttons & VPAD_BUTTON_PLUS) || (wpad_buttons & WPAD_BUTTON_PLUS) || (classic_buttons & WPAD_CLASSIC_BUTTON_PLUS) || (pro_buttons & WPAD_PRO_BUTTON_PLUS));
|
||||||
|
io.AddKeyEvent(ImGuiKey_GamepadBack, (vpad_buttons & VPAD_BUTTON_MINUS) || (wpad_buttons & WPAD_BUTTON_MINUS) || (classic_buttons & WPAD_CLASSIC_BUTTON_MINUS) || (pro_buttons & WPAD_PRO_BUTTON_MINUS));
|
||||||
|
io.AddKeyEvent(ImGuiKey_GamepadFaceLeft, (vpad_buttons & VPAD_BUTTON_X) || (classic_buttons & WPAD_CLASSIC_BUTTON_X) || (pro_buttons & WPAD_PRO_BUTTON_X));
|
||||||
|
io.AddKeyEvent(ImGuiKey_GamepadFaceRight, (vpad_buttons & VPAD_BUTTON_B) || (wpad_buttons & WPAD_BUTTON_B) || (classic_buttons & WPAD_CLASSIC_BUTTON_B) || (pro_buttons & WPAD_PRO_BUTTON_B));
|
||||||
|
io.AddKeyEvent(ImGuiKey_GamepadFaceUp, (vpad_buttons & VPAD_BUTTON_Y) || (classic_buttons & WPAD_CLASSIC_BUTTON_Y) || (pro_buttons & WPAD_PRO_BUTTON_Y));
|
||||||
|
io.AddKeyEvent(ImGuiKey_GamepadFaceDown, (vpad_buttons & VPAD_BUTTON_A) || (wpad_buttons & WPAD_BUTTON_A) || (classic_buttons & WPAD_CLASSIC_BUTTON_A) || (pro_buttons & WPAD_PRO_BUTTON_A));
|
||||||
|
io.AddKeyEvent(ImGuiKey_GamepadDpadLeft, (vpad_buttons & VPAD_BUTTON_LEFT) || (wpad_buttons & WPAD_BUTTON_LEFT) || (classic_buttons & WPAD_CLASSIC_BUTTON_LEFT) || (pro_buttons & WPAD_PRO_BUTTON_LEFT));
|
||||||
|
io.AddKeyEvent(ImGuiKey_GamepadDpadRight, (vpad_buttons & VPAD_BUTTON_RIGHT) || (wpad_buttons & WPAD_BUTTON_RIGHT) || (classic_buttons & WPAD_CLASSIC_BUTTON_RIGHT) || (pro_buttons & WPAD_PRO_BUTTON_RIGHT));
|
||||||
|
io.AddKeyEvent(ImGuiKey_GamepadDpadUp, (vpad_buttons & VPAD_BUTTON_UP) || (wpad_buttons & WPAD_BUTTON_UP) || (classic_buttons & WPAD_CLASSIC_BUTTON_UP) || (pro_buttons & WPAD_PRO_BUTTON_UP));
|
||||||
|
io.AddKeyEvent(ImGuiKey_GamepadDpadDown, (vpad_buttons & VPAD_BUTTON_DOWN) || (wpad_buttons & WPAD_BUTTON_DOWN) || (classic_buttons & WPAD_CLASSIC_BUTTON_DOWN) || (pro_buttons & WPAD_PRO_BUTTON_DOWN));
|
||||||
|
io.AddKeyEvent(ImGuiKey_GamepadL1, (vpad_buttons & VPAD_BUTTON_L) || (classic_buttons & WPAD_CLASSIC_BUTTON_L) || (pro_buttons & WPAD_PRO_TRIGGER_L));
|
||||||
|
io.AddKeyEvent(ImGuiKey_GamepadR1, (vpad_buttons & VPAD_BUTTON_R) || (classic_buttons & WPAD_CLASSIC_BUTTON_R) || (pro_buttons & WPAD_PRO_TRIGGER_R));
|
||||||
|
io.AddKeyEvent(ImGuiKey_GamepadL2, (vpad_buttons & VPAD_BUTTON_ZL) || (classic_buttons & WPAD_CLASSIC_BUTTON_ZL) || (pro_buttons & WPAD_PRO_TRIGGER_ZL));
|
||||||
|
io.AddKeyEvent(ImGuiKey_GamepadR2, (vpad_buttons & VPAD_BUTTON_ZR) || (classic_buttons & WPAD_CLASSIC_BUTTON_ZR) || (pro_buttons & WPAD_PRO_TRIGGER_ZR));
|
||||||
|
io.AddKeyEvent(ImGuiKey_GamepadL3, (vpad_buttons & VPAD_BUTTON_STICK_L) || (pro_buttons & WPAD_PRO_BUTTON_STICK_L));
|
||||||
|
io.AddKeyEvent(ImGuiKey_GamepadR3, (vpad_buttons & VPAD_BUTTON_STICK_R) || (pro_buttons & WPAD_PRO_BUTTON_STICK_R));
|
||||||
|
|
||||||
|
stick_l_x = IM_CLAMP(stick_l_x, -1.0f, 1.0f);
|
||||||
|
io.AddKeyAnalogEvent(ImGuiKey_GamepadLStickLeft, stick_l_x < -0.1f, (stick_l_x < -0.1f) ? (stick_l_x * -1.0f) : 0.0f);
|
||||||
|
io.AddKeyAnalogEvent(ImGuiKey_GamepadLStickRight, stick_l_x > 0.1f, (stick_l_x > 0.1f) ? stick_l_x : 0.0f);
|
||||||
|
|
||||||
|
stick_l_y = IM_CLAMP(stick_l_y, -1.0f, 1.0f);
|
||||||
|
io.AddKeyAnalogEvent(ImGuiKey_GamepadLStickUp, stick_l_y > 0.1f, (stick_l_y > 0.1f) ? stick_l_y : 0.0f);
|
||||||
|
io.AddKeyAnalogEvent(ImGuiKey_GamepadLStickDown, stick_l_y < -0.1f, (stick_l_y < -0.1f) ? (stick_l_y * -1.0f) : 0.0f);
|
||||||
|
|
||||||
|
stick_r_x = IM_CLAMP(stick_r_x, -1.0f, 1.0f);
|
||||||
|
io.AddKeyAnalogEvent(ImGuiKey_GamepadRStickLeft, stick_r_x < -0.1f, (stick_r_x < -0.1f) ? (stick_r_x * -1.0f) : 0.0f);
|
||||||
|
io.AddKeyAnalogEvent(ImGuiKey_GamepadRStickRight, stick_r_x > 0.1f, (stick_r_x > 0.1f) ? stick_r_x : 0.0f);
|
||||||
|
|
||||||
|
stick_r_y = IM_CLAMP(stick_r_y, -1.0f, 1.0f);
|
||||||
|
io.AddKeyAnalogEvent(ImGuiKey_GamepadRStickUp, stick_r_y > 0.1f, (stick_r_y > 0.1f) ? stick_r_y : 0.0f);
|
||||||
|
io.AddKeyAnalogEvent(ImGuiKey_GamepadRStickDown, stick_r_y < -0.1f, (stick_r_y < -0.1f) ? (stick_r_y * -1.0f) : 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ImGui_ImplWiiU_ProcessInput(ImGui_ImplWiiU_ControllerInput* input)
|
||||||
|
{
|
||||||
|
ImGui_ImplWiiU_Data* bd = ImGui_ImplWiiU_GetBackendData();
|
||||||
|
IM_ASSERT(bd != NULL && "Did you call ImGui_ImplWiiU_Init()?");
|
||||||
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
// Show keyboard if wanted
|
||||||
|
if (io.WantTextInput && !bd->WantedTextInput)
|
||||||
|
{
|
||||||
|
// Open the keyboard for the controller which requested the text input
|
||||||
|
bd->AppearArg.keyboardArg.configArg.controllerType = bd->LastController;
|
||||||
|
|
||||||
|
if (nn::swkbd::GetStateInputForm() == nn::swkbd::State::Hidden)
|
||||||
|
nn::swkbd::AppearInputForm(bd->AppearArg);
|
||||||
|
}
|
||||||
|
bd->WantedTextInput = io.WantTextInput;
|
||||||
|
|
||||||
|
// Update keyboard input
|
||||||
|
if (nn::swkbd::GetStateInputForm() != nn::swkbd::State::Hidden)
|
||||||
|
{
|
||||||
|
ImGui_ImplWiiU_UpdateKeyboardInput(input);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update touch screen
|
||||||
|
ImGui_ImplWiiU_UpdateTouchInput(input);
|
||||||
|
|
||||||
|
// Update gamepads
|
||||||
|
ImGui_ImplWiiU_UpdateControllerInput(input);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGui_ImplWiiU_DrawKeyboardOverlay(ImGui_ImplWiiU_KeyboardOverlayType type)
|
||||||
|
{
|
||||||
|
ImGui_ImplWiiU_Data* bd = ImGui_ImplWiiU_GetBackendData();
|
||||||
|
IM_ASSERT(bd != NULL && "Did you call ImGui_ImplWiiU_Init()?");
|
||||||
|
|
||||||
|
if (nn::swkbd::GetStateInputForm() != nn::swkbd::State::Hidden)
|
||||||
|
{
|
||||||
|
if (type == ImGui_KeyboardOverlay_Auto)
|
||||||
|
{
|
||||||
|
if (bd->LastController == nn::swkbd::ControllerType::DrcGamepad)
|
||||||
|
nn::swkbd::DrawDRC();
|
||||||
|
else
|
||||||
|
nn::swkbd::DrawTV();
|
||||||
|
}
|
||||||
|
else if (type == ImGui_KeyboardOverlay_DRC)
|
||||||
|
nn::swkbd::DrawDRC();
|
||||||
|
else if (type == ImGui_KeyboardOverlay_TV)
|
||||||
|
nn::swkbd::DrawTV();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
// dear imgui: Platform Backend for the Wii U
|
||||||
|
#pragma once
|
||||||
|
#include "imgui.h" // IMGUI_IMPL_API
|
||||||
|
|
||||||
|
// GamePad Input
|
||||||
|
#include <vpad/input.h>
|
||||||
|
// Controller Input
|
||||||
|
#include <padscore/kpad.h>
|
||||||
|
|
||||||
|
struct ImGui_ImplWiiU_ControllerInput
|
||||||
|
{
|
||||||
|
VPADStatus* vpad = nullptr;
|
||||||
|
KPADStatus* kpad[4] = { nullptr };
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ImGui_ImplWiiU_KeyboardOverlayType
|
||||||
|
{
|
||||||
|
//! Draw for the DRC
|
||||||
|
ImGui_KeyboardOverlay_DRC,
|
||||||
|
//! Draw for the TV
|
||||||
|
ImGui_KeyboardOverlay_TV,
|
||||||
|
//! Draw for the controller which requested the keyboard
|
||||||
|
ImGui_KeyboardOverlay_Auto
|
||||||
|
};
|
||||||
|
|
||||||
|
IMGUI_IMPL_API bool ImGui_ImplWiiU_Init();
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplWiiU_Shutdown();
|
||||||
|
IMGUI_IMPL_API bool ImGui_ImplWiiU_ProcessInput(ImGui_ImplWiiU_ControllerInput* input);
|
||||||
|
IMGUI_IMPL_API void ImGui_ImplWiiU_DrawKeyboardOverlay(ImGui_ImplWiiU_KeyboardOverlayType type = ImGui_KeyboardOverlay_Auto);
|
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# to build shaders you need to place a copy of latte-assembler into the current directory
|
||||||
|
# latte-assembler is part of decaf-emu <https://github.com/decaf-emu/decaf-emu>
|
||||||
|
|
||||||
|
# shader
|
||||||
|
./latte-assembler assemble --vsh=shader.vsh --psh=shader.psh shader.gsh
|
||||||
|
xxd -i shader.gsh > shader.h
|
@ -0,0 +1,148 @@
|
|||||||
|
unsigned char shader_gsh[] = {
|
||||||
|
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, 0xd8, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x01, 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, 0xf8, 0x00, 0x00, 0x00, 0x03,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02,
|
||||||
|
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, 0x70,
|
||||||
|
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, 0x03, 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, 0x78, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xca, 0x70, 0x01, 0x80,
|
||||||
|
0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xca, 0x70, 0x01, 0x8c, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x01, 0xca, 0x70, 0x01, 0x90, 0x00, 0x00, 0x00, 0x0b,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x50, 0x72, 0x6f, 0x6a,
|
||||||
|
0x4d, 0x74, 0x78, 0x00, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x55, 0x56, 0x00, 0x00, 0x43, 0x6f, 0x6c, 0x6f,
|
||||||
|
0x72, 0x00, 0x00, 0x00, 0xd0, 0x60, 0x00, 0xe8, 0xd0, 0x60, 0x01, 0x08,
|
||||||
|
0xca, 0x70, 0x01, 0x34, 0xca, 0x70, 0x01, 0x48, 0xca, 0x70, 0x01, 0x58,
|
||||||
|
0xca, 0x70, 0x01, 0x68, 0x7d, 0x42, 0x4c, 0x4b, 0x00, 0x00, 0x00, 0x28,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x98, 0xd0, 0x60, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x20, 0xd0, 0x60, 0x01, 0x78, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x06, 0xd0, 0x60, 0x01, 0x98, 0x42, 0x4c, 0x4b, 0x7b,
|
||||||
|
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x01, 0x70, 0x00, 0x00, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x09,
|
||||||
|
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xa0, 0x3c, 0xa0, 0x00, 0x00,
|
||||||
|
0x88, 0x06, 0x00, 0x94, 0x00, 0x40, 0x01, 0x00, 0x08, 0x09, 0x80, 0x13,
|
||||||
|
0x01, 0xc0, 0x01, 0x00, 0x88, 0x06, 0x20, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x60, 0x20, 0x00,
|
||||||
|
0x80, 0x00, 0x00, 0x00, 0xfd, 0x64, 0xa0, 0x00, 0x80, 0x00, 0x00, 0x20,
|
||||||
|
0xfd, 0x68, 0x20, 0x01, 0x80, 0x00, 0x00, 0x40, 0xfd, 0x6c, 0xa0, 0x81,
|
||||||
|
0x80, 0x00, 0x00, 0x60, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f,
|
||||||
|
0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x01, 0x24, 0x20, 0x00,
|
||||||
|
0xfe, 0x00, 0xe2, 0x0f, 0x01, 0x24, 0xa0, 0x00, 0xfe, 0x04, 0xe2, 0x2f,
|
||||||
|
0x01, 0x24, 0x20, 0x01, 0xfe, 0x08, 0xe2, 0x4f, 0x01, 0x24, 0xa0, 0x81,
|
||||||
|
0xfe, 0x0c, 0xe2, 0x6f, 0x01, 0x00, 0x20, 0x00, 0xfe, 0x00, 0x22, 0x00,
|
||||||
|
0x01, 0x00, 0xa0, 0x00, 0xfe, 0x04, 0x22, 0x20, 0x01, 0x00, 0x20, 0x01,
|
||||||
|
0xfe, 0x08, 0x22, 0x40, 0x01, 0x00, 0xa0, 0x81, 0xfe, 0x0c, 0x22, 0x60,
|
||||||
|
0x42, 0x4c, 0x4b, 0x7b, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x01, 0x2c,
|
||||||
|
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
|
||||||
|
0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 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, 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, 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, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xca, 0x70, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0xd0, 0x60, 0x00, 0xd4,
|
||||||
|
0xca, 0x70, 0x00, 0xe8, 0x7d, 0x42, 0x4c, 0x4b, 0x00, 0x00, 0x00, 0x28,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xd0, 0x60, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x08, 0xd0, 0x60, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x02, 0xd0, 0x60, 0x00, 0xfc, 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, 0x20, 0x80, 0x01,
|
||||||
|
0x90, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x01, 0x90, 0x00, 0x00, 0x20,
|
||||||
|
0x00, 0x28, 0x80, 0x00, 0x90, 0x00, 0x00, 0x40, 0x00, 0x2c, 0x00, 0x80,
|
||||||
|
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
|
||||||
|
};
|
||||||
|
unsigned int shader_gsh_len = 1732;
|
@ -0,0 +1,25 @@
|
|||||||
|
; $MODE = "UniformRegister"
|
||||||
|
|
||||||
|
; $NUM_SPI_PS_INPUT_CNTL = 2
|
||||||
|
; Frag_UV R0
|
||||||
|
; $SPI_PS_INPUT_CNTL[0].SEMANTIC = 0
|
||||||
|
; $SPI_PS_INPUT_CNTL[0].DEFAULT_VAL = 1
|
||||||
|
; Frag_Color R1
|
||||||
|
; $SPI_PS_INPUT_CNTL[1].SEMANTIC = 1
|
||||||
|
; $SPI_PS_INPUT_CNTL[1].DEFAULT_VAL = 1
|
||||||
|
|
||||||
|
; $SAMPLER_VARS[0].name = "Texture"
|
||||||
|
; $SAMPLER_VARS[0].type = "SAMPLER2D"
|
||||||
|
; $SAMPLER_VARS[0].location = 0
|
||||||
|
|
||||||
|
; Note: R1 is swapped for endianness
|
||||||
|
|
||||||
|
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, R1.w
|
||||||
|
y: MUL R0.y, R0.y, R1.z
|
||||||
|
z: MUL R0.z, R0.z, R1.y
|
||||||
|
w: MUL R0.w, R0.w, R1.x
|
||||||
|
02 EXP_DONE: PIX0, R0
|
||||||
|
END_OF_PROGRAM
|
@ -0,0 +1,47 @@
|
|||||||
|
; $MODE = "UniformRegister"
|
||||||
|
|
||||||
|
; $SPI_VS_OUT_CONFIG.VS_EXPORT_COUNT = 1
|
||||||
|
; $NUM_SPI_VS_OUT_ID = 1
|
||||||
|
; uv
|
||||||
|
; $SPI_VS_OUT_ID[0].SEMANTIC_0 = 0
|
||||||
|
; color
|
||||||
|
; $SPI_VS_OUT_ID[0].SEMANTIC_1 = 1
|
||||||
|
|
||||||
|
; C0
|
||||||
|
; $UNIFORM_VARS[0].name = "ProjMtx"
|
||||||
|
; $UNIFORM_VARS[0].type = "mat4"
|
||||||
|
; $UNIFORM_VARS[0].count = 1
|
||||||
|
; $UNIFORM_VARS[0].block = -1
|
||||||
|
; $UNIFORM_VARS[0].offset = 0
|
||||||
|
|
||||||
|
; R1
|
||||||
|
; $ATTRIB_VARS[0].name = "Position"
|
||||||
|
; $ATTRIB_VARS[0].type = "vec2"
|
||||||
|
; $ATTRIB_VARS[0].location = 0
|
||||||
|
; R2
|
||||||
|
; $ATTRIB_VARS[1].name = "UV"
|
||||||
|
; $ATTRIB_VARS[1].type = "vec2"
|
||||||
|
; $ATTRIB_VARS[1].location = 1
|
||||||
|
; R3
|
||||||
|
; $ATTRIB_VARS[2].name = "Color"
|
||||||
|
; $ATTRIB_VARS[2].type = "vec4"
|
||||||
|
; $ATTRIB_VARS[2].location = 2
|
||||||
|
|
||||||
|
00 CALL_FS NO_BARRIER
|
||||||
|
01 ALU: ADDR(32) CNT(14)
|
||||||
|
0 x: MUL ____, 1.0f, C3.x
|
||||||
|
y: MUL ____, 1.0f, C3.y
|
||||||
|
z: MUL ____, 1.0f, C3.z
|
||||||
|
w: MUL ____, 1.0f, C3.w
|
||||||
|
1 x: MULADD R127.x, R1.y, C1.x, PV0.x
|
||||||
|
y: MULADD R127.y, R1.y, C1.y, PV0.y
|
||||||
|
z: MULADD R127.z, R1.y, C1.z, PV0.z
|
||||||
|
w: MULADD R127.w, R1.y, C1.w, PV0.w
|
||||||
|
2 x: MULADD R1.x, R1.x, C0.x, PV0.x
|
||||||
|
y: MULADD R1.y, R1.x, C0.y, PV0.y
|
||||||
|
z: MULADD R1.z, R1.x, C0.z, PV0.z
|
||||||
|
w: MULADD R1.w, R1.x, C0.w, PV0.w
|
||||||
|
02 EXP_DONE: POS0, R1
|
||||||
|
03 EXP: PARAM0, R2.xy00 NO_BARRIER
|
||||||
|
04 EXP_DONE: PARAM1, R3 NO_BARRIER
|
||||||
|
END_OF_PROGRAM
|
@ -761,7 +761,12 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
|
|||||||
|
|
||||||
// Temporary buffer
|
// Temporary buffer
|
||||||
// The first <points_count> items are normals at each line point, then after that there are either 2 or 4 temp points for each line point
|
// The first <points_count> items are normals at each line point, then after that there are either 2 or 4 temp points for each line point
|
||||||
|
#ifdef __WIIU__
|
||||||
|
// avoid using alloca on the Wii U
|
||||||
|
ImVec2 temp_normals[points_count * ((use_texture || !thick_line) ? 3 : 5) * sizeof(ImVec2)]; //-V630
|
||||||
|
#else
|
||||||
ImVec2* temp_normals = (ImVec2*)alloca(points_count * ((use_texture || !thick_line) ? 3 : 5) * sizeof(ImVec2)); //-V630
|
ImVec2* temp_normals = (ImVec2*)alloca(points_count * ((use_texture || !thick_line) ? 3 : 5) * sizeof(ImVec2)); //-V630
|
||||||
|
#endif
|
||||||
ImVec2* temp_points = temp_normals + points_count;
|
ImVec2* temp_points = temp_normals + points_count;
|
||||||
|
|
||||||
// Calculate normals (tangents) for each line segment
|
// Calculate normals (tangents) for each line segment
|
||||||
@ -1009,7 +1014,12 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compute normals
|
// Compute normals
|
||||||
|
#ifdef __WIIU__
|
||||||
|
// Avoid using alloca on the Wii U
|
||||||
|
ImVec2 temp_normals[points_count * sizeof(ImVec2)]; //-V630
|
||||||
|
#else
|
||||||
ImVec2* temp_normals = (ImVec2*)alloca(points_count * sizeof(ImVec2)); //-V630
|
ImVec2* temp_normals = (ImVec2*)alloca(points_count * sizeof(ImVec2)); //-V630
|
||||||
|
#endif
|
||||||
for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++)
|
for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++)
|
||||||
{
|
{
|
||||||
const ImVec2& p0 = points[i0];
|
const ImVec2& p0 = points[i0];
|
||||||
|
@ -111,6 +111,12 @@ void Mercury::reload() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::ifstream ifs(this->path_);
|
std::ifstream ifs(this->path_);
|
||||||
|
|
||||||
|
#ifdef __WIIU__
|
||||||
|
alignas(0x40) char buffer[8192];
|
||||||
|
ifs.rdbuf()->pubsetbuf(buffer, sizeof(buffer));
|
||||||
|
#endif
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this->rjson = json::parse(ifs);
|
this->rjson = json::parse(ifs);
|
||||||
this->vjson = this->rjson.flatten();
|
this->vjson = this->rjson.flatten();
|
||||||
@ -122,5 +128,11 @@ void Mercury::reload() {
|
|||||||
|
|
||||||
void Mercury::save() const {
|
void Mercury::save() const {
|
||||||
std::ofstream file(this->path_);
|
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);
|
file << this->vjson.unflatten().dump(4);
|
||||||
}
|
}
|
||||||
|
@ -286,7 +286,7 @@ SPDLOG_INLINE int utc_minutes_offset(const std::tm &tm)
|
|||||||
return offset;
|
return offset;
|
||||||
#else
|
#else
|
||||||
|
|
||||||
# if defined(sun) || defined(__sun) || defined(_AIX) || (!defined(_BSD_SOURCE) && !defined(_GNU_SOURCE))
|
# if defined(sun) || defined(__sun) || defined(_AIX) || (!defined(_BSD_SOURCE) && !defined(_GNU_SOURCE)) || defined(__WIIU__)
|
||||||
// 'tm_gmtoff' field is BSD extension and it's missing on SunOS/Solaris
|
// 'tm_gmtoff' field is BSD extension and it's missing on SunOS/Solaris
|
||||||
struct helper
|
struct helper
|
||||||
{
|
{
|
||||||
|
509
libultraship/libultraship/WiiUController.cpp
Normal file
509
libultraship/libultraship/WiiUController.cpp
Normal file
@ -0,0 +1,509 @@
|
|||||||
|
#ifdef __WIIU__
|
||||||
|
#include "WiiUController.h"
|
||||||
|
#include "GlobalCtx2.h"
|
||||||
|
#include "Window.h"
|
||||||
|
#include "ImGuiImpl.h"
|
||||||
|
|
||||||
|
#include "WiiUImpl.h"
|
||||||
|
|
||||||
|
namespace Ship {
|
||||||
|
WiiUController::WiiUController(WPADChan chan) : Controller(), chan(chan) {
|
||||||
|
connected = false;
|
||||||
|
extensionType = (WPADExtensionType) -1;
|
||||||
|
|
||||||
|
controllerName = std::string("Wii U Controller ") + std::to_string((int) chan) + " (Disconnected)";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WiiUController::Open() {
|
||||||
|
KPADError error;
|
||||||
|
KPADStatus* status = Ship::WiiU::GetKPADStatus(chan, &error);
|
||||||
|
if (!status || error != KPAD_ERROR_OK) {
|
||||||
|
Close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
connected = true;
|
||||||
|
extensionType = (WPADExtensionType) status->extensionType;
|
||||||
|
|
||||||
|
// Create a GUID and name based on extension and channel
|
||||||
|
GUID = std::string("WiiU") + GetControllerExtensionName() + std::to_string((int) chan);
|
||||||
|
controllerName = std::string("Wii U ") + GetControllerExtensionName() + std::string(" ") + std::to_string((int) chan);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiiUController::Close() {
|
||||||
|
connected = false;
|
||||||
|
extensionType = (WPADExtensionType) -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAXCONTROLLERS; i++) {
|
||||||
|
getPressedButtons(i) = 0;
|
||||||
|
getLeftStickX(i) = 0;
|
||||||
|
getLeftStickY(i) = 0;
|
||||||
|
getRightStickX(i) = 0;
|
||||||
|
getRightStickY(i) = 0;
|
||||||
|
getGyroX(i) = 0;
|
||||||
|
getGyroY(i) = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiiUController::ReadFromSource(int32_t virtualSlot) {
|
||||||
|
auto profile = getProfile(virtualSlot);
|
||||||
|
|
||||||
|
KPADError error;
|
||||||
|
KPADStatus* status = Ship::WiiU::GetKPADStatus(chan, &error);
|
||||||
|
if (!status) {
|
||||||
|
Close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the controller type doesn't change after opening
|
||||||
|
if (status->extensionType != extensionType) {
|
||||||
|
Close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPressedButtons(virtualSlot) = 0;
|
||||||
|
getLeftStickX(virtualSlot) = 0;
|
||||||
|
getLeftStickY(virtualSlot) = 0;
|
||||||
|
getRightStickX(virtualSlot) = 0;
|
||||||
|
getRightStickY(virtualSlot) = 0;
|
||||||
|
getGyroX(virtualSlot) = 0;
|
||||||
|
getGyroY(virtualSlot) = 0;
|
||||||
|
|
||||||
|
if (error != KPAD_ERROR_OK) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t stickX = 0;
|
||||||
|
int16_t stickY = 0;
|
||||||
|
int16_t camX = 0;
|
||||||
|
int16_t camY = 0;
|
||||||
|
|
||||||
|
switch (extensionType) {
|
||||||
|
case WPAD_EXT_PRO_CONTROLLER:
|
||||||
|
for (uint32_t i = WPAD_PRO_BUTTON_UP; i <= WPAD_PRO_STICK_R_EMULATION_UP; i <<= 1) {
|
||||||
|
if (profile->Mappings.contains(i)) {
|
||||||
|
// check if the stick is mapped to an analog stick
|
||||||
|
if (i >= WPAD_PRO_STICK_L_EMULATION_LEFT) {
|
||||||
|
float axisX = i >= WPAD_PRO_STICK_R_EMULATION_LEFT ? status->pro.rightStick.x : status->pro.leftStick.x;
|
||||||
|
float axisY = i >= WPAD_PRO_STICK_R_EMULATION_LEFT ? status->pro.rightStick.y : status->pro.leftStick.y;
|
||||||
|
|
||||||
|
if (profile->Mappings[i] == BTN_STICKRIGHT || profile->Mappings[i] == BTN_STICKLEFT) {
|
||||||
|
stickX = axisX * 85;
|
||||||
|
continue;
|
||||||
|
} else if (profile->Mappings[i] == BTN_STICKDOWN || profile->Mappings[i] == BTN_STICKUP) {
|
||||||
|
stickY = axisY * 85;
|
||||||
|
continue;
|
||||||
|
} else if (profile->Mappings[i] == BTN_VSTICKRIGHT || profile->Mappings[i] == BTN_VSTICKLEFT) {
|
||||||
|
camX = axisX * 85;
|
||||||
|
continue;
|
||||||
|
} else if (profile->Mappings[i] == BTN_VSTICKDOWN || profile->Mappings[i] == BTN_VSTICKUP) {
|
||||||
|
camY = axisY * 85;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status->pro.hold & i) {
|
||||||
|
getPressedButtons(virtualSlot) |= profile->Mappings[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WPAD_EXT_CLASSIC:
|
||||||
|
case WPAD_EXT_MPLUS_CLASSIC:
|
||||||
|
for (uint32_t i = WPAD_CLASSIC_BUTTON_UP; i <= WPAD_CLASSIC_STICK_R_EMULATION_UP; i <<= 1) {
|
||||||
|
if (profile->Mappings.contains(i)) {
|
||||||
|
// check if the stick is mapped to an analog stick
|
||||||
|
if (i >= WPAD_CLASSIC_STICK_L_EMULATION_LEFT) {
|
||||||
|
float axisX = i >= WPAD_CLASSIC_STICK_R_EMULATION_LEFT ? status->classic.rightStick.x : status->classic.leftStick.x;
|
||||||
|
float axisY = i >= WPAD_CLASSIC_STICK_R_EMULATION_LEFT ? status->classic.rightStick.y : status->classic.leftStick.y;
|
||||||
|
|
||||||
|
if (profile->Mappings[i] == BTN_STICKRIGHT || profile->Mappings[i] == BTN_STICKLEFT) {
|
||||||
|
stickX = axisX * 85;
|
||||||
|
continue;
|
||||||
|
} else if (profile->Mappings[i] == BTN_STICKDOWN || profile->Mappings[i] == BTN_STICKUP) {
|
||||||
|
stickY = axisY * 85;
|
||||||
|
continue;
|
||||||
|
} else if (profile->Mappings[i] == BTN_VSTICKRIGHT || profile->Mappings[i] == BTN_VSTICKLEFT) {
|
||||||
|
camX = axisX * 85;
|
||||||
|
continue;
|
||||||
|
} else if (profile->Mappings[i] == BTN_VSTICKDOWN || profile->Mappings[i] == BTN_VSTICKUP) {
|
||||||
|
camY = axisY * 85;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status->classic.hold & i) {
|
||||||
|
getPressedButtons(virtualSlot) |= profile->Mappings[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WPAD_EXT_NUNCHUK:
|
||||||
|
case WPAD_EXT_MPLUS_NUNCHUK:
|
||||||
|
case WPAD_EXT_MPLUS:
|
||||||
|
case WPAD_EXT_CORE:
|
||||||
|
for (uint32_t i = WPAD_BUTTON_LEFT; i <= WPAD_BUTTON_HOME; i <<= 1) {
|
||||||
|
if (profile->Mappings.contains(i)) {
|
||||||
|
if (status->hold & i) {
|
||||||
|
getPressedButtons(virtualSlot) |= profile->Mappings[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stickX += status->nunchuck.stick.x * 85;
|
||||||
|
stickY += status->nunchuck.stick.y * 85;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stickX || stickY) {
|
||||||
|
NormalizeStickAxis(virtualSlot, stickX, stickY, profile->AxisDeadzones[0], false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (camX || camY) {
|
||||||
|
NormalizeStickAxis(virtualSlot, camX, camY, profile->AxisDeadzones[2], true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiiUController::WriteToSource(int32_t virtualSlot, ControllerCallback* controller) {
|
||||||
|
if (getProfile(virtualSlot)->UseRumble) {
|
||||||
|
WPADControlMotor(chan, controller->rumble);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiiUController::ClearRawPress() {
|
||||||
|
// Clear already triggered buttons
|
||||||
|
KPADError error;
|
||||||
|
KPADStatus* status = Ship::WiiU::GetKPADStatus(chan, &error);
|
||||||
|
if (status) {
|
||||||
|
switch (extensionType) {
|
||||||
|
case WPAD_EXT_PRO_CONTROLLER:
|
||||||
|
status->pro.trigger = 0;
|
||||||
|
break;
|
||||||
|
case WPAD_EXT_CLASSIC:
|
||||||
|
case WPAD_EXT_MPLUS_CLASSIC:
|
||||||
|
status->classic.trigger = 0;
|
||||||
|
break;
|
||||||
|
case WPAD_EXT_NUNCHUK:
|
||||||
|
case WPAD_EXT_MPLUS_NUNCHUK:
|
||||||
|
case WPAD_EXT_MPLUS:
|
||||||
|
case WPAD_EXT_CORE:
|
||||||
|
status->trigger = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t WiiUController::ReadRawPress() {
|
||||||
|
KPADError error;
|
||||||
|
KPADStatus* status = Ship::WiiU::GetKPADStatus(chan, &error);
|
||||||
|
if (!status || error != KPAD_ERROR_OK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (extensionType) {
|
||||||
|
case WPAD_EXT_PRO_CONTROLLER:
|
||||||
|
for (uint32_t i = WPAD_PRO_BUTTON_UP; i <= WPAD_PRO_STICK_R_EMULATION_UP; i <<= 1) {
|
||||||
|
if (status->pro.trigger & i) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status->pro.leftStick.x > 0.7f) {
|
||||||
|
return WPAD_PRO_STICK_L_EMULATION_RIGHT;
|
||||||
|
}
|
||||||
|
if (status->pro.leftStick.x < -0.7f) {
|
||||||
|
return WPAD_PRO_STICK_L_EMULATION_LEFT;
|
||||||
|
}
|
||||||
|
if (status->pro.leftStick.y > 0.7f) {
|
||||||
|
return WPAD_PRO_STICK_L_EMULATION_UP;
|
||||||
|
}
|
||||||
|
if (status->pro.leftStick.y < -0.7f) {
|
||||||
|
return WPAD_PRO_STICK_L_EMULATION_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status->pro.rightStick.x > 0.7f) {
|
||||||
|
return WPAD_PRO_STICK_R_EMULATION_RIGHT;
|
||||||
|
}
|
||||||
|
if (status->pro.rightStick.x < -0.7f) {
|
||||||
|
return WPAD_PRO_STICK_R_EMULATION_LEFT;
|
||||||
|
}
|
||||||
|
if (status->pro.rightStick.y > 0.7f) {
|
||||||
|
return WPAD_PRO_STICK_R_EMULATION_UP;
|
||||||
|
}
|
||||||
|
if (status->pro.rightStick.y < -0.7f) {
|
||||||
|
return WPAD_PRO_STICK_R_EMULATION_DOWN;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WPAD_EXT_CLASSIC:
|
||||||
|
case WPAD_EXT_MPLUS_CLASSIC:
|
||||||
|
for (uint32_t i = WPAD_CLASSIC_BUTTON_UP; i <= WPAD_CLASSIC_STICK_R_EMULATION_UP; i <<= 1) {
|
||||||
|
if (status->classic.trigger & i) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status->classic.leftStick.x > 0.7f) {
|
||||||
|
return WPAD_CLASSIC_STICK_L_EMULATION_RIGHT;
|
||||||
|
}
|
||||||
|
if (status->classic.leftStick.x < -0.7f) {
|
||||||
|
return WPAD_CLASSIC_STICK_L_EMULATION_LEFT;
|
||||||
|
}
|
||||||
|
if (status->classic.leftStick.y > 0.7f) {
|
||||||
|
return WPAD_CLASSIC_STICK_L_EMULATION_UP;
|
||||||
|
}
|
||||||
|
if (status->classic.leftStick.y < -0.7f) {
|
||||||
|
return WPAD_CLASSIC_STICK_L_EMULATION_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status->classic.rightStick.x > 0.7f) {
|
||||||
|
return WPAD_CLASSIC_STICK_R_EMULATION_RIGHT;
|
||||||
|
}
|
||||||
|
if (status->classic.rightStick.x < -0.7f) {
|
||||||
|
return WPAD_CLASSIC_STICK_R_EMULATION_LEFT;
|
||||||
|
}
|
||||||
|
if (status->classic.rightStick.y > 0.7f) {
|
||||||
|
return WPAD_CLASSIC_STICK_R_EMULATION_UP;
|
||||||
|
}
|
||||||
|
if (status->classic.rightStick.y < -0.7f) {
|
||||||
|
return WPAD_CLASSIC_STICK_R_EMULATION_DOWN;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WPAD_EXT_NUNCHUK:
|
||||||
|
case WPAD_EXT_MPLUS_NUNCHUK:
|
||||||
|
case WPAD_EXT_MPLUS:
|
||||||
|
case WPAD_EXT_CORE:
|
||||||
|
for (uint32_t i = WPAD_BUTTON_LEFT; i <= WPAD_BUTTON_HOME; i <<= 1) {
|
||||||
|
if (status->trigger & i) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string WiiUController::GetButtonName(int32_t virtualSlot, int n64Button) {
|
||||||
|
std::map<int32_t, int32_t>& Mappings = getProfile(virtualSlot)->Mappings;
|
||||||
|
const auto find = std::find_if(Mappings.begin(), Mappings.end(), [n64Button](const std::pair<int32_t, int32_t>& pair) {
|
||||||
|
return pair.second == n64Button;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (find == Mappings.end()) return "Unknown";
|
||||||
|
|
||||||
|
uint32_t btn = find->first;
|
||||||
|
|
||||||
|
switch (extensionType) {
|
||||||
|
case WPAD_EXT_PRO_CONTROLLER:
|
||||||
|
switch (btn) {
|
||||||
|
case WPAD_PRO_BUTTON_A: return "A";
|
||||||
|
case WPAD_PRO_BUTTON_B: return "B";
|
||||||
|
case WPAD_PRO_BUTTON_X: return "X";
|
||||||
|
case WPAD_PRO_BUTTON_Y: return "Y";
|
||||||
|
case WPAD_PRO_BUTTON_LEFT: return "D-pad Left";
|
||||||
|
case WPAD_PRO_BUTTON_RIGHT: return "D-pad Right";
|
||||||
|
case WPAD_PRO_BUTTON_UP: return "D-pad Up";
|
||||||
|
case WPAD_PRO_BUTTON_DOWN: return "D-pad Down";
|
||||||
|
case WPAD_PRO_TRIGGER_ZL: return "ZL";
|
||||||
|
case WPAD_PRO_TRIGGER_ZR: return "ZR";
|
||||||
|
case WPAD_PRO_TRIGGER_L: return "L";
|
||||||
|
case WPAD_PRO_TRIGGER_R: return "R";
|
||||||
|
case WPAD_PRO_BUTTON_PLUS: return "+ (START)";
|
||||||
|
case WPAD_PRO_BUTTON_MINUS: return "- (SELECT)";
|
||||||
|
case WPAD_PRO_BUTTON_STICK_R: return "Stick Button R";
|
||||||
|
case WPAD_PRO_BUTTON_STICK_L: return "Stick Button L";
|
||||||
|
case WPAD_PRO_STICK_R_EMULATION_LEFT: return "Right Stick Left";
|
||||||
|
case WPAD_PRO_STICK_R_EMULATION_RIGHT: return "Right Stick Right";
|
||||||
|
case WPAD_PRO_STICK_R_EMULATION_UP: return "Right Stick Up";
|
||||||
|
case WPAD_PRO_STICK_R_EMULATION_DOWN: return "Right Stick Down";
|
||||||
|
case WPAD_PRO_STICK_L_EMULATION_LEFT: return "Left Stick Left";
|
||||||
|
case WPAD_PRO_STICK_L_EMULATION_RIGHT: return "Left Stick Right";
|
||||||
|
case WPAD_PRO_STICK_L_EMULATION_UP: return "Left Stick Up";
|
||||||
|
case WPAD_PRO_STICK_L_EMULATION_DOWN: return "Left Stick Down";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WPAD_EXT_CLASSIC:
|
||||||
|
case WPAD_EXT_MPLUS_CLASSIC:
|
||||||
|
switch (btn) {
|
||||||
|
case WPAD_CLASSIC_BUTTON_A: return "A";
|
||||||
|
case WPAD_CLASSIC_BUTTON_B: return "B";
|
||||||
|
case WPAD_CLASSIC_BUTTON_X: return "X";
|
||||||
|
case WPAD_CLASSIC_BUTTON_Y: return "Y";
|
||||||
|
case WPAD_CLASSIC_BUTTON_LEFT: return "D-pad Left";
|
||||||
|
case WPAD_CLASSIC_BUTTON_RIGHT: return "D-pad Right";
|
||||||
|
case WPAD_CLASSIC_BUTTON_UP: return "D-pad Up";
|
||||||
|
case WPAD_CLASSIC_BUTTON_DOWN: return "D-pad Down";
|
||||||
|
case WPAD_CLASSIC_BUTTON_ZL: return "ZL";
|
||||||
|
case WPAD_CLASSIC_BUTTON_ZR: return "ZR";
|
||||||
|
case WPAD_CLASSIC_BUTTON_L: return "L";
|
||||||
|
case WPAD_CLASSIC_BUTTON_R: return "R";
|
||||||
|
case WPAD_CLASSIC_BUTTON_PLUS: return "+ (START)";
|
||||||
|
case WPAD_CLASSIC_BUTTON_MINUS: return "- (SELECT)";
|
||||||
|
case WPAD_CLASSIC_STICK_R_EMULATION_LEFT: return "Right Stick Left";
|
||||||
|
case WPAD_CLASSIC_STICK_R_EMULATION_RIGHT: return "Right Stick Right";
|
||||||
|
case WPAD_CLASSIC_STICK_R_EMULATION_UP: return "Right Stick Up";
|
||||||
|
case WPAD_CLASSIC_STICK_R_EMULATION_DOWN: return "Right Stick Down";
|
||||||
|
case WPAD_CLASSIC_STICK_L_EMULATION_LEFT: return "Left Stick Left";
|
||||||
|
case WPAD_CLASSIC_STICK_L_EMULATION_RIGHT: return "Left Stick Right";
|
||||||
|
case WPAD_CLASSIC_STICK_L_EMULATION_UP: return "Left Stick Up";
|
||||||
|
case WPAD_CLASSIC_STICK_L_EMULATION_DOWN: return "Left Stick Down";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WPAD_EXT_NUNCHUK:
|
||||||
|
case WPAD_EXT_MPLUS_NUNCHUK:
|
||||||
|
case WPAD_EXT_MPLUS:
|
||||||
|
case WPAD_EXT_CORE:
|
||||||
|
switch (btn) {
|
||||||
|
case WPAD_BUTTON_A: return "A";
|
||||||
|
case WPAD_BUTTON_B: return "B";
|
||||||
|
case WPAD_BUTTON_1: return "1";
|
||||||
|
case WPAD_BUTTON_2: return "2";
|
||||||
|
case WPAD_BUTTON_LEFT: return "D-pad Left";
|
||||||
|
case WPAD_BUTTON_RIGHT: return "D-pad Right";
|
||||||
|
case WPAD_BUTTON_UP: return "D-pad Up";
|
||||||
|
case WPAD_BUTTON_DOWN: return "D-pad Down";
|
||||||
|
case WPAD_BUTTON_Z: return "Z";
|
||||||
|
case WPAD_BUTTON_C: return "C";
|
||||||
|
case WPAD_BUTTON_PLUS: return "+ (START)";
|
||||||
|
case WPAD_BUTTON_MINUS: return "- (SELECT)";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string WiiUController::GetControllerName() {
|
||||||
|
return controllerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiiUController::NormalizeStickAxis(int32_t virtualSlot, float x, float y, uint16_t threshold, bool isRightStick) {
|
||||||
|
auto profile = getProfile(virtualSlot);
|
||||||
|
|
||||||
|
//create scaled circular dead-zone in range {-15 ... +15}
|
||||||
|
auto len = sqrt(x * x + y * y);
|
||||||
|
if (len < threshold) {
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
else if (len > 85.0) {
|
||||||
|
len = 85.0 / len;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
len = (len - threshold) * 85.0 / (85.0 - threshold) / len;
|
||||||
|
}
|
||||||
|
x *= len;
|
||||||
|
y *= len;
|
||||||
|
|
||||||
|
//bound diagonals to an octagonal range {-68 ... +68}
|
||||||
|
if (x != 0.0 && y != 0.0) {
|
||||||
|
auto slope = y / x;
|
||||||
|
auto edgex = copysign(85.0 / (fabs(slope) + 16.0 / 69.0), x);
|
||||||
|
auto edgey = copysign(std::min(fabs(edgex * slope), 85.0 / (1.0 / fabs(slope) + 16.0 / 69.0)), y);
|
||||||
|
edgex = edgey / slope;
|
||||||
|
|
||||||
|
auto scale = sqrt(edgex * edgex + edgey * edgey) / 85.0;
|
||||||
|
x *= scale;
|
||||||
|
y *= scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRightStick) {
|
||||||
|
getRightStickX(virtualSlot) = x * profile->AxisSensitivities[2];
|
||||||
|
getRightStickY(virtualSlot) = y * profile->AxisSensitivities[3];
|
||||||
|
} else {
|
||||||
|
getLeftStickX(virtualSlot) = x * profile->AxisSensitivities[0];
|
||||||
|
getLeftStickY(virtualSlot) = y * profile->AxisSensitivities[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiiUController::CreateDefaultBinding(int32_t virtualSlot) {
|
||||||
|
auto profile = getProfile(virtualSlot);
|
||||||
|
profile->Mappings.clear();
|
||||||
|
|
||||||
|
profile->UseRumble = true;
|
||||||
|
profile->RumbleStrength = 1.0f;
|
||||||
|
profile->UseGyro = false;
|
||||||
|
|
||||||
|
switch (extensionType) {
|
||||||
|
case WPAD_EXT_PRO_CONTROLLER:
|
||||||
|
profile->Mappings[WPAD_PRO_STICK_R_EMULATION_RIGHT] = BTN_CRIGHT;
|
||||||
|
profile->Mappings[WPAD_PRO_STICK_R_EMULATION_LEFT] = BTN_CLEFT;
|
||||||
|
profile->Mappings[WPAD_PRO_STICK_R_EMULATION_DOWN] = BTN_CDOWN;
|
||||||
|
profile->Mappings[WPAD_PRO_STICK_R_EMULATION_UP] = BTN_CUP;
|
||||||
|
profile->Mappings[WPAD_PRO_TRIGGER_ZR] = BTN_R;
|
||||||
|
profile->Mappings[WPAD_PRO_TRIGGER_L] = BTN_L;
|
||||||
|
profile->Mappings[WPAD_PRO_BUTTON_RIGHT] = BTN_DRIGHT;
|
||||||
|
profile->Mappings[WPAD_PRO_BUTTON_LEFT] = BTN_DLEFT;
|
||||||
|
profile->Mappings[WPAD_PRO_BUTTON_DOWN] = BTN_DDOWN;
|
||||||
|
profile->Mappings[WPAD_PRO_BUTTON_UP] = BTN_DUP;
|
||||||
|
profile->Mappings[WPAD_PRO_BUTTON_PLUS] = BTN_START;
|
||||||
|
profile->Mappings[WPAD_PRO_TRIGGER_ZL] = BTN_Z;
|
||||||
|
profile->Mappings[WPAD_PRO_BUTTON_B] = BTN_B;
|
||||||
|
profile->Mappings[WPAD_PRO_BUTTON_A] = BTN_A;
|
||||||
|
profile->Mappings[WPAD_PRO_STICK_L_EMULATION_RIGHT] = BTN_STICKRIGHT;
|
||||||
|
profile->Mappings[WPAD_PRO_STICK_L_EMULATION_LEFT] = BTN_STICKLEFT;
|
||||||
|
profile->Mappings[WPAD_PRO_STICK_L_EMULATION_DOWN] = BTN_STICKDOWN;
|
||||||
|
profile->Mappings[WPAD_PRO_STICK_L_EMULATION_UP] = BTN_STICKUP;
|
||||||
|
break;
|
||||||
|
case WPAD_EXT_CLASSIC:
|
||||||
|
case WPAD_EXT_MPLUS_CLASSIC:
|
||||||
|
profile->Mappings[WPAD_CLASSIC_STICK_R_EMULATION_RIGHT] = BTN_CRIGHT;
|
||||||
|
profile->Mappings[WPAD_CLASSIC_STICK_R_EMULATION_LEFT] = BTN_CLEFT;
|
||||||
|
profile->Mappings[WPAD_CLASSIC_STICK_R_EMULATION_DOWN] = BTN_CDOWN;
|
||||||
|
profile->Mappings[WPAD_CLASSIC_STICK_R_EMULATION_UP] = BTN_CUP;
|
||||||
|
profile->Mappings[WPAD_CLASSIC_BUTTON_ZR] = BTN_R;
|
||||||
|
profile->Mappings[WPAD_CLASSIC_BUTTON_L] = BTN_L;
|
||||||
|
profile->Mappings[WPAD_CLASSIC_BUTTON_RIGHT] = BTN_DRIGHT;
|
||||||
|
profile->Mappings[WPAD_CLASSIC_BUTTON_LEFT] = BTN_DLEFT;
|
||||||
|
profile->Mappings[WPAD_CLASSIC_BUTTON_DOWN] = BTN_DDOWN;
|
||||||
|
profile->Mappings[WPAD_CLASSIC_BUTTON_UP] = BTN_DUP;
|
||||||
|
profile->Mappings[WPAD_CLASSIC_BUTTON_PLUS] = BTN_START;
|
||||||
|
profile->Mappings[WPAD_CLASSIC_BUTTON_ZL] = BTN_Z;
|
||||||
|
profile->Mappings[WPAD_CLASSIC_BUTTON_B] = BTN_B;
|
||||||
|
profile->Mappings[WPAD_CLASSIC_BUTTON_A] = BTN_A;
|
||||||
|
profile->Mappings[WPAD_CLASSIC_STICK_L_EMULATION_RIGHT] = BTN_STICKRIGHT;
|
||||||
|
profile->Mappings[WPAD_CLASSIC_STICK_L_EMULATION_LEFT] = BTN_STICKLEFT;
|
||||||
|
profile->Mappings[WPAD_CLASSIC_STICK_L_EMULATION_DOWN] = BTN_STICKDOWN;
|
||||||
|
profile->Mappings[WPAD_CLASSIC_STICK_L_EMULATION_UP] = BTN_STICKUP;
|
||||||
|
break;
|
||||||
|
case WPAD_EXT_NUNCHUK:
|
||||||
|
case WPAD_EXT_MPLUS_NUNCHUK:
|
||||||
|
case WPAD_EXT_MPLUS:
|
||||||
|
case WPAD_EXT_CORE:
|
||||||
|
profile->Mappings[WPAD_BUTTON_1] = BTN_R;
|
||||||
|
profile->Mappings[WPAD_BUTTON_2] = BTN_L;
|
||||||
|
profile->Mappings[WPAD_BUTTON_RIGHT] = BTN_DRIGHT;
|
||||||
|
profile->Mappings[WPAD_BUTTON_LEFT] = BTN_DLEFT;
|
||||||
|
profile->Mappings[WPAD_BUTTON_DOWN] = BTN_DDOWN;
|
||||||
|
profile->Mappings[WPAD_BUTTON_UP] = BTN_DUP;
|
||||||
|
profile->Mappings[WPAD_BUTTON_PLUS] = BTN_START;
|
||||||
|
profile->Mappings[WPAD_BUTTON_MINUS] = BTN_Z;
|
||||||
|
profile->Mappings[WPAD_BUTTON_B] = BTN_B;
|
||||||
|
profile->Mappings[WPAD_BUTTON_A] = BTN_A;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
profile->AxisSensitivities[i] = 1.0f;
|
||||||
|
profile->AxisDeadzones[i] = 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string WiiUController::GetControllerExtensionName() {
|
||||||
|
switch (extensionType) {
|
||||||
|
case WPAD_EXT_PRO_CONTROLLER:
|
||||||
|
return "ProController";
|
||||||
|
case WPAD_EXT_CLASSIC:
|
||||||
|
case WPAD_EXT_MPLUS_CLASSIC:
|
||||||
|
return "ClassicController";
|
||||||
|
case WPAD_EXT_NUNCHUK:
|
||||||
|
case WPAD_EXT_MPLUS_NUNCHUK:
|
||||||
|
case WPAD_EXT_MPLUS:
|
||||||
|
case WPAD_EXT_CORE:
|
||||||
|
return "WiiRemote";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Controller";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
38
libultraship/libultraship/WiiUController.h
Normal file
38
libultraship/libultraship/WiiUController.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Controller.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <padscore/wpad.h>
|
||||||
|
|
||||||
|
namespace Ship {
|
||||||
|
class WiiUController : public Controller {
|
||||||
|
public:
|
||||||
|
WiiUController(WPADChan chan);
|
||||||
|
bool Open();
|
||||||
|
void Close();
|
||||||
|
|
||||||
|
void ReadFromSource(int32_t virtualSlot) override;
|
||||||
|
void WriteToSource(int32_t virtualSlot, ControllerCallback* controller) override;
|
||||||
|
bool Connected() const override { return connected; };
|
||||||
|
bool CanGyro() const override { return false; }
|
||||||
|
bool CanRumble() const override { return true; };
|
||||||
|
|
||||||
|
void ClearRawPress() override;
|
||||||
|
int32_t ReadRawPress() override;
|
||||||
|
|
||||||
|
const std::string GetButtonName(int32_t virtualSlot, int n64Button) override;
|
||||||
|
const std::string GetControllerName() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void NormalizeStickAxis(int32_t virtualSlot, float x, float y, uint16_t threshold, bool isRightStick);
|
||||||
|
void CreateDefaultBinding(int32_t virtualSlot) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string GetControllerExtensionName();
|
||||||
|
std::string controllerName;
|
||||||
|
|
||||||
|
bool connected;
|
||||||
|
WPADChan chan;
|
||||||
|
WPADExtensionType extensionType;
|
||||||
|
};
|
||||||
|
}
|
329
libultraship/libultraship/WiiUGamepad.cpp
Normal file
329
libultraship/libultraship/WiiUGamepad.cpp
Normal file
@ -0,0 +1,329 @@
|
|||||||
|
#ifdef __WIIU__
|
||||||
|
#include "WiiUGamepad.h"
|
||||||
|
#include "GlobalCtx2.h"
|
||||||
|
#include "ImGuiImpl.h"
|
||||||
|
|
||||||
|
#include "WiiUImpl.h"
|
||||||
|
|
||||||
|
namespace Ship {
|
||||||
|
WiiUGamepad::WiiUGamepad() : Controller(), connected(true), rumblePatternStrength(1.0f) {
|
||||||
|
memset(rumblePattern, 0xff, sizeof(rumblePattern));
|
||||||
|
|
||||||
|
GUID = "WiiUGamepad";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WiiUGamepad::Open() {
|
||||||
|
VPADReadError error;
|
||||||
|
VPADStatus* status = Ship::WiiU::GetVPADStatus(&error);
|
||||||
|
if (!status || error == VPAD_READ_INVALID_CONTROLLER) {
|
||||||
|
Close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiiUGamepad::Close() {
|
||||||
|
connected = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAXCONTROLLERS; i++) {
|
||||||
|
getPressedButtons(i) = 0;
|
||||||
|
getLeftStickX(i) = 0;
|
||||||
|
getLeftStickY(i) = 0;
|
||||||
|
getRightStickX(i) = 0;
|
||||||
|
getRightStickY(i) = 0;
|
||||||
|
getGyroX(i) = 0;
|
||||||
|
getGyroY(i) = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiiUGamepad::ReadFromSource(int32_t virtualSlot) {
|
||||||
|
auto profile = getProfile(virtualSlot);
|
||||||
|
|
||||||
|
VPADReadError error;
|
||||||
|
VPADStatus* status = Ship::WiiU::GetVPADStatus(&error);
|
||||||
|
if (!status) {
|
||||||
|
Close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPressedButtons(virtualSlot) = 0;
|
||||||
|
getLeftStickX(virtualSlot) = 0;
|
||||||
|
getLeftStickY(virtualSlot) = 0;
|
||||||
|
getRightStickX(virtualSlot) = 0;
|
||||||
|
getRightStickY(virtualSlot) = 0;
|
||||||
|
getGyroX(virtualSlot) = 0;
|
||||||
|
getGyroY(virtualSlot) = 0;
|
||||||
|
|
||||||
|
if (error != VPAD_READ_SUCCESS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t stickX = 0;
|
||||||
|
int16_t stickY = 0;
|
||||||
|
int16_t camX = 0;
|
||||||
|
int16_t camY = 0;
|
||||||
|
|
||||||
|
for (uint32_t i = VPAD_BUTTON_SYNC; i <= VPAD_STICK_L_EMULATION_LEFT; i <<= 1) {
|
||||||
|
if (profile->Mappings.contains(i)) {
|
||||||
|
// check if the stick is mapped to an analog stick
|
||||||
|
if (i >= VPAD_STICK_R_EMULATION_DOWN) {
|
||||||
|
float axisX = i >= VPAD_STICK_L_EMULATION_DOWN ? status->leftStick.x : status->rightStick.x;
|
||||||
|
float axisY = i >= VPAD_STICK_L_EMULATION_DOWN ? status->leftStick.y : status->rightStick.y;
|
||||||
|
|
||||||
|
if (profile->Mappings[i] == BTN_STICKRIGHT || profile->Mappings[i] == BTN_STICKLEFT) {
|
||||||
|
stickX = axisX * 85;
|
||||||
|
continue;
|
||||||
|
} else if (profile->Mappings[i] == BTN_STICKDOWN || profile->Mappings[i] == BTN_STICKUP) {
|
||||||
|
stickY = axisY * 85;
|
||||||
|
continue;
|
||||||
|
} else if (profile->Mappings[i] == BTN_VSTICKRIGHT || profile->Mappings[i] == BTN_VSTICKLEFT) {
|
||||||
|
camX = axisX * 85;
|
||||||
|
continue;
|
||||||
|
} else if (profile->Mappings[i] == BTN_VSTICKDOWN || profile->Mappings[i] == BTN_VSTICKUP) {
|
||||||
|
camY = axisY * 85;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status->hold & i) {
|
||||||
|
getPressedButtons(virtualSlot) |= profile->Mappings[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stickX || stickY) {
|
||||||
|
NormalizeStickAxis(virtualSlot, stickX, stickY, profile->AxisDeadzones[0], false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (camX || camY) {
|
||||||
|
NormalizeStickAxis(virtualSlot, camX, camY, profile->AxisDeadzones[2], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (profile->UseGyro) {
|
||||||
|
float gyroX = status->gyro.x * -8.0f;
|
||||||
|
float gyroY = status->gyro.z * 8.0f;
|
||||||
|
|
||||||
|
float gyro_drift_x = profile->GyroData[DRIFT_X] / 100.0f;
|
||||||
|
float gyro_drift_y = profile->GyroData[DRIFT_Y] / 100.0f;
|
||||||
|
const float gyro_sensitivity = profile->GyroData[GYRO_SENSITIVITY];
|
||||||
|
|
||||||
|
if (gyro_drift_x == 0) {
|
||||||
|
gyro_drift_x = gyroX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gyro_drift_y == 0) {
|
||||||
|
gyro_drift_y = gyroY;
|
||||||
|
}
|
||||||
|
|
||||||
|
profile->GyroData[DRIFT_X] = gyro_drift_x * 100.0f;
|
||||||
|
profile->GyroData[DRIFT_Y] = gyro_drift_y * 100.0f;
|
||||||
|
|
||||||
|
getGyroX(virtualSlot) = gyroX - gyro_drift_x;
|
||||||
|
getGyroY(virtualSlot) = gyroY - gyro_drift_y;
|
||||||
|
|
||||||
|
getGyroX(virtualSlot) *= gyro_sensitivity;
|
||||||
|
getGyroY(virtualSlot) *= gyro_sensitivity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiiUGamepad::WriteToSource(int32_t virtualSlot, ControllerCallback* controller) {
|
||||||
|
auto profile = getProfile(virtualSlot);
|
||||||
|
|
||||||
|
if (profile->UseRumble) {
|
||||||
|
int patternSize = sizeof(rumblePattern) * 8;
|
||||||
|
|
||||||
|
// update rumble pattern if strength changed
|
||||||
|
if (rumblePatternStrength != profile->RumbleStrength) {
|
||||||
|
rumblePatternStrength = profile->RumbleStrength;
|
||||||
|
if (rumblePatternStrength > 1.0f) {
|
||||||
|
rumblePatternStrength = 1.0f;
|
||||||
|
} else if (rumblePatternStrength < 0.0f) {
|
||||||
|
rumblePatternStrength = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(rumblePattern, 0, sizeof(rumblePattern));
|
||||||
|
|
||||||
|
// distribute wanted amount of bits equally in pattern
|
||||||
|
float scale = (rumblePatternStrength * (1.0f - 0.3f)) + 0.3f;
|
||||||
|
int bitcnt = patternSize * scale;
|
||||||
|
for (int i = 0; i < bitcnt; i++) {
|
||||||
|
int bitpos = ((i * patternSize) / bitcnt) % patternSize;
|
||||||
|
rumblePattern[bitpos / 8] |= 1 << (bitpos % 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VPADControlMotor(VPAD_CHAN_0, rumblePattern, controller->rumble ? patternSize : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiiUGamepad::ClearRawPress() {
|
||||||
|
// Clear already triggered buttons
|
||||||
|
VPADReadError error;
|
||||||
|
VPADStatus* status = Ship::WiiU::GetVPADStatus(&error);
|
||||||
|
if (status) {
|
||||||
|
status->trigger = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t WiiUGamepad::ReadRawPress() {
|
||||||
|
VPADReadError error;
|
||||||
|
VPADStatus* status = Ship::WiiU::GetVPADStatus(&error);
|
||||||
|
if (!status || error != VPAD_READ_SUCCESS) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = VPAD_BUTTON_SYNC; i <= VPAD_BUTTON_STICK_L; i <<= 1) {
|
||||||
|
if (status->trigger & i) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status->leftStick.x > 0.7f) {
|
||||||
|
return VPAD_STICK_L_EMULATION_RIGHT;
|
||||||
|
}
|
||||||
|
if (status->leftStick.x < -0.7f) {
|
||||||
|
return VPAD_STICK_L_EMULATION_LEFT;
|
||||||
|
}
|
||||||
|
if (status->leftStick.y > 0.7f) {
|
||||||
|
return VPAD_STICK_L_EMULATION_UP;
|
||||||
|
}
|
||||||
|
if (status->leftStick.y < -0.7f) {
|
||||||
|
return VPAD_STICK_L_EMULATION_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status->rightStick.x > 0.7f) {
|
||||||
|
return VPAD_STICK_R_EMULATION_RIGHT;
|
||||||
|
}
|
||||||
|
if (status->rightStick.x < -0.7f) {
|
||||||
|
return VPAD_STICK_R_EMULATION_LEFT;
|
||||||
|
}
|
||||||
|
if (status->rightStick.y > 0.7f) {
|
||||||
|
return VPAD_STICK_R_EMULATION_UP;
|
||||||
|
}
|
||||||
|
if (status->rightStick.y < -0.7f) {
|
||||||
|
return VPAD_STICK_R_EMULATION_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string WiiUGamepad::GetButtonName(int32_t virtualSlot, int n64Button) {
|
||||||
|
std::map<int32_t, int32_t>& Mappings = getProfile(virtualSlot)->Mappings;
|
||||||
|
const auto find = std::find_if(Mappings.begin(), Mappings.end(), [n64Button](const std::pair<int32_t, int32_t>& pair) {
|
||||||
|
return pair.second == n64Button;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (find == Mappings.end()) return "Unknown";
|
||||||
|
|
||||||
|
uint32_t btn = find->first;
|
||||||
|
switch (btn) {
|
||||||
|
case VPAD_BUTTON_A: return "A";
|
||||||
|
case VPAD_BUTTON_B: return "B";
|
||||||
|
case VPAD_BUTTON_X: return "X";
|
||||||
|
case VPAD_BUTTON_Y: return "Y";
|
||||||
|
case VPAD_BUTTON_LEFT: return "D-pad Left";
|
||||||
|
case VPAD_BUTTON_RIGHT: return "D-pad Right";
|
||||||
|
case VPAD_BUTTON_UP: return "D-pad Up";
|
||||||
|
case VPAD_BUTTON_DOWN: return "D-pad Down";
|
||||||
|
case VPAD_BUTTON_ZL: return "ZL";
|
||||||
|
case VPAD_BUTTON_ZR: return "ZR";
|
||||||
|
case VPAD_BUTTON_L: return "L";
|
||||||
|
case VPAD_BUTTON_R: return "R";
|
||||||
|
case VPAD_BUTTON_PLUS: return "+ (START)";
|
||||||
|
case VPAD_BUTTON_MINUS: return "- (SELECT)";
|
||||||
|
case VPAD_BUTTON_STICK_R: return "Stick Button R";
|
||||||
|
case VPAD_BUTTON_STICK_L: return "Stick Button L";
|
||||||
|
case VPAD_STICK_R_EMULATION_LEFT: return "Right Stick Left";
|
||||||
|
case VPAD_STICK_R_EMULATION_RIGHT: return "Right Stick Right";
|
||||||
|
case VPAD_STICK_R_EMULATION_UP: return "Right Stick Up";
|
||||||
|
case VPAD_STICK_R_EMULATION_DOWN: return "Right Stick Down";
|
||||||
|
case VPAD_STICK_L_EMULATION_LEFT: return "Left Stick Left";
|
||||||
|
case VPAD_STICK_L_EMULATION_RIGHT: return "Left Stick Right";
|
||||||
|
case VPAD_STICK_L_EMULATION_UP: return "Left Stick Up";
|
||||||
|
case VPAD_STICK_L_EMULATION_DOWN: return "Left Stick Down";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string WiiUGamepad::GetControllerName() {
|
||||||
|
return Connected() ? "Wii U GamePad" : "Wii U GamePad (Disconnected)";
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiiUGamepad::NormalizeStickAxis(int32_t virtualSlot, float x, float y, uint16_t threshold, bool isRightStick) {
|
||||||
|
auto profile = getProfile(virtualSlot);
|
||||||
|
|
||||||
|
//create scaled circular dead-zone in range {-15 ... +15}
|
||||||
|
auto len = sqrt(x * x + y * y);
|
||||||
|
if (len < threshold) {
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
else if (len > 85.0) {
|
||||||
|
len = 85.0 / len;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
len = (len - threshold) * 85.0 / (85.0 - threshold) / len;
|
||||||
|
}
|
||||||
|
x *= len;
|
||||||
|
y *= len;
|
||||||
|
|
||||||
|
//bound diagonals to an octagonal range {-68 ... +68}
|
||||||
|
if (x != 0.0 && y != 0.0) {
|
||||||
|
auto slope = y / x;
|
||||||
|
auto edgex = copysign(85.0 / (fabs(slope) + 16.0 / 69.0), x);
|
||||||
|
auto edgey = copysign(std::min(fabs(edgex * slope), 85.0 / (1.0 / fabs(slope) + 16.0 / 69.0)), y);
|
||||||
|
edgex = edgey / slope;
|
||||||
|
|
||||||
|
auto scale = sqrt(edgex * edgex + edgey * edgey) / 85.0;
|
||||||
|
x *= scale;
|
||||||
|
y *= scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRightStick) {
|
||||||
|
getRightStickX(virtualSlot) = x * profile->AxisSensitivities[2];
|
||||||
|
getRightStickY(virtualSlot) = y * profile->AxisSensitivities[3];
|
||||||
|
} else {
|
||||||
|
getLeftStickX(virtualSlot) = x * profile->AxisSensitivities[0];
|
||||||
|
getLeftStickY(virtualSlot) = y * profile->AxisSensitivities[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WiiUGamepad::CreateDefaultBinding(int32_t virtualSlot) {
|
||||||
|
auto profile = getProfile(virtualSlot);
|
||||||
|
profile->Mappings.clear();
|
||||||
|
|
||||||
|
profile->UseRumble = true;
|
||||||
|
profile->RumbleStrength = 1.0f;
|
||||||
|
profile->UseGyro = false;
|
||||||
|
|
||||||
|
profile->Mappings[VPAD_STICK_R_EMULATION_RIGHT] = BTN_CRIGHT;
|
||||||
|
profile->Mappings[VPAD_STICK_R_EMULATION_LEFT] = BTN_CLEFT;
|
||||||
|
profile->Mappings[VPAD_STICK_R_EMULATION_DOWN] = BTN_CDOWN;
|
||||||
|
profile->Mappings[VPAD_STICK_R_EMULATION_UP] = BTN_CUP;
|
||||||
|
profile->Mappings[VPAD_BUTTON_ZR] = BTN_R;
|
||||||
|
profile->Mappings[VPAD_BUTTON_L] = BTN_L;
|
||||||
|
profile->Mappings[VPAD_BUTTON_RIGHT] = BTN_DRIGHT;
|
||||||
|
profile->Mappings[VPAD_BUTTON_LEFT] = BTN_DLEFT;
|
||||||
|
profile->Mappings[VPAD_BUTTON_DOWN] = BTN_DDOWN;
|
||||||
|
profile->Mappings[VPAD_BUTTON_UP] = BTN_DUP;
|
||||||
|
profile->Mappings[VPAD_BUTTON_PLUS] = BTN_START;
|
||||||
|
profile->Mappings[VPAD_BUTTON_ZL] = BTN_Z;
|
||||||
|
profile->Mappings[VPAD_BUTTON_B] = BTN_B;
|
||||||
|
profile->Mappings[VPAD_BUTTON_A] = BTN_A;
|
||||||
|
profile->Mappings[VPAD_STICK_L_EMULATION_RIGHT] = BTN_STICKRIGHT;
|
||||||
|
profile->Mappings[VPAD_STICK_L_EMULATION_LEFT] = BTN_STICKLEFT;
|
||||||
|
profile->Mappings[VPAD_STICK_L_EMULATION_DOWN] = BTN_STICKDOWN;
|
||||||
|
profile->Mappings[VPAD_STICK_L_EMULATION_UP] = BTN_STICKUP;
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
profile->AxisSensitivities[i] = 1.0f;
|
||||||
|
profile->AxisDeadzones[i] = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
profile->GyroData[GYRO_SENSITIVITY] = 1.0f;
|
||||||
|
profile->GyroData[DRIFT_X] = 0.0f;
|
||||||
|
profile->GyroData[DRIFT_Y] = 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
34
libultraship/libultraship/WiiUGamepad.h
Normal file
34
libultraship/libultraship/WiiUGamepad.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Controller.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Ship {
|
||||||
|
class WiiUGamepad : public Controller {
|
||||||
|
public:
|
||||||
|
WiiUGamepad();
|
||||||
|
|
||||||
|
bool Open();
|
||||||
|
void Close();
|
||||||
|
|
||||||
|
void ReadFromSource(int32_t virtualSlot) override;
|
||||||
|
void WriteToSource(int32_t virtualSlot, ControllerCallback* controller) override;
|
||||||
|
bool Connected() const override { return connected; };
|
||||||
|
bool CanGyro() const override { return true; }
|
||||||
|
bool CanRumble() const override { return true; };
|
||||||
|
|
||||||
|
void ClearRawPress() override;
|
||||||
|
int32_t ReadRawPress() override;
|
||||||
|
|
||||||
|
const std::string GetButtonName(int32_t virtualSlot, int n64Button) override;
|
||||||
|
const std::string GetControllerName() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void NormalizeStickAxis(int32_t virtualSlot, float x, float y, uint16_t threshold, bool isRightStick);
|
||||||
|
void CreateDefaultBinding(int32_t virtualSlot) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool connected = true;
|
||||||
|
float rumblePatternStrength;
|
||||||
|
uint8_t rumblePattern[15];
|
||||||
|
};
|
||||||
|
}
|
134
libultraship/libultraship/WiiUImpl.cpp
Normal file
134
libultraship/libultraship/WiiUImpl.cpp
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
#ifdef __WIIU__
|
||||||
|
#include "WiiUImpl.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/iosupport.h>
|
||||||
|
|
||||||
|
#include <whb/log.h>
|
||||||
|
#include <whb/log_udp.h>
|
||||||
|
#include <coreinit/debug.h>
|
||||||
|
|
||||||
|
#include "Window.h"
|
||||||
|
|
||||||
|
namespace Ship {
|
||||||
|
namespace WiiU {
|
||||||
|
|
||||||
|
static bool hasVpad = false;
|
||||||
|
static VPADReadError vpadError;
|
||||||
|
static VPADStatus vpadStatus;
|
||||||
|
|
||||||
|
static bool hasKpad[4] = { false };
|
||||||
|
static KPADError kpadError[4] = { KPAD_ERROR_OK };
|
||||||
|
static KPADStatus kpadStatus[4];
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
extern "C" {
|
||||||
|
void __wrap_abort() {
|
||||||
|
printf("Abort called.\n");
|
||||||
|
// force a stack trace
|
||||||
|
*(uint32_t*)0xdeadc0de = 0xcafebabe;
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t wiiu_log_write(struct _reent* r, void* fd, const char* ptr, size_t len) {
|
||||||
|
char buf[1024];
|
||||||
|
snprintf(buf, sizeof(buf), "%*.*s", len, len, ptr);
|
||||||
|
OSReport(buf);
|
||||||
|
WHBLogWritef("%*.*s", len, len, ptr);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const devoptab_t dotab_stdout = {
|
||||||
|
.name = "stdout_whb",
|
||||||
|
.write_r = wiiu_log_write,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Init() {
|
||||||
|
#ifdef _DEBUG
|
||||||
|
WHBLogUdpInit();
|
||||||
|
WHBLogPrint("Hello World!");
|
||||||
|
|
||||||
|
devoptab_list[STD_OUT] = &dotab_stdout;
|
||||||
|
devoptab_list[STD_ERR] = &dotab_stdout;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// make sure the required folders exist
|
||||||
|
mkdir("/vol/external01/wiiu/", 0755);
|
||||||
|
mkdir("/vol/external01/wiiu/apps/", 0755);
|
||||||
|
mkdir("/vol/external01/wiiu/apps/soh/", 0755);
|
||||||
|
|
||||||
|
chdir("/vol/external01/wiiu/apps/soh/");
|
||||||
|
|
||||||
|
KPADInit();
|
||||||
|
WPADEnableURCC(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Exit() {
|
||||||
|
KPADShutdown();
|
||||||
|
|
||||||
|
WHBLogUdpDeinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThrowMissingOTR(const char* otrPath) {
|
||||||
|
// TODO handle this better in the future
|
||||||
|
OSFatal("Main OTR file not found!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update() {
|
||||||
|
bool rescan = false;
|
||||||
|
|
||||||
|
VPADRead(VPAD_CHAN_0, &vpadStatus, 1, &vpadError);
|
||||||
|
if (vpadError == VPAD_READ_SUCCESS) {
|
||||||
|
if (!hasVpad) {
|
||||||
|
rescan = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasVpad = true;
|
||||||
|
} else if (vpadError != VPAD_READ_NO_SAMPLES) {
|
||||||
|
if (hasVpad) {
|
||||||
|
rescan = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasVpad = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
KPADReadEx((KPADChan) i, &kpadStatus[i], 1, &kpadError[i]);
|
||||||
|
if (kpadError[i] == KPAD_ERROR_OK && kpadStatus[i].extensionType != 255) {
|
||||||
|
if (!hasKpad[i]) {
|
||||||
|
rescan = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasKpad[i] = true;
|
||||||
|
} else if (kpadError[i] != KPAD_ERROR_NO_SAMPLES) {
|
||||||
|
if (hasKpad[i]) {
|
||||||
|
rescan = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasKpad[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rescan devices if connection state changed
|
||||||
|
if (rescan) {
|
||||||
|
Ship::GlobalCtx2::GetInstance()->GetWindow()->GetControlDeck()->ScanPhysicalDevices();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VPADStatus *GetVPADStatus(VPADReadError *error) {
|
||||||
|
*error = vpadError;
|
||||||
|
return hasVpad ? &vpadStatus : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
KPADStatus *GetKPADStatus(WPADChan chan, KPADError *error) {
|
||||||
|
*error = kpadError[chan];
|
||||||
|
return hasKpad[chan] ? &kpadStatus[chan] : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
22
libultraship/libultraship/WiiUImpl.h
Normal file
22
libultraship/libultraship/WiiUImpl.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vpad/input.h>
|
||||||
|
#include <padscore/kpad.h>
|
||||||
|
|
||||||
|
namespace Ship {
|
||||||
|
namespace WiiU {
|
||||||
|
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
void Exit();
|
||||||
|
|
||||||
|
void ThrowMissingOTR(const char* otrPath);
|
||||||
|
|
||||||
|
void Update();
|
||||||
|
|
||||||
|
VPADStatus *GetVPADStatus(VPADReadError *error);
|
||||||
|
|
||||||
|
KPADStatus *GetKPADStatus(WPADChan chan, KPADError *error);
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
@ -33,6 +33,7 @@ extern "C" {
|
|||||||
int32_t osContInit(OSMesgQueue* mq, uint8_t* controllerBits, OSContStatus* status) {
|
int32_t osContInit(OSMesgQueue* mq, uint8_t* controllerBits, OSContStatus* status) {
|
||||||
*controllerBits = 0;
|
*controllerBits = 0;
|
||||||
|
|
||||||
|
#ifndef __WIIU__
|
||||||
if (SDL_Init(SDL_INIT_GAMECONTROLLER) != 0) {
|
if (SDL_Init(SDL_INIT_GAMECONTROLLER) != 0) {
|
||||||
SPDLOG_ERROR("Failed to initialize SDL game controllers ({})", SDL_GetError());
|
SPDLOG_ERROR("Failed to initialize SDL game controllers ({})", SDL_GetError());
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -46,6 +47,7 @@ extern "C" {
|
|||||||
} else {
|
} else {
|
||||||
SPDLOG_ERROR("Failed add SDL game controller mappings from \"{}\" ({})", controllerDb, SDL_GetError());
|
SPDLOG_ERROR("Failed add SDL game controller mappings from \"{}\" ({})", controllerDb, SDL_GetError());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Ship::GlobalCtx2::GetInstance()->GetWindow()->GetControlDeck()->Init(controllerBits);
|
Ship::GlobalCtx2::GetInstance()->GetWindow()->GetControlDeck()->Init(controllerBits);
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
#include "Lib/Fast3D/gfx_opengl.h"
|
#include "Lib/Fast3D/gfx_opengl.h"
|
||||||
#include "Lib/Fast3D/gfx_direct3d11.h"
|
#include "Lib/Fast3D/gfx_direct3d11.h"
|
||||||
#include "Lib/Fast3D/gfx_direct3d12.h"
|
#include "Lib/Fast3D/gfx_direct3d12.h"
|
||||||
|
#include "Lib/Fast3D/gfx_wiiu.h"
|
||||||
|
#include "Lib/Fast3D/gfx_gx2.h"
|
||||||
#include "Lib/Fast3D/gfx_window_manager_api.h"
|
#include "Lib/Fast3D/gfx_window_manager_api.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -38,6 +40,10 @@ void SetWindowManager(struct GfxWindowManagerAPI** WmApi, struct GfxRenderingAPI
|
|||||||
*RenderingApi = &gfx_direct3d11_api;
|
*RenderingApi = &gfx_direct3d11_api;
|
||||||
*WmApi = &gfx_dxgi_api;
|
*WmApi = &gfx_dxgi_api;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef __WIIU__
|
||||||
|
*RenderingApi = &gfx_gx2_api;
|
||||||
|
*WmApi = &gfx_wiiu;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Config can override
|
// Config can override
|
||||||
#ifdef ENABLE_DX11
|
#ifdef ENABLE_DX11
|
||||||
|
4
scripts/wiiu/build.sh
Executable file
4
scripts/wiiu/build.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cmake -H. -Bbuild-wiiu -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/WiiU.cmake -DCMAKE_BUILD_TYPE:STRING=Release
|
||||||
|
cmake --build build-wiiu --target soh --config Release
|
@ -1696,9 +1696,20 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
|||||||
STORMLIB_NO_AUTO_LINK
|
STORMLIB_NO_AUTO_LINK
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
elseif (CMAKE_SYSTEM_NAME STREQUAL "CafeOS")
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|Clang|AppleClang")
|
"$<$<CONFIG:Debug>:"
|
||||||
|
"_DEBUG"
|
||||||
|
">"
|
||||||
|
"$<$<CONFIG:Release>:"
|
||||||
|
"NDEBUG"
|
||||||
|
">"
|
||||||
|
"SPDLOG_ACTIVE_LEVEL=3;"
|
||||||
|
"SPDLOG_NO_THREAD_ID;"
|
||||||
|
"SPDLOG_NO_TLS;"
|
||||||
|
"STBI_NO_THREAD_LOCALS;"
|
||||||
|
)
|
||||||
|
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|Clang|AppleClang")
|
||||||
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
||||||
"$<$<CONFIG:Debug>:"
|
"$<$<CONFIG:Debug>:"
|
||||||
"_DEBUG"
|
"_DEBUG"
|
||||||
@ -1825,6 +1836,26 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
|
|||||||
target_link_options(${PROJECT_NAME} PRIVATE
|
target_link_options(${PROJECT_NAME} PRIVATE
|
||||||
-pthread
|
-pthread
|
||||||
)
|
)
|
||||||
|
elseif (CMAKE_SYSTEM_NAME STREQUAL "CafeOS")
|
||||||
|
target_compile_options(${PROJECT_NAME} PRIVATE
|
||||||
|
-O2
|
||||||
|
|
||||||
|
# disable some warnings to not clutter output
|
||||||
|
-Wno-multichar
|
||||||
|
-Wno-return-type
|
||||||
|
-Wno-narrowing
|
||||||
|
-Wno-switch-outside-range
|
||||||
|
$<$<COMPILE_LANGUAGE:C>:
|
||||||
|
-Wno-incompatible-pointer-types
|
||||||
|
-Wno-discarded-array-qualifiers
|
||||||
|
-Wno-discarded-qualifiers
|
||||||
|
-Wno-int-conversion
|
||||||
|
-Wno-implicit-function-declaration
|
||||||
|
-Wno-builtin-declaration-mismatch
|
||||||
|
-Wno-switch-unreachable
|
||||||
|
-Wno-stringop-overflow
|
||||||
|
>
|
||||||
|
)
|
||||||
else()
|
else()
|
||||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
|
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64")
|
||||||
set(CPU_OPTION -msse2 -mfpmath=sse)
|
set(CPU_OPTION -msse2 -mfpmath=sse)
|
||||||
@ -1908,6 +1939,18 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "NintendoSwitch")
|
|||||||
-lglad
|
-lglad
|
||||||
Threads::Threads
|
Threads::Threads
|
||||||
)
|
)
|
||||||
|
elseif(CMAKE_SYSTEM_NAME STREQUAL "CafeOS")
|
||||||
|
find_package(SDL2 REQUIRED)
|
||||||
|
set(ADDITIONAL_LIBRARY_DEPENDENCIES
|
||||||
|
"libultraship;"
|
||||||
|
"ZAPDUtils;"
|
||||||
|
SDL2::SDL2-static
|
||||||
|
|
||||||
|
"$<$<CONFIG:Debug>:-Wl,--wrap=abort>"
|
||||||
|
)
|
||||||
|
target_include_directories(${PROJECT_NAME} PRIVATE
|
||||||
|
${DEVKITPRO}/portlibs/wiiu/include/
|
||||||
|
)
|
||||||
else()
|
else()
|
||||||
find_package(SDL2)
|
find_package(SDL2)
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
@ -1961,7 +2004,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT CMAKE_SYSTEM_NAME STREQUAL "NintendoSwitch")
|
if(NOT CMAKE_SYSTEM_NAME MATCHES "NintendoSwitch|CafeOS")
|
||||||
INSTALL(TARGETS soh DESTINATION . COMPONENT ship)
|
INSTALL(TARGETS soh DESTINATION . COMPONENT ship)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -1970,7 +2013,7 @@ execute_process(COMMAND ${CURL} -sSfL https://raw.githubusercontent.com/gabomdq/
|
|||||||
|
|
||||||
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
|
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
|
||||||
INSTALL(FILES ${CMAKE_BINARY_DIR}/gamecontrollerdb.txt DESTINATION ../MacOS COMPONENT ship)
|
INSTALL(FILES ${CMAKE_BINARY_DIR}/gamecontrollerdb.txt DESTINATION ../MacOS COMPONENT ship)
|
||||||
elseif(NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "NintendoSwitch")
|
elseif(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "NintendoSwitch|CafeOS")
|
||||||
INSTALL(FILES ${CMAKE_BINARY_DIR}/gamecontrollerdb.txt DESTINATION . COMPONENT ship)
|
INSTALL(FILES ${CMAKE_BINARY_DIR}/gamecontrollerdb.txt DESTINATION . COMPONENT ship)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -1982,9 +2025,9 @@ install(CODE "
|
|||||||
")
|
")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME STREQUAL "NintendoSwitch")
|
if(CMAKE_SYSTEM_NAME MATCHES "NintendoSwitch|CafeOS")
|
||||||
if (NOT TARGET pathconf)
|
if (NOT TARGET pathconf)
|
||||||
add_library(pathconf OBJECT switch/pathconf.c)
|
add_library(pathconf OBJECT platform/pathconf.c)
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE "${ADDITIONAL_LIBRARY_DEPENDENCIES}" $<TARGET_OBJECTS:pathconf> )
|
target_link_libraries(${PROJECT_NAME} PRIVATE "${ADDITIONAL_LIBRARY_DEPENDENCIES}" $<TARGET_OBJECTS:pathconf> )
|
||||||
else()
|
else()
|
||||||
@ -2006,4 +2049,10 @@ nx_create_nro(soh
|
|||||||
|
|
||||||
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/soh.nro DESTINATION . COMPONENT ship)
|
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/soh.nro DESTINATION . COMPONENT ship)
|
||||||
|
|
||||||
|
elseif(CMAKE_SYSTEM_NAME MATCHES "CafeOS")
|
||||||
|
|
||||||
|
wut_create_rpx(${PROJECT_NAME})
|
||||||
|
|
||||||
|
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/soh.rpx DESTINATION . COMPONENT ship)
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
@ -60,7 +60,9 @@ void Locale_ResetRegion(void);
|
|||||||
u32 func_80001F48(void);
|
u32 func_80001F48(void);
|
||||||
u32 func_80001F8C(void);
|
u32 func_80001F8C(void);
|
||||||
u32 Locale_IsRegionNative(void);
|
u32 Locale_IsRegionNative(void);
|
||||||
#if !defined(__APPLE__) && !defined(__SWITCH__)
|
#ifdef __WIIU__
|
||||||
|
void _assert(const char* exp, const char* file, s32 line);
|
||||||
|
#elif !defined(__APPLE__) && !defined(__SWITCH__)
|
||||||
void __assert(const char* exp, const char* file, s32 line);
|
void __assert(const char* exp, const char* file, s32 line);
|
||||||
#endif
|
#endif
|
||||||
#if defined(__APPLE__) && defined(NDEBUG)
|
#if defined(__APPLE__) && defined(NDEBUG)
|
||||||
|
@ -233,7 +233,11 @@ extern GraphicsContext* __gfxCtx;
|
|||||||
|
|
||||||
#define VTX_T(x,y,z,s,t,cr,cg,cb,a) { { x, y, z }, 0, { s, t }, { cr, cg, cb, a } }
|
#define VTX_T(x,y,z,s,t,cr,cg,cb,a) { { x, y, z }, 0, { s, t }, { cr, cg, cb, a } }
|
||||||
|
|
||||||
|
#ifdef __WIIU__
|
||||||
|
#define ASSERT(expression) (void)((!!(expression)) || (_assert(#expression, __FILE__, (unsigned)(__LINE__)), 0))
|
||||||
|
#else
|
||||||
#define ASSERT(expression) (void)((!!(expression)) || (__assert(#expression, __FILE__, (unsigned)(__LINE__)), 0))
|
#define ASSERT(expression) (void)((!!(expression)) || (__assert(#expression, __FILE__, (unsigned)(__LINE__)), 0))
|
||||||
|
#endif
|
||||||
|
|
||||||
#define gDPSetTileCustom(pkt, fmt, siz, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
|
#define gDPSetTileCustom(pkt, fmt, siz, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
|
||||||
do { \
|
do { \
|
||||||
|
@ -49,6 +49,8 @@
|
|||||||
|
|
||||||
#ifdef __SWITCH__
|
#ifdef __SWITCH__
|
||||||
#include "SwitchImpl.h"
|
#include "SwitchImpl.h"
|
||||||
|
#elif defined(__WIIU__)
|
||||||
|
#include "WiiUImpl.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <Audio.h>
|
#include <Audio.h>
|
||||||
@ -171,6 +173,8 @@ extern "C" void OTRExtScanner() {
|
|||||||
extern "C" void InitOTR() {
|
extern "C" void InitOTR() {
|
||||||
#ifdef __SWITCH__
|
#ifdef __SWITCH__
|
||||||
Ship::Switch::Init(Ship::PreInitPhase);
|
Ship::Switch::Init(Ship::PreInitPhase);
|
||||||
|
#elif defined(__WIIU__)
|
||||||
|
Ship::WiiU::Init();
|
||||||
#endif
|
#endif
|
||||||
OTRGlobals::Instance = new OTRGlobals();
|
OTRGlobals::Instance = new OTRGlobals();
|
||||||
SaveManager::Instance = new SaveManager();
|
SaveManager::Instance = new SaveManager();
|
||||||
@ -235,6 +239,7 @@ extern "C" void Graph_ProcessFrame(void (*run_one_game_iter)(void)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void Graph_StartFrame() {
|
extern "C" void Graph_StartFrame() {
|
||||||
|
#ifndef __WIIU__
|
||||||
// Why -1?
|
// Why -1?
|
||||||
int32_t dwScancode = OTRGlobals::Instance->context->GetWindow()->lastScancode;
|
int32_t dwScancode = OTRGlobals::Instance->context->GetWindow()->lastScancode;
|
||||||
OTRGlobals::Instance->context->GetWindow()->lastScancode = -1;
|
OTRGlobals::Instance->context->GetWindow()->lastScancode = -1;
|
||||||
@ -292,6 +297,7 @@ extern "C" void Graph_StartFrame() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
OTRGlobals::Instance->context->GetWindow()->StartFrame();
|
OTRGlobals::Instance->context->GetWindow()->StartFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,6 +152,12 @@ void SaveManager::Init() {
|
|||||||
// If the global save file exist, load it. Otherwise, create it.
|
// If the global save file exist, load it. Otherwise, create it.
|
||||||
if (std::filesystem::exists(sGlobalPath)) {
|
if (std::filesystem::exists(sGlobalPath)) {
|
||||||
std::ifstream input(sGlobalPath);
|
std::ifstream input(sGlobalPath);
|
||||||
|
|
||||||
|
#ifdef __WIIU__
|
||||||
|
alignas(0x40) char buffer[8192];
|
||||||
|
input.rdbuf()->pubsetbuf(buffer, sizeof(buffer));
|
||||||
|
#endif
|
||||||
|
|
||||||
nlohmann::json globalBlock;
|
nlohmann::json globalBlock;
|
||||||
input >> globalBlock;
|
input >> globalBlock;
|
||||||
|
|
||||||
@ -474,6 +480,12 @@ void SaveManager::SaveFile(int fileNum) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::ofstream output(GetFileName(fileNum));
|
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;
|
output << std::setw(4) << baseBlock << std::endl;
|
||||||
|
|
||||||
InitMeta(fileNum);
|
InitMeta(fileNum);
|
||||||
@ -486,6 +498,12 @@ void SaveManager::SaveGlobal() {
|
|||||||
globalBlock["zTargetSetting"] = gSaveContext.zTargetSetting;
|
globalBlock["zTargetSetting"] = gSaveContext.zTargetSetting;
|
||||||
globalBlock["language"] = gSaveContext.language;
|
globalBlock["language"] = gSaveContext.language;
|
||||||
std::ofstream output("Save/global.sav");
|
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;
|
output << std::setw(4) << globalBlock << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,6 +512,12 @@ void SaveManager::LoadFile(int fileNum) {
|
|||||||
InitFile(false);
|
InitFile(false);
|
||||||
|
|
||||||
std::ifstream input(GetFileName(fileNum));
|
std::ifstream input(GetFileName(fileNum));
|
||||||
|
|
||||||
|
#ifdef __WIIU__
|
||||||
|
alignas(0x40) char buffer[8192];
|
||||||
|
input.rdbuf()->pubsetbuf(buffer, sizeof(buffer));
|
||||||
|
#endif
|
||||||
|
|
||||||
nlohmann::json saveBlock;
|
nlohmann::json saveBlock;
|
||||||
input >> saveBlock;
|
input >> saveBlock;
|
||||||
if (!saveBlock.contains("version")) {
|
if (!saveBlock.contains("version")) {
|
||||||
@ -1125,10 +1149,41 @@ void SaveManager::LoadStruct(const std::string& name, LoadStructFunc func) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __WIIU__
|
||||||
|
// std::filesystem::copy_file doesn't work properly with the Wii U's toolchain atm
|
||||||
|
int copy_file(const char* src, const char* dst)
|
||||||
|
{
|
||||||
|
alignas(0x40) uint8_t buf[4096];
|
||||||
|
FILE* r = fopen(src, "r");
|
||||||
|
if (!r) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
FILE* w = fopen(dst, "w");
|
||||||
|
if (!w) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t res;
|
||||||
|
while ((res = fread(buf, 1, sizeof(buf), r)) > 0) {
|
||||||
|
if (fwrite(buf, 1, res, w) != res) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(r);
|
||||||
|
fclose(w);
|
||||||
|
return res >= 0 ? 0 : res;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void SaveManager::CopyZeldaFile(int from, int to) {
|
void SaveManager::CopyZeldaFile(int from, int to) {
|
||||||
assert(std::filesystem::exists(GetFileName(from)));
|
assert(std::filesystem::exists(GetFileName(from)));
|
||||||
DeleteZeldaFile(to);
|
DeleteZeldaFile(to);
|
||||||
|
#ifdef __WIIU__
|
||||||
|
assert(copy_file(GetFileName(from).c_str(), GetFileName(to).c_str()) == 0);
|
||||||
|
#else
|
||||||
std::filesystem::copy_file(GetFileName(from), GetFileName(to));
|
std::filesystem::copy_file(GetFileName(from), GetFileName(to));
|
||||||
|
#endif
|
||||||
fileMetaInfo[to].valid = true;
|
fileMetaInfo[to].valid = true;
|
||||||
fileMetaInfo[to].deaths = fileMetaInfo[from].deaths;
|
fileMetaInfo[to].deaths = fileMetaInfo[from].deaths;
|
||||||
for (int i = 0; i < ARRAY_COUNT(fileMetaInfo[to].playerName); i++) {
|
for (int i = 0; i < ARRAY_COUNT(fileMetaInfo[to].playerName); i++) {
|
||||||
@ -1457,6 +1512,12 @@ void SaveManager::ConvertFromUnversioned() {
|
|||||||
#define SLOT_OFFSET(index) (SRAM_HEADER_SIZE + 0x10 + (index * SLOT_SIZE))
|
#define SLOT_OFFSET(index) (SRAM_HEADER_SIZE + 0x10 + (index * SLOT_SIZE))
|
||||||
|
|
||||||
std::ifstream input("oot_save.sav", std::ios::binary);
|
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), {});
|
std::vector<char> data(std::istreambuf_iterator<char>(input), {});
|
||||||
input.close();
|
input.close();
|
||||||
|
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
#include "global.h"
|
#include "global.h"
|
||||||
|
|
||||||
#ifndef __SWITCH__
|
#ifndef __SWITCH__
|
||||||
|
#ifdef __WIIU__
|
||||||
|
void _assert(const char* exp, const char* file, s32 line) {
|
||||||
|
#else
|
||||||
void __assert(const char* exp, const char* file, s32 line) {
|
void __assert(const char* exp, const char* file, s32 line) {
|
||||||
|
#endif
|
||||||
char msg[256];
|
char msg[256];
|
||||||
|
|
||||||
osSyncPrintf("Assertion failed: %s, file %s, line %d, thread %d\n", exp, file, line, osGetThreadId(NULL));
|
osSyncPrintf("Assertion failed: %s, file %s, line %d, thread %d\n", exp, file, line, osGetThreadId(NULL));
|
||||||
|
@ -397,6 +397,16 @@ s32 CollisionPoly_LineVsPoly(CollisionPoly* poly, Vec3s* vtxList, Vec3f* posA, V
|
|||||||
(poly->normal.x * posB->x + poly->normal.y * posB->y + poly->normal.z * posB->z) * COLPOLY_NORMAL_FRAC +
|
(poly->normal.x * posB->x + poly->normal.y * posB->y + poly->normal.z * posB->z) * COLPOLY_NORMAL_FRAC +
|
||||||
plane.originDist;
|
plane.originDist;
|
||||||
|
|
||||||
|
#ifdef __WIIU__
|
||||||
|
// on some platforms this ends up as very small numbers due to rounding issues
|
||||||
|
if (IS_ZERO(planeDistA)) {
|
||||||
|
planeDistA = 0.0f;
|
||||||
|
}
|
||||||
|
if (IS_ZERO(planeDistB)) {
|
||||||
|
planeDistB = 0.0f;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
planeDistDelta = planeDistA - planeDistB;
|
planeDistDelta = planeDistA - planeDistB;
|
||||||
if ((planeDistA >= 0.0f && planeDistB >= 0.0f) || (planeDistA < 0.0f && planeDistB < 0.0f) ||
|
if ((planeDistA >= 0.0f && planeDistB >= 0.0f) || (planeDistA < 0.0f && planeDistB < 0.0f) ||
|
||||||
(chkOneFace && planeDistA < 0.0f && planeDistB > 0.0f) || IS_ZERO(planeDistDelta)) {
|
(chkOneFace && planeDistA < 0.0f && planeDistB > 0.0f) || IS_ZERO(planeDistDelta)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user