Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10df158dc6 | ||
|
|
a110843115 |
@@ -59,7 +59,7 @@ jobs:
|
||||
name: ${{ env.OS }}-${{ env.TARGET }}
|
||||
path: artifacts/
|
||||
macos:
|
||||
runs-on: ${{ (matrix.target == 'x86_64' && 'macos-13') || 'macos-14' }}
|
||||
runs-on: macos-13
|
||||
strategy:
|
||||
matrix:
|
||||
target: ["x86_64", "arm64"]
|
||||
@@ -92,7 +92,7 @@ jobs:
|
||||
path: ${{ env.OS }}-${{ env.TARGET }}
|
||||
key: ${{ runner.os }}-${{ matrix.target }}-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
macos-universal:
|
||||
runs-on: macos-14
|
||||
runs-on: macos-13
|
||||
needs: macos
|
||||
env:
|
||||
OS: macos
|
||||
@@ -233,7 +233,7 @@ jobs:
|
||||
name: ${{ env.OS }}-${{ env.TARGET }}
|
||||
path: src/android/app/artifacts/
|
||||
ios:
|
||||
runs-on: macos-14
|
||||
runs-on: macos-13
|
||||
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
env:
|
||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||
|
||||
+2
-1
@@ -74,7 +74,8 @@ CMAKE_DEPENDENT_OPTION(ENABLE_DEDICATED_ROOM "Enable generating dedicated room e
|
||||
option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
|
||||
option(ENABLE_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)
|
||||
|
||||
CMAKE_DEPENDENT_OPTION(ENABLE_LIBUSB "Enable libusb for GameCube Adapter support" ON "NOT IOS" OFF)
|
||||
|
||||
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+705
-774
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+414
-478
File diff suppressed because it is too large
Load Diff
Vendored
+695
-759
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+450
-517
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+397
-461
File diff suppressed because it is too large
Load Diff
Vendored
+395
-459
File diff suppressed because it is too large
Load Diff
Vendored
+5
@@ -288,6 +288,11 @@ endif()
|
||||
target_compile_options(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT)
|
||||
target_link_libraries(httplib INTERFACE ${OPENSSL_LIBRARIES})
|
||||
|
||||
if(ANDROID)
|
||||
add_subdirectory(android-ifaddrs)
|
||||
target_link_libraries(httplib INTERFACE ifaddrs)
|
||||
endif()
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
add_subdirectory(gamemode)
|
||||
endif()
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
add_library(ifaddrs
|
||||
ifaddrs.c
|
||||
ifaddrs.h
|
||||
)
|
||||
|
||||
create_target_directory_groups(ifaddrs)
|
||||
|
||||
target_include_directories(ifaddrs INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
Vendored
+600
@@ -0,0 +1,600 @@
|
||||
/*
|
||||
Copyright (c) 2013, Kenneth MacKay
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ifaddrs.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
|
||||
typedef struct NetlinkList
|
||||
{
|
||||
struct NetlinkList *m_next;
|
||||
struct nlmsghdr *m_data;
|
||||
unsigned int m_size;
|
||||
} NetlinkList;
|
||||
|
||||
static int netlink_socket(void)
|
||||
{
|
||||
int l_socket = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
if(l_socket < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_nl l_addr;
|
||||
memset(&l_addr, 0, sizeof(l_addr));
|
||||
l_addr.nl_family = AF_NETLINK;
|
||||
if(bind(l_socket, (struct sockaddr *)&l_addr, sizeof(l_addr)) < 0)
|
||||
{
|
||||
close(l_socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return l_socket;
|
||||
}
|
||||
|
||||
static int netlink_send(int p_socket, int p_request)
|
||||
{
|
||||
char l_buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + NLMSG_ALIGN(sizeof(struct rtgenmsg))];
|
||||
memset(l_buffer, 0, sizeof(l_buffer));
|
||||
struct nlmsghdr *l_hdr = (struct nlmsghdr *)l_buffer;
|
||||
struct rtgenmsg *l_msg = (struct rtgenmsg *)NLMSG_DATA(l_hdr);
|
||||
|
||||
l_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*l_msg));
|
||||
l_hdr->nlmsg_type = p_request;
|
||||
l_hdr->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
|
||||
l_hdr->nlmsg_pid = 0;
|
||||
l_hdr->nlmsg_seq = p_socket;
|
||||
l_msg->rtgen_family = AF_UNSPEC;
|
||||
|
||||
struct sockaddr_nl l_addr;
|
||||
memset(&l_addr, 0, sizeof(l_addr));
|
||||
l_addr.nl_family = AF_NETLINK;
|
||||
return (sendto(p_socket, l_hdr, l_hdr->nlmsg_len, 0, (struct sockaddr *)&l_addr, sizeof(l_addr)));
|
||||
}
|
||||
|
||||
static int netlink_recv(int p_socket, void *p_buffer, size_t p_len)
|
||||
{
|
||||
struct msghdr l_msg;
|
||||
struct iovec l_iov = { p_buffer, p_len };
|
||||
struct sockaddr_nl l_addr;
|
||||
int l_result;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
l_msg.msg_name = (void *)&l_addr;
|
||||
l_msg.msg_namelen = sizeof(l_addr);
|
||||
l_msg.msg_iov = &l_iov;
|
||||
l_msg.msg_iovlen = 1;
|
||||
l_msg.msg_control = NULL;
|
||||
l_msg.msg_controllen = 0;
|
||||
l_msg.msg_flags = 0;
|
||||
int l_result = recvmsg(p_socket, &l_msg, 0);
|
||||
|
||||
if(l_result < 0)
|
||||
{
|
||||
if(errno == EINTR)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
if(l_msg.msg_flags & MSG_TRUNC)
|
||||
{ // buffer was too small
|
||||
return -1;
|
||||
}
|
||||
return l_result;
|
||||
}
|
||||
}
|
||||
|
||||
static struct nlmsghdr *getNetlinkResponse(int p_socket, int *p_size, int *p_done)
|
||||
{
|
||||
size_t l_size = 4096;
|
||||
void *l_buffer = NULL;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
free(l_buffer);
|
||||
l_buffer = malloc(l_size);
|
||||
|
||||
int l_read = netlink_recv(p_socket, l_buffer, l_size);
|
||||
*p_size = l_read;
|
||||
if(l_read == -2)
|
||||
{
|
||||
free(l_buffer);
|
||||
return NULL;
|
||||
}
|
||||
if(l_read >= 0)
|
||||
{
|
||||
pid_t l_pid = getpid();
|
||||
struct nlmsghdr *l_hdr;
|
||||
for(l_hdr = (struct nlmsghdr *)l_buffer; NLMSG_OK(l_hdr, (unsigned int)l_read); l_hdr = (struct nlmsghdr *)NLMSG_NEXT(l_hdr, l_read))
|
||||
{
|
||||
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_DONE)
|
||||
{
|
||||
*p_done = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_ERROR)
|
||||
{
|
||||
free(l_buffer);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return l_buffer;
|
||||
}
|
||||
|
||||
l_size *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
static NetlinkList *newListItem(struct nlmsghdr *p_data, unsigned int p_size)
|
||||
{
|
||||
NetlinkList *l_item = malloc(sizeof(NetlinkList));
|
||||
l_item->m_next = NULL;
|
||||
l_item->m_data = p_data;
|
||||
l_item->m_size = p_size;
|
||||
return l_item;
|
||||
}
|
||||
|
||||
static void freeResultList(NetlinkList *p_list)
|
||||
{
|
||||
NetlinkList *l_cur;
|
||||
while(p_list)
|
||||
{
|
||||
l_cur = p_list;
|
||||
p_list = p_list->m_next;
|
||||
free(l_cur->m_data);
|
||||
free(l_cur);
|
||||
}
|
||||
}
|
||||
|
||||
static NetlinkList *getResultList(int p_socket, int p_request)
|
||||
{
|
||||
if(netlink_send(p_socket, p_request) < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NetlinkList *l_list = NULL;
|
||||
NetlinkList *l_end = NULL;
|
||||
int l_size;
|
||||
int l_done = 0;
|
||||
while(!l_done)
|
||||
{
|
||||
struct nlmsghdr *l_hdr = getNetlinkResponse(p_socket, &l_size, &l_done);
|
||||
if(!l_hdr)
|
||||
{ // error
|
||||
freeResultList(l_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NetlinkList *l_item = newListItem(l_hdr, l_size);
|
||||
if(!l_list)
|
||||
{
|
||||
l_list = l_item;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_end->m_next = l_item;
|
||||
}
|
||||
l_end = l_item;
|
||||
}
|
||||
return l_list;
|
||||
}
|
||||
|
||||
static size_t maxSize(size_t a, size_t b)
|
||||
{
|
||||
return (a > b ? a : b);
|
||||
}
|
||||
|
||||
static size_t calcAddrLen(sa_family_t p_family, int p_dataSize)
|
||||
{
|
||||
switch(p_family)
|
||||
{
|
||||
case AF_INET:
|
||||
return sizeof(struct sockaddr_in);
|
||||
case AF_INET6:
|
||||
return sizeof(struct sockaddr_in6);
|
||||
case AF_PACKET:
|
||||
return maxSize(sizeof(struct sockaddr_ll), offsetof(struct sockaddr_ll, sll_addr) + p_dataSize);
|
||||
default:
|
||||
return maxSize(sizeof(struct sockaddr), offsetof(struct sockaddr, sa_data) + p_dataSize);
|
||||
}
|
||||
}
|
||||
|
||||
static void makeSockaddr(sa_family_t p_family, struct sockaddr *p_dest, void *p_data, size_t p_size)
|
||||
{
|
||||
switch(p_family)
|
||||
{
|
||||
case AF_INET:
|
||||
memcpy(&((struct sockaddr_in*)p_dest)->sin_addr, p_data, p_size);
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(&((struct sockaddr_in6*)p_dest)->sin6_addr, p_data, p_size);
|
||||
break;
|
||||
case AF_PACKET:
|
||||
memcpy(((struct sockaddr_ll*)p_dest)->sll_addr, p_data, p_size);
|
||||
((struct sockaddr_ll*)p_dest)->sll_halen = p_size;
|
||||
break;
|
||||
default:
|
||||
memcpy(p_dest->sa_data, p_data, p_size);
|
||||
break;
|
||||
}
|
||||
p_dest->sa_family = p_family;
|
||||
}
|
||||
|
||||
static void addToEnd(struct ifaddrs **p_resultList, struct ifaddrs *p_entry)
|
||||
{
|
||||
if(!*p_resultList)
|
||||
{
|
||||
*p_resultList = p_entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct ifaddrs *l_cur = *p_resultList;
|
||||
while(l_cur->ifa_next)
|
||||
{
|
||||
l_cur = l_cur->ifa_next;
|
||||
}
|
||||
l_cur->ifa_next = p_entry;
|
||||
}
|
||||
}
|
||||
|
||||
static void interpretLink(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
|
||||
{
|
||||
struct ifinfomsg *l_info = (struct ifinfomsg *)NLMSG_DATA(p_hdr);
|
||||
|
||||
size_t l_nameSize = 0;
|
||||
size_t l_addrSize = 0;
|
||||
size_t l_dataSize = 0;
|
||||
|
||||
size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
|
||||
struct rtattr *l_rta;
|
||||
for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
void *l_rtaData = RTA_DATA(l_rta);
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFLA_ADDRESS:
|
||||
case IFLA_BROADCAST:
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(AF_PACKET, l_rtaDataSize));
|
||||
break;
|
||||
case IFLA_IFNAME:
|
||||
l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
|
||||
break;
|
||||
case IFLA_STATS:
|
||||
l_dataSize += NLMSG_ALIGN(l_rtaSize);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize + l_dataSize);
|
||||
memset(l_entry, 0, sizeof(struct ifaddrs));
|
||||
l_entry->ifa_name = "";
|
||||
|
||||
char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
|
||||
char *l_addr = l_name + l_nameSize;
|
||||
char *l_data = l_addr + l_addrSize;
|
||||
|
||||
l_entry->ifa_flags = l_info->ifi_flags;
|
||||
|
||||
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifinfomsg));
|
||||
for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifinfomsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
void *l_rtaData = RTA_DATA(l_rta);
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFLA_ADDRESS:
|
||||
case IFLA_BROADCAST:
|
||||
{
|
||||
size_t l_addrLen = calcAddrLen(AF_PACKET, l_rtaDataSize);
|
||||
makeSockaddr(AF_PACKET, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
|
||||
((struct sockaddr_ll *)l_addr)->sll_ifindex = l_info->ifi_index;
|
||||
((struct sockaddr_ll *)l_addr)->sll_hatype = l_info->ifi_type;
|
||||
if(l_rta->rta_type == IFLA_ADDRESS)
|
||||
{
|
||||
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
l_addr += NLMSG_ALIGN(l_addrLen);
|
||||
break;
|
||||
}
|
||||
case IFLA_IFNAME:
|
||||
strncpy(l_name, l_rtaData, l_rtaDataSize);
|
||||
l_name[l_rtaDataSize] = '\0';
|
||||
l_entry->ifa_name = l_name;
|
||||
break;
|
||||
case IFLA_STATS:
|
||||
memcpy(l_data, l_rtaData, l_rtaDataSize);
|
||||
l_entry->ifa_data = l_data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
addToEnd(p_resultList, l_entry);
|
||||
p_links[l_info->ifi_index - 1] = l_entry;
|
||||
}
|
||||
|
||||
static void interpretAddr(struct nlmsghdr *p_hdr, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
|
||||
{
|
||||
struct ifaddrmsg *l_info = (struct ifaddrmsg *)NLMSG_DATA(p_hdr);
|
||||
|
||||
size_t l_nameSize = 0;
|
||||
size_t l_addrSize = 0;
|
||||
|
||||
int l_addedNetmask = 0;
|
||||
|
||||
size_t l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
|
||||
struct rtattr *l_rta;
|
||||
for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
void *l_rtaData = RTA_DATA(l_rta);
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
if(l_info->ifa_family == AF_PACKET)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFA_ADDRESS:
|
||||
case IFA_LOCAL:
|
||||
if((l_info->ifa_family == AF_INET || l_info->ifa_family == AF_INET6) && !l_addedNetmask)
|
||||
{ // make room for netmask
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
|
||||
l_addedNetmask = 1;
|
||||
}
|
||||
case IFA_BROADCAST:
|
||||
l_addrSize += NLMSG_ALIGN(calcAddrLen(l_info->ifa_family, l_rtaDataSize));
|
||||
break;
|
||||
case IFA_LABEL:
|
||||
l_nameSize += NLMSG_ALIGN(l_rtaSize + 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct ifaddrs *l_entry = malloc(sizeof(struct ifaddrs) + l_nameSize + l_addrSize);
|
||||
memset(l_entry, 0, sizeof(struct ifaddrs));
|
||||
l_entry->ifa_name = p_links[l_info->ifa_index - 1]->ifa_name;
|
||||
|
||||
char *l_name = ((char *)l_entry) + sizeof(struct ifaddrs);
|
||||
char *l_addr = l_name + l_nameSize;
|
||||
|
||||
l_entry->ifa_flags = l_info->ifa_flags | p_links[l_info->ifa_index - 1]->ifa_flags;
|
||||
|
||||
l_rtaSize = NLMSG_PAYLOAD(p_hdr, sizeof(struct ifaddrmsg));
|
||||
for(l_rta = (struct rtattr *)(((char *)l_info) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))); RTA_OK(l_rta, l_rtaSize); l_rta = RTA_NEXT(l_rta, l_rtaSize))
|
||||
{
|
||||
void *l_rtaData = RTA_DATA(l_rta);
|
||||
size_t l_rtaDataSize = RTA_PAYLOAD(l_rta);
|
||||
switch(l_rta->rta_type)
|
||||
{
|
||||
case IFA_ADDRESS:
|
||||
case IFA_BROADCAST:
|
||||
case IFA_LOCAL:
|
||||
{
|
||||
size_t l_addrLen = calcAddrLen(l_info->ifa_family, l_rtaDataSize);
|
||||
makeSockaddr(l_info->ifa_family, (struct sockaddr *)l_addr, l_rtaData, l_rtaDataSize);
|
||||
if(l_info->ifa_family == AF_INET6)
|
||||
{
|
||||
if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)l_rtaData) || IN6_IS_ADDR_MC_LINKLOCAL((struct in6_addr *)l_rtaData))
|
||||
{
|
||||
((struct sockaddr_in6 *)l_addr)->sin6_scope_id = l_info->ifa_index;
|
||||
}
|
||||
}
|
||||
|
||||
if(l_rta->rta_type == IFA_ADDRESS)
|
||||
{ // apparently in a point-to-point network IFA_ADDRESS contains the dest address and IFA_LOCAL contains the local address
|
||||
if(l_entry->ifa_addr)
|
||||
{
|
||||
l_entry->ifa_dstaddr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
}
|
||||
else if(l_rta->rta_type == IFA_LOCAL)
|
||||
{
|
||||
if(l_entry->ifa_addr)
|
||||
{
|
||||
l_entry->ifa_dstaddr = l_entry->ifa_addr;
|
||||
}
|
||||
l_entry->ifa_addr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_entry->ifa_broadaddr = (struct sockaddr *)l_addr;
|
||||
}
|
||||
l_addr += NLMSG_ALIGN(l_addrLen);
|
||||
break;
|
||||
}
|
||||
case IFA_LABEL:
|
||||
strncpy(l_name, l_rtaData, l_rtaDataSize);
|
||||
l_name[l_rtaDataSize] = '\0';
|
||||
l_entry->ifa_name = l_name;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(l_entry->ifa_addr && (l_entry->ifa_addr->sa_family == AF_INET || l_entry->ifa_addr->sa_family == AF_INET6))
|
||||
{
|
||||
unsigned l_maxPrefix = (l_entry->ifa_addr->sa_family == AF_INET ? 32 : 128);
|
||||
unsigned l_prefix = (l_info->ifa_prefixlen > l_maxPrefix ? l_maxPrefix : l_info->ifa_prefixlen);
|
||||
char l_mask[16] = {0};
|
||||
unsigned i;
|
||||
for(i=0; i<(l_prefix/8); ++i)
|
||||
{
|
||||
l_mask[i] = 0xff;
|
||||
}
|
||||
l_mask[i] = 0xff << (8 - (l_prefix % 8));
|
||||
|
||||
makeSockaddr(l_entry->ifa_addr->sa_family, (struct sockaddr *)l_addr, l_mask, l_maxPrefix / 8);
|
||||
l_entry->ifa_netmask = (struct sockaddr *)l_addr;
|
||||
}
|
||||
|
||||
addToEnd(p_resultList, l_entry);
|
||||
}
|
||||
|
||||
static void interpret(int p_socket, NetlinkList *p_netlinkList, struct ifaddrs **p_links, struct ifaddrs **p_resultList)
|
||||
{
|
||||
pid_t l_pid = getpid();
|
||||
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
|
||||
{
|
||||
unsigned int l_nlsize = p_netlinkList->m_size;
|
||||
struct nlmsghdr *l_hdr;
|
||||
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
|
||||
{
|
||||
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_DONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == RTM_NEWLINK)
|
||||
{
|
||||
interpretLink(l_hdr, p_links, p_resultList);
|
||||
}
|
||||
else if(l_hdr->nlmsg_type == RTM_NEWADDR)
|
||||
{
|
||||
interpretAddr(l_hdr, p_links, p_resultList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned countLinks(int p_socket, NetlinkList *p_netlinkList)
|
||||
{
|
||||
unsigned l_links = 0;
|
||||
pid_t l_pid = getpid();
|
||||
for(; p_netlinkList; p_netlinkList = p_netlinkList->m_next)
|
||||
{
|
||||
unsigned int l_nlsize = p_netlinkList->m_size;
|
||||
struct nlmsghdr *l_hdr;
|
||||
for(l_hdr = p_netlinkList->m_data; NLMSG_OK(l_hdr, l_nlsize); l_hdr = NLMSG_NEXT(l_hdr, l_nlsize))
|
||||
{
|
||||
if((pid_t)l_hdr->nlmsg_pid != l_pid || (int)l_hdr->nlmsg_seq != p_socket)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == NLMSG_DONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(l_hdr->nlmsg_type == RTM_NEWLINK)
|
||||
{
|
||||
++l_links;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return l_links;
|
||||
}
|
||||
|
||||
int getifaddrs(struct ifaddrs **ifap)
|
||||
{
|
||||
if(!ifap)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*ifap = NULL;
|
||||
|
||||
int l_socket = netlink_socket();
|
||||
if(l_socket < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
NetlinkList *l_linkResults = getResultList(l_socket, RTM_GETLINK);
|
||||
if(!l_linkResults)
|
||||
{
|
||||
close(l_socket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
NetlinkList *l_addrResults = getResultList(l_socket, RTM_GETADDR);
|
||||
if(!l_addrResults)
|
||||
{
|
||||
close(l_socket);
|
||||
freeResultList(l_linkResults);
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned l_numLinks = countLinks(l_socket, l_linkResults) + countLinks(l_socket, l_addrResults);
|
||||
struct ifaddrs *l_links[l_numLinks];
|
||||
memset(l_links, 0, l_numLinks * sizeof(struct ifaddrs *));
|
||||
|
||||
interpret(l_socket, l_linkResults, l_links, ifap);
|
||||
interpret(l_socket, l_addrResults, l_links, ifap);
|
||||
|
||||
freeResultList(l_linkResults);
|
||||
freeResultList(l_addrResults);
|
||||
close(l_socket);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void freeifaddrs(struct ifaddrs *ifa)
|
||||
{
|
||||
struct ifaddrs *l_cur;
|
||||
while(ifa)
|
||||
{
|
||||
l_cur = ifa;
|
||||
ifa = ifa->ifa_next;
|
||||
free(l_cur);
|
||||
}
|
||||
}
|
||||
Vendored
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 1999
|
||||
* Berkeley Software Design, Inc. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
|
||||
*/
|
||||
|
||||
#ifndef _IFADDRS_H_
|
||||
#define _IFADDRS_H_
|
||||
|
||||
struct ifaddrs {
|
||||
struct ifaddrs *ifa_next;
|
||||
char *ifa_name;
|
||||
unsigned int ifa_flags;
|
||||
struct sockaddr *ifa_addr;
|
||||
struct sockaddr *ifa_netmask;
|
||||
struct sockaddr *ifa_dstaddr;
|
||||
void *ifa_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* This may have been defined in <net/if.h>. Note that if <net/if.h> is
|
||||
* to be included it must be included before this header file.
|
||||
*/
|
||||
#ifndef ifa_broadaddr
|
||||
#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
|
||||
#endif
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
extern int getifaddrs(struct ifaddrs **ifap);
|
||||
extern void freeifaddrs(struct ifaddrs *ifa);
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
||||
Vendored
+1
-1
Submodule externals/cubeb updated: 799e775484...48689ae7a7
Vendored
+1
-1
Submodule externals/dynarmic updated: ca0e264f4f...d333a09b3b
Vendored
+1
-1
Submodule externals/oaknut updated: 9d091109de...e6eecc3f94
@@ -244,12 +244,14 @@ void Config::ReadValues() {
|
||||
|
||||
// Miscellaneous
|
||||
ReadSetting("Miscellaneous", Settings::values.log_filter);
|
||||
ReadSetting("Miscellaneous", Settings::values.log_regex_filter);
|
||||
|
||||
// Apply the log_filter setting as the logger has already been initialized
|
||||
// and doesn't pick up the filter on its own.
|
||||
Common::Log::Filter filter;
|
||||
filter.ParseFilterString(Settings::values.log_filter.GetValue());
|
||||
Common::Log::SetGlobalFilter(filter);
|
||||
Common::Log::SetRegexFilter(Settings::values.log_regex_filter.GetValue());
|
||||
|
||||
// Debugging
|
||||
Settings::values.record_frame_times =
|
||||
|
||||
@@ -306,12 +306,14 @@ void Config::ReadValues() {
|
||||
|
||||
// Miscellaneous
|
||||
ReadSetting("Miscellaneous", Settings::values.log_filter);
|
||||
ReadSetting("Miscellaneous", Settings::values.log_regex_filter);
|
||||
|
||||
// Apply the log_filter setting as the logger has already been initialized
|
||||
// and doesn't pick up the filter on its own.
|
||||
Common::Log::Filter filter;
|
||||
filter.ParseFilterString(Settings::values.log_filter.GetValue());
|
||||
Common::Log::SetGlobalFilter(filter);
|
||||
Common::Log::SetRegexFilter(Settings::values.log_regex_filter.GetValue());
|
||||
|
||||
// Debugging
|
||||
Settings::values.record_frame_times =
|
||||
|
||||
@@ -531,6 +531,7 @@ void Config::ReadMiscellaneousValues() {
|
||||
qt_config->beginGroup(QStringLiteral("Miscellaneous"));
|
||||
|
||||
ReadBasicSetting(Settings::values.log_filter);
|
||||
ReadBasicSetting(Settings::values.log_regex_filter);
|
||||
ReadBasicSetting(Settings::values.enable_gamemode);
|
||||
|
||||
qt_config->endGroup();
|
||||
@@ -1054,6 +1055,7 @@ void Config::SaveMiscellaneousValues() {
|
||||
qt_config->beginGroup(QStringLiteral("Miscellaneous"));
|
||||
|
||||
WriteBasicSetting(Settings::values.log_filter);
|
||||
WriteBasicSetting(Settings::values.log_regex_filter);
|
||||
WriteBasicSetting(Settings::values.enable_gamemode);
|
||||
|
||||
qt_config->endGroup();
|
||||
|
||||
@@ -97,6 +97,8 @@ void ConfigureDebug::SetConfiguration() {
|
||||
ui->toggle_console->setEnabled(!is_powered_on);
|
||||
ui->toggle_console->setChecked(UISettings::values.show_console.GetValue());
|
||||
ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter.GetValue()));
|
||||
ui->log_regex_filter_edit->setText(
|
||||
QString::fromStdString(Settings::values.log_regex_filter.GetValue()));
|
||||
ui->toggle_cpu_jit->setChecked(Settings::values.use_cpu_jit.GetValue());
|
||||
ui->delay_start_for_lle_modules->setChecked(
|
||||
Settings::values.delay_start_for_lle_modules.GetValue());
|
||||
@@ -126,10 +128,12 @@ void ConfigureDebug::ApplyConfiguration() {
|
||||
Settings::values.gdbstub_port = ui->gdbport_spinbox->value();
|
||||
UISettings::values.show_console = ui->toggle_console->isChecked();
|
||||
Settings::values.log_filter = ui->log_filter_edit->text().toStdString();
|
||||
Settings::values.log_regex_filter = ui->log_regex_filter_edit->text().toStdString();
|
||||
Debugger::ToggleConsole();
|
||||
Common::Log::Filter filter;
|
||||
filter.ParseFilterString(Settings::values.log_filter.GetValue());
|
||||
Common::Log::SetGlobalFilter(filter);
|
||||
Common::Log::SetRegexFilter(Settings::values.log_regex_filter.GetValue());
|
||||
Settings::values.use_cpu_jit = ui->toggle_cpu_jit->isChecked();
|
||||
Settings::values.delay_start_for_lle_modules = ui->delay_start_for_lle_modules->isChecked();
|
||||
Settings::values.renderer_debug = ui->toggle_renderer_debug->isChecked();
|
||||
|
||||
@@ -85,6 +85,20 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Regex Log Filter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="log_regex_filter_edit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
|
||||
@@ -3,14 +3,12 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cstring>
|
||||
#include <QFileDialog>
|
||||
#include <QFutureWatcher>
|
||||
#include <QMessageBox>
|
||||
#include <QProgressDialog>
|
||||
#include <QtConcurrent/QtConcurrentMap>
|
||||
#include "citra_qt/configuration/configuration_shared.h"
|
||||
#include "citra_qt/configuration/configure_system.h"
|
||||
#include "common/file_util.h"
|
||||
#include "common/settings.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/service/am/am.h"
|
||||
@@ -238,32 +236,6 @@ ConfigureSystem::ConfigureSystem(Core::System& system_, QWidget* parent)
|
||||
&ConfigureSystem::RefreshConsoleID);
|
||||
connect(ui->button_start_download, &QPushButton::clicked, this,
|
||||
&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++) {
|
||||
if (std::strcmp(country_names.at(i), "") != 0) {
|
||||
ui->combo_country->addItem(tr(country_names.at(i)), i);
|
||||
@@ -332,7 +304,6 @@ void ConfigureSystem::SetConfiguration() {
|
||||
ReadSystemSettings();
|
||||
|
||||
ui->group_system_settings->setEnabled(enabled);
|
||||
ui->group_real_console_unique_data->setEnabled(enabled);
|
||||
if (enabled) {
|
||||
ui->label_disable_info->hide();
|
||||
}
|
||||
@@ -383,9 +354,6 @@ void ConfigureSystem::ReadSystemSettings() {
|
||||
|
||||
// set firmware download region
|
||||
ui->combo_download_region->setCurrentIndex(static_cast<int>(cfg->GetRegionValue()));
|
||||
|
||||
// Refresh secure data status
|
||||
RefreshSecureDataStatus();
|
||||
}
|
||||
|
||||
void ConfigureSystem::ApplyConfiguration() {
|
||||
@@ -554,59 +522,6 @@ void ConfigureSystem::RefreshConsoleID() {
|
||||
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() {
|
||||
ui->retranslateUi(this);
|
||||
}
|
||||
|
||||
@@ -20,12 +20,6 @@ namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Service {
|
||||
namespace AM {
|
||||
class Module;
|
||||
} // namespace AM
|
||||
} // namespace Service
|
||||
|
||||
namespace Service {
|
||||
namespace CFG {
|
||||
class Module;
|
||||
@@ -52,10 +46,6 @@ private:
|
||||
void UpdateInitTicks(int init_ticks_type);
|
||||
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 DownloadFromNUS();
|
||||
|
||||
@@ -506,123 +506,6 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</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>
|
||||
<widget class="QLabel" name="label_disable_info">
|
||||
<property name="text">
|
||||
|
||||
@@ -20,7 +20,7 @@ inline bool IsWithin128M(uintptr_t ref, 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>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <chrono>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
@@ -234,6 +235,19 @@ public:
|
||||
filter = f;
|
||||
}
|
||||
|
||||
bool SetRegexFilter(const std::string& regex) {
|
||||
if (regex.empty()) {
|
||||
regex_filter = boost::regex();
|
||||
return true;
|
||||
}
|
||||
regex_filter = boost::regex(regex, boost::regex_constants::no_except);
|
||||
if (regex_filter.status() != 0) {
|
||||
regex_filter = boost::regex();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetColorConsoleBackendEnabled(bool enabled) {
|
||||
color_console_backend.SetEnabled(enabled);
|
||||
}
|
||||
@@ -243,8 +257,13 @@ public:
|
||||
if (!filter.CheckMessage(log_class, log_level)) {
|
||||
return;
|
||||
}
|
||||
message_queue.EmplaceWait(
|
||||
CreateEntry(log_class, log_level, filename, line_num, function, std::move(message)));
|
||||
Entry new_entry =
|
||||
CreateEntry(log_class, log_level, filename, line_num, function, std::move(message));
|
||||
if (!regex_filter.empty() &&
|
||||
!boost::regex_search(FormatLogMessage(new_entry), regex_filter)) {
|
||||
return;
|
||||
}
|
||||
message_queue.EmplaceWait(new_entry);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -406,6 +425,7 @@ private:
|
||||
static inline std::unique_ptr<Impl, decltype(&Deleter)> instance{nullptr, Deleter};
|
||||
|
||||
Filter filter;
|
||||
boost::regex regex_filter;
|
||||
DebuggerBackend debugger_backend{};
|
||||
ColorConsoleBackend color_console_backend{};
|
||||
FileBackend file_backend;
|
||||
@@ -446,6 +466,10 @@ void SetGlobalFilter(const Filter& filter) {
|
||||
Impl::Instance().SetGlobalFilter(filter);
|
||||
}
|
||||
|
||||
bool SetRegexFilter(const std::string& regex) {
|
||||
return Impl::Instance().SetRegexFilter(regex);
|
||||
}
|
||||
|
||||
void SetColorConsoleBackendEnabled(bool enabled) {
|
||||
Impl::Instance().SetColorConsoleBackendEnabled(enabled);
|
||||
}
|
||||
|
||||
@@ -26,5 +26,11 @@ void DisableLoggingInTests();
|
||||
*/
|
||||
void SetGlobalFilter(const Filter& filter);
|
||||
|
||||
/**
|
||||
* Only allow messages that match the specified regex. The regex is matched against the final log
|
||||
* text.
|
||||
*/
|
||||
bool SetRegexFilter(const std::string& regex);
|
||||
|
||||
void SetColorConsoleBackendEnabled(bool enabled);
|
||||
} // namespace Common::Log
|
||||
|
||||
@@ -542,6 +542,7 @@ struct Values {
|
||||
|
||||
// Miscellaneous
|
||||
Setting<std::string> log_filter{"*:Info", "log_filter"};
|
||||
Setting<std::string> log_regex_filter{"", "log_regex_filter"};
|
||||
|
||||
// Video Dumping
|
||||
std::string output_format;
|
||||
|
||||
@@ -80,35 +80,6 @@ struct TicketInfo {
|
||||
|
||||
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 {
|
||||
public:
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
const auto media_type = rp.Pop<u8>();
|
||||
@@ -1846,66 +1802,13 @@ void Module::serialize(Archive& ar, const unsigned int) {
|
||||
}
|
||||
SERIALIZE_IMPL(Module)
|
||||
|
||||
void Module::Interface::GetDeviceCert(Kernel::HLERequestContext& ctx) {
|
||||
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) {
|
||||
Module::Module(Core::System& system) : system(system) {
|
||||
ScanForAllTitles();
|
||||
LoadCTCertFile(ct_cert);
|
||||
system_updater_mutex = system.Kernel().CreateMutex(false, "AM::SystemUpdaterMutex");
|
||||
}
|
||||
|
||||
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) {
|
||||
auto& service_manager = system.ServiceManager();
|
||||
auto am = std::make_shared<Module>(system);
|
||||
|
||||
@@ -68,31 +68,6 @@ enum class InstallStatus : u32 {
|
||||
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
|
||||
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> GetModule() const {
|
||||
return am;
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* AM::GetNumPrograms service function
|
||||
@@ -444,16 +415,6 @@ public:
|
||||
*/
|
||||
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
|
||||
* Inputs:
|
||||
@@ -741,32 +702,10 @@ public:
|
||||
*/
|
||||
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:
|
||||
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:
|
||||
/**
|
||||
* Scans the for titles in a storage medium for listing.
|
||||
@@ -783,15 +722,12 @@ private:
|
||||
bool cia_installing = false;
|
||||
std::array<std::vector<u64_le>, 3> am_title_list;
|
||||
std::shared_ptr<Kernel::Mutex> system_updater_mutex;
|
||||
CTCert ct_cert{};
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, const unsigned int);
|
||||
friend class boost::serialization::access;
|
||||
};
|
||||
|
||||
std::shared_ptr<Module> GetModule(Core::System& system);
|
||||
|
||||
void InstallInterfaces(Core::System& system);
|
||||
|
||||
} // namespace Service::AM
|
||||
|
||||
@@ -19,7 +19,7 @@ AM_NET::AM_NET(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "a
|
||||
{0x0007, &AM_NET::DeleteTicket, "DeleteTicket"},
|
||||
{0x0008, &AM_NET::GetNumTickets, "GetNumTickets"},
|
||||
{0x0009, &AM_NET::GetTicketList, "GetTicketList"},
|
||||
{0x000A, &AM_NET::GetDeviceID, "GetDeviceID"},
|
||||
{0x000A, nullptr, "GetDeviceID"},
|
||||
{0x000B, nullptr, "GetNumImportTitleContexts"},
|
||||
{0x000C, nullptr, "GetImportTitleContextList"},
|
||||
{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"},
|
||||
{0x0816, nullptr, "Sign"},
|
||||
{0x0817, nullptr, "Verify"},
|
||||
{0x0818, &AM_NET::GetDeviceCert, "GetDeviceCert"},
|
||||
{0x0818, nullptr, "GetDeviceCert"},
|
||||
{0x0819, nullptr, "ImportCertificates"},
|
||||
{0x081A, nullptr, "ImportCertificate"},
|
||||
{0x081B, nullptr, "CommitImportTitlesAndUpdateFirmwareAuto"},
|
||||
|
||||
@@ -19,7 +19,7 @@ AM_SYS::AM_SYS(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "a
|
||||
{0x0007, &AM_SYS::DeleteTicket, "DeleteTicket"},
|
||||
{0x0008, &AM_SYS::GetNumTickets, "GetNumTickets"},
|
||||
{0x0009, &AM_SYS::GetTicketList, "GetTicketList"},
|
||||
{0x000A, &AM_SYS::GetDeviceID, "GetDeviceID"},
|
||||
{0x000A, nullptr, "GetDeviceID"},
|
||||
{0x000B, nullptr, "GetNumImportTitleContexts"},
|
||||
{0x000C, nullptr, "GetImportTitleContextList"},
|
||||
{0x000D, nullptr, "GetImportTitleContexts"},
|
||||
|
||||
@@ -19,7 +19,7 @@ AM_U::AM_U(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "am:u"
|
||||
{0x0007, &AM_U::DeleteTicket, "DeleteTicket"},
|
||||
{0x0008, &AM_U::GetNumTickets, "GetNumTickets"},
|
||||
{0x0009, &AM_U::GetTicketList, "GetTicketList"},
|
||||
{0x000A, &AM_U::GetDeviceID, "GetDeviceID"},
|
||||
{0x000A, nullptr, "GetDeviceID"},
|
||||
{0x000B, nullptr, "GetNumImportTitleContexts"},
|
||||
{0x000C, nullptr, "GetImportTitleContextList"},
|
||||
{0x000D, nullptr, "GetImportTitleContexts"},
|
||||
|
||||
@@ -217,39 +217,12 @@ void Module::Interface::GetRegion(Kernel::HLERequestContext& ctx) {
|
||||
void Module::Interface::SecureInfoGetByte101(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
|
||||
u8 ret = 0;
|
||||
if (cfg->secure_info_a_loaded) {
|
||||
ret = cfg->secure_info_a.unknown;
|
||||
}
|
||||
LOG_DEBUG(Service_CFG, "(STUBBED) called");
|
||||
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u8>(ret);
|
||||
}
|
||||
|
||||
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);
|
||||
// According to 3dbrew this is normally 0.
|
||||
rb.Push<u8>(0);
|
||||
}
|
||||
|
||||
void Module::Interface::SetUUIDClockSequence(Kernel::HLERequestContext& ctx) {
|
||||
@@ -392,43 +365,6 @@ void Module::Interface::UpdateConfigNANDSavegame(Kernel::HLERequestContext& ctx)
|
||||
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) {
|
||||
IPC::RequestParser rp(ctx);
|
||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||
@@ -570,14 +506,6 @@ Result Module::UpdateConfigNANDSavegame() {
|
||||
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 res = DeleteConfigNANDSaveFile();
|
||||
// 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();
|
||||
}
|
||||
|
||||
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() {
|
||||
FileUtil::IOFile mcu_data_file(
|
||||
fmt::format("{}/mcu.dat", FileUtil::GetUserPath(FileUtil::UserPath::SysDataDir)), "rb");
|
||||
@@ -737,8 +616,6 @@ Module::Module(Core::System& system_) : system(system_) {
|
||||
SetEULAVersion(default_version);
|
||||
UpdateConfigNANDSavegame();
|
||||
}
|
||||
LoadSecureInfoAFile();
|
||||
LoadLocalFriendCodeSeedBFile();
|
||||
}
|
||||
|
||||
Module::~Module() = default;
|
||||
|
||||
@@ -176,28 +176,6 @@ enum class AccessFlag : u16 {
|
||||
};
|
||||
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 {
|
||||
public:
|
||||
Module(Core::System& system_);
|
||||
@@ -252,18 +230,6 @@ public:
|
||||
*/
|
||||
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
|
||||
* Inputs:
|
||||
@@ -379,27 +345,6 @@ public:
|
||||
*/
|
||||
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
|
||||
* Inputs:
|
||||
@@ -630,34 +575,6 @@ public:
|
||||
*/
|
||||
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
|
||||
*/
|
||||
@@ -673,10 +590,6 @@ private:
|
||||
std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer;
|
||||
std::unique_ptr<FileSys::ArchiveBackend> cfg_system_save_data_archive;
|
||||
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;
|
||||
MCUData mcu_data{};
|
||||
|
||||
|
||||
@@ -28,11 +28,11 @@ CFG_I::CFG_I(std::shared_ptr<Module> cfg) : Module::Interface(std::move(cfg), "c
|
||||
{0x0401, &CFG_I::GetSystemConfig, "GetSystemConfig"},
|
||||
{0x0402, &CFG_I::SetSystemConfig, "SetSystemConfig"},
|
||||
{0x0403, &CFG_I::UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
|
||||
{0x0404, &CFG_I::GetLocalFriendCodeSeedData, "GetLocalFriendCodeSeedData"},
|
||||
{0x0405, &CFG_I::GetLocalFriendCodeSeed, "GetLocalFriendCodeSeed"},
|
||||
{0x0404, nullptr, "GetLocalFriendCodeSeedData"},
|
||||
{0x0405, nullptr, "GetLocalFriendCodeSeed"},
|
||||
{0x0406, &CFG_I::GetRegion, "GetRegion"},
|
||||
{0x0407, &CFG_I::SecureInfoGetByte101, "SecureInfoGetByte101"},
|
||||
{0x0408, &CFG_I::SecureInfoGetSerialNo, "SecureInfoGetSerialNo"},
|
||||
{0x0408, nullptr, "SecureInfoGetSerialNo"},
|
||||
{0x0409, nullptr, "UpdateConfigBlk00040003"},
|
||||
// cfg:i
|
||||
{0x0801, &CFG_I::GetSystemConfig, "GetSystemConfig"},
|
||||
|
||||
@@ -28,11 +28,11 @@ CFG_S::CFG_S(std::shared_ptr<Module> cfg) : Module::Interface(std::move(cfg), "c
|
||||
{0x0401, &CFG_S::GetSystemConfig, "GetSystemConfig"},
|
||||
{0x0402, &CFG_S::SetSystemConfig, "SetSystemConfig"},
|
||||
{0x0403, &CFG_S::UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
|
||||
{0x0404, &CFG_S::GetLocalFriendCodeSeedData, "GetLocalFriendCodeSeedData"},
|
||||
{0x0405, &CFG_S::GetLocalFriendCodeSeed, "GetLocalFriendCodeSeed"},
|
||||
{0x0404, nullptr, "GetLocalFriendCodeSeedData"},
|
||||
{0x0405, nullptr, "GetLocalFriendCodeSeed"},
|
||||
{0x0406, &CFG_S::GetRegion, "GetRegion"},
|
||||
{0x0407, &CFG_S::SecureInfoGetByte101, "SecureInfoGetByte101"},
|
||||
{0x0408, &CFG_S::SecureInfoGetSerialNo, "SecureInfoGetSerialNo"},
|
||||
{0x0408, nullptr, "SecureInfoGetSerialNo"},
|
||||
{0x0409, nullptr, "UpdateConfigBlk00040003"},
|
||||
{0x040D, &CFG_S::SetUUIDClockSequence, "SetUUIDClockSequence"},
|
||||
{0x040E, &CFG_S::GetUUIDClockSequence, "GetUUIDClockSequence"},
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
#include <boost/serialization/unordered_map.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include <boost/serialization/weak_ptr.hpp>
|
||||
#if defined(__ANDROID__)
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
#include <httplib.h>
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/shared_memory.h"
|
||||
|
||||
@@ -285,20 +285,19 @@ std::pair<Common::Vec4<u8>, Common::Vec4<u8>> ComputeFragmentsColors(
|
||||
}
|
||||
}
|
||||
|
||||
const bool shadow_primary_enable =
|
||||
lighting.config0.shadow_primary && !lighting.IsShadowDisabled(num);
|
||||
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);
|
||||
auto diffuse =
|
||||
(light_config.diffuse.ToVec3f() * dot_product + light_config.ambient.ToVec3f()) *
|
||||
dist_atten * spot_atten;
|
||||
auto specular = (specular_0 + specular_1) * clamp_highlights * dist_atten * spot_atten;
|
||||
|
||||
const auto diffuse = (light_config.diffuse.ToVec3f() * dot_product * shadow_primary +
|
||||
light_config.ambient.ToVec3f()) *
|
||||
dist_atten * spot_atten;
|
||||
const auto specular = (specular_0 + specular_1) * clamp_highlights * dist_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);
|
||||
specular_sum += Common::MakeVec(specular, 0.0f);
|
||||
|
||||
@@ -810,8 +810,8 @@ void FragmentModule::WriteLighting() {
|
||||
|
||||
// Compute primary fragment color (diffuse lighting) function
|
||||
out += fmt::format(
|
||||
"diffuse_sum.rgb += (({}.diffuse * dot_product{}) + {}.ambient) * {} * {};\n",
|
||||
light_src, shadow_primary, light_src, dist_atten, spot_atten);
|
||||
"diffuse_sum.rgb += (({}.diffuse * dot_product) + {}.ambient) * {} * {}{};\n",
|
||||
light_src, light_src, dist_atten, spot_atten, shadow_primary);
|
||||
|
||||
// Compute secondary fragment color (specular lighting) function
|
||||
out += fmt::format("specular_sum.rgb += ({} + {}) * clamp_highlights * {} * {}{};\n",
|
||||
|
||||
@@ -768,7 +768,7 @@ void JitShader::Compile_LOOP(Instruction instr) {
|
||||
Label 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);
|
||||
ADD(LOOPCOUNT_REG, LOOPCOUNT_REG, LOOPINC); // Increment LOOPCOUNT_REG by Z-component
|
||||
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_;
|
||||
|
||||
// Reset flow control state
|
||||
program = xptr<CompiledShader*>();
|
||||
program = (CompiledShader*)current_address();
|
||||
program_counter = 0;
|
||||
loop_depth = 0;
|
||||
instruction_labels.fill(Label());
|
||||
@@ -968,13 +968,15 @@ void JitShader::Compile(const std::array<u32, MAX_PROGRAM_CODE_LENGTH>* program_
|
||||
protect();
|
||||
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!");
|
||||
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();
|
||||
CompilePrelude();
|
||||
}
|
||||
@@ -984,8 +986,8 @@ void JitShader::CompilePrelude() {
|
||||
exp2_subroutine = CompilePrelude_Exp2();
|
||||
}
|
||||
|
||||
Label JitShader::CompilePrelude_Log2() {
|
||||
Label subroutine;
|
||||
oaknut::Label JitShader::CompilePrelude_Log2() {
|
||||
oaknut::Label subroutine;
|
||||
|
||||
// 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
|
||||
@@ -993,40 +995,44 @@ Label JitShader::CompilePrelude_Log2() {
|
||||
// range. Coefficients for the minimax polynomial.
|
||||
// f(x) computes approximately log2(x) / (x - 1).
|
||||
// f(x) = c4 + x * (c3 + x * (c2 + x * (c1 + x * c0)).
|
||||
oaknut::Label c0;
|
||||
align(16);
|
||||
const void* c0 = xptr<const void*>();
|
||||
l(c0);
|
||||
dw(0x3d74552f);
|
||||
|
||||
align(16);
|
||||
const void* c14 = xptr<const void*>();
|
||||
oaknut::Label c14;
|
||||
l(c14);
|
||||
dw(0xbeee7397);
|
||||
dw(0x3fbd96dd);
|
||||
dw(0xc02153f6);
|
||||
dw(0x4038d96c);
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
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);
|
||||
l(input_out_of_range);
|
||||
B(Cond::EQ, input_is_zero);
|
||||
MOVP2R(XSCRATCH0, default_qnan_vector);
|
||||
MOVP2R(XSCRATCH0, default_qnan_vector.ptr<void*>());
|
||||
LDR(SRC1, XSCRATCH0);
|
||||
RET();
|
||||
|
||||
l(input_is_zero);
|
||||
MOVP2R(XSCRATCH0, negative_infinity_vector);
|
||||
MOVP2R(XSCRATCH0, negative_infinity_vector.ptr<void*>());
|
||||
LDR(SRC1, XSCRATCH0);
|
||||
RET();
|
||||
|
||||
@@ -1058,14 +1064,14 @@ Label JitShader::CompilePrelude_Log2() {
|
||||
UCVTF(VSCRATCH1.toS(), VSCRATCH1.toS());
|
||||
// VSCRATCH1 now contains the exponent of the input.
|
||||
|
||||
MOVP2R(XSCRATCH0, c0);
|
||||
MOVP2R(XSCRATCH0, c0.ptr<void*>());
|
||||
LDR(XSCRATCH0.toW(), XSCRATCH0);
|
||||
MOV(VSCRATCH0.Selem()[0], XSCRATCH0.toW());
|
||||
|
||||
// Complete computation of polynomial
|
||||
// Load C1,C2,C3,C4 into a single scratch register
|
||||
const QReg C14 = SRC2;
|
||||
MOVP2R(XSCRATCH0, c14);
|
||||
MOVP2R(XSCRATCH0, c14.ptr<void*>());
|
||||
LDR(C14, XSCRATCH0);
|
||||
FMUL(VSCRATCH0.toS(), VSCRATCH0.toS(), SRC1.toS());
|
||||
FMLA(VSCRATCH0.toS(), ONE.toS(), C14.Selem()[0]);
|
||||
@@ -1091,32 +1097,32 @@ Label JitShader::CompilePrelude_Log2() {
|
||||
return subroutine;
|
||||
}
|
||||
|
||||
Label JitShader::CompilePrelude_Exp2() {
|
||||
Label subroutine;
|
||||
oaknut::Label JitShader::CompilePrelude_Exp2() {
|
||||
oaknut::Label subroutine;
|
||||
|
||||
// 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
|
||||
// result into the appropriate range.
|
||||
|
||||
align(16);
|
||||
const void* input_max = xptr<const void*>();
|
||||
const void* input_max = (const void*)current_address();
|
||||
dw(0x43010000);
|
||||
const void* input_min = xptr<const void*>();
|
||||
const void* input_min = (const void*)current_address();
|
||||
dw(0xc2fdffff);
|
||||
const void* c0 = xptr<const void*>();
|
||||
const void* c0 = (const void*)current_address();
|
||||
dw(0x3c5dbe69);
|
||||
const void* half = xptr<const void*>();
|
||||
const void* half = (const void*)current_address();
|
||||
dw(0x3f000000);
|
||||
const void* c1 = xptr<const void*>();
|
||||
const void* c1 = (const void*)current_address();
|
||||
dw(0x3d5509f9);
|
||||
const void* c2 = xptr<const void*>();
|
||||
const void* c2 = (const void*)current_address();
|
||||
dw(0x3e773cc5);
|
||||
const void* c3 = xptr<const void*>();
|
||||
const void* c3 = (const void*)current_address();
|
||||
dw(0x3f3168b3);
|
||||
const void* c4 = xptr<const void*>();
|
||||
const void* c4 = (const void*)current_address();
|
||||
dw(0x3f800016);
|
||||
|
||||
Label ret_label;
|
||||
oaknut::Label ret_label;
|
||||
|
||||
align(16);
|
||||
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
|
||||
* 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:
|
||||
JitShader();
|
||||
|
||||
void Run(const ShaderSetup& setup, ShaderUnit& state, u32 offset) const {
|
||||
program(&setup.uniforms, &state,
|
||||
reinterpret_cast<std::byte*>(oaknut::CodeBlock::ptr()) +
|
||||
instruction_labels[offset].offset());
|
||||
program(&setup.uniforms, &state, instruction_labels[offset].ptr<const std::byte*>());
|
||||
}
|
||||
|
||||
void Compile(const std::array<u32, MAX_PROGRAM_CODE_LENGTH>* program_code,
|
||||
|
||||
@@ -17,7 +17,9 @@ create_target_directory_groups(web_service)
|
||||
target_compile_definitions(web_service PUBLIC -DENABLE_WEB_SERVICE)
|
||||
target_link_libraries(web_service PRIVATE citra_common network json-headers httplib cpp-jwt)
|
||||
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)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <fmt/format.h>
|
||||
#if defined(__ANDROID__)
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
#include <httplib.h>
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
|
||||
Reference in New Issue
Block a user