Author SHA1 Message Date
PabloMK7 e0dd6e96f1 Add BUILD_PLATFORM 2024-01-31 10:09:18 +01:00
PabloMK7 f35fd80ebe Add HOST_TICK to svcGetSystemInfo CITRA_INFORMATION type 2024-01-25 23:50:17 +01:00
70 changed files with 10214 additions and 11583 deletions
+3 -3
View File
@@ -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
View File
@@ -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)
+395 -459
View File
File diff suppressed because it is too large Load Diff
+705 -774
View File
File diff suppressed because it is too large Load Diff
+395 -459
View File
File diff suppressed because it is too large Load Diff
+395 -459
View File
File diff suppressed because it is too large Load Diff
+395 -459
View File
File diff suppressed because it is too large Load Diff
+414 -478
View File
File diff suppressed because it is too large Load Diff
+695 -759
View File
File diff suppressed because it is too large Load Diff
+395 -459
View File
File diff suppressed because it is too large Load Diff
+395 -459
View File
File diff suppressed because it is too large Load Diff
+395 -459
View File
File diff suppressed because it is too large Load Diff
+395 -459
View File
File diff suppressed because it is too large Load Diff
+395 -459
View File
File diff suppressed because it is too large Load Diff
+395 -459
View File
File diff suppressed because it is too large Load Diff
+395 -459
View File
File diff suppressed because it is too large Load Diff
+395 -459
View File
File diff suppressed because it is too large Load Diff
+450 -517
View File
File diff suppressed because it is too large Load Diff
+395 -459
View File
File diff suppressed because it is too large Load Diff
+395 -459
View File
File diff suppressed because it is too large Load Diff
+395 -459
View File
File diff suppressed because it is too large Load Diff
+395 -459
View File
File diff suppressed because it is too large Load Diff
+397 -461
View File
File diff suppressed because it is too large Load Diff
+395 -459
View File
File diff suppressed because it is too large Load Diff
+5
View File
@@ -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
View File
@@ -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})
+600
View File
@@ -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);
}
}
+54
View File
@@ -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
@@ -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(
+7 -2
View File
@@ -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
View File
@@ -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) {
-1
View File
@@ -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
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -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;
} }
+4 -3
View File
@@ -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;
+33
View File
@@ -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));
+1 -98
View File
@@ -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);
-64
View File
@@ -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
+2 -2
View File
@@ -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"},
+1 -1
View File
@@ -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"},
+1 -1
View File
@@ -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"},
+3 -126
View File
@@ -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;
-87
View File
@@ -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{};
+3 -3
View File
@@ -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"},
+3 -3
View File
@@ -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"},
+3
View File
@@ -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"
+10 -15
View File
@@ -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;
+3 -3
View File
@@ -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,
+3 -1
View File
@@ -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()
+3
View File
@@ -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"