Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e0dd6e96f1 | ||
|
|
f35fd80ebe |
@@ -59,7 +59,7 @@ jobs:
|
|||||||
name: ${{ env.OS }}-${{ env.TARGET }}
|
name: ${{ env.OS }}-${{ env.TARGET }}
|
||||||
path: artifacts/
|
path: artifacts/
|
||||||
macos:
|
macos:
|
||||||
runs-on: ${{ (matrix.target == 'x86_64' && 'macos-13') || 'macos-14' }}
|
runs-on: macos-13
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
target: ["x86_64", "arm64"]
|
target: ["x86_64", "arm64"]
|
||||||
@@ -92,7 +92,7 @@ jobs:
|
|||||||
path: ${{ env.OS }}-${{ env.TARGET }}
|
path: ${{ env.OS }}-${{ env.TARGET }}
|
||||||
key: ${{ runner.os }}-${{ matrix.target }}-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}
|
key: ${{ runner.os }}-${{ matrix.target }}-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}
|
||||||
macos-universal:
|
macos-universal:
|
||||||
runs-on: macos-14
|
runs-on: macos-13
|
||||||
needs: macos
|
needs: macos
|
||||||
env:
|
env:
|
||||||
OS: macos
|
OS: macos
|
||||||
@@ -233,7 +233,7 @@ jobs:
|
|||||||
name: ${{ env.OS }}-${{ env.TARGET }}
|
name: ${{ env.OS }}-${{ env.TARGET }}
|
||||||
path: src/android/app/artifacts/
|
path: src/android/app/artifacts/
|
||||||
ios:
|
ios:
|
||||||
runs-on: macos-14
|
runs-on: macos-13
|
||||||
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||||
env:
|
env:
|
||||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||||
|
|||||||
+2
-1
@@ -74,7 +74,8 @@ CMAKE_DEPENDENT_OPTION(ENABLE_DEDICATED_ROOM "Enable generating dedicated room e
|
|||||||
option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
|
option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
|
||||||
option(ENABLE_SCRIPTING "Enable RPC server for scripting" ON)
|
option(ENABLE_SCRIPTING "Enable RPC server for scripting" ON)
|
||||||
|
|
||||||
CMAKE_DEPENDENT_OPTION(ENABLE_CUBEB "Enables the cubeb audio backend" ON "NOT IOS" OFF)
|
# TODO: cubeb currently causes issues on macOS, see: https://github.com/mozilla/cubeb/issues/771
|
||||||
|
CMAKE_DEPENDENT_OPTION(ENABLE_CUBEB "Enables the cubeb audio backend" ON "NOT APPLE" OFF)
|
||||||
option(ENABLE_OPENAL "Enables the OpenAL audio backend" ON)
|
option(ENABLE_OPENAL "Enables the OpenAL audio backend" ON)
|
||||||
|
|
||||||
CMAKE_DEPENDENT_OPTION(ENABLE_LIBUSB "Enable libusb for GameCube Adapter support" ON "NOT IOS" OFF)
|
CMAKE_DEPENDENT_OPTION(ENABLE_LIBUSB "Enable libusb for GameCube Adapter support" ON "NOT IOS" OFF)
|
||||||
|
|||||||
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+705
-774
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+414
-478
File diff suppressed because it is too large
Load Diff
Vendored
+695
-759
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+450
-517
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+397
-461
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+5
@@ -288,6 +288,11 @@ endif()
|
|||||||
target_compile_options(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT)
|
target_compile_options(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT)
|
||||||
target_link_libraries(httplib INTERFACE ${OPENSSL_LIBRARIES})
|
target_link_libraries(httplib INTERFACE ${OPENSSL_LIBRARIES})
|
||||||
|
|
||||||
|
if(ANDROID)
|
||||||
|
add_subdirectory(android-ifaddrs)
|
||||||
|
target_link_libraries(httplib INTERFACE ifaddrs)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE)
|
if (UNIX AND NOT APPLE)
|
||||||
add_subdirectory(gamemode)
|
add_subdirectory(gamemode)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
add_library(ifaddrs
|
||||||
|
ifaddrs.c
|
||||||
|
ifaddrs.h
|
||||||
|
)
|
||||||
|
|
||||||
|
create_target_directory_groups(ifaddrs)
|
||||||
|
|
||||||
|
target_include_directories(ifaddrs INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
Vendored
+600
@@ -0,0 +1,600 @@
|
|||||||
|
/*
|
||||||
|
Copyright (c) 2013, Kenneth MacKay
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ifaddrs.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <net/if_arp.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <linux/netlink.h>
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
typedef struct NetlinkList
|
||||||
|
{
|
||||||
|
struct NetlinkList *m_next;
|
||||||
|
struct nlmsghdr *m_data;
|
||||||
|
unsigned int m_size;
|
||||||
|
} NetlinkList;
|
||||||
|
|
||||||
|
static int netlink_socket(void)
|
||||||
|
{
|
||||||
|
int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||||
|
if(l_socket < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_nl l_addr;
|
||||||
|
memset(&l_addr, 0, sizeof(l_addr));
|
||||||
|
l_addr.nl_family = AF_NETLINK;
|
||||||
|
if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0)
|
||||||
|
{
|
||||||
|
close(l_socket);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return l_socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int netlink_send(int p_socket, int p_request)
|
||||||
|
{
|
||||||
|
char l_buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))];
|
||||||
|
memset(l_buffer, 0, sizeof(l_buffer));
|
||||||
|
struct nlmsghdr *l_hdr = (struct nlmsghdr *)l_buffer;
|
||||||
|
struct rtgenmsg *l_msg = (struct rtgenmsg *)NLMSG_DATA(l_hdr);
|
||||||
|
|
||||||
|
l_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*l_msg));
|
||||||
|
l_hdr->nlmsg_type = p_request;
|
||||||
|
l_hdr->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
|
||||||
|
l_hdr->nlmsg_pid = 0;
|
||||||
|
l_hdr->nlmsg_seq = p_socket;
|
||||||
|
l_msg->rtgen_family = AF_UNSPEC;
|
||||||
|
|
||||||
|
struct sockaddr_nl l_addr;
|
||||||
|
memset(&l_addr, 0, sizeof(l_addr));
|
||||||
|
l_addr.nl_family = AF_NETLINK;
|
||||||
|
return (sendto(p_socket, l_hdr, l_hdr->nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int netlink_recv(int p_socket, void *p_buffer, size_t p_len)
|
||||||
|
{
|
||||||
|
struct msghdr l_msg;
|
||||||
|
struct iovec l_iov = { p_buffer, p_len };
|
||||||
|
struct sockaddr_nl l_addr;
|
||||||
|
int l_result;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
l_msg.msg_name = (void *)&l_addr;
|
||||||
|
l_msg.msg_namelen = sizeof(l_addr);
|
||||||
|
l_msg.msg_iov = &l_iov;
|
||||||
|
l_msg.msg_iovlen = 1;
|
||||||
|
l_msg.msg_control = NULL;
|
||||||
|
l_msg.msg_controllen = 0;
|
||||||
|
l_msg.msg_flags = 0;
|
||||||
|
int l_result = recvmsg(p_socket, &l_msg, 0);
|
||||||
|
|
||||||
|
if(l_result < 0)
|
||||||
|
{
|
||||||
|
if(errno == EINTR)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(l_msg.msg_flags & MSG_TRUNC)
|
||||||
|
{ // buffer was too small
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return l_result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done)
|
||||||
|
{
|
||||||
|
size_t l_size = 4096;
|
||||||
|
void *l_buffer = NULL;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
free(l_buffer);
|
||||||
|
l_buffer = malloc(l_size);
|
||||||
|
|
||||||
|
int l_read = netlink_recv(p_socket, l_buffer, l_size);
|
||||||
|
*p_size = l_read;
|
||||||
|
if(l_read == -2)
|
||||||
|
{
|
||||||
|
free(l_buffer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(l_read >= 0)
|
||||||
|
{
|
||||||
|
pid_t l_pid = getpid();
|
||||||
|
struct nlmsghdr *l_hdr;
|
||||||
|
for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read))
|
||||||
|
{
|
||||||
|
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(l_hdr->nlmsg_type == NLMSG_DONE)
|
||||||
|
{
|
||||||
|
*p_done = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(l_hdr->nlmsg_type == NLMSG_ERROR)
|
||||||
|
{
|
||||||
|
free(l_buffer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return l_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
l_size *= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size)
|
||||||
|
{
|
||||||
|
NetlinkList *l_item = malloc(sizeof(NetlinkList));
|
||||||
|
l_item->m_next = NULL;
|
||||||
|
l_item->m_data = p_data;
|
||||||
|
l_item->m_size = p_size;
|
||||||
|
return l_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void freeResultList(NetlinkList *p_list)
|
||||||
|
{
|
||||||
|
NetlinkList *l_cur;
|
||||||
|
while(p_list)
|
||||||
|
{
|
||||||
|
l_cur = p_list;
|
||||||
|
p_list = p_list->m_next;
|
||||||
|
free(l_cur->m_data);
|
||||||
|
free(l_cur);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static NetlinkList *getResultList(int p_socket, int p_request)
|
||||||
|
{
|
||||||
|
if(netlink_send(p_socket, p_request) < 0)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetlinkList *l_list = NULL;
|
||||||
|
NetlinkList *l_end = NULL;
|
||||||
|
int l_size;
|
||||||
|
int l_done = 0;
|
||||||
|
while(!l_done)
|
||||||
|
{
|
||||||
|
struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done);
|
||||||
|
if(!l_hdr)
|
||||||
|
{ // error
|
||||||
|
freeResultList(l_list);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetlinkList *l_item = newListItem(l_hdr, l_size);
|
||||||
|
if(!l_list)
|
||||||
|
{
|
||||||
|
l_list = l_item;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
l_end->m_next = l_item;
|
||||||
|
}
|
||||||
|
l_end = l_item;
|
||||||
|
}
|
||||||
|
return l_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t maxSize(size_t a, size_t b)
|
||||||
|
{
|
||||||
|
return (a > b ? a : b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t calcAddrLen(sa_family_t p_family, int p_dataSize)
|
||||||
|
{
|
||||||
|
switch(p_family)
|
||||||
|
{
|
||||||
|
case AF_INET:
|
||||||
|
return sizeof(struct sockaddr_in);
|
||||||
|
case AF_INET6:
|
||||||
|
return sizeof(struct sockaddr_in6);
|
||||||
|
case AF_PACKET:
|
||||||
|
return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize);
|
||||||
|
default:
|
||||||
|
return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size)
|
||||||
|
{
|
||||||
|
switch(p_family)
|
||||||
|
{
|
||||||
|
case AF_INET:
|
||||||
|
memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size);
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size);
|
||||||
|
break;
|
||||||
|
case AF_PACKET:
|
||||||
|
memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size);
|
||||||
|
((struct sockaddr_ll*)p_dest)->sll_halen = p_size;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
memcpy(p_dest->sa_data, p_data, p_size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p_dest->sa_family = p_family;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry)
|
||||||
|
{
|
||||||
|
if(!*p_resultList)
|
||||||
|
{
|
||||||
|
*p_resultList = p_entry;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct ifaddrs *l_cur = *p_resultList;
|
||||||
|
while(l_cur->ifa_next)
|
||||||
|
{
|
||||||
|
l_cur = l_cur->ifa_next;
|
||||||
|
}
|
||||||
|
l_cur->ifa_next = p_entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
|
||||||
|
{
|
||||||
|
struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr);
|
||||||
|
|
||||||
|
size_t l_nameSize = 0;
|
||||||
|
size_t l_addrSize = 0;
|
||||||
|
size_t l_dataSize = 0;
|
||||||
|
|
||||||
|
size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
|
||||||
|
struct rtattr *l_rta;
|
||||||
|
for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||||
|
{
|
||||||
|
void *l_rtaData = RTA_DATA(l_rta);
|
||||||
|
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||||
|
switch(l_rta->rta_type)
|
||||||
|
{
|
||||||
|
case IFLA_ADDRESS:
|
||||||
|
case IFLA_BROADCAST:
|
||||||
|
l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize));
|
||||||
|
break;
|
||||||
|
case IFLA_IFNAME:
|
||||||
|
l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
|
||||||
|
break;
|
||||||
|
case IFLA_STATS:
|
||||||
|
l_dataSize += NLMSG_ALIGN(l_rtaSize);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize + l_dataSize);
|
||||||
|
memset(l_entry, 0, sizeof(struct ifaddrs));
|
||||||
|
l_entry->ifa_name = "";
|
||||||
|
|
||||||
|
char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
|
||||||
|
char *l_addr = l_name + l_nameSize;
|
||||||
|
char *l_data = l_addr + l_addrSize;
|
||||||
|
|
||||||
|
l_entry->ifa_flags = l_info->ifi_flags;
|
||||||
|
|
||||||
|
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
|
||||||
|
for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||||
|
{
|
||||||
|
void *l_rtaData = RTA_DATA(l_rta);
|
||||||
|
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||||
|
switch(l_rta->rta_type)
|
||||||
|
{
|
||||||
|
case IFLA_ADDRESS:
|
||||||
|
case IFLA_BROADCAST:
|
||||||
|
{
|
||||||
|
size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize);
|
||||||
|
makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
|
||||||
|
((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index;
|
||||||
|
((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type;
|
||||||
|
if(l_rta->rta_type == IFLA_ADDRESS)
|
||||||
|
{
|
||||||
|
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
|
||||||
|
}
|
||||||
|
l_addr += NLMSG_ALIGN(l_addrLen);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IFLA_IFNAME:
|
||||||
|
strncpy(l_name, l_rtaData, l_rtaDataSize);
|
||||||
|
l_name[l_rtaDataSize] = '\0';
|
||||||
|
l_entry->ifa_name = l_name;
|
||||||
|
break;
|
||||||
|
case IFLA_STATS:
|
||||||
|
memcpy(l_data, l_rtaData, l_rtaDataSize);
|
||||||
|
l_entry->ifa_data = l_data;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addToEnd(p_resultList, l_entry);
|
||||||
|
p_links[l_info->ifi_index - 1] = l_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
|
||||||
|
{
|
||||||
|
struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr);
|
||||||
|
|
||||||
|
size_t l_nameSize = 0;
|
||||||
|
size_t l_addrSize = 0;
|
||||||
|
|
||||||
|
int l_addedNetmask = 0;
|
||||||
|
|
||||||
|
size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
|
||||||
|
struct rtattr *l_rta;
|
||||||
|
for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||||
|
{
|
||||||
|
void *l_rtaData = RTA_DATA(l_rta);
|
||||||
|
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||||
|
if(l_info->ifa_family == AF_PACKET)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(l_rta->rta_type)
|
||||||
|
{
|
||||||
|
case IFA_ADDRESS:
|
||||||
|
case IFA_LOCAL:
|
||||||
|
if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask)
|
||||||
|
{ // make room for netmask
|
||||||
|
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
|
||||||
|
l_addedNetmask = 1;
|
||||||
|
}
|
||||||
|
case IFA_BROADCAST:
|
||||||
|
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
|
||||||
|
break;
|
||||||
|
case IFA_LABEL:
|
||||||
|
l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize);
|
||||||
|
memset(l_entry, 0, sizeof(struct ifaddrs));
|
||||||
|
l_entry->ifa_name = p_links[l_info->ifa_index - 1]->ifa_name;
|
||||||
|
|
||||||
|
char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
|
||||||
|
char *l_addr = l_name + l_nameSize;
|
||||||
|
|
||||||
|
l_entry->ifa_flags = l_info->ifa_flags | p_links[l_info->ifa_index - 1]->ifa_flags;
|
||||||
|
|
||||||
|
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
|
||||||
|
for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||||
|
{
|
||||||
|
void *l_rtaData = RTA_DATA(l_rta);
|
||||||
|
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||||
|
switch(l_rta->rta_type)
|
||||||
|
{
|
||||||
|
case IFA_ADDRESS:
|
||||||
|
case IFA_BROADCAST:
|
||||||
|
case IFA_LOCAL:
|
||||||
|
{
|
||||||
|
size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize);
|
||||||
|
makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
|
||||||
|
if(l_info->ifa_family == AF_INET6)
|
||||||
|
{
|
||||||
|
if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData))
|
||||||
|
{
|
||||||
|
((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(l_rta->rta_type == IFA_ADDRESS)
|
||||||
|
{ // apparently in a point-to-point network IFA_ADDRESS contains the dest address and IFA_LOCAL contains the local address
|
||||||
|
if(l_entry->ifa_addr)
|
||||||
|
{
|
||||||
|
l_entry->ifa_dstaddr = (struct sockaddr *)l_addr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(l_rta->rta_type == IFA_LOCAL)
|
||||||
|
{
|
||||||
|
if(l_entry->ifa_addr)
|
||||||
|
{
|
||||||
|
l_entry->ifa_dstaddr = l_entry->ifa_addr;
|
||||||
|
}
|
||||||
|
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
|
||||||
|
}
|
||||||
|
l_addr += NLMSG_ALIGN(l_addrLen);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IFA_LABEL:
|
||||||
|
strncpy(l_name, l_rtaData, l_rtaDataSize);
|
||||||
|
l_name[l_rtaDataSize] = '\0';
|
||||||
|
l_entry->ifa_name = l_name;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6))
|
||||||
|
{
|
||||||
|
unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128);
|
||||||
|
unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
|
||||||
|
char l_mask[16] = {0};
|
||||||
|
unsigned i;
|
||||||
|
for(i=0; i<(l_prefix/8); ++i)
|
||||||
|
{
|
||||||
|
l_mask[i] = 0xff;
|
||||||
|
}
|
||||||
|
l_mask[i] = 0xff << (8 - (l_prefix % 8));
|
||||||
|
|
||||||
|
makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8);
|
||||||
|
l_entry->ifa_netmask = (struct sockaddr *)l_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
addToEnd(p_resultList, l_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void interpret(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
|
||||||
|
{
|
||||||
|
pid_t l_pid = getpid();
|
||||||
|
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
|
||||||
|
{
|
||||||
|
unsigned int l_nlsize = p_netlinkList->m_size;
|
||||||
|
struct nlmsghdr *l_hdr;
|
||||||
|
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
|
||||||
|
{
|
||||||
|
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(l_hdr->nlmsg_type == NLMSG_DONE)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(l_hdr->nlmsg_type == RTM_NEWLINK)
|
||||||
|
{
|
||||||
|
interpretLink(l_hdr, p_links, p_resultList);
|
||||||
|
}
|
||||||
|
else if(l_hdr->nlmsg_type == RTM_NEWADDR)
|
||||||
|
{
|
||||||
|
interpretAddr(l_hdr, p_links, p_resultList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned countLinks(int p_socket, NetlinkList *p_netlinkList)
|
||||||
|
{
|
||||||
|
unsigned l_links = 0;
|
||||||
|
pid_t l_pid = getpid();
|
||||||
|
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
|
||||||
|
{
|
||||||
|
unsigned int l_nlsize = p_netlinkList->m_size;
|
||||||
|
struct nlmsghdr *l_hdr;
|
||||||
|
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
|
||||||
|
{
|
||||||
|
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(l_hdr->nlmsg_type == NLMSG_DONE)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(l_hdr->nlmsg_type == RTM_NEWLINK)
|
||||||
|
{
|
||||||
|
++l_links;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return l_links;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getifaddrs(struct ifaddrs **ifap)
|
||||||
|
{
|
||||||
|
if(!ifap)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*ifap = NULL;
|
||||||
|
|
||||||
|
int l_socket = netlink_socket();
|
||||||
|
if(l_socket < 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetlinkList *l_linkResults = getResultList(l_socket, RTM_GETLINK);
|
||||||
|
if(!l_linkResults)
|
||||||
|
{
|
||||||
|
close(l_socket);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetlinkList *l_addrResults = getResultList(l_socket, RTM_GETADDR);
|
||||||
|
if(!l_addrResults)
|
||||||
|
{
|
||||||
|
close(l_socket);
|
||||||
|
freeResultList(l_linkResults);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned l_numLinks = countLinks(l_socket, l_linkResults) + countLinks(l_socket, l_addrResults);
|
||||||
|
struct ifaddrs *l_links[l_numLinks];
|
||||||
|
memset(l_links, 0, l_numLinks * sizeof(struct ifaddrs *));
|
||||||
|
|
||||||
|
interpret(l_socket, l_linkResults, l_links, ifap);
|
||||||
|
interpret(l_socket, l_addrResults, l_links, ifap);
|
||||||
|
|
||||||
|
freeResultList(l_linkResults);
|
||||||
|
freeResultList(l_addrResults);
|
||||||
|
close(l_socket);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeifaddrs(struct ifaddrs *ifa)
|
||||||
|
{
|
||||||
|
struct ifaddrs *l_cur;
|
||||||
|
while(ifa)
|
||||||
|
{
|
||||||
|
l_cur = ifa;
|
||||||
|
ifa = ifa->ifa_next;
|
||||||
|
free(l_cur);
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+54
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 1995, 1999
|
||||||
|
* Berkeley Software Design, Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _IFADDRS_H_
|
||||||
|
#define _IFADDRS_H_
|
||||||
|
|
||||||
|
struct ifaddrs {
|
||||||
|
struct ifaddrs *ifa_next;
|
||||||
|
char *ifa_name;
|
||||||
|
unsigned int ifa_flags;
|
||||||
|
struct sockaddr *ifa_addr;
|
||||||
|
struct sockaddr *ifa_netmask;
|
||||||
|
struct sockaddr *ifa_dstaddr;
|
||||||
|
void *ifa_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This may have been defined in <net/if.h>. Note that if <net/if.h> is
|
||||||
|
* to be included it must be included before this header file.
|
||||||
|
*/
|
||||||
|
#ifndef ifa_broadaddr
|
||||||
|
#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
extern int getifaddrs(struct ifaddrs **ifap);
|
||||||
|
extern void freeifaddrs(struct ifaddrs *ifa);
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif
|
||||||
Vendored
+1
-1
Submodule externals/cubeb updated: 799e775484...48689ae7a7
Vendored
+1
-1
Submodule externals/dynarmic updated: ca0e264f4f...d333a09b3b
Vendored
+1
-1
Submodule externals/oaknut updated: 9d091109de...e6eecc3f94
+2
-2
@@ -687,8 +687,8 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
|
|||||||
1,
|
1,
|
||||||
10,
|
10,
|
||||||
"x",
|
"x",
|
||||||
IntSetting.RESOLUTION_FACTOR.key,
|
IntSetting.GRAPHICS_API.key,
|
||||||
IntSetting.RESOLUTION_FACTOR.defaultValue.toFloat()
|
IntSetting.GRAPHICS_API.defaultValue.toFloat()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
add(
|
add(
|
||||||
|
|||||||
@@ -179,8 +179,6 @@ add_executable(citra-qt
|
|||||||
qt_image_interface.h
|
qt_image_interface.h
|
||||||
util/clickable_label.cpp
|
util/clickable_label.cpp
|
||||||
util/clickable_label.h
|
util/clickable_label.h
|
||||||
util/graphics_device_info.cpp
|
|
||||||
util/graphics_device_info.h
|
|
||||||
util/sequence_dialog/sequence_dialog.cpp
|
util/sequence_dialog/sequence_dialog.cpp
|
||||||
util/sequence_dialog/sequence_dialog.h
|
util/sequence_dialog/sequence_dialog.h
|
||||||
util/spinbox.cpp
|
util/spinbox.cpp
|
||||||
@@ -189,6 +187,13 @@ add_executable(citra-qt
|
|||||||
util/util.h
|
util/util.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (ENABLE_VULKAN)
|
||||||
|
target_sources(citra-qt PRIVATE
|
||||||
|
util/vk_device_info.cpp
|
||||||
|
util/vk_device_info.h
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
file(GLOB COMPAT_LIST
|
file(GLOB COMPAT_LIST
|
||||||
${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.qrc
|
${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.qrc
|
||||||
${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json)
|
${PROJECT_BINARY_DIR}/dist/compatibility_list/compatibility_list.json)
|
||||||
|
|||||||
@@ -23,16 +23,14 @@
|
|||||||
#include "ui_configure.h"
|
#include "ui_configure.h"
|
||||||
|
|
||||||
ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, Core::System& system_,
|
ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, Core::System& system_,
|
||||||
QString gl_renderer, std::span<const QString> physical_devices,
|
std::span<const QString> physical_devices, bool enable_web_config)
|
||||||
bool enable_web_config)
|
|
||||||
: QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()}, registry{registry_},
|
: QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()}, registry{registry_},
|
||||||
system{system_}, is_powered_on{system.IsPoweredOn()},
|
system{system_}, is_powered_on{system.IsPoweredOn()},
|
||||||
general_tab{std::make_unique<ConfigureGeneral>(this)},
|
general_tab{std::make_unique<ConfigureGeneral>(this)},
|
||||||
system_tab{std::make_unique<ConfigureSystem>(system, this)},
|
system_tab{std::make_unique<ConfigureSystem>(system, this)},
|
||||||
input_tab{std::make_unique<ConfigureInput>(this)},
|
input_tab{std::make_unique<ConfigureInput>(this)},
|
||||||
hotkeys_tab{std::make_unique<ConfigureHotkeys>(this)},
|
hotkeys_tab{std::make_unique<ConfigureHotkeys>(this)},
|
||||||
graphics_tab{
|
graphics_tab{std::make_unique<ConfigureGraphics>(physical_devices, is_powered_on, this)},
|
||||||
std::make_unique<ConfigureGraphics>(gl_renderer, physical_devices, is_powered_on, this)},
|
|
||||||
enhancements_tab{std::make_unique<ConfigureEnhancements>(this)},
|
enhancements_tab{std::make_unique<ConfigureEnhancements>(this)},
|
||||||
audio_tab{std::make_unique<ConfigureAudio>(is_powered_on, this)},
|
audio_tab{std::make_unique<ConfigureAudio>(is_powered_on, this)},
|
||||||
camera_tab{std::make_unique<ConfigureCamera>(this)},
|
camera_tab{std::make_unique<ConfigureCamera>(this)},
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class ConfigureDialog : public QDialog {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, Core::System& system,
|
explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, Core::System& system,
|
||||||
QString gl_renderer, std::span<const QString> physical_devices,
|
std::span<const QString> physical_devices,
|
||||||
bool enable_web_config = true);
|
bool enable_web_config = true);
|
||||||
~ConfigureDialog() override;
|
~ConfigureDialog() override;
|
||||||
|
|
||||||
|
|||||||
@@ -12,13 +12,17 @@
|
|||||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ConfigureGraphics::ConfigureGraphics(QString gl_renderer, std::span<const QString> physical_devices,
|
ConfigureGraphics::ConfigureGraphics(std::span<const QString> physical_devices, bool is_powered_on,
|
||||||
bool is_powered_on, QWidget* parent)
|
QWidget* parent)
|
||||||
: QWidget(parent), ui(std::make_unique<Ui::ConfigureGraphics>()) {
|
: QWidget(parent), ui(std::make_unique<Ui::ConfigureGraphics>()) {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
SetupPerGameUI();
|
SetupPerGameUI();
|
||||||
|
|
||||||
|
for (const QString& name : physical_devices) {
|
||||||
|
ui->physical_device_combo->addItem(name);
|
||||||
|
}
|
||||||
|
|
||||||
ui->graphics_api_combo->setEnabled(!is_powered_on);
|
ui->graphics_api_combo->setEnabled(!is_powered_on);
|
||||||
ui->physical_device_combo->setEnabled(!is_powered_on);
|
ui->physical_device_combo->setEnabled(!is_powered_on);
|
||||||
ui->toggle_async_shaders->setEnabled(!is_powered_on);
|
ui->toggle_async_shaders->setEnabled(!is_powered_on);
|
||||||
@@ -33,15 +37,11 @@ ConfigureGraphics::ConfigureGraphics(QString gl_renderer, std::span<const QStrin
|
|||||||
graphics_api_combo_model->item(static_cast<u32>(Settings::GraphicsAPI::Software));
|
graphics_api_combo_model->item(static_cast<u32>(Settings::GraphicsAPI::Software));
|
||||||
software_item->setFlags(software_item->flags() & ~Qt::ItemIsEnabled);
|
software_item->setFlags(software_item->flags() & ~Qt::ItemIsEnabled);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ENABLE_OPENGL
|
#ifndef ENABLE_OPENGL
|
||||||
const auto opengl_item =
|
const auto opengl_item =
|
||||||
graphics_api_combo_model->item(static_cast<u32>(Settings::GraphicsAPI::OpenGL));
|
graphics_api_combo_model->item(static_cast<u32>(Settings::GraphicsAPI::OpenGL));
|
||||||
opengl_item->setFlags(opengl_item->flags() & ~Qt::ItemIsEnabled);
|
opengl_item->setFlags(opengl_item->flags() & ~Qt::ItemIsEnabled);
|
||||||
#else
|
|
||||||
ui->opengl_renderer_name_label->setText(gl_renderer);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef ENABLE_VULKAN
|
#ifndef ENABLE_VULKAN
|
||||||
const auto vulkan_item =
|
const auto vulkan_item =
|
||||||
graphics_api_combo_model->item(static_cast<u32>(Settings::GraphicsAPI::Vulkan));
|
graphics_api_combo_model->item(static_cast<u32>(Settings::GraphicsAPI::Vulkan));
|
||||||
@@ -54,10 +54,6 @@ ConfigureGraphics::ConfigureGraphics(QString gl_renderer, std::span<const QStrin
|
|||||||
|
|
||||||
ui->physical_device_combo->setVisible(false);
|
ui->physical_device_combo->setVisible(false);
|
||||||
ui->spirv_shader_gen->setVisible(false);
|
ui->spirv_shader_gen->setVisible(false);
|
||||||
} else {
|
|
||||||
for (const QString& name : physical_devices) {
|
|
||||||
ui->physical_device_combo->addItem(name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -206,24 +202,24 @@ void ConfigureGraphics::SetupPerGameUI() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureGraphics::SetPhysicalDeviceComboVisibility(int index) {
|
void ConfigureGraphics::SetPhysicalDeviceComboVisibility(int index) {
|
||||||
Settings::GraphicsAPI effective_api{};
|
bool is_visible{};
|
||||||
|
|
||||||
// When configuring per-game the physical device combo should be
|
// When configuring per-game the physical device combo should be
|
||||||
// shown either when the global api is used and that is Vulkan or
|
// shown either when the global api is used and that is Vulkan or
|
||||||
// Vulkan is set as the per-game api.
|
// Vulkan is set as the per-game api.
|
||||||
if (!Settings::IsConfiguringGlobal()) {
|
if (!Settings::IsConfiguringGlobal()) {
|
||||||
|
const auto global_graphics_api = Settings::values.graphics_api.GetValue(true);
|
||||||
const bool using_global = index == 0;
|
const bool using_global = index == 0;
|
||||||
if (using_global) {
|
if (!using_global) {
|
||||||
effective_api = Settings::values.graphics_api.GetValue(true);
|
index -= ConfigurationShared::USE_GLOBAL_OFFSET;
|
||||||
} else {
|
|
||||||
effective_api =
|
|
||||||
static_cast<Settings::GraphicsAPI>(index - ConfigurationShared::USE_GLOBAL_OFFSET);
|
|
||||||
}
|
}
|
||||||
|
const auto graphics_api = static_cast<Settings::GraphicsAPI>(index);
|
||||||
|
is_visible = (using_global && global_graphics_api == Settings::GraphicsAPI::Vulkan) ||
|
||||||
|
graphics_api == Settings::GraphicsAPI::Vulkan;
|
||||||
} else {
|
} else {
|
||||||
effective_api = static_cast<Settings::GraphicsAPI>(index);
|
const auto graphics_api = static_cast<Settings::GraphicsAPI>(index);
|
||||||
|
is_visible = graphics_api == Settings::GraphicsAPI::Vulkan;
|
||||||
}
|
}
|
||||||
|
ui->physical_device_group->setVisible(is_visible);
|
||||||
ui->physical_device_group->setVisible(effective_api == Settings::GraphicsAPI::Vulkan);
|
ui->spirv_shader_gen->setVisible(is_visible);
|
||||||
ui->spirv_shader_gen->setVisible(effective_api == Settings::GraphicsAPI::Vulkan);
|
|
||||||
ui->opengl_renderer_group->setVisible(effective_api == Settings::GraphicsAPI::OpenGL);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ class ConfigureGraphics : public QWidget {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ConfigureGraphics(QString gl_renderer, std::span<const QString> physical_devices,
|
explicit ConfigureGraphics(std::span<const QString> physical_devices, bool is_powered_on,
|
||||||
bool is_powered_on, QWidget* parent = nullptr);
|
QWidget* parent = nullptr);
|
||||||
~ConfigureGraphics() override;
|
~ConfigureGraphics() override;
|
||||||
|
|
||||||
void ApplyConfiguration();
|
void ApplyConfiguration();
|
||||||
|
|||||||
@@ -101,34 +101,6 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QWidget" name="opengl_renderer_group" native="true">
|
|
||||||
<layout class="QHBoxLayout" name="opengl_renderer_group_2">
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="opengl_renderer_label">
|
|
||||||
<property name="text">
|
|
||||||
<string>OpenGL Renderer</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="opengl_renderer_name_label"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="spirv_shader_gen">
|
<widget class="QCheckBox" name="spirv_shader_gen">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
|||||||
@@ -24,8 +24,7 @@
|
|||||||
#include "ui_configure_per_game.h"
|
#include "ui_configure_per_game.h"
|
||||||
|
|
||||||
ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const QString& file_name,
|
ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const QString& file_name,
|
||||||
QString gl_renderer, std::span<const QString> physical_devices,
|
std::span<const QString> physical_devices, Core::System& system_)
|
||||||
Core::System& system_)
|
|
||||||
: QDialog(parent), ui(std::make_unique<Ui::ConfigurePerGame>()),
|
: QDialog(parent), ui(std::make_unique<Ui::ConfigurePerGame>()),
|
||||||
filename{file_name.toStdString()}, title_id{title_id_}, system{system_} {
|
filename{file_name.toStdString()}, title_id{title_id_}, system{system_} {
|
||||||
const auto config_file_name = title_id == 0 ? std::string(FileUtil::GetFilename(filename))
|
const auto config_file_name = title_id == 0 ? std::string(FileUtil::GetFilename(filename))
|
||||||
@@ -36,8 +35,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const QString
|
|||||||
audio_tab = std::make_unique<ConfigureAudio>(is_powered_on, this);
|
audio_tab = std::make_unique<ConfigureAudio>(is_powered_on, this);
|
||||||
general_tab = std::make_unique<ConfigureGeneral>(this);
|
general_tab = std::make_unique<ConfigureGeneral>(this);
|
||||||
enhancements_tab = std::make_unique<ConfigureEnhancements>(this);
|
enhancements_tab = std::make_unique<ConfigureEnhancements>(this);
|
||||||
graphics_tab =
|
graphics_tab = std::make_unique<ConfigureGraphics>(physical_devices, is_powered_on, this);
|
||||||
std::make_unique<ConfigureGraphics>(gl_renderer, physical_devices, is_powered_on, this);
|
|
||||||
system_tab = std::make_unique<ConfigureSystem>(system, this);
|
system_tab = std::make_unique<ConfigureSystem>(system, this);
|
||||||
debug_tab = std::make_unique<ConfigureDebug>(is_powered_on, this);
|
debug_tab = std::make_unique<ConfigureDebug>(is_powered_on, this);
|
||||||
cheat_tab = std::make_unique<ConfigureCheats>(system.CheatEngine(), title_id, this);
|
cheat_tab = std::make_unique<ConfigureCheats>(system.CheatEngine(), title_id, this);
|
||||||
|
|||||||
@@ -38,8 +38,7 @@ class ConfigurePerGame : public QDialog {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ConfigurePerGame(QWidget* parent, u64 title_id_, const QString& file_name,
|
explicit ConfigurePerGame(QWidget* parent, u64 title_id_, const QString& file_name,
|
||||||
QString gl_renderer, std::span<const QString> physical_devices,
|
std::span<const QString> physical_devices, Core::System& system_);
|
||||||
Core::System& system_);
|
|
||||||
~ConfigurePerGame() override;
|
~ConfigurePerGame() override;
|
||||||
|
|
||||||
/// Loads all button configurations to settings file
|
/// Loads all button configurations to settings file
|
||||||
|
|||||||
@@ -3,14 +3,12 @@
|
|||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QFutureWatcher>
|
#include <QFutureWatcher>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QProgressDialog>
|
#include <QProgressDialog>
|
||||||
#include <QtConcurrent/QtConcurrentMap>
|
#include <QtConcurrent/QtConcurrentMap>
|
||||||
#include "citra_qt/configuration/configuration_shared.h"
|
#include "citra_qt/configuration/configuration_shared.h"
|
||||||
#include "citra_qt/configuration/configure_system.h"
|
#include "citra_qt/configuration/configure_system.h"
|
||||||
#include "common/file_util.h"
|
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
@@ -238,32 +236,6 @@ ConfigureSystem::ConfigureSystem(Core::System& system_, QWidget* parent)
|
|||||||
&ConfigureSystem::RefreshConsoleID);
|
&ConfigureSystem::RefreshConsoleID);
|
||||||
connect(ui->button_start_download, &QPushButton::clicked, this,
|
connect(ui->button_start_download, &QPushButton::clicked, this,
|
||||||
&ConfigureSystem::DownloadFromNUS);
|
&ConfigureSystem::DownloadFromNUS);
|
||||||
|
|
||||||
connect(ui->button_secure_info, &QPushButton::clicked, this, [this] {
|
|
||||||
ui->button_secure_info->setEnabled(false);
|
|
||||||
const QString file_path_qtstr = QFileDialog::getOpenFileName(
|
|
||||||
this, tr("Select SecureInfo_A/B"), QString(),
|
|
||||||
tr("SecureInfo_A/B (SecureInfo_A SecureInfo_B);;All Files (*.*)"));
|
|
||||||
ui->button_secure_info->setEnabled(true);
|
|
||||||
InstallSecureData(file_path_qtstr.toStdString(), cfg->GetSecureInfoAPath());
|
|
||||||
});
|
|
||||||
connect(ui->button_friend_code_seed, &QPushButton::clicked, this, [this] {
|
|
||||||
ui->button_friend_code_seed->setEnabled(false);
|
|
||||||
const QString file_path_qtstr =
|
|
||||||
QFileDialog::getOpenFileName(this, tr("Select LocalFriendCodeSeed_A/B"), QString(),
|
|
||||||
tr("LocalFriendCodeSeed_A/B (LocalFriendCodeSeed_A "
|
|
||||||
"LocalFriendCodeSeed_B);;All Files (*.*)"));
|
|
||||||
ui->button_friend_code_seed->setEnabled(true);
|
|
||||||
InstallSecureData(file_path_qtstr.toStdString(), cfg->GetLocalFriendCodeSeedBPath());
|
|
||||||
});
|
|
||||||
connect(ui->button_ct_cert, &QPushButton::clicked, this, [this] {
|
|
||||||
ui->button_ct_cert->setEnabled(false);
|
|
||||||
const QString file_path_qtstr = QFileDialog::getOpenFileName(
|
|
||||||
this, tr("Select CTCert"), QString(), tr("CTCert.bin (*.bin);;All Files (*.*)"));
|
|
||||||
ui->button_ct_cert->setEnabled(true);
|
|
||||||
InstallCTCert(file_path_qtstr.toStdString());
|
|
||||||
});
|
|
||||||
|
|
||||||
for (u8 i = 0; i < country_names.size(); i++) {
|
for (u8 i = 0; i < country_names.size(); i++) {
|
||||||
if (std::strcmp(country_names.at(i), "") != 0) {
|
if (std::strcmp(country_names.at(i), "") != 0) {
|
||||||
ui->combo_country->addItem(tr(country_names.at(i)), i);
|
ui->combo_country->addItem(tr(country_names.at(i)), i);
|
||||||
@@ -332,7 +304,6 @@ void ConfigureSystem::SetConfiguration() {
|
|||||||
ReadSystemSettings();
|
ReadSystemSettings();
|
||||||
|
|
||||||
ui->group_system_settings->setEnabled(enabled);
|
ui->group_system_settings->setEnabled(enabled);
|
||||||
ui->group_real_console_unique_data->setEnabled(enabled);
|
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
ui->label_disable_info->hide();
|
ui->label_disable_info->hide();
|
||||||
}
|
}
|
||||||
@@ -383,9 +354,6 @@ void ConfigureSystem::ReadSystemSettings() {
|
|||||||
|
|
||||||
// set firmware download region
|
// set firmware download region
|
||||||
ui->combo_download_region->setCurrentIndex(static_cast<int>(cfg->GetRegionValue()));
|
ui->combo_download_region->setCurrentIndex(static_cast<int>(cfg->GetRegionValue()));
|
||||||
|
|
||||||
// Refresh secure data status
|
|
||||||
RefreshSecureDataStatus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureSystem::ApplyConfiguration() {
|
void ConfigureSystem::ApplyConfiguration() {
|
||||||
@@ -554,59 +522,6 @@ void ConfigureSystem::RefreshConsoleID() {
|
|||||||
tr("Console ID: 0x%1").arg(QString::number(console_id, 16).toUpper()));
|
tr("Console ID: 0x%1").arg(QString::number(console_id, 16).toUpper()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureSystem::InstallSecureData(const std::string& from_path, const std::string& to_path) {
|
|
||||||
std::string from =
|
|
||||||
FileUtil::SanitizePath(from_path, FileUtil::DirectorySeparator::PlatformDefault);
|
|
||||||
std::string to = FileUtil::SanitizePath(to_path, FileUtil::DirectorySeparator::PlatformDefault);
|
|
||||||
if (from.empty() || from == to) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
FileUtil::CreateFullPath(to_path);
|
|
||||||
FileUtil::Copy(from, to);
|
|
||||||
cfg->InvalidateSecureData();
|
|
||||||
RefreshSecureDataStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigureSystem::InstallCTCert(const std::string& from_path) {
|
|
||||||
std::string from =
|
|
||||||
FileUtil::SanitizePath(from_path, FileUtil::DirectorySeparator::PlatformDefault);
|
|
||||||
std::string to = FileUtil::SanitizePath(Service::AM::Module::GetCTCertPath(),
|
|
||||||
FileUtil::DirectorySeparator::PlatformDefault);
|
|
||||||
if (from.empty() || from == to) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
FileUtil::Copy(from, to);
|
|
||||||
RefreshSecureDataStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigureSystem::RefreshSecureDataStatus() {
|
|
||||||
auto status_to_str = [](Service::CFG::SecureDataLoadStatus status) {
|
|
||||||
switch (status) {
|
|
||||||
case Service::CFG::SecureDataLoadStatus::Loaded:
|
|
||||||
return "Loaded";
|
|
||||||
case Service::CFG::SecureDataLoadStatus::NotFound:
|
|
||||||
return "Not Found";
|
|
||||||
case Service::CFG::SecureDataLoadStatus::Invalid:
|
|
||||||
return "Invalid";
|
|
||||||
case Service::CFG::SecureDataLoadStatus::IOError:
|
|
||||||
return "IO Error";
|
|
||||||
default:
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Service::AM::CTCert ct_cert;
|
|
||||||
|
|
||||||
ui->label_secure_info_status->setText(
|
|
||||||
tr((std::string("Status: ") + status_to_str(cfg->LoadSecureInfoAFile())).c_str()));
|
|
||||||
ui->label_friend_code_seed_status->setText(
|
|
||||||
tr((std::string("Status: ") + status_to_str(cfg->LoadLocalFriendCodeSeedBFile())).c_str()));
|
|
||||||
ui->label_ct_cert_status->setText(
|
|
||||||
tr((std::string("Status: ") + status_to_str(static_cast<Service::CFG::SecureDataLoadStatus>(
|
|
||||||
Service::AM::Module::LoadCTCertFile(ct_cert))))
|
|
||||||
.c_str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigureSystem::RetranslateUI() {
|
void ConfigureSystem::RetranslateUI() {
|
||||||
ui->retranslateUi(this);
|
ui->retranslateUi(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,12 +20,6 @@ namespace Core {
|
|||||||
class System;
|
class System;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Service {
|
|
||||||
namespace AM {
|
|
||||||
class Module;
|
|
||||||
} // namespace AM
|
|
||||||
} // namespace Service
|
|
||||||
|
|
||||||
namespace Service {
|
namespace Service {
|
||||||
namespace CFG {
|
namespace CFG {
|
||||||
class Module;
|
class Module;
|
||||||
@@ -52,10 +46,6 @@ private:
|
|||||||
void UpdateInitTicks(int init_ticks_type);
|
void UpdateInitTicks(int init_ticks_type);
|
||||||
void RefreshConsoleID();
|
void RefreshConsoleID();
|
||||||
|
|
||||||
void InstallSecureData(const std::string& from_path, const std::string& to_path);
|
|
||||||
void InstallCTCert(const std::string& from_path);
|
|
||||||
void RefreshSecureDataStatus();
|
|
||||||
|
|
||||||
void SetupPerGameUI();
|
void SetupPerGameUI();
|
||||||
|
|
||||||
void DownloadFromNUS();
|
void DownloadFromNUS();
|
||||||
|
|||||||
@@ -506,123 +506,6 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="group_real_console_unique_data">
|
|
||||||
<property name="title">
|
|
||||||
<string>Real Console Unique Data</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" name="gridLayout1">
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_secure_info">
|
|
||||||
<property name="text">
|
|
||||||
<string>SecureInfo_A/B</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QWidget" name="secure_info">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_secure_info">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_secure_info_status">
|
|
||||||
<property name="text">
|
|
||||||
<string></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="button_secure_info">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="layoutDirection">
|
|
||||||
<enum>Qt::RightToLeft</enum>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Choose</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_friend_code_seed">
|
|
||||||
<property name="text">
|
|
||||||
<string>LocalFriendCodeSeed_A/B</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QWidget" name="friend_code_seed">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_friend_code_seed">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_friend_code_seed_status">
|
|
||||||
<property name="text">
|
|
||||||
<string></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="button_friend_code_seed">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="layoutDirection">
|
|
||||||
<enum>Qt::RightToLeft</enum>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Choose</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_ct_cert">
|
|
||||||
<property name="text">
|
|
||||||
<string>CTCert</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QWidget" name="ct_cert">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_ct_cert">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_ct_cert_status">
|
|
||||||
<property name="text">
|
|
||||||
<string></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="button_ct_cert">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="layoutDirection">
|
|
||||||
<enum>Qt::RightToLeft</enum>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Choose</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_disable_info">
|
<widget class="QLabel" name="label_disable_info">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
|||||||
+3
-15
@@ -64,7 +64,7 @@
|
|||||||
#include "citra_qt/uisettings.h"
|
#include "citra_qt/uisettings.h"
|
||||||
#include "citra_qt/updater/updater.h"
|
#include "citra_qt/updater/updater.h"
|
||||||
#include "citra_qt/util/clickable_label.h"
|
#include "citra_qt/util/clickable_label.h"
|
||||||
#include "citra_qt/util/graphics_device_info.h"
|
#include "citra_qt/util/vk_device_info.h"
|
||||||
#include "common/arch.h"
|
#include "common/arch.h"
|
||||||
#include "common/common_paths.h"
|
#include "common/common_paths.h"
|
||||||
#include "common/detached_tasks.h"
|
#include "common/detached_tasks.h"
|
||||||
@@ -270,18 +270,6 @@ GMainWindow::GMainWindow(Core::System& system_)
|
|||||||
connect(&mouse_hide_timer, &QTimer::timeout, this, &GMainWindow::HideMouseCursor);
|
connect(&mouse_hide_timer, &QTimer::timeout, this, &GMainWindow::HideMouseCursor);
|
||||||
connect(ui->menubar, &QMenuBar::hovered, this, &GMainWindow::OnMouseActivity);
|
connect(ui->menubar, &QMenuBar::hovered, this, &GMainWindow::OnMouseActivity);
|
||||||
|
|
||||||
#ifdef ENABLE_OPENGL
|
|
||||||
gl_renderer = GetOpenGLRenderer();
|
|
||||||
#if defined(_WIN32)
|
|
||||||
if (gl_renderer.startsWith(QStringLiteral("D3D12"))) {
|
|
||||||
// OpenGLOn12 supports but does not yet advertise OpenGL 4.0+
|
|
||||||
// We can override the version here to allow Citra to work.
|
|
||||||
// TODO: Remove this when OpenGL 4.0+ is advertised.
|
|
||||||
qputenv("MESA_GL_VERSION_OVERRIDE", "4.6");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_VULKAN
|
#ifdef ENABLE_VULKAN
|
||||||
physical_devices = GetVulkanPhysicalDevices();
|
physical_devices = GetVulkanPhysicalDevices();
|
||||||
if (physical_devices.empty()) {
|
if (physical_devices.empty()) {
|
||||||
@@ -2170,7 +2158,7 @@ void GMainWindow::OnLoadState() {
|
|||||||
void GMainWindow::OnConfigure() {
|
void GMainWindow::OnConfigure() {
|
||||||
game_list->SetDirectoryWatcherEnabled(false);
|
game_list->SetDirectoryWatcherEnabled(false);
|
||||||
Settings::SetConfiguringGlobal(true);
|
Settings::SetConfiguringGlobal(true);
|
||||||
ConfigureDialog configureDialog(this, hotkey_registry, system, gl_renderer, physical_devices,
|
ConfigureDialog configureDialog(this, hotkey_registry, system, physical_devices,
|
||||||
!multiplayer_state->IsHostingPublicRoom());
|
!multiplayer_state->IsHostingPublicRoom());
|
||||||
connect(&configureDialog, &ConfigureDialog::LanguageChanged, this,
|
connect(&configureDialog, &ConfigureDialog::LanguageChanged, this,
|
||||||
&GMainWindow::OnLanguageChanged);
|
&GMainWindow::OnLanguageChanged);
|
||||||
@@ -3018,7 +3006,7 @@ void GMainWindow::OnConfigurePerGame() {
|
|||||||
|
|
||||||
void GMainWindow::OpenPerGameConfiguration(u64 title_id, const QString& file_name) {
|
void GMainWindow::OpenPerGameConfiguration(u64 title_id, const QString& file_name) {
|
||||||
Settings::SetConfiguringGlobal(false);
|
Settings::SetConfiguringGlobal(false);
|
||||||
ConfigurePerGame dialog(this, title_id, file_name, gl_renderer, physical_devices, system);
|
ConfigurePerGame dialog(this, title_id, file_name, physical_devices, system);
|
||||||
const auto result = dialog.exec();
|
const auto result = dialog.exec();
|
||||||
|
|
||||||
if (result != QDialog::Accepted) {
|
if (result != QDialog::Accepted) {
|
||||||
|
|||||||
@@ -344,7 +344,6 @@ private:
|
|||||||
// Whether game was paused due to stopping video dumping
|
// Whether game was paused due to stopping video dumping
|
||||||
bool game_paused_for_dumping = false;
|
bool game_paused_for_dumping = false;
|
||||||
|
|
||||||
QString gl_renderer;
|
|
||||||
std::vector<QString> physical_devices;
|
std::vector<QString> physical_devices;
|
||||||
|
|
||||||
// Debugger panes
|
// Debugger panes
|
||||||
|
|||||||
@@ -2,34 +2,9 @@
|
|||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "citra_qt/util/graphics_device_info.h"
|
#include "citra_qt/util/vk_device_info.h"
|
||||||
|
|
||||||
#ifdef ENABLE_OPENGL
|
|
||||||
#include <QOffscreenSurface>
|
|
||||||
#include <QOpenGLContext>
|
|
||||||
#include <QOpenGLFunctions>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_VULKAN
|
|
||||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_OPENGL
|
|
||||||
QString GetOpenGLRenderer() {
|
|
||||||
QOffscreenSurface surface;
|
|
||||||
surface.create();
|
|
||||||
|
|
||||||
QOpenGLContext context;
|
|
||||||
if (context.create()) {
|
|
||||||
context.makeCurrent(&surface);
|
|
||||||
return QString::fromUtf8(context.functions()->glGetString(GL_RENDERER));
|
|
||||||
} else {
|
|
||||||
return QStringLiteral("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_VULKAN
|
|
||||||
std::vector<QString> GetVulkanPhysicalDevices() {
|
std::vector<QString> GetVulkanPhysicalDevices() {
|
||||||
std::vector<QString> result;
|
std::vector<QString> result;
|
||||||
try {
|
try {
|
||||||
@@ -46,4 +21,3 @@ std::vector<QString> GetVulkanPhysicalDevices() {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
@@ -7,12 +7,5 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#ifdef ENABLE_OPENGL
|
|
||||||
/// Returns the name of the OpenGL renderer.
|
|
||||||
QString GetOpenGLRenderer();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_VULKAN
|
|
||||||
/// Returns a list of all available vulkan GPUs.
|
/// Returns a list of all available vulkan GPUs.
|
||||||
std::vector<QString> GetVulkanPhysicalDevices();
|
std::vector<QString> GetVulkanPhysicalDevices();
|
||||||
#endif
|
|
||||||
@@ -20,7 +20,7 @@ inline bool IsWithin128M(uintptr_t ref, uintptr_t target) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsWithin128M(const oaknut::CodeGenerator& code, uintptr_t target) {
|
inline bool IsWithin128M(const oaknut::CodeGenerator& code, uintptr_t target) {
|
||||||
return IsWithin128M(code.xptr<uintptr_t>(), target);
|
return IsWithin128M(code.ptr<uintptr_t>(), target);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ void vfp_put_float(ARMul_State* state, s32 val, unsigned int reg) {
|
|||||||
|
|
||||||
u64 vfp_get_double(ARMul_State* state, unsigned int reg) {
|
u64 vfp_get_double(ARMul_State* state, unsigned int reg) {
|
||||||
u64 result = ((u64)state->ExtReg[reg * 2 + 1]) << 32 | state->ExtReg[reg * 2];
|
u64 result = ((u64)state->ExtReg[reg * 2 + 1]) << 32 | state->ExtReg[reg * 2];
|
||||||
LOG_TRACE(Core_ARM11, "VFP get double: s[{}-{}]=[{:016x}]", reg * 2 + 1, reg * 2, result);
|
LOG_TRACE(Core_ARM11, "VFP get double: s[{}-{}]=[{:016llx}]", reg * 2 + 1, reg * 2, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ static struct vfp_double vfp_double_default_qnan = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void vfp_double_dump(const char* str, struct vfp_double* d) {
|
static void vfp_double_dump(const char* str, struct vfp_double* d) {
|
||||||
LOG_TRACE(Core_ARM11, "VFP: {}: sign={} exponent={} significand={:016x}", str, d->sign != 0,
|
LOG_TRACE(Core_ARM11, "VFP: {}: sign={} exponent={} significand={:016llx}", str, d->sign != 0,
|
||||||
d->exponent, d->significand);
|
d->exponent, d->significand);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +166,7 @@ u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double* vd,
|
|||||||
} else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vd->sign != 0))
|
} else if ((rmode == FPSCR_ROUND_PLUSINF) ^ (vd->sign != 0))
|
||||||
incr = (1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1;
|
incr = (1ULL << (VFP_DOUBLE_LOW_BITS + 1)) - 1;
|
||||||
|
|
||||||
LOG_TRACE(Core_ARM11, "VFP: rounding increment = 0x{:08x}", incr);
|
LOG_TRACE(Core_ARM11, "VFP: rounding increment = 0x{:08llx}", incr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Is our rounding going to overflow?
|
* Is our rounding going to overflow?
|
||||||
@@ -221,7 +221,8 @@ pack:
|
|||||||
vfp_double_dump("pack: final", vd);
|
vfp_double_dump("pack: final", vd);
|
||||||
{
|
{
|
||||||
s64 d = vfp_double_pack(vd);
|
s64 d = vfp_double_pack(vd);
|
||||||
LOG_TRACE(Core_ARM11, "VFP: {}: d(d{})={:016x} exceptions={:08x}", func, dd, d, exceptions);
|
LOG_TRACE(Core_ARM11, "VFP: {}: d(d{})={:016llx} exceptions={:08x}", func, dd, d,
|
||||||
|
exceptions);
|
||||||
vfp_put_double(state, d, dd);
|
vfp_put_double(state, d, dd);
|
||||||
}
|
}
|
||||||
return exceptions;
|
return exceptions;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <chrono>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include "common/archives.h"
|
#include "common/archives.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
@@ -268,8 +269,10 @@ enum class SystemInfoMemUsageRegion {
|
|||||||
*/
|
*/
|
||||||
enum class SystemInfoCitraInformation {
|
enum class SystemInfoCitraInformation {
|
||||||
IS_CITRA = 0, // Always set the output to 1, signaling the app is running on Citra.
|
IS_CITRA = 0, // Always set the output to 1, signaling the app is running on Citra.
|
||||||
|
HOST_TICK = 1, // Tick reference from the host in ns, unaffected by lag or cpu speed.
|
||||||
BUILD_NAME = 10, // (ie: Nightly, Canary).
|
BUILD_NAME = 10, // (ie: Nightly, Canary).
|
||||||
BUILD_VERSION = 11, // Build version.
|
BUILD_VERSION = 11, // Build version.
|
||||||
|
BUILD_PLATFORM = 12, // Build platform, see SystemInfoCitraPlatform.
|
||||||
BUILD_DATE_PART1 = 20, // Build date first 7 characters.
|
BUILD_DATE_PART1 = 20, // Build date first 7 characters.
|
||||||
BUILD_DATE_PART2 = 21, // Build date next 7 characters.
|
BUILD_DATE_PART2 = 21, // Build date next 7 characters.
|
||||||
BUILD_DATE_PART3 = 22, // Build date next 7 characters.
|
BUILD_DATE_PART3 = 22, // Build date next 7 characters.
|
||||||
@@ -280,6 +283,17 @@ enum class SystemInfoCitraInformation {
|
|||||||
BUILD_GIT_DESCRIPTION_PART2 = 41, // Git description (commit) last 7 characters.
|
BUILD_GIT_DESCRIPTION_PART2 = 41, // Git description (commit) last 7 characters.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current officially supported platforms.
|
||||||
|
*/
|
||||||
|
enum class SystemInfoCitraPlatform {
|
||||||
|
PLATFORM_UNKNOWN = 0,
|
||||||
|
PLATFORM_WINDOWS = 1,
|
||||||
|
PLATFORM_LINUX = 2,
|
||||||
|
PLATFORM_APPLE = 3,
|
||||||
|
PLATFORM_ANDROID = 4,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accepted by the custom svcControlProcess.
|
* Accepted by the custom svcControlProcess.
|
||||||
*/
|
*/
|
||||||
@@ -1740,12 +1754,31 @@ Result SVC::GetSystemInfo(s64* out, u32 type, s32 param) {
|
|||||||
case SystemInfoCitraInformation::IS_CITRA:
|
case SystemInfoCitraInformation::IS_CITRA:
|
||||||
*out = 1;
|
*out = 1;
|
||||||
break;
|
break;
|
||||||
|
case SystemInfoCitraInformation::HOST_TICK:
|
||||||
|
*out = static_cast<s64>(std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||||
|
std::chrono::steady_clock::now().time_since_epoch())
|
||||||
|
.count());
|
||||||
|
break;
|
||||||
case SystemInfoCitraInformation::BUILD_NAME:
|
case SystemInfoCitraInformation::BUILD_NAME:
|
||||||
CopyStringPart(reinterpret_cast<char*>(out), Common::g_build_name, 0, sizeof(s64));
|
CopyStringPart(reinterpret_cast<char*>(out), Common::g_build_name, 0, sizeof(s64));
|
||||||
break;
|
break;
|
||||||
case SystemInfoCitraInformation::BUILD_VERSION:
|
case SystemInfoCitraInformation::BUILD_VERSION:
|
||||||
CopyStringPart(reinterpret_cast<char*>(out), Common::g_build_version, 0, sizeof(s64));
|
CopyStringPart(reinterpret_cast<char*>(out), Common::g_build_version, 0, sizeof(s64));
|
||||||
break;
|
break;
|
||||||
|
case SystemInfoCitraInformation::BUILD_PLATFORM: {
|
||||||
|
#if defined(_WIN32)
|
||||||
|
*out = static_cast<s64>(SystemInfoCitraPlatform::PLATFORM_WINDOWS);
|
||||||
|
#elif defined(ANDROID)
|
||||||
|
*out = static_cast<s64>(SystemInfoCitraPlatform::PLATFORM_ANDROID);
|
||||||
|
#elif defined(__linux__)
|
||||||
|
*out = static_cast<s64>(SystemInfoCitraPlatform::PLATFORM_LINUX);
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
*out = static_cast<s64>(SystemInfoCitraPlatform::PLATFORM_APPLE);
|
||||||
|
#else
|
||||||
|
*out = static_cast<s64>(SystemInfoCitraPlatform::PLATFORM_UNKNOWN);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
case SystemInfoCitraInformation::BUILD_DATE_PART1:
|
case SystemInfoCitraInformation::BUILD_DATE_PART1:
|
||||||
CopyStringPart(reinterpret_cast<char*>(out), Common::g_build_date,
|
CopyStringPart(reinterpret_cast<char*>(out), Common::g_build_date,
|
||||||
(sizeof(s64) - 1) * 0, sizeof(s64));
|
(sizeof(s64) - 1) * 0, sizeof(s64));
|
||||||
|
|||||||
@@ -80,35 +80,6 @@ struct TicketInfo {
|
|||||||
|
|
||||||
static_assert(sizeof(TicketInfo) == 0x18, "Ticket info structure size is wrong");
|
static_assert(sizeof(TicketInfo) == 0x18, "Ticket info structure size is wrong");
|
||||||
|
|
||||||
bool CTCert::IsValid() const {
|
|
||||||
constexpr std::string_view expected_issuer_prod = "Nintendo CA - G3_NintendoCTR2prod";
|
|
||||||
constexpr std::string_view expected_issuer_dev = "Nintendo CA - G3_NintendoCTR2dev";
|
|
||||||
constexpr u32 expected_signature_type = 0x010005;
|
|
||||||
|
|
||||||
return signature_type == expected_signature_type &&
|
|
||||||
(std::string(issuer.data()) == expected_issuer_prod ||
|
|
||||||
std::string(issuer.data()) == expected_issuer_dev);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 CTCert::GetDeviceID() const {
|
|
||||||
constexpr std::string_view key_id_prefix = "CT";
|
|
||||||
|
|
||||||
const std::string key_id_str(key_id.data());
|
|
||||||
if (key_id_str.starts_with(key_id_prefix)) {
|
|
||||||
const std::string device_id =
|
|
||||||
key_id_str.substr(key_id_prefix.size(), key_id_str.find('-') - key_id_prefix.size());
|
|
||||||
char* end_ptr;
|
|
||||||
const u32 device_id_value = std::strtoul(device_id.c_str(), &end_ptr, 16);
|
|
||||||
if (*end_ptr == '\0') {
|
|
||||||
return device_id_value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Error
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
class CIAFile::DecryptionState {
|
class CIAFile::DecryptionState {
|
||||||
public:
|
public:
|
||||||
std::vector<CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption> content;
|
std::vector<CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption> content;
|
||||||
@@ -1242,21 +1213,6 @@ void Module::Interface::GetTicketList(Kernel::HLERequestContext& ctx) {
|
|||||||
ticket_list_count, ticket_index);
|
ticket_list_count, ticket_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::GetDeviceID(Kernel::HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp(ctx);
|
|
||||||
|
|
||||||
const u32 deviceID = am->ct_cert.IsValid() ? am->ct_cert.GetDeviceID() : 0;
|
|
||||||
|
|
||||||
if (deviceID == 0) {
|
|
||||||
LOG_ERROR(Service_AM, "Invalid or missing CTCert");
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(3, 0);
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push(0);
|
|
||||||
rb.Push(deviceID);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Module::Interface::NeedsCleanup(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::NeedsCleanup(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
const auto media_type = rp.Pop<u8>();
|
const auto media_type = rp.Pop<u8>();
|
||||||
@@ -1846,66 +1802,13 @@ void Module::serialize(Archive& ar, const unsigned int) {
|
|||||||
}
|
}
|
||||||
SERIALIZE_IMPL(Module)
|
SERIALIZE_IMPL(Module)
|
||||||
|
|
||||||
void Module::Interface::GetDeviceCert(Kernel::HLERequestContext& ctx) {
|
Module::Module(Core::System& system) : system(system) {
|
||||||
IPC::RequestParser rp(ctx);
|
|
||||||
[[maybe_unused]] u32 size = rp.Pop<u32>();
|
|
||||||
auto buffer = rp.PopMappedBuffer();
|
|
||||||
|
|
||||||
if (!am->ct_cert.IsValid()) {
|
|
||||||
LOG_ERROR(Service_AM, "Invalid or missing CTCert");
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.Write(&am->ct_cert, 0, std::min(sizeof(CTCert), buffer.GetSize()));
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 2);
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push(0);
|
|
||||||
rb.PushMappedBuffer(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Module::GetCTCertPath() {
|
|
||||||
return FileUtil::GetUserPath(FileUtil::UserPath::SysDataDir) + "CTCert.bin";
|
|
||||||
}
|
|
||||||
|
|
||||||
CTCertLoadStatus Module::LoadCTCertFile(CTCert& output) {
|
|
||||||
if (output.IsValid()) {
|
|
||||||
return CTCertLoadStatus::Loaded;
|
|
||||||
}
|
|
||||||
std::string file_path = GetCTCertPath();
|
|
||||||
if (!FileUtil::Exists(file_path)) {
|
|
||||||
return CTCertLoadStatus::NotFound;
|
|
||||||
}
|
|
||||||
FileUtil::IOFile file(file_path, "rb");
|
|
||||||
if (!file.IsOpen()) {
|
|
||||||
return CTCertLoadStatus::IOError;
|
|
||||||
}
|
|
||||||
if (file.GetSize() != sizeof(CTCert)) {
|
|
||||||
return CTCertLoadStatus::Invalid;
|
|
||||||
}
|
|
||||||
if (file.ReadBytes(&output, sizeof(CTCert)) != sizeof(CTCert)) {
|
|
||||||
return CTCertLoadStatus::IOError;
|
|
||||||
}
|
|
||||||
if (!output.IsValid()) {
|
|
||||||
output = CTCert();
|
|
||||||
return CTCertLoadStatus::Invalid;
|
|
||||||
}
|
|
||||||
return CTCertLoadStatus::Loaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
Module::Module(Core::System& _system) : system(_system) {
|
|
||||||
ScanForAllTitles();
|
ScanForAllTitles();
|
||||||
LoadCTCertFile(ct_cert);
|
|
||||||
system_updater_mutex = system.Kernel().CreateMutex(false, "AM::SystemUpdaterMutex");
|
system_updater_mutex = system.Kernel().CreateMutex(false, "AM::SystemUpdaterMutex");
|
||||||
}
|
}
|
||||||
|
|
||||||
Module::~Module() = default;
|
Module::~Module() = default;
|
||||||
|
|
||||||
std::shared_ptr<Module> GetModule(Core::System& system) {
|
|
||||||
auto am = system.ServiceManager().GetService<Service::AM::Module::Interface>("am:u");
|
|
||||||
if (!am)
|
|
||||||
return nullptr;
|
|
||||||
return am->GetModule();
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstallInterfaces(Core::System& system) {
|
void InstallInterfaces(Core::System& system) {
|
||||||
auto& service_manager = system.ServiceManager();
|
auto& service_manager = system.ServiceManager();
|
||||||
auto am = std::make_shared<Module>(system);
|
auto am = std::make_shared<Module>(system);
|
||||||
|
|||||||
@@ -68,31 +68,6 @@ enum class InstallStatus : u32 {
|
|||||||
ErrorEncrypted,
|
ErrorEncrypted,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class CTCertLoadStatus {
|
|
||||||
Loaded,
|
|
||||||
NotFound,
|
|
||||||
Invalid,
|
|
||||||
IOError,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CTCert {
|
|
||||||
u32_be signature_type{};
|
|
||||||
std::array<u8, 0x1E> signature_r{};
|
|
||||||
std::array<u8, 0x1E> signature_s{};
|
|
||||||
INSERT_PADDING_BYTES(0x40){};
|
|
||||||
std::array<char, 0x40> issuer{};
|
|
||||||
u32_be key_type{};
|
|
||||||
std::array<char, 0x40> key_id{};
|
|
||||||
u32_be expiration_time{};
|
|
||||||
std::array<u8, 0x1E> public_key_x{};
|
|
||||||
std::array<u8, 0x1E> public_key_y{};
|
|
||||||
INSERT_PADDING_BYTES(0x3C){};
|
|
||||||
|
|
||||||
bool IsValid() const;
|
|
||||||
u32 GetDeviceID() const;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(CTCert) == 0x180, "Invalid CTCert size.");
|
|
||||||
|
|
||||||
// Title ID valid length
|
// Title ID valid length
|
||||||
constexpr std::size_t TITLE_ID_VALID_LENGTH = 16;
|
constexpr std::size_t TITLE_ID_VALID_LENGTH = 16;
|
||||||
|
|
||||||
@@ -241,10 +216,6 @@ public:
|
|||||||
Interface(std::shared_ptr<Module> am, const char* name, u32 max_session);
|
Interface(std::shared_ptr<Module> am, const char* name, u32 max_session);
|
||||||
~Interface();
|
~Interface();
|
||||||
|
|
||||||
std::shared_ptr<Module> GetModule() const {
|
|
||||||
return am;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* AM::GetNumPrograms service function
|
* AM::GetNumPrograms service function
|
||||||
@@ -444,16 +415,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
void GetTicketList(Kernel::HLERequestContext& ctx);
|
void GetTicketList(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
/**
|
|
||||||
* AM::GetDeviceID service function
|
|
||||||
* Inputs:
|
|
||||||
* Outputs:
|
|
||||||
* 1 : Result, 0 on success, otherwise error code
|
|
||||||
* 2 : Unknown
|
|
||||||
* 3 : DeviceID
|
|
||||||
*/
|
|
||||||
void GetDeviceID(Kernel::HLERequestContext& ctx);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AM::NeedsCleanup service function
|
* AM::NeedsCleanup service function
|
||||||
* Inputs:
|
* Inputs:
|
||||||
@@ -741,32 +702,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
void EndImportTicket(Kernel::HLERequestContext& ctx);
|
void EndImportTicket(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
/**
|
|
||||||
* AM::GetDeviceCert service function
|
|
||||||
* Inputs:
|
|
||||||
* Outputs:
|
|
||||||
* 1 : Result, 0 on success, otherwise error code
|
|
||||||
* 2 : Unknown
|
|
||||||
* 3-4 : Device cert
|
|
||||||
*/
|
|
||||||
void GetDeviceCert(Kernel::HLERequestContext& ctx);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<Module> am;
|
std::shared_ptr<Module> am;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the CTCert.bin path in the host filesystem
|
|
||||||
* @returns std::string CTCert.bin path in the host filesystem
|
|
||||||
*/
|
|
||||||
static std::string GetCTCertPath();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the CTCert.bin file from the filesystem.
|
|
||||||
* @returns CTCertLoadStatus indicating the file load status.
|
|
||||||
*/
|
|
||||||
static CTCertLoadStatus LoadCTCertFile(CTCert& output);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Scans the for titles in a storage medium for listing.
|
* Scans the for titles in a storage medium for listing.
|
||||||
@@ -783,15 +722,12 @@ private:
|
|||||||
bool cia_installing = false;
|
bool cia_installing = false;
|
||||||
std::array<std::vector<u64_le>, 3> am_title_list;
|
std::array<std::vector<u64_le>, 3> am_title_list;
|
||||||
std::shared_ptr<Kernel::Mutex> system_updater_mutex;
|
std::shared_ptr<Kernel::Mutex> system_updater_mutex;
|
||||||
CTCert ct_cert{};
|
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int);
|
void serialize(Archive& ar, const unsigned int);
|
||||||
friend class boost::serialization::access;
|
friend class boost::serialization::access;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<Module> GetModule(Core::System& system);
|
|
||||||
|
|
||||||
void InstallInterfaces(Core::System& system);
|
void InstallInterfaces(Core::System& system);
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ AM_NET::AM_NET(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "a
|
|||||||
{0x0007, &AM_NET::DeleteTicket, "DeleteTicket"},
|
{0x0007, &AM_NET::DeleteTicket, "DeleteTicket"},
|
||||||
{0x0008, &AM_NET::GetNumTickets, "GetNumTickets"},
|
{0x0008, &AM_NET::GetNumTickets, "GetNumTickets"},
|
||||||
{0x0009, &AM_NET::GetTicketList, "GetTicketList"},
|
{0x0009, &AM_NET::GetTicketList, "GetTicketList"},
|
||||||
{0x000A, &AM_NET::GetDeviceID, "GetDeviceID"},
|
{0x000A, nullptr, "GetDeviceID"},
|
||||||
{0x000B, nullptr, "GetNumImportTitleContexts"},
|
{0x000B, nullptr, "GetNumImportTitleContexts"},
|
||||||
{0x000C, nullptr, "GetImportTitleContextList"},
|
{0x000C, nullptr, "GetImportTitleContextList"},
|
||||||
{0x000D, nullptr, "GetImportTitleContexts"},
|
{0x000D, nullptr, "GetImportTitleContexts"},
|
||||||
@@ -103,7 +103,7 @@ AM_NET::AM_NET(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "a
|
|||||||
{0x0815, nullptr, "GetCurrentImportContentContexts"},
|
{0x0815, nullptr, "GetCurrentImportContentContexts"},
|
||||||
{0x0816, nullptr, "Sign"},
|
{0x0816, nullptr, "Sign"},
|
||||||
{0x0817, nullptr, "Verify"},
|
{0x0817, nullptr, "Verify"},
|
||||||
{0x0818, &AM_NET::GetDeviceCert, "GetDeviceCert"},
|
{0x0818, nullptr, "GetDeviceCert"},
|
||||||
{0x0819, nullptr, "ImportCertificates"},
|
{0x0819, nullptr, "ImportCertificates"},
|
||||||
{0x081A, nullptr, "ImportCertificate"},
|
{0x081A, nullptr, "ImportCertificate"},
|
||||||
{0x081B, nullptr, "CommitImportTitlesAndUpdateFirmwareAuto"},
|
{0x081B, nullptr, "CommitImportTitlesAndUpdateFirmwareAuto"},
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ AM_SYS::AM_SYS(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "a
|
|||||||
{0x0007, &AM_SYS::DeleteTicket, "DeleteTicket"},
|
{0x0007, &AM_SYS::DeleteTicket, "DeleteTicket"},
|
||||||
{0x0008, &AM_SYS::GetNumTickets, "GetNumTickets"},
|
{0x0008, &AM_SYS::GetNumTickets, "GetNumTickets"},
|
||||||
{0x0009, &AM_SYS::GetTicketList, "GetTicketList"},
|
{0x0009, &AM_SYS::GetTicketList, "GetTicketList"},
|
||||||
{0x000A, &AM_SYS::GetDeviceID, "GetDeviceID"},
|
{0x000A, nullptr, "GetDeviceID"},
|
||||||
{0x000B, nullptr, "GetNumImportTitleContexts"},
|
{0x000B, nullptr, "GetNumImportTitleContexts"},
|
||||||
{0x000C, nullptr, "GetImportTitleContextList"},
|
{0x000C, nullptr, "GetImportTitleContextList"},
|
||||||
{0x000D, nullptr, "GetImportTitleContexts"},
|
{0x000D, nullptr, "GetImportTitleContexts"},
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ AM_U::AM_U(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "am:u"
|
|||||||
{0x0007, &AM_U::DeleteTicket, "DeleteTicket"},
|
{0x0007, &AM_U::DeleteTicket, "DeleteTicket"},
|
||||||
{0x0008, &AM_U::GetNumTickets, "GetNumTickets"},
|
{0x0008, &AM_U::GetNumTickets, "GetNumTickets"},
|
||||||
{0x0009, &AM_U::GetTicketList, "GetTicketList"},
|
{0x0009, &AM_U::GetTicketList, "GetTicketList"},
|
||||||
{0x000A, &AM_U::GetDeviceID, "GetDeviceID"},
|
{0x000A, nullptr, "GetDeviceID"},
|
||||||
{0x000B, nullptr, "GetNumImportTitleContexts"},
|
{0x000B, nullptr, "GetNumImportTitleContexts"},
|
||||||
{0x000C, nullptr, "GetImportTitleContextList"},
|
{0x000C, nullptr, "GetImportTitleContextList"},
|
||||||
{0x000D, nullptr, "GetImportTitleContexts"},
|
{0x000D, nullptr, "GetImportTitleContexts"},
|
||||||
|
|||||||
@@ -217,39 +217,12 @@ void Module::Interface::GetRegion(Kernel::HLERequestContext& ctx) {
|
|||||||
void Module::Interface::SecureInfoGetByte101(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::SecureInfoGetByte101(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
|
|
||||||
u8 ret = 0;
|
LOG_DEBUG(Service_CFG, "(STUBBED) called");
|
||||||
if (cfg->secure_info_a_loaded) {
|
|
||||||
ret = cfg->secure_info_a.unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.Push<u8>(ret);
|
// According to 3dbrew this is normally 0.
|
||||||
}
|
rb.Push<u8>(0);
|
||||||
|
|
||||||
void Module::Interface::SecureInfoGetSerialNo(Kernel::HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp(ctx);
|
|
||||||
[[maybe_unused]] u32 out_size = rp.Pop<u32>();
|
|
||||||
auto out_buffer = rp.PopMappedBuffer();
|
|
||||||
|
|
||||||
if (out_buffer.GetSize() < sizeof(SecureInfoA::serial_number)) {
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
||||||
rb.Push(Result(ErrorDescription::InvalidSize, ErrorModule::Config,
|
|
||||||
ErrorSummary::WrongArgument, ErrorLevel::Permanent));
|
|
||||||
}
|
|
||||||
// Never happens on real hardware, but may happen if user didn't supply a dump.
|
|
||||||
// Always make sure to have available both secure data kinds or error otherwise.
|
|
||||||
if (!cfg->secure_info_a_loaded || !cfg->local_friend_code_seed_b_loaded) {
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
||||||
rb.Push(Result(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::InvalidState,
|
|
||||||
ErrorLevel::Permanent));
|
|
||||||
}
|
|
||||||
|
|
||||||
out_buffer.Write(&cfg->secure_info_a.serial_number, 0, sizeof(SecureInfoA::serial_number));
|
|
||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.PushMappedBuffer(out_buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::SetUUIDClockSequence(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::SetUUIDClockSequence(Kernel::HLERequestContext& ctx) {
|
||||||
@@ -392,43 +365,6 @@ void Module::Interface::UpdateConfigNANDSavegame(Kernel::HLERequestContext& ctx)
|
|||||||
rb.Push(cfg->UpdateConfigNANDSavegame());
|
rb.Push(cfg->UpdateConfigNANDSavegame());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::Interface::GetLocalFriendCodeSeedData(Kernel::HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp(ctx);
|
|
||||||
[[maybe_unused]] u32 out_size = rp.Pop<u32>();
|
|
||||||
auto out_buffer = rp.PopMappedBuffer();
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
||||||
|
|
||||||
if (out_buffer.GetSize() < sizeof(LocalFriendCodeSeedB)) {
|
|
||||||
rb.Push(Result(ErrorDescription::InvalidSize, ErrorModule::Config,
|
|
||||||
ErrorSummary::WrongArgument, ErrorLevel::Permanent));
|
|
||||||
}
|
|
||||||
// Never happens on real hardware, but may happen if user didn't supply a dump.
|
|
||||||
// Always make sure to have available both secure data kinds or error otherwise.
|
|
||||||
if (!cfg->secure_info_a_loaded || !cfg->local_friend_code_seed_b_loaded) {
|
|
||||||
rb.Push(Result(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::InvalidState,
|
|
||||||
ErrorLevel::Permanent));
|
|
||||||
}
|
|
||||||
|
|
||||||
out_buffer.Write(&cfg->local_friend_code_seed_b, 0, sizeof(LocalFriendCodeSeedB));
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Module::Interface::GetLocalFriendCodeSeed(Kernel::HLERequestContext& ctx) {
|
|
||||||
IPC::RequestParser rp(ctx);
|
|
||||||
|
|
||||||
// Never happens on real hardware, but may happen if user didn't supply a dump.
|
|
||||||
// Always make sure to have available both secure data kinds or error otherwise.
|
|
||||||
if (!cfg->secure_info_a_loaded || !cfg->local_friend_code_seed_b_loaded) {
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
||||||
rb.Push(Result(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::InvalidState,
|
|
||||||
ErrorLevel::Permanent));
|
|
||||||
}
|
|
||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(3, 0);
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push<u64>(cfg->local_friend_code_seed_b.friend_code_seed);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Module::Interface::FormatConfig(Kernel::HLERequestContext& ctx) {
|
void Module::Interface::FormatConfig(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
@@ -570,14 +506,6 @@ Result Module::UpdateConfigNANDSavegame() {
|
|||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Module::GetLocalFriendCodeSeedBPath() {
|
|
||||||
return FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + "rw/sys/LocalFriendCodeSeed_B";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Module::GetSecureInfoAPath() {
|
|
||||||
return FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + "rw/sys/SecureInfo_A";
|
|
||||||
}
|
|
||||||
|
|
||||||
Result Module::FormatConfig() {
|
Result Module::FormatConfig() {
|
||||||
Result res = DeleteConfigNANDSaveFile();
|
Result res = DeleteConfigNANDSaveFile();
|
||||||
// The delete command fails if the file doesn't exist, so we have to check that too
|
// The delete command fails if the file doesn't exist, so we have to check that too
|
||||||
@@ -651,55 +579,6 @@ Result Module::LoadConfigNANDSaveFile() {
|
|||||||
return FormatConfig();
|
return FormatConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::InvalidateSecureData() {
|
|
||||||
secure_info_a_loaded = local_friend_code_seed_b_loaded = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
SecureDataLoadStatus Module::LoadSecureInfoAFile() {
|
|
||||||
if (secure_info_a_loaded) {
|
|
||||||
return SecureDataLoadStatus::Loaded;
|
|
||||||
}
|
|
||||||
std::string file_path = GetSecureInfoAPath();
|
|
||||||
if (!FileUtil::Exists(file_path)) {
|
|
||||||
return SecureDataLoadStatus::NotFound;
|
|
||||||
}
|
|
||||||
FileUtil::IOFile file(file_path, "rb");
|
|
||||||
if (!file.IsOpen()) {
|
|
||||||
return SecureDataLoadStatus::IOError;
|
|
||||||
}
|
|
||||||
if (file.GetSize() != sizeof(SecureInfoA)) {
|
|
||||||
return SecureDataLoadStatus::Invalid;
|
|
||||||
}
|
|
||||||
if (file.ReadBytes(&secure_info_a, sizeof(SecureInfoA)) != sizeof(SecureInfoA)) {
|
|
||||||
return SecureDataLoadStatus::IOError;
|
|
||||||
}
|
|
||||||
secure_info_a_loaded = true;
|
|
||||||
return SecureDataLoadStatus::Loaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
SecureDataLoadStatus Module::LoadLocalFriendCodeSeedBFile() {
|
|
||||||
if (local_friend_code_seed_b_loaded) {
|
|
||||||
return SecureDataLoadStatus::Loaded;
|
|
||||||
}
|
|
||||||
std::string file_path = GetLocalFriendCodeSeedBPath();
|
|
||||||
if (!FileUtil::Exists(file_path)) {
|
|
||||||
return SecureDataLoadStatus::NotFound;
|
|
||||||
}
|
|
||||||
FileUtil::IOFile file(file_path, "rb");
|
|
||||||
if (!file.IsOpen()) {
|
|
||||||
return SecureDataLoadStatus::IOError;
|
|
||||||
}
|
|
||||||
if (file.GetSize() != sizeof(LocalFriendCodeSeedB)) {
|
|
||||||
return SecureDataLoadStatus::Invalid;
|
|
||||||
}
|
|
||||||
if (file.ReadBytes(&local_friend_code_seed_b, sizeof(LocalFriendCodeSeedB)) !=
|
|
||||||
sizeof(LocalFriendCodeSeedB)) {
|
|
||||||
return SecureDataLoadStatus::IOError;
|
|
||||||
}
|
|
||||||
local_friend_code_seed_b_loaded = true;
|
|
||||||
return SecureDataLoadStatus::Loaded;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Module::LoadMCUConfig() {
|
void Module::LoadMCUConfig() {
|
||||||
FileUtil::IOFile mcu_data_file(
|
FileUtil::IOFile mcu_data_file(
|
||||||
fmt::format("{}/mcu.dat", FileUtil::GetUserPath(FileUtil::UserPath::SysDataDir)), "rb");
|
fmt::format("{}/mcu.dat", FileUtil::GetUserPath(FileUtil::UserPath::SysDataDir)), "rb");
|
||||||
@@ -737,8 +616,6 @@ Module::Module(Core::System& system_) : system(system_) {
|
|||||||
SetEULAVersion(default_version);
|
SetEULAVersion(default_version);
|
||||||
UpdateConfigNANDSavegame();
|
UpdateConfigNANDSavegame();
|
||||||
}
|
}
|
||||||
LoadSecureInfoAFile();
|
|
||||||
LoadLocalFriendCodeSeedBFile();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Module::~Module() = default;
|
Module::~Module() = default;
|
||||||
|
|||||||
@@ -176,28 +176,6 @@ enum class AccessFlag : u16 {
|
|||||||
};
|
};
|
||||||
DECLARE_ENUM_FLAG_OPERATORS(AccessFlag);
|
DECLARE_ENUM_FLAG_OPERATORS(AccessFlag);
|
||||||
|
|
||||||
struct SecureInfoA {
|
|
||||||
std::array<u8, 0x100> signature;
|
|
||||||
u8 region;
|
|
||||||
u8 unknown;
|
|
||||||
std::array<u8, 0xF> serial_number;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(SecureInfoA) == 0x111);
|
|
||||||
|
|
||||||
struct LocalFriendCodeSeedB {
|
|
||||||
std::array<u8, 0x100> signature;
|
|
||||||
u64 unknown;
|
|
||||||
u64 friend_code_seed;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(LocalFriendCodeSeedB) == 0x110);
|
|
||||||
|
|
||||||
enum class SecureDataLoadStatus {
|
|
||||||
Loaded,
|
|
||||||
NotFound,
|
|
||||||
Invalid,
|
|
||||||
IOError,
|
|
||||||
};
|
|
||||||
|
|
||||||
class Module final {
|
class Module final {
|
||||||
public:
|
public:
|
||||||
Module(Core::System& system_);
|
Module(Core::System& system_);
|
||||||
@@ -252,18 +230,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
void SecureInfoGetByte101(Kernel::HLERequestContext& ctx);
|
void SecureInfoGetByte101(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
/**
|
|
||||||
* CFG::SecureInfoGetSerialNo service function
|
|
||||||
* Inputs:
|
|
||||||
* 1 : Buffer Size
|
|
||||||
* 2-3: Output mapped buffer
|
|
||||||
* Outputs:
|
|
||||||
* 0 : Result Header code
|
|
||||||
* 1 : Result of function, 0 on success, otherwise error code
|
|
||||||
* 2-3 : Output mapped buffer
|
|
||||||
*/
|
|
||||||
void SecureInfoGetSerialNo(Kernel::HLERequestContext& ctx);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CFG::SetUUIDClockSequence service function
|
* CFG::SetUUIDClockSequence service function
|
||||||
* Inputs:
|
* Inputs:
|
||||||
@@ -379,27 +345,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
void UpdateConfigNANDSavegame(Kernel::HLERequestContext& ctx);
|
void UpdateConfigNANDSavegame(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
/**
|
|
||||||
* CFG::GetLocalFriendCodeSeedData service function
|
|
||||||
* Inputs:
|
|
||||||
* 1 : Buffer Size
|
|
||||||
* 2-3: Output mapped buffer
|
|
||||||
* Outputs:
|
|
||||||
* 0 : Result Header code
|
|
||||||
* 1 : Result of function, 0 on success, otherwise error code
|
|
||||||
*/
|
|
||||||
void GetLocalFriendCodeSeedData(Kernel::HLERequestContext& ctx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CFG::GetLocalFriendCodeSeed service function
|
|
||||||
* Inputs:
|
|
||||||
* Outputs:
|
|
||||||
* 0 : Result Header code
|
|
||||||
* 1 : Result of function, 0 on success, otherwise error code
|
|
||||||
* 2-3 : Friend code seed
|
|
||||||
*/
|
|
||||||
void GetLocalFriendCodeSeed(Kernel::HLERequestContext& ctx);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CFG::FormatConfig service function
|
* CFG::FormatConfig service function
|
||||||
* Inputs:
|
* Inputs:
|
||||||
@@ -630,34 +575,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
Result UpdateConfigNANDSavegame();
|
Result UpdateConfigNANDSavegame();
|
||||||
|
|
||||||
/**
|
|
||||||
* Invalidates the loaded secure data so that it is loaded again.
|
|
||||||
*/
|
|
||||||
void InvalidateSecureData();
|
|
||||||
/**
|
|
||||||
* Loads the LocalFriendCodeSeed_B file from NAND.
|
|
||||||
* @returns LocalFriendCodeSeedBLoadStatus indicating the file load status.
|
|
||||||
*/
|
|
||||||
SecureDataLoadStatus LoadSecureInfoAFile();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the LocalFriendCodeSeed_B file from NAND.
|
|
||||||
* @returns LocalFriendCodeSeedBLoadStatus indicating the file load status.
|
|
||||||
*/
|
|
||||||
SecureDataLoadStatus LoadLocalFriendCodeSeedBFile();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the SecureInfo_A path in the host filesystem
|
|
||||||
* @returns std::string SecureInfo_A path in the host filesystem
|
|
||||||
*/
|
|
||||||
std::string GetSecureInfoAPath();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the LocalFriendCodeSeed_B path in the host filesystem
|
|
||||||
* @returns std::string LocalFriendCodeSeed_B path in the host filesystem
|
|
||||||
*/
|
|
||||||
std::string GetLocalFriendCodeSeedBPath();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves MCU specific data
|
* Saves MCU specific data
|
||||||
*/
|
*/
|
||||||
@@ -673,10 +590,6 @@ private:
|
|||||||
std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer;
|
std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer;
|
||||||
std::unique_ptr<FileSys::ArchiveBackend> cfg_system_save_data_archive;
|
std::unique_ptr<FileSys::ArchiveBackend> cfg_system_save_data_archive;
|
||||||
u32 preferred_region_code = 0;
|
u32 preferred_region_code = 0;
|
||||||
bool secure_info_a_loaded = false;
|
|
||||||
SecureInfoA secure_info_a;
|
|
||||||
bool local_friend_code_seed_b_loaded = false;
|
|
||||||
LocalFriendCodeSeedB local_friend_code_seed_b;
|
|
||||||
bool preferred_region_chosen = false;
|
bool preferred_region_chosen = false;
|
||||||
MCUData mcu_data{};
|
MCUData mcu_data{};
|
||||||
|
|
||||||
|
|||||||
@@ -28,11 +28,11 @@ CFG_I::CFG_I(std::shared_ptr<Module> cfg) : Module::Interface(std::move(cfg), "c
|
|||||||
{0x0401, &CFG_I::GetSystemConfig, "GetSystemConfig"},
|
{0x0401, &CFG_I::GetSystemConfig, "GetSystemConfig"},
|
||||||
{0x0402, &CFG_I::SetSystemConfig, "SetSystemConfig"},
|
{0x0402, &CFG_I::SetSystemConfig, "SetSystemConfig"},
|
||||||
{0x0403, &CFG_I::UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
|
{0x0403, &CFG_I::UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
|
||||||
{0x0404, &CFG_I::GetLocalFriendCodeSeedData, "GetLocalFriendCodeSeedData"},
|
{0x0404, nullptr, "GetLocalFriendCodeSeedData"},
|
||||||
{0x0405, &CFG_I::GetLocalFriendCodeSeed, "GetLocalFriendCodeSeed"},
|
{0x0405, nullptr, "GetLocalFriendCodeSeed"},
|
||||||
{0x0406, &CFG_I::GetRegion, "GetRegion"},
|
{0x0406, &CFG_I::GetRegion, "GetRegion"},
|
||||||
{0x0407, &CFG_I::SecureInfoGetByte101, "SecureInfoGetByte101"},
|
{0x0407, &CFG_I::SecureInfoGetByte101, "SecureInfoGetByte101"},
|
||||||
{0x0408, &CFG_I::SecureInfoGetSerialNo, "SecureInfoGetSerialNo"},
|
{0x0408, nullptr, "SecureInfoGetSerialNo"},
|
||||||
{0x0409, nullptr, "UpdateConfigBlk00040003"},
|
{0x0409, nullptr, "UpdateConfigBlk00040003"},
|
||||||
// cfg:i
|
// cfg:i
|
||||||
{0x0801, &CFG_I::GetSystemConfig, "GetSystemConfig"},
|
{0x0801, &CFG_I::GetSystemConfig, "GetSystemConfig"},
|
||||||
|
|||||||
@@ -28,11 +28,11 @@ CFG_S::CFG_S(std::shared_ptr<Module> cfg) : Module::Interface(std::move(cfg), "c
|
|||||||
{0x0401, &CFG_S::GetSystemConfig, "GetSystemConfig"},
|
{0x0401, &CFG_S::GetSystemConfig, "GetSystemConfig"},
|
||||||
{0x0402, &CFG_S::SetSystemConfig, "SetSystemConfig"},
|
{0x0402, &CFG_S::SetSystemConfig, "SetSystemConfig"},
|
||||||
{0x0403, &CFG_S::UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
|
{0x0403, &CFG_S::UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
|
||||||
{0x0404, &CFG_S::GetLocalFriendCodeSeedData, "GetLocalFriendCodeSeedData"},
|
{0x0404, nullptr, "GetLocalFriendCodeSeedData"},
|
||||||
{0x0405, &CFG_S::GetLocalFriendCodeSeed, "GetLocalFriendCodeSeed"},
|
{0x0405, nullptr, "GetLocalFriendCodeSeed"},
|
||||||
{0x0406, &CFG_S::GetRegion, "GetRegion"},
|
{0x0406, &CFG_S::GetRegion, "GetRegion"},
|
||||||
{0x0407, &CFG_S::SecureInfoGetByte101, "SecureInfoGetByte101"},
|
{0x0407, &CFG_S::SecureInfoGetByte101, "SecureInfoGetByte101"},
|
||||||
{0x0408, &CFG_S::SecureInfoGetSerialNo, "SecureInfoGetSerialNo"},
|
{0x0408, nullptr, "SecureInfoGetSerialNo"},
|
||||||
{0x0409, nullptr, "UpdateConfigBlk00040003"},
|
{0x0409, nullptr, "UpdateConfigBlk00040003"},
|
||||||
{0x040D, &CFG_S::SetUUIDClockSequence, "SetUUIDClockSequence"},
|
{0x040D, &CFG_S::SetUUIDClockSequence, "SetUUIDClockSequence"},
|
||||||
{0x040E, &CFG_S::GetUUIDClockSequence, "GetUUIDClockSequence"},
|
{0x040E, &CFG_S::GetUUIDClockSequence, "GetUUIDClockSequence"},
|
||||||
|
|||||||
@@ -17,6 +17,9 @@
|
|||||||
#include <boost/serialization/unordered_map.hpp>
|
#include <boost/serialization/unordered_map.hpp>
|
||||||
#include <boost/serialization/vector.hpp>
|
#include <boost/serialization/vector.hpp>
|
||||||
#include <boost/serialization/weak_ptr.hpp>
|
#include <boost/serialization/weak_ptr.hpp>
|
||||||
|
#if defined(__ANDROID__)
|
||||||
|
#include <ifaddrs.h>
|
||||||
|
#endif
|
||||||
#include <httplib.h>
|
#include <httplib.h>
|
||||||
#include "core/hle/ipc_helpers.h"
|
#include "core/hle/ipc_helpers.h"
|
||||||
#include "core/hle/kernel/shared_memory.h"
|
#include "core/hle/kernel/shared_memory.h"
|
||||||
|
|||||||
@@ -838,7 +838,7 @@ void SOC_U::Bind(Kernel::HLERequestContext& ctx) {
|
|||||||
SocketHolder& holder = socket_holder_optional->get();
|
SocketHolder& holder = socket_holder_optional->get();
|
||||||
|
|
||||||
CTRSockAddr ctr_sock_addr;
|
CTRSockAddr ctr_sock_addr;
|
||||||
std::memcpy(&ctr_sock_addr, sock_addr_buf.data(), std::min<size_t>(len, sizeof(ctr_sock_addr)));
|
std::memcpy(&ctr_sock_addr, sock_addr_buf.data(), len);
|
||||||
|
|
||||||
sockaddr sock_addr = CTRSockAddr::ToPlatform(ctr_sock_addr);
|
sockaddr sock_addr = CTRSockAddr::ToPlatform(ctr_sock_addr);
|
||||||
|
|
||||||
@@ -977,7 +977,7 @@ void SOC_U::Accept(Kernel::HLERequestContext& ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ctr_addr_buf.size() > async_data->max_addr_len) {
|
if (ctr_addr_buf.size() > async_data->max_addr_len) {
|
||||||
LOG_DEBUG(Service_SOC, "CTRSockAddr is too long, truncating data.");
|
LOG_WARNING(Frontend, "CTRSockAddr is too long, truncating data.");
|
||||||
ctr_addr_buf.resize(async_data->max_addr_len);
|
ctr_addr_buf.resize(async_data->max_addr_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1107,8 +1107,7 @@ void SOC_U::SendToOther(Kernel::HLERequestContext& ctx) {
|
|||||||
s32 ret = -1;
|
s32 ret = -1;
|
||||||
if (addr_len > 0) {
|
if (addr_len > 0) {
|
||||||
CTRSockAddr ctr_dest_addr;
|
CTRSockAddr ctr_dest_addr;
|
||||||
std::memcpy(&ctr_dest_addr, dest_addr_buffer.data(),
|
std::memcpy(&ctr_dest_addr, dest_addr_buffer.data(), sizeof(ctr_dest_addr));
|
||||||
std::min<size_t>(addr_len, sizeof(ctr_dest_addr)));
|
|
||||||
sockaddr dest_addr = CTRSockAddr::ToPlatform(ctr_dest_addr);
|
sockaddr dest_addr = CTRSockAddr::ToPlatform(ctr_dest_addr);
|
||||||
ret = static_cast<s32>(::sendto(holder.socket_fd,
|
ret = static_cast<s32>(::sendto(holder.socket_fd,
|
||||||
reinterpret_cast<const char*>(input_buff.data()), len,
|
reinterpret_cast<const char*>(input_buff.data()), len,
|
||||||
@@ -1157,8 +1156,7 @@ s32 SOC_U::SendToImpl(SocketHolder& holder, u32 len, u32 flags, u32 addr_len,
|
|||||||
s32 ret = -1;
|
s32 ret = -1;
|
||||||
if (addr_len > 0) {
|
if (addr_len > 0) {
|
||||||
CTRSockAddr ctr_dest_addr;
|
CTRSockAddr ctr_dest_addr;
|
||||||
std::memcpy(&ctr_dest_addr, dest_addr_buff,
|
std::memcpy(&ctr_dest_addr, dest_addr_buff, sizeof(ctr_dest_addr));
|
||||||
std::min<size_t>(addr_len, sizeof(ctr_dest_addr)));
|
|
||||||
sockaddr dest_addr = CTRSockAddr::ToPlatform(ctr_dest_addr);
|
sockaddr dest_addr = CTRSockAddr::ToPlatform(ctr_dest_addr);
|
||||||
ret = static_cast<s32>(::sendto(holder.socket_fd,
|
ret = static_cast<s32>(::sendto(holder.socket_fd,
|
||||||
reinterpret_cast<const char*>(input_buff.data()), len,
|
reinterpret_cast<const char*>(input_buff.data()), len,
|
||||||
@@ -1308,8 +1306,7 @@ void SOC_U::RecvFromOther(Kernel::HLERequestContext& ctx) {
|
|||||||
async_data->len, async_data->flags, &src_addr, &src_addr_len));
|
async_data->len, async_data->flags, &src_addr, &src_addr_len));
|
||||||
if (async_data->ret >= 0 && src_addr_len > 0) {
|
if (async_data->ret >= 0 && src_addr_len > 0) {
|
||||||
ctr_src_addr = CTRSockAddr::FromPlatform(src_addr);
|
ctr_src_addr = CTRSockAddr::FromPlatform(src_addr);
|
||||||
std::memcpy(async_data->addr_buff.data(), &ctr_src_addr,
|
std::memcpy(async_data->addr_buff.data(), &ctr_src_addr, async_data->addr_len);
|
||||||
std::min<size_t>(async_data->addr_len, sizeof(ctr_src_addr)));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
async_data->ret = static_cast<s32>(
|
async_data->ret = static_cast<s32>(
|
||||||
@@ -1425,8 +1422,7 @@ void SOC_U::RecvFrom(Kernel::HLERequestContext& ctx) {
|
|||||||
async_data->len, async_data->flags, &src_addr, &src_addr_len));
|
async_data->len, async_data->flags, &src_addr, &src_addr_len));
|
||||||
if (async_data->ret >= 0 && src_addr_len > 0) {
|
if (async_data->ret >= 0 && src_addr_len > 0) {
|
||||||
ctr_src_addr = CTRSockAddr::FromPlatform(src_addr);
|
ctr_src_addr = CTRSockAddr::FromPlatform(src_addr);
|
||||||
std::memcpy(async_data->addr_buff.data(), &ctr_src_addr,
|
std::memcpy(async_data->addr_buff.data(), &ctr_src_addr, async_data->addr_len);
|
||||||
std::min<size_t>(async_data->addr_len, sizeof(ctr_src_addr)));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
async_data->ret = static_cast<s32>(
|
async_data->ret = static_cast<s32>(
|
||||||
@@ -1570,7 +1566,7 @@ void SOC_U::GetSockName(Kernel::HLERequestContext& ctx) {
|
|||||||
ret = TranslateError(GET_ERRNO);
|
ret = TranslateError(GET_ERRNO);
|
||||||
|
|
||||||
if (dest_addr_buff.size() > max_addr_len) {
|
if (dest_addr_buff.size() > max_addr_len) {
|
||||||
LOG_DEBUG(Service_SOC, "CTRSockAddr is too long, truncating data.");
|
LOG_WARNING(Frontend, "CTRSockAddr is too long, truncating data.");
|
||||||
dest_addr_buff.resize(max_addr_len);
|
dest_addr_buff.resize(max_addr_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1712,7 +1708,7 @@ void SOC_U::GetPeerName(Kernel::HLERequestContext& ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dest_addr_buff.size() > max_addr_len) {
|
if (dest_addr_buff.size() > max_addr_len) {
|
||||||
LOG_DEBUG(Service_SOC, "CTRSockAddr is too long, truncating data.");
|
LOG_WARNING(Frontend, "CTRSockAddr is too long, truncating data.");
|
||||||
dest_addr_buff.resize(max_addr_len);
|
dest_addr_buff.resize(max_addr_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1728,7 +1724,7 @@ void SOC_U::GetPeerName(Kernel::HLERequestContext& ctx) {
|
|||||||
void SOC_U::Connect(Kernel::HLERequestContext& ctx) {
|
void SOC_U::Connect(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
const auto socket_handle = rp.Pop<u32>();
|
const auto socket_handle = rp.Pop<u32>();
|
||||||
const auto input_addr_len = rp.Pop<u32>();
|
[[maybe_unused]] const auto input_addr_len = rp.Pop<u32>();
|
||||||
const u32 pid = rp.PopPID();
|
const u32 pid = rp.PopPID();
|
||||||
auto input_addr_buf = rp.PopStaticBuffer();
|
auto input_addr_buf = rp.PopStaticBuffer();
|
||||||
|
|
||||||
@@ -1755,8 +1751,7 @@ void SOC_U::Connect(Kernel::HLERequestContext& ctx) {
|
|||||||
async_data->pid = pid;
|
async_data->pid = pid;
|
||||||
|
|
||||||
CTRSockAddr ctr_input_addr;
|
CTRSockAddr ctr_input_addr;
|
||||||
std::memcpy(&ctr_input_addr, input_addr_buf.data(),
|
std::memcpy(&ctr_input_addr, input_addr_buf.data(), sizeof(ctr_input_addr));
|
||||||
std::min<size_t>(input_addr_len, sizeof(ctr_input_addr)));
|
|
||||||
|
|
||||||
async_data->input_addr = CTRSockAddr::ToPlatform(ctr_input_addr);
|
async_data->input_addr = CTRSockAddr::ToPlatform(ctr_input_addr);
|
||||||
async_data->socket_handle = socket_handle;
|
async_data->socket_handle = socket_handle;
|
||||||
|
|||||||
@@ -76,9 +76,9 @@ public:
|
|||||||
public:
|
public:
|
||||||
Uniforms uniforms;
|
Uniforms uniforms;
|
||||||
PackedAttribute uniform_queue;
|
PackedAttribute uniform_queue;
|
||||||
ProgramCode program_code{};
|
ProgramCode program_code;
|
||||||
SwizzleData swizzle_data{};
|
SwizzleData swizzle_data;
|
||||||
u32 entry_point{};
|
u32 entry_point;
|
||||||
const void* cached_shader{};
|
const void* cached_shader{};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -285,20 +285,19 @@ std::pair<Common::Vec4<u8>, Common::Vec4<u8>> ComputeFragmentsColors(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool shadow_primary_enable =
|
auto diffuse =
|
||||||
lighting.config0.shadow_primary && !lighting.IsShadowDisabled(num);
|
(light_config.diffuse.ToVec3f() * dot_product + light_config.ambient.ToVec3f()) *
|
||||||
const bool shadow_secondary_enable =
|
|
||||||
lighting.config0.shadow_secondary && !lighting.IsShadowDisabled(num);
|
|
||||||
const auto shadow_primary =
|
|
||||||
shadow_primary_enable ? shadow.xyz() : Common::MakeVec(1.f, 1.f, 1.f);
|
|
||||||
const auto shadow_secondary =
|
|
||||||
shadow_secondary_enable ? shadow.xyz() : Common::MakeVec(1.f, 1.f, 1.f);
|
|
||||||
|
|
||||||
const auto diffuse = (light_config.diffuse.ToVec3f() * dot_product * shadow_primary +
|
|
||||||
light_config.ambient.ToVec3f()) *
|
|
||||||
dist_atten * spot_atten;
|
dist_atten * spot_atten;
|
||||||
const auto specular = (specular_0 + specular_1) * clamp_highlights * dist_atten *
|
auto specular = (specular_0 + specular_1) * clamp_highlights * dist_atten * spot_atten;
|
||||||
spot_atten * shadow_secondary;
|
|
||||||
|
if (!lighting.IsShadowDisabled(num)) {
|
||||||
|
if (lighting.config0.shadow_primary) {
|
||||||
|
diffuse = diffuse * shadow.xyz();
|
||||||
|
}
|
||||||
|
if (lighting.config0.shadow_secondary) {
|
||||||
|
specular = specular * shadow.xyz();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
diffuse_sum += Common::MakeVec(diffuse, 0.0f);
|
diffuse_sum += Common::MakeVec(diffuse, 0.0f);
|
||||||
specular_sum += Common::MakeVec(specular, 0.0f);
|
specular_sum += Common::MakeVec(specular, 0.0f);
|
||||||
|
|||||||
@@ -629,7 +629,7 @@ void Instance::CreateAllocator() {
|
|||||||
.device = *device,
|
.device = *device,
|
||||||
.pVulkanFunctions = &functions,
|
.pVulkanFunctions = &functions,
|
||||||
.instance = *instance,
|
.instance = *instance,
|
||||||
.vulkanApiVersion = properties.apiVersion,
|
.vulkanApiVersion = vk::enumerateInstanceVersion(),
|
||||||
};
|
};
|
||||||
|
|
||||||
const VkResult result = vmaCreateAllocator(&allocator_info, &allocator);
|
const VkResult result = vmaCreateAllocator(&allocator_info, &allocator);
|
||||||
|
|||||||
@@ -810,8 +810,8 @@ void FragmentModule::WriteLighting() {
|
|||||||
|
|
||||||
// Compute primary fragment color (diffuse lighting) function
|
// Compute primary fragment color (diffuse lighting) function
|
||||||
out += fmt::format(
|
out += fmt::format(
|
||||||
"diffuse_sum.rgb += (({}.diffuse * dot_product{}) + {}.ambient) * {} * {};\n",
|
"diffuse_sum.rgb += (({}.diffuse * dot_product) + {}.ambient) * {} * {}{};\n",
|
||||||
light_src, shadow_primary, light_src, dist_atten, spot_atten);
|
light_src, light_src, dist_atten, spot_atten, shadow_primary);
|
||||||
|
|
||||||
// Compute secondary fragment color (specular lighting) function
|
// Compute secondary fragment color (specular lighting) function
|
||||||
out += fmt::format("specular_sum.rgb += ({} + {}) * clamp_highlights * {} * {}{};\n",
|
out += fmt::format("specular_sum.rgb += ({} + {}) * clamp_highlights * {} * {}{};\n",
|
||||||
|
|||||||
@@ -768,7 +768,7 @@ void JitShader::Compile_LOOP(Instruction instr) {
|
|||||||
Label l_loop_start;
|
Label l_loop_start;
|
||||||
l(l_loop_start);
|
l(l_loop_start);
|
||||||
|
|
||||||
loop_break_labels.emplace_back(Label());
|
loop_break_labels.emplace_back(oaknut::Label());
|
||||||
Compile_Block(instr.flow_control.dest_offset + 1);
|
Compile_Block(instr.flow_control.dest_offset + 1);
|
||||||
ADD(LOOPCOUNT_REG, LOOPCOUNT_REG, LOOPINC); // Increment LOOPCOUNT_REG by Z-component
|
ADD(LOOPCOUNT_REG, LOOPCOUNT_REG, LOOPINC); // Increment LOOPCOUNT_REG by Z-component
|
||||||
SUBS(LOOPCOUNT, LOOPCOUNT, 1); // Increment loop count by 1
|
SUBS(LOOPCOUNT, LOOPCOUNT, 1); // Increment loop count by 1
|
||||||
@@ -922,7 +922,7 @@ void JitShader::Compile(const std::array<u32, MAX_PROGRAM_CODE_LENGTH>* program_
|
|||||||
swizzle_data = swizzle_data_;
|
swizzle_data = swizzle_data_;
|
||||||
|
|
||||||
// Reset flow control state
|
// Reset flow control state
|
||||||
program = xptr<CompiledShader*>();
|
program = (CompiledShader*)current_address();
|
||||||
program_counter = 0;
|
program_counter = 0;
|
||||||
loop_depth = 0;
|
loop_depth = 0;
|
||||||
instruction_labels.fill(Label());
|
instruction_labels.fill(Label());
|
||||||
@@ -968,13 +968,15 @@ void JitShader::Compile(const std::array<u32, MAX_PROGRAM_CODE_LENGTH>* program_
|
|||||||
protect();
|
protect();
|
||||||
invalidate_all();
|
invalidate_all();
|
||||||
|
|
||||||
const std::size_t code_size = static_cast<std::size_t>(offset());
|
const std::size_t code_size =
|
||||||
|
current_address() - reinterpret_cast<uintptr_t>(oaknut::CodeBlock::ptr());
|
||||||
|
|
||||||
ASSERT_MSG(code_size <= MAX_SHADER_SIZE, "Compiled a shader that exceeds the allocated size!");
|
ASSERT_MSG(code_size <= MAX_SHADER_SIZE, "Compiled a shader that exceeds the allocated size!");
|
||||||
LOG_DEBUG(HW_GPU, "Compiled shader size={}", code_size);
|
LOG_DEBUG(HW_GPU, "Compiled shader size={}", code_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
JitShader::JitShader() : CodeBlock(MAX_SHADER_SIZE), CodeGenerator(CodeBlock::ptr()) {
|
JitShader::JitShader()
|
||||||
|
: oaknut::CodeBlock(MAX_SHADER_SIZE), oaknut::CodeGenerator(oaknut::CodeBlock::ptr()) {
|
||||||
unprotect();
|
unprotect();
|
||||||
CompilePrelude();
|
CompilePrelude();
|
||||||
}
|
}
|
||||||
@@ -984,8 +986,8 @@ void JitShader::CompilePrelude() {
|
|||||||
exp2_subroutine = CompilePrelude_Exp2();
|
exp2_subroutine = CompilePrelude_Exp2();
|
||||||
}
|
}
|
||||||
|
|
||||||
Label JitShader::CompilePrelude_Log2() {
|
oaknut::Label JitShader::CompilePrelude_Log2() {
|
||||||
Label subroutine;
|
oaknut::Label subroutine;
|
||||||
|
|
||||||
// We perform this approximation by first performing a range reduction into the range
|
// We perform this approximation by first performing a range reduction into the range
|
||||||
// [1.0, 2.0). A minimax polynomial which was fit for the function log2(x) / (x - 1) is then
|
// [1.0, 2.0). A minimax polynomial which was fit for the function log2(x) / (x - 1) is then
|
||||||
@@ -993,40 +995,44 @@ Label JitShader::CompilePrelude_Log2() {
|
|||||||
// range. Coefficients for the minimax polynomial.
|
// range. Coefficients for the minimax polynomial.
|
||||||
// f(x) computes approximately log2(x) / (x - 1).
|
// f(x) computes approximately log2(x) / (x - 1).
|
||||||
// f(x) = c4 + x * (c3 + x * (c2 + x * (c1 + x * c0)).
|
// f(x) = c4 + x * (c3 + x * (c2 + x * (c1 + x * c0)).
|
||||||
|
oaknut::Label c0;
|
||||||
align(16);
|
align(16);
|
||||||
const void* c0 = xptr<const void*>();
|
l(c0);
|
||||||
dw(0x3d74552f);
|
dw(0x3d74552f);
|
||||||
|
|
||||||
align(16);
|
align(16);
|
||||||
const void* c14 = xptr<const void*>();
|
oaknut::Label c14;
|
||||||
|
l(c14);
|
||||||
dw(0xbeee7397);
|
dw(0xbeee7397);
|
||||||
dw(0x3fbd96dd);
|
dw(0x3fbd96dd);
|
||||||
dw(0xc02153f6);
|
dw(0xc02153f6);
|
||||||
dw(0x4038d96c);
|
dw(0x4038d96c);
|
||||||
|
|
||||||
align(16);
|
align(16);
|
||||||
const void* negative_infinity_vector = xptr<const void*>();
|
oaknut::Label negative_infinity_vector;
|
||||||
|
l(negative_infinity_vector);
|
||||||
dw(0xff800000);
|
dw(0xff800000);
|
||||||
dw(0xff800000);
|
dw(0xff800000);
|
||||||
dw(0xff800000);
|
dw(0xff800000);
|
||||||
dw(0xff800000);
|
dw(0xff800000);
|
||||||
const void* default_qnan_vector = xptr<const void*>();
|
oaknut::Label default_qnan_vector;
|
||||||
|
l(default_qnan_vector);
|
||||||
dw(0x7fc00000);
|
dw(0x7fc00000);
|
||||||
dw(0x7fc00000);
|
dw(0x7fc00000);
|
||||||
dw(0x7fc00000);
|
dw(0x7fc00000);
|
||||||
dw(0x7fc00000);
|
dw(0x7fc00000);
|
||||||
|
|
||||||
Label input_is_nan, input_is_zero, input_out_of_range;
|
oaknut::Label input_is_nan, input_is_zero, input_out_of_range;
|
||||||
|
|
||||||
align(16);
|
align(16);
|
||||||
l(input_out_of_range);
|
l(input_out_of_range);
|
||||||
B(Cond::EQ, input_is_zero);
|
B(Cond::EQ, input_is_zero);
|
||||||
MOVP2R(XSCRATCH0, default_qnan_vector);
|
MOVP2R(XSCRATCH0, default_qnan_vector.ptr<void*>());
|
||||||
LDR(SRC1, XSCRATCH0);
|
LDR(SRC1, XSCRATCH0);
|
||||||
RET();
|
RET();
|
||||||
|
|
||||||
l(input_is_zero);
|
l(input_is_zero);
|
||||||
MOVP2R(XSCRATCH0, negative_infinity_vector);
|
MOVP2R(XSCRATCH0, negative_infinity_vector.ptr<void*>());
|
||||||
LDR(SRC1, XSCRATCH0);
|
LDR(SRC1, XSCRATCH0);
|
||||||
RET();
|
RET();
|
||||||
|
|
||||||
@@ -1058,14 +1064,14 @@ Label JitShader::CompilePrelude_Log2() {
|
|||||||
UCVTF(VSCRATCH1.toS(), VSCRATCH1.toS());
|
UCVTF(VSCRATCH1.toS(), VSCRATCH1.toS());
|
||||||
// VSCRATCH1 now contains the exponent of the input.
|
// VSCRATCH1 now contains the exponent of the input.
|
||||||
|
|
||||||
MOVP2R(XSCRATCH0, c0);
|
MOVP2R(XSCRATCH0, c0.ptr<void*>());
|
||||||
LDR(XSCRATCH0.toW(), XSCRATCH0);
|
LDR(XSCRATCH0.toW(), XSCRATCH0);
|
||||||
MOV(VSCRATCH0.Selem()[0], XSCRATCH0.toW());
|
MOV(VSCRATCH0.Selem()[0], XSCRATCH0.toW());
|
||||||
|
|
||||||
// Complete computation of polynomial
|
// Complete computation of polynomial
|
||||||
// Load C1,C2,C3,C4 into a single scratch register
|
// Load C1,C2,C3,C4 into a single scratch register
|
||||||
const QReg C14 = SRC2;
|
const QReg C14 = SRC2;
|
||||||
MOVP2R(XSCRATCH0, c14);
|
MOVP2R(XSCRATCH0, c14.ptr<void*>());
|
||||||
LDR(C14, XSCRATCH0);
|
LDR(C14, XSCRATCH0);
|
||||||
FMUL(VSCRATCH0.toS(), VSCRATCH0.toS(), SRC1.toS());
|
FMUL(VSCRATCH0.toS(), VSCRATCH0.toS(), SRC1.toS());
|
||||||
FMLA(VSCRATCH0.toS(), ONE.toS(), C14.Selem()[0]);
|
FMLA(VSCRATCH0.toS(), ONE.toS(), C14.Selem()[0]);
|
||||||
@@ -1091,32 +1097,32 @@ Label JitShader::CompilePrelude_Log2() {
|
|||||||
return subroutine;
|
return subroutine;
|
||||||
}
|
}
|
||||||
|
|
||||||
Label JitShader::CompilePrelude_Exp2() {
|
oaknut::Label JitShader::CompilePrelude_Exp2() {
|
||||||
Label subroutine;
|
oaknut::Label subroutine;
|
||||||
|
|
||||||
// This approximation first performs a range reduction into the range [-0.5, 0.5). A minmax
|
// This approximation first performs a range reduction into the range [-0.5, 0.5). A minmax
|
||||||
// polynomial which was fit for the function exp2(x) is then evaluated. We then restore the
|
// polynomial which was fit for the function exp2(x) is then evaluated. We then restore the
|
||||||
// result into the appropriate range.
|
// result into the appropriate range.
|
||||||
|
|
||||||
align(16);
|
align(16);
|
||||||
const void* input_max = xptr<const void*>();
|
const void* input_max = (const void*)current_address();
|
||||||
dw(0x43010000);
|
dw(0x43010000);
|
||||||
const void* input_min = xptr<const void*>();
|
const void* input_min = (const void*)current_address();
|
||||||
dw(0xc2fdffff);
|
dw(0xc2fdffff);
|
||||||
const void* c0 = xptr<const void*>();
|
const void* c0 = (const void*)current_address();
|
||||||
dw(0x3c5dbe69);
|
dw(0x3c5dbe69);
|
||||||
const void* half = xptr<const void*>();
|
const void* half = (const void*)current_address();
|
||||||
dw(0x3f000000);
|
dw(0x3f000000);
|
||||||
const void* c1 = xptr<const void*>();
|
const void* c1 = (const void*)current_address();
|
||||||
dw(0x3d5509f9);
|
dw(0x3d5509f9);
|
||||||
const void* c2 = xptr<const void*>();
|
const void* c2 = (const void*)current_address();
|
||||||
dw(0x3e773cc5);
|
dw(0x3e773cc5);
|
||||||
const void* c3 = xptr<const void*>();
|
const void* c3 = (const void*)current_address();
|
||||||
dw(0x3f3168b3);
|
dw(0x3f3168b3);
|
||||||
const void* c4 = xptr<const void*>();
|
const void* c4 = (const void*)current_address();
|
||||||
dw(0x3f800016);
|
dw(0x3f800016);
|
||||||
|
|
||||||
Label ret_label;
|
oaknut::Label ret_label;
|
||||||
|
|
||||||
align(16);
|
align(16);
|
||||||
l(subroutine);
|
l(subroutine);
|
||||||
|
|||||||
@@ -37,14 +37,12 @@ constexpr std::size_t MAX_SHADER_SIZE = MAX_PROGRAM_CODE_LENGTH * 256;
|
|||||||
* This class implements the shader JIT compiler. It recompiles a Pica shader program into x86_64
|
* This class implements the shader JIT compiler. It recompiles a Pica shader program into x86_64
|
||||||
* code that can be executed on the host machine directly.
|
* code that can be executed on the host machine directly.
|
||||||
*/
|
*/
|
||||||
class JitShader : private oaknut::CodeBlock, private oaknut::CodeGenerator {
|
class JitShader : private oaknut::CodeBlock, public oaknut::CodeGenerator {
|
||||||
public:
|
public:
|
||||||
JitShader();
|
JitShader();
|
||||||
|
|
||||||
void Run(const ShaderSetup& setup, ShaderUnit& state, u32 offset) const {
|
void Run(const ShaderSetup& setup, ShaderUnit& state, u32 offset) const {
|
||||||
program(&setup.uniforms, &state,
|
program(&setup.uniforms, &state, instruction_labels[offset].ptr<const std::byte*>());
|
||||||
reinterpret_cast<std::byte*>(oaknut::CodeBlock::ptr()) +
|
|
||||||
instruction_labels[offset].offset());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compile(const std::array<u32, MAX_PROGRAM_CODE_LENGTH>* program_code,
|
void Compile(const std::array<u32, MAX_PROGRAM_CODE_LENGTH>* program_code,
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ create_target_directory_groups(web_service)
|
|||||||
target_compile_definitions(web_service PUBLIC -DENABLE_WEB_SERVICE)
|
target_compile_definitions(web_service PUBLIC -DENABLE_WEB_SERVICE)
|
||||||
target_link_libraries(web_service PRIVATE citra_common network json-headers httplib cpp-jwt)
|
target_link_libraries(web_service PRIVATE citra_common network json-headers httplib cpp-jwt)
|
||||||
target_link_libraries(web_service PUBLIC ${OPENSSL_LIBS})
|
target_link_libraries(web_service PUBLIC ${OPENSSL_LIBS})
|
||||||
if(WIN32)
|
if (ANDROID)
|
||||||
|
target_link_libraries(web_service PRIVATE ifaddrs)
|
||||||
|
elseif(WIN32)
|
||||||
target_link_libraries(web_service PRIVATE crypt32)
|
target_link_libraries(web_service PRIVATE crypt32)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,9 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
#if defined(__ANDROID__)
|
||||||
|
#include <ifaddrs.h>
|
||||||
|
#endif
|
||||||
#include <httplib.h>
|
#include <httplib.h>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
|||||||
Reference in New Issue
Block a user