Compare commits

..

38 Commits

Author SHA1 Message Date
Morph
fa2aac1bf5 yuzu: main: Ensure enough space is available for RomFS dumping
This warns the user if there isn't enough free space to dump the entire RomFS to disk. It requires at least the size of the extracted RomFS + 1 GiB as a buffer of free space.
2021-06-11 14:04:11 -04:00
Morph
fbb170857f Merge pull request #6450 from lat9nq/update-sdl
externals: Update SDL to 2f248a2a
2021-06-11 06:33:50 -04:00
lat9nq
f738c6b231 externals: Update SDL to 2f248a2a 2021-06-11 04:40:16 -04:00
bunnei
c1b8e59ea0 Merge pull request #6407 from lat9nq/fix-libusb-2
cmake: Use autotools for libusb linking generally on GNU, and cleanup
2021-06-10 23:35:30 -07:00
bunnei
46ec0ee55b Merge pull request #6445 from degasus/fix_ubsn
Fix GCC undefined behavior sanitizer.
2021-06-10 22:17:33 -07:00
bunnei
4547b2735a Merge pull request #6444 from bunnei/fix-sm-sessions
hle: service: sm: Remove redundant session reservation, etc.
2021-06-10 12:17:13 -07:00
Markus Wick
6755025310 Fix GCC undefined behavior sanitizer.
* Wrong alignment in u64 LOG_DEBUG -> memcpy.
* Huge shift exponent in stride calculation for linear buffer, unused result -> skipped.
* Large shift in buffer cache if word = 0, skip checking for set bits.

Non of those were critical, so this should not change any behavior.
At least with the assumption, that the last one used masking behavior, which always yield continuous_bits = 0.
2021-06-10 21:07:27 +02:00
bunnei
781c85b951 hle: service: sm: Remove redundant session reservation, etc.
- We were double-reserving, causing us to run out of sessions in Pokemon Sword & Shield.
2021-06-10 11:34:41 -07:00
bunnei
fa8a0065ca hle: service: Increase arbitrary max sessions limit.
- Pokemon Sword/Shield are still hitting this for some reason, causing an svcBreak.
2021-06-10 00:08:09 -07:00
bunnei
74f0087bfa Merge pull request #6441 from bunnei/fix-session-handler
hle: kernel: KServerSession: Fix client disconnected.
2021-06-09 22:53:25 -07:00
bunnei
b259e95c09 hle: kernel: KClientPort: Add an assert for session count.
- Prevents us from over decrementing num_sessions.
2021-06-09 22:36:42 -07:00
bunnei
ec5674a6ad hle: service: sm: Fix GetService setup of session & port. 2021-06-09 22:29:18 -07:00
bunnei
2aa6a8d889 hle: service: Use correct size for ServerSessionCountMax. 2021-06-09 22:04:36 -07:00
bunnei
b2971b48ed hle: kernel: KServerSession: Fix client disconnected.
- Prevents a cloned session's handler from being overwritten by another disconnected session.
- Fixes session handler nullptr asserts with Pokemon Sword & Shield.
2021-06-09 21:37:11 -07:00
Ameer J
86d832ab9a Merge pull request #6439 from lat9nq/ci-no-7z
ci: common: Remove 7z packaging
2021-06-09 19:47:08 -04:00
Mai M
61c7a81ec8 Merge pull request #6440 from bunnei/cancel-synch
kernel: svc: Add missing error check to CancelSynchronization.
2021-06-09 19:08:36 -04:00
lat9nq
fbad68de0f ci: windows: Compress using xz
Use XZ instead of gzip for packing. Should save about 10 MB.
2021-06-09 18:54:23 -04:00
bunnei
c63ea608aa kernel: svc: Add missing error check to CancelSynchronization.
- Avoids a potential crash if the handle is invalid, and also makes this code accurate to real kernel behavior.
2021-06-09 15:24:46 -07:00
lat9nq
6eeb532c96 ci: common: Remove 7z packaging
Removes the 7z from being package during CI, as only .tar.xz preserves
information needed on Linux, and otherwise is just extremely redundant
to package in addition to the .tar.xz.  This affects Linux releases and
PR-verify artifacts only. MSVC releases do not use this script to my
knowledge.
2021-06-09 17:16:29 -04:00
Mai M
5857067a18 Merge pull request #6436 from liushuyu/master
src/common/CMakeLists.txt: fix variable escaping
2021-06-09 15:38:56 -04:00
bunnei
2d32fc2318 hle: service: Increase arbitrary max sessions limit.
- Pokemon Sword/Shield are still hitting this for some reason, causing an svcBreak.
2021-06-09 11:59:34 -07:00
bunnei
75a4ac12c6 Merge pull request #6413 from Kewlan/limitable_input_dialog_limit
limitable_input_dialog: Implement character limiter
2021-06-09 11:55:36 -07:00
liushuyu
eb9deffab6 src/common/CMakeLists.txt: fix variable escaping 2021-06-09 02:20:55 -06:00
Morph
15483c07c6 Merge pull request #6435 from lioncash/nodisc2
common/fs/path_util: Remove [[nodiscard]] from function with void return
2021-06-09 02:44:41 -04:00
bunnei
f9c3e2e872 Merge pull request #6434 from lioncash/tcontext
configure_ui: Add translation context for file-scope strings
2021-06-08 19:36:44 -07:00
bunnei
3c621d37f0 Merge pull request #6428 from bunnei/service-thread-crash-fix
hle: kernel: Remove service thread manager and use weak_ptr.
2021-06-08 16:43:55 -07:00
Lioncash
dd8577e91d common/fs/path_util: Remove [[nodiscard]] from function with void return
We can't make use of the return value here, since we don't a return
value to work with.
2021-06-08 19:36:09 -04:00
Lioncash
b3eb08254b configure_ui: Add translation context for file-scope strings
Allows for these strings to show up in the translation files.
2021-06-08 19:33:23 -04:00
Mai M
f09c9b5fcc Merge pull request #6426 from lat9nq/context-menu-start
yuzu qt: Start games from context menu
2021-06-08 17:09:25 -04:00
bunnei
3b5673daca Merge pull request #6412 from clementgallet/yuzu-cmd-window-gl
yuzu-cmd: Fix OpenGL rendering
2021-06-07 21:12:17 -07:00
lat9nq
5ac018d1df yuzu qt: Start games from context menu
This connects the BootGame function to the context menu. In addition,
there is an option to boot without using the custom configuration.
2021-06-07 20:27:51 -04:00
Kewlan
058196a089 limitable_input_dialog: Implement character limiter
When using GetText() you can now choose what set of characters the user can't enter.
2021-06-06 09:07:55 +02:00
Clément Gallet
2e1c58b905 Avoid -Wshadow warning
Co-authored-by: Mai M. <mathew1800@gmail.com>
2021-06-05 18:43:10 +02:00
Clément Gallet
9ff8504452 yuzu-cmd: Fix OpenGL rendering 2021-06-04 11:39:04 +02:00
lat9nq
7395cd3124 externals: libusb: Call program names not full paths 2021-06-03 04:53:01 -04:00
lat9nq
890acfa2c0 externals: libusb: Link libusb statically on Linux
Turns out that this is possible. Also addresses my own review comment.
2021-06-03 04:38:29 -04:00
lat9nq
ddc47e6df8 cmake: General improvements to libusb linking
Delegates libusb external communication to externals/CMakeLists.txt
Ensures an interface library `usb` for every pathway
input_common just links to the `usb` library now
externals/libusb/CMakeLists.txt sets variables to override SDL2's libusb
finding
Other minor cleanup
2021-06-03 03:49:35 -04:00
lat9nq
55dd027115 cmake: Use autotools to build libusb generally for GNU
Building libusb was also broken on GCC (and maybe Clang) on our
CMakeLists after upgrading to 1.0.24, but it was not being checked
because our 18.04 container had libusb installed on it.
This builds on the MinGW work from earlier and extends it to the rest of
the GNU toolchains. In addition we make use of pkg-config when present
to find libusb. pkg-config is preferrable because we can specify a
minimum required version.
2021-06-03 02:49:53 -04:00
28 changed files with 238 additions and 122 deletions

View File

@@ -9,11 +9,5 @@ cp "${REV_NAME}-source.tar.xz" "$DIR_NAME"
tar $COMPRESSION_FLAGS "$ARCHIVE_NAME" "$DIR_NAME"
mv "$DIR_NAME" $RELEASE_NAME
mv "${REV_NAME}-source.tar.xz" $RELEASE_NAME
7z a "$REV_NAME.7z" $RELEASE_NAME
# move the compiled archive into the artifacts directory to be uploaded by travis releases
mv "$ARCHIVE_NAME" "${ARTIFACTS_DIR}/"
mv "$REV_NAME.7z" "${ARTIFACTS_DIR}/"

View File

@@ -3,8 +3,8 @@
. .ci/scripts/common/pre-upload.sh
REV_NAME="yuzu-windows-mingw-${GITDATE}-${GITREV}"
ARCHIVE_NAME="${REV_NAME}.tar.gz"
COMPRESSION_FLAGS="-czvf"
ARCHIVE_NAME="${REV_NAME}.tar.xz"
COMPRESSION_FLAGS="-cJvf"
if [ "${RELEASE_NAME}" = "mainline" ]; then
DIR_NAME="${REV_NAME}"

View File

@@ -23,6 +23,8 @@ option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
option(YUZU_USE_BUNDLED_BOOST "Download bundled Boost" OFF)
option(YUZU_USE_BUNDLED_LIBUSB "Compile bundled libusb" OFF)
CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" ON "WIN32" OFF)
option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
@@ -420,14 +422,22 @@ elseif (TARGET Boost::boost)
endif()
# Ensure libusb is properly configured (based on dolphin libusb include)
if(NOT APPLE)
if(NOT APPLE AND NOT YUZU_USE_BUNDLED_LIBUSB)
include(FindPkgConfig)
find_package(LibUSB)
endif()
if (NOT LIBUSB_FOUND)
add_subdirectory(externals/libusb)
set(LIBUSB_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/externals/libusb/libusb/libusb")
set(LIBUSB_LIBRARIES usb)
if (PKG_CONFIG_FOUND)
pkg_check_modules(LIBUSB QUIET libusb-1.0>=1.0.24)
else()
find_package(LibUSB)
endif()
if (LIBUSB_FOUND)
add_library(usb INTERFACE)
target_include_directories(usb INTERFACE "${LIBUSB_INCLUDE_DIRS}")
target_link_libraries(usb INTERFACE "${LIBUSB_LIBRARIES}")
else()
message(WARNING "libusb not found, falling back to externals")
set(YUZU_USE_BUNDLED_LIBUSB ON)
endif()
endif()
# List of all FFmpeg components required

View File

@@ -45,6 +45,11 @@ target_include_directories(microprofile INTERFACE ./microprofile)
add_library(unicorn-headers INTERFACE)
target_include_directories(unicorn-headers INTERFACE ./unicorn/include)
# libusb
if (NOT LIBUSB_FOUND OR YUZU_USE_BUNDLED_LIBUSB)
add_subdirectory(libusb)
endif()
# SDL2
if (NOT SDL2_FOUND AND ENABLE_SDL2)
if (NOT WIN32)

2
externals/SDL vendored

View File

@@ -1,10 +1,13 @@
if (MINGW)
# The MinGW toolchain for some reason doesn't work with this CMakeLists file after updating to
# 1.0.24, so we do it the old-fashioned way for now. We may want to move native Linux toolchains
# to here, too (TODO lat9nq?).
set(LIBUSB_FOUND ON CACHE BOOL "libusb is present" FORCE)
set(LIBUSB_VERSION "1.0.24" CACHE STRING "libusb version string" FORCE)
if (MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux"))
# GNU toolchains for some reason doesn't work with the later half of this CMakeLists after
# updating to 1.0.24, so we do it the old-fashioned way for now.
set(LIBUSB_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/libusb")
set(LIBUSB_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libusb")
# Workarounds for MSYS/MinGW
if (MSYS)
# CMake on Windows passes `C:/`, but we need `/C/` or `/c/` to use `configure`
@@ -19,36 +22,42 @@ if (MINGW)
set(LIBUSB_CONFIGURE "${LIBUSB_SRC_DIR}/configure")
set(LIBUSB_MAKEFILE "${LIBUSB_PREFIX}/Makefile")
set(LIBUSB_LIBRARY "${LIBUSB_PREFIX}/libusb/.libs/libusb-1.0.dll.a")
set(LIBUSB_SHARED_LIBRARY "${LIBUSB_PREFIX}/libusb/.libs/libusb-1.0.dll")
set(LIBUSB_SHARED_LIBRARY_DEST "${CMAKE_BINARY_DIR}/bin/libusb-1.0.dll")
# Causes "externals/libusb/libusb/libusb/os/windows_winusb.c:1427:2: error: conversion to non-scalar type requested", so cannot statically link it for now.
# set(LIBUSB_CFLAGS "-DGUID_DEVINTERFACE_USB_DEVICE=\\(GUID\\){0xA5DCBF10,0x6530,0x11D2,{0x90,0x1F,0x00,0xC0,0x4F,0xB9,0x51,0xED}}")
if (MINGW)
set(LIBUSB_LIBRARIES "${LIBUSB_PREFIX}/libusb/.libs/libusb-1.0.dll.a" CACHE PATH "libusb library path" FORCE)
set(LIBUSB_SHARED_LIBRARY "${LIBUSB_PREFIX}/libusb/.libs/libusb-1.0.dll")
set(LIBUSB_SHARED_LIBRARY_DEST "${CMAKE_BINARY_DIR}/bin/libusb-1.0.dll")
set(LIBUSB_CONFIGURE_ARGS --host=x86_64-w64-mingw32 --build=x86_64-windows)
else()
set(LIBUSB_LIBRARIES "${LIBUSB_PREFIX}/libusb/.libs/libusb-1.0.a" CACHE PATH "libusb library path" FORCE)
endif()
set(LIBUSB_INCLUDE_DIRS "${LIBUSB_SRC_DIR}/libusb" CACHE PATH "libusb headers path" FORCE)
# MINGW: causes "externals/libusb/libusb/libusb/os/windows_winusb.c:1427:2: error: conversion to non-scalar type requested", so cannot statically link it for now.
if (NOT MINGW)
set(LIBUSB_CFLAGS "-DGUID_DEVINTERFACE_USB_DEVICE=\\(GUID\\){0xA5DCBF10,0x6530,0x11D2,{0x90,0x1F,0x00,0xC0,0x4F,0xB9,0x51,0xED}}")
endif()
make_directory("${LIBUSB_PREFIX}")
add_custom_command(
OUTPUT
"${LIBUSB_LIBRARY}"
"${LIBUSB_LIBRARIES}"
COMMAND
make
WORKING_DIRECTORY
"${LIBUSB_PREFIX}"
)
# We may use this path for other GNU toolchains, so put all of the MinGW-specific stuff here
if (MINGW)
set(LIBUSB_CONFIGURE_ARGS --host=x86_64-w64-mingw32 --build=x86_64-windows)
endif()
add_custom_command(
OUTPUT
"${LIBUSB_MAKEFILE}"
COMMAND
# /bin/env
# CFLAGS="${LIBUSB_CFLAGS}"
/bin/sh "${LIBUSB_CONFIGURE}"
env
CFLAGS="${LIBUSB_CFLAGS}"
sh "${LIBUSB_CONFIGURE}"
${LIBUSB_CONFIGURE_ARGS}
--srcdir="${LIBUSB_SRC_DIR}"
WORKING_DIRECTORY
@@ -59,7 +68,7 @@ if (MINGW)
OUTPUT
"${LIBUSB_CONFIGURE}"
COMMAND
/bin/sh "${LIBUSB_SRC_DIR}/bootstrap.sh"
sh "${LIBUSB_SRC_DIR}/bootstrap.sh"
WORKING_DIRECTORY
"${LIBUSB_SRC_DIR}"
)
@@ -68,19 +77,30 @@ if (MINGW)
OUTPUT
"${LIBUSB_SHARED_LIBRARY_DEST}"
COMMAND
/bin/cp "${LIBUSB_SHARED_LIBRARY}" "${LIBUSB_SHARED_LIBRARY_DEST}"
cp "${LIBUSB_SHARED_LIBRARY}" "${LIBUSB_SHARED_LIBRARY_DEST}"
)
add_custom_target(usb-bootstrap ALL DEPENDS "${LIBUSB_CONFIGURE}")
add_custom_target(usb-configure ALL DEPENDS "${LIBUSB_MAKEFILE}" usb-bootstrap)
add_custom_target(usb-build ALL DEPENDS "${LIBUSB_LIBRARY}" usb-configure)
add_custom_target(usb-bootstrap DEPENDS "${LIBUSB_CONFIGURE}")
add_custom_target(usb-configure DEPENDS "${LIBUSB_MAKEFILE}" usb-bootstrap)
add_custom_target(usb-build ALL DEPENDS "${LIBUSB_LIBRARIES}" usb-configure)
# Workaround since static linking didn't work out -- We need to copy the DLL to the bin directory
add_custom_target(usb-copy ALL DEPENDS "${LIBUSB_SHARED_LIBRARY_DEST}" usb-build)
# Make `usb` alias to LIBUSB_LIBRARY
add_library(usb INTERFACE)
target_link_libraries(usb INTERFACE "${LIBUSB_LIBRARY}")
else() # MINGW
add_dependencies(usb usb-copy)
target_link_libraries(usb INTERFACE "${LIBUSB_LIBRARIES}")
target_include_directories(usb INTERFACE "${LIBUSB_INCLUDE_DIRS}")
if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
Include(FindPkgConfig)
pkg_check_modules(LIBUDEV REQUIRED libudev)
if (LIBUDEV_FOUND)
target_include_directories(usb INTERFACE "${LIBUDEV_INCLUDE_DIRS}")
target_link_libraries(usb INTERFACE "${LIBUDEV_STATIC_LIBRARIES}")
endif()
endif()
else() # MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
# Ensure libusb compiles with UTF-8 encoding on MSVC
if(MSVC)
add_compile_options(/utf-8)
@@ -236,4 +256,4 @@ else() # MINGW
configure_file(config.h.in config.h)
endif() # MINGW
endif() # MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux")

View File

@@ -21,14 +21,14 @@ find_package(Git QUIET)
add_custom_command(OUTPUT scm_rev.cpp
COMMAND ${CMAKE_COMMAND}
-DSRC_DIR="${CMAKE_SOURCE_DIR}"
-DBUILD_REPOSITORY="${BUILD_REPOSITORY}"
-DTITLE_BAR_FORMAT_IDLE="${TITLE_BAR_FORMAT_IDLE}"
-DTITLE_BAR_FORMAT_RUNNING="${TITLE_BAR_FORMAT_RUNNING}"
-DBUILD_TAG="${BUILD_TAG}"
-DBUILD_ID="${DISPLAY_VERSION}"
-DGIT_EXECUTABLE="${GIT_EXECUTABLE}"
-P "${CMAKE_SOURCE_DIR}/CMakeModules/GenerateSCMRev.cmake"
-DSRC_DIR=${CMAKE_SOURCE_DIR}
-DBUILD_REPOSITORY=${BUILD_REPOSITORY}
-DTITLE_BAR_FORMAT_IDLE=${TITLE_BAR_FORMAT_IDLE}
-DTITLE_BAR_FORMAT_RUNNING=${TITLE_BAR_FORMAT_RUNNING}
-DBUILD_TAG=${BUILD_TAG}
-DBUILD_ID=${DISPLAY_VERSION}
-DGIT_EXECUTABLE=${GIT_EXECUTABLE}
-P ${CMAKE_SOURCE_DIR}/CMakeModules/GenerateSCMRev.cmake
DEPENDS
# WARNING! It was too much work to try and make a common location for this list,
# so if you need to change it, please update CMakeModules/GenerateSCMRev.cmake as well
@@ -92,6 +92,7 @@ add_custom_command(OUTPUT scm_rev.cpp
"${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.h"
# technically we should regenerate if the git version changed, but its not worth the effort imo
"${CMAKE_SOURCE_DIR}/CMakeModules/GenerateSCMRev.cmake"
VERBATIM
)
add_library(common STATIC

View File

@@ -209,7 +209,7 @@ void SetYuzuPath(YuzuPath yuzu_path, const std::filesystem::path& new_path);
#ifdef _WIN32
template <typename Path>
[[nodiscard]] void SetYuzuPath(YuzuPath yuzu_path, const Path& new_path) {
void SetYuzuPath(YuzuPath yuzu_path, const Path& new_path) {
if constexpr (IsChar<typename Path::value_type>) {
SetYuzuPath(yuzu_path, ToU8String(new_path));
} else {

View File

@@ -150,7 +150,9 @@ void ProgramMetadata::Print() const {
LOG_DEBUG(Service_FS, " > Is Retail: {}", acid_header.is_retail ? "YES" : "NO");
LOG_DEBUG(Service_FS, "Title ID Min: 0x{:016X}", acid_header.title_id_min);
LOG_DEBUG(Service_FS, "Title ID Max: 0x{:016X}", acid_header.title_id_max);
LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", acid_file_access.permissions);
u64_le permissions_l; // local copy to fix alignment error
std::memcpy(&permissions_l, &acid_file_access.permissions, sizeof(permissions_l));
LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", permissions_l);
// Begin ACI0 printing (actual perms, unsigned)
LOG_DEBUG(Service_FS, "Magic: {:.4}", aci_header.magic.data());

View File

@@ -57,11 +57,11 @@ bool SessionRequestManager::HasSessionRequestHandler(const HLERequestContext& co
}
void SessionRequestHandler::ClientConnected(KServerSession* session) {
session->SetSessionHandler(shared_from_this());
session->ClientConnected(shared_from_this());
}
void SessionRequestHandler::ClientDisconnected(KServerSession* session) {
session->SetSessionHandler(nullptr);
session->ClientDisconnected();
}
HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_,

View File

@@ -28,6 +28,9 @@ void KClientPort::Initialize(KPort* parent_port_, s32 max_sessions_, std::string
void KClientPort::OnSessionFinalized() {
KScopedSchedulerLock sl{kernel};
// This might happen if a session was improperly used with this port.
ASSERT_MSG(num_sessions > 0, "num_sessions is invalid");
const auto prev = num_sessions--;
if (prev == max_sessions) {
this->NotifyAvailable();
@@ -66,7 +69,7 @@ ResultCode KClientPort::CreateSession(KClientSession** out,
// Update the session counts.
{
// Atomically increment the number of sessions.
s32 new_sessions;
s32 new_sessions{};
{
const auto max = max_sessions;
auto cur_sessions = num_sessions.load(std::memory_order_acquire);

View File

@@ -62,15 +62,14 @@ public:
void OnClientClosed();
/**
* Sets the HLE handler for the session. This handler will be called to service IPC requests
* instead of the regular IPC machinery. (The regular IPC machinery is currently not
* implemented.)
*/
void SetSessionHandler(SessionRequestHandlerPtr handler) {
void ClientConnected(SessionRequestHandlerPtr handler) {
manager->SetSessionHandler(std::move(handler));
}
void ClientDisconnected() {
manager = nullptr;
}
/**
* Handle a sync request from the emulated application.
*

View File

@@ -449,8 +449,8 @@ static ResultCode CancelSynchronization(Core::System& system, Handle handle) {
// Get the thread from its handle.
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(
static_cast<Handle>(handle));
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Cancel the thread's wait.
thread->WaitCancel();

View File

@@ -40,9 +40,11 @@ namespace SM {
class ServiceManager;
}
static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 characters)
/// Arbitrary default number of maximum connections to an HLE service.
static const u32 DefaultMaxSessions = 64;
/// Default number of maximum connections to a server session.
static constexpr u32 ServerSessionCountMax = 0x40;
static_assert(ServerSessionCountMax == 0x40,
"ServerSessionCountMax isn't 0x40 somehow, this assert is a reminder that this will "
"break lots of things");
/**
* This is an non-templated base of ServiceFramework to reduce code bloat and compilation times, it
@@ -178,7 +180,7 @@ protected:
* connected to this service at the same time.
*/
explicit ServiceFramework(Core::System& system_, const char* service_name_,
u32 max_sessions_ = DefaultMaxSessions)
u32 max_sessions_ = ServerSessionCountMax)
: ServiceFrameworkBase(system_, service_name_, max_sessions_, Invoker) {}
/// Registers handlers in the service.

View File

@@ -151,31 +151,23 @@ ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(Kernel::HLERequestContext&
std::string name(PopServiceName(rp));
// Find the named port.
auto result = service_manager.GetServicePort(name);
if (result.Failed()) {
LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.Code().raw);
return result.Code();
auto port_result = service_manager.GetServicePort(name);
if (port_result.Failed()) {
LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, port_result.Code().raw);
return port_result.Code();
}
auto* port = result.Unwrap();
// Reserve a new session from the process resource limit.
Kernel::KScopedResourceReservation session_reservation(
kernel.CurrentProcess()->GetResourceLimit(), Kernel::LimitableResource::Sessions);
R_UNLESS(session_reservation.Succeeded(), Kernel::ResultLimitReached);
auto& port = port_result.Unwrap()->GetClientPort();
// Create a new session.
auto* session = Kernel::KSession::Create(kernel);
session->Initialize(&port->GetClientPort(), std::move(name));
// Commit the session reservation.
session_reservation.Commit();
// Enqueue the session with the named port.
port->EnqueueSession(&session->GetServerSession());
Kernel::KClientSession* session{};
if (const auto result = port.CreateSession(std::addressof(session)); result.IsError()) {
LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.raw);
return result;
}
LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId());
return MakeResult(&session->GetClientSession());
return MakeResult(session);
}
void SM::RegisterService(Kernel::HLERequestContext& ctx) {

View File

@@ -71,8 +71,7 @@ if (ENABLE_SDL2)
target_compile_definitions(input_common PRIVATE HAVE_SDL2)
endif()
target_include_directories(input_common SYSTEM PRIVATE ${LIBUSB_INCLUDE_DIR})
target_link_libraries(input_common PRIVATE ${LIBUSB_LIBRARIES})
target_link_libraries(input_common PRIVATE usb)
create_target_directory_groups(input_common)
target_link_libraries(input_common PUBLIC core PRIVATE common Boost::boost)

View File

@@ -476,6 +476,9 @@ private:
current_size = 0;
on_going = false;
}
if (empty_bits == PAGES_PER_WORD) {
break;
}
page += empty_bits;
const int continuous_bits = std::countr_one(word >> page);

View File

@@ -647,6 +647,9 @@ u32 CalculateLayerSize(const ImageInfo& info) noexcept {
}
LevelArray CalculateMipLevelOffsets(const ImageInfo& info) noexcept {
if (info.type == ImageType::Linear) {
return {};
}
ASSERT(info.resources.levels <= static_cast<s32>(MAX_MIP_LEVELS));
const LevelInfo level_info = MakeLevelInfo(info);
LevelArray offsets{};

View File

@@ -1395,7 +1395,8 @@ void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) {
void ConfigureInputPlayer::CreateProfile() {
const auto profile_name =
LimitableInputDialog::GetText(this, tr("New Profile"), tr("Enter a profile name:"), 1, 20);
LimitableInputDialog::GetText(this, tr("New Profile"), tr("Enter a profile name:"), 1, 20,
LimitableInputDialog::InputLimiter::Filesystem);
if (profile_name.isEmpty()) {
return;

View File

@@ -17,17 +17,30 @@
namespace {
constexpr std::array default_icon_sizes{
std::make_pair(0, QT_TR_NOOP("None")),
std::make_pair(32, QT_TR_NOOP("Small (32x32)")),
std::make_pair(64, QT_TR_NOOP("Standard (64x64)")),
std::make_pair(128, QT_TR_NOOP("Large (128x128)")),
std::make_pair(256, QT_TR_NOOP("Full Size (256x256)")),
std::make_pair(0, QT_TRANSLATE_NOOP("ConfigureUI", "None")),
std::make_pair(32, QT_TRANSLATE_NOOP("ConfigureUI", "Small (32x32)")),
std::make_pair(64, QT_TRANSLATE_NOOP("ConfigureUI", "Standard (64x64)")),
std::make_pair(128, QT_TRANSLATE_NOOP("ConfigureUI", "Large (128x128)")),
std::make_pair(256, QT_TRANSLATE_NOOP("ConfigureUI", "Full Size (256x256)")),
};
// clang-format off
constexpr std::array row_text_names{
QT_TR_NOOP("Filename"), QT_TR_NOOP("Filetype"), QT_TR_NOOP("Title ID"),
QT_TR_NOOP("Title Name"), QT_TR_NOOP("None"),
QT_TRANSLATE_NOOP("ConfigureUI", "Filename"),
QT_TRANSLATE_NOOP("ConfigureUI", "Filetype"),
QT_TRANSLATE_NOOP("ConfigureUI", "Title ID"),
QT_TRANSLATE_NOOP("ConfigureUI", "Title Name"),
QT_TRANSLATE_NOOP("ConfigureUI", "None"),
};
// clang-format on
QString GetTranslatedIconSize(size_t index) {
return QCoreApplication::translate("ConfigureUI", default_icon_sizes[index].second);
}
QString GetTranslatedRowTextName(size_t index) {
return QCoreApplication::translate("ConfigureUI", row_text_names[index]);
}
} // Anonymous namespace
ConfigureUi::ConfigureUi(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureUi) {
@@ -121,11 +134,11 @@ void ConfigureUi::RetranslateUI() {
ui->retranslateUi(this);
for (int i = 0; i < ui->icon_size_combobox->count(); i++) {
ui->icon_size_combobox->setItemText(i, tr(default_icon_sizes[i].second));
ui->icon_size_combobox->setItemText(i, GetTranslatedIconSize(static_cast<size_t>(i)));
}
for (int i = 0; i < ui->row_1_text_combobox->count(); i++) {
const QString name = tr(row_text_names[i]);
const QString name = GetTranslatedRowTextName(static_cast<size_t>(i));
ui->row_1_text_combobox->setItemText(i, name);
ui->row_2_text_combobox->setItemText(i, name);
@@ -152,8 +165,9 @@ void ConfigureUi::InitializeLanguageComboBox() {
}
void ConfigureUi::InitializeIconSizeComboBox() {
for (const auto& size : default_icon_sizes) {
ui->icon_size_combobox->addItem(QString::fromUtf8(size.second), size.first);
for (size_t i = 0; i < default_icon_sizes.size(); i++) {
const auto size = default_icon_sizes[i].first;
ui->icon_size_combobox->addItem(GetTranslatedIconSize(i), size);
}
}
@@ -170,7 +184,7 @@ void ConfigureUi::UpdateFirstRowComboBox(bool init) {
ui->row_1_text_combobox->clear();
for (std::size_t i = 0; i < row_text_names.size(); i++) {
const QString row_text_name = QString::fromUtf8(row_text_names[i]);
const QString row_text_name = GetTranslatedRowTextName(i);
ui->row_1_text_combobox->addItem(row_text_name, QVariant::fromValue(i));
}
@@ -189,7 +203,7 @@ void ConfigureUi::UpdateSecondRowComboBox(bool init) {
ui->row_2_text_combobox->clear();
for (std::size_t i = 0; i < row_text_names.size(); ++i) {
const QString row_text_name = QString::fromUtf8(row_text_names[i]);
const QString row_text_name = GetTranslatedRowTextName(i);
ui->row_2_text_combobox->addItem(row_text_name, QVariant::fromValue(i));
}

View File

@@ -505,6 +505,10 @@ void GameList::PopupContextMenu(const QPoint& menu_location) {
void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::string& path) {
QAction* favorite = context_menu.addAction(tr("Favorite"));
context_menu.addSeparator();
QAction* start_game = context_menu.addAction(tr("Start Game"));
QAction* start_game_global =
context_menu.addAction(tr("Start Game without Custom Configuration"));
context_menu.addSeparator();
QAction* open_save_location = context_menu.addAction(tr("Open Save Data Location"));
QAction* open_mod_location = context_menu.addAction(tr("Open Mod Data Location"));
QAction* open_transferable_shader_cache =
@@ -540,6 +544,12 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri
connect(open_save_location, &QAction::triggered, [this, program_id, path]() {
emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData, path);
});
connect(start_game, &QAction::triggered, [this, path]() {
emit BootGame(QString::fromStdString(path), 0, StartGameType::Normal);
});
connect(start_game_global, &QAction::triggered, [this, path]() {
emit BootGame(QString::fromStdString(path), 0, StartGameType::Global);
});
connect(open_mod_location, &QAction::triggered, [this, program_id, path]() {
emit OpenFolderRequested(program_id, GameListOpenTarget::ModData, path);
});

View File

@@ -28,6 +28,7 @@ class GameListWorker;
class GameListSearchField;
class GameListDir;
class GMainWindow;
enum class StartGameType;
namespace FileSys {
class ManualContentProvider;
@@ -82,6 +83,7 @@ public:
static const QStringList supported_file_extensions;
signals:
void BootGame(const QString& game_path, std::size_t program_index, StartGameType type);
void GameChosen(const QString& game_path);
void ShouldCancelWorker();
void OpenFolderRequested(u64 program_id, GameListOpenTarget target,

View File

@@ -1094,6 +1094,7 @@ void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) {
}
void GMainWindow::ConnectWidgetEvents() {
connect(game_list, &GameList::BootGame, this, &GMainWindow::BootGame);
connect(game_list, &GameList::GameChosen, this, &GMainWindow::OnGameListLoadFile);
connect(game_list, &GameList::OpenDirectory, this, &GMainWindow::OnGameListOpenDirectory);
connect(game_list, &GameList::OpenFolderRequested, this, &GMainWindow::OnGameListOpenFolder);
@@ -1320,7 +1321,7 @@ void GMainWindow::SelectAndSetCurrentUser() {
Settings::values.current_user = dialog.GetIndex();
}
void GMainWindow::BootGame(const QString& filename, std::size_t program_index) {
void GMainWindow::BootGame(const QString& filename, std::size_t program_index, StartGameType type) {
LOG_INFO(Frontend, "yuzu starting...");
StoreRecentFile(filename); // Put the filename on top of the list
@@ -1332,7 +1333,8 @@ void GMainWindow::BootGame(const QString& filename, std::size_t program_index) {
const auto v_file = Core::GetGameFileFromPath(vfs, filename.toUtf8().constData());
const auto loader = Loader::GetLoader(system, v_file, program_index);
if (!(loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success)) {
if (loader != nullptr && loader->ReadProgramId(title_id) == Loader::ResultStatus::Success &&
type == StartGameType::Normal) {
// Load per game settings
const auto file_path = std::filesystem::path{filename.toStdU16String()};
const auto config_file_name = title_id == 0
@@ -1944,6 +1946,18 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa
const auto full = res == selections.constFirst();
const auto entry_size = CalculateRomFSEntrySize(extracted, full);
// The minimum required space is the size of the extracted RomFS + 1 GiB
const auto minimum_free_space = extracted->GetSize() + 0x40000000;
if (full && Common::FS::GetFreeSpaceSize(path) < minimum_free_space) {
QMessageBox::warning(this, tr("RomFS Extraction Failed!"),
tr("There is not enough free space at %1 to extract the RomFS. Please "
"free up space or select a different dump directory at "
"Emulation > Configure > System > Filesystem > Dump Root")
.arg(QString::fromStdString(path)));
return;
}
QProgressDialog progress(tr("Extracting RomFS..."), tr("Cancel"), 0,
static_cast<s32>(entry_size), this);
progress.setWindowModality(Qt::WindowModal);

View File

@@ -39,6 +39,11 @@ class GameListPlaceholder;
class QtSoftwareKeyboardDialog;
enum class StartGameType {
Normal, // Can use custom configuration
Global, // Only uses global configuration
};
namespace Core::Frontend {
struct ControllerParameters;
struct InlineAppearParameters;
@@ -181,7 +186,8 @@ private:
void AllowOSSleep();
bool LoadROM(const QString& filename, std::size_t program_index);
void BootGame(const QString& filename, std::size_t program_index = 0);
void BootGame(const QString& filename, std::size_t program_index = 0,
StartGameType with_config = StartGameType::Normal);
void ShutdownGame();
void ShowTelemetryCallout();

View File

@@ -21,11 +21,13 @@ void LimitableInputDialog::CreateUI() {
text_label = new QLabel(this);
text_entry = new QLineEdit(this);
text_label_invalid = new QLabel(this);
buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
auto* const layout = new QVBoxLayout;
layout->addWidget(text_label);
layout->addWidget(text_entry);
layout->addWidget(text_label_invalid);
layout->addWidget(buttons);
setLayout(layout);
@@ -37,18 +39,36 @@ void LimitableInputDialog::ConnectEvents() {
}
QString LimitableInputDialog::GetText(QWidget* parent, const QString& title, const QString& text,
int min_character_limit, int max_character_limit) {
int min_character_limit, int max_character_limit,
InputLimiter limit_type) {
Q_ASSERT(min_character_limit <= max_character_limit);
LimitableInputDialog dialog{parent};
dialog.setWindowTitle(title);
dialog.text_label->setText(text);
dialog.text_entry->setMaxLength(max_character_limit);
dialog.text_label_invalid->show();
switch (limit_type) {
case InputLimiter::Filesystem:
dialog.invalid_characters = QStringLiteral("<>:;\"/\\|,.!?*");
break;
default:
dialog.invalid_characters.clear();
dialog.text_label_invalid->hide();
break;
}
dialog.text_label_invalid->setText(
tr("The text can't contain any of the following characters:\n%1")
.arg(dialog.invalid_characters));
auto* const ok_button = dialog.buttons->button(QDialogButtonBox::Ok);
ok_button->setEnabled(false);
connect(dialog.text_entry, &QLineEdit::textEdited, [&](const QString& new_text) {
ok_button->setEnabled(new_text.length() >= min_character_limit);
connect(dialog.text_entry, &QLineEdit::textEdited, [&] {
if (!dialog.invalid_characters.isEmpty()) {
dialog.RemoveInvalidCharacters();
}
ok_button->setEnabled(dialog.text_entry->text().length() >= min_character_limit);
});
if (dialog.exec() != QDialog::Accepted) {
@@ -57,3 +77,15 @@ QString LimitableInputDialog::GetText(QWidget* parent, const QString& title, con
return dialog.text_entry->text();
}
void LimitableInputDialog::RemoveInvalidCharacters() {
auto cpos = text_entry->cursorPosition();
for (int i = 0; i < text_entry->text().length(); i++) {
if (invalid_characters.contains(text_entry->text().at(i))) {
text_entry->setText(text_entry->text().remove(i, 1));
i--;
cpos--;
}
}
text_entry->setCursorPosition(cpos);
}

View File

@@ -18,14 +18,24 @@ public:
explicit LimitableInputDialog(QWidget* parent = nullptr);
~LimitableInputDialog() override;
enum class InputLimiter {
None,
Filesystem,
};
static QString GetText(QWidget* parent, const QString& title, const QString& text,
int min_character_limit, int max_character_limit);
int min_character_limit, int max_character_limit,
InputLimiter limit_type = InputLimiter::None);
private:
void CreateUI();
void ConnectEvents();
void RemoveInvalidCharacters();
QString invalid_characters;
QLabel* text_label;
QLineEdit* text_entry;
QLabel* text_label_invalid;
QDialogButtonBox* buttons;
};

View File

@@ -32,17 +32,17 @@
class SDLGLContext : public Core::Frontend::GraphicsContext {
public:
explicit SDLGLContext() {
// create a hidden window to make the shared context against
window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 0, 0,
SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL);
explicit SDLGLContext(SDL_Window* window_) : window{window_} {
context = SDL_GL_CreateContext(window);
}
~SDLGLContext() {
DoneCurrent();
SDL_GL_DeleteContext(context);
SDL_DestroyWindow(window);
}
void SwapBuffers() override {
SDL_GL_SwapWindow(window);
}
void MakeCurrent() override {
@@ -114,9 +114,6 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste
exit(1);
}
dummy_window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 0, 0,
SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL);
SetWindowIcon();
if (fullscreen) {
@@ -159,5 +156,5 @@ EmuWindow_SDL2_GL::~EmuWindow_SDL2_GL() {
}
std::unique_ptr<Core::Frontend::GraphicsContext> EmuWindow_SDL2_GL::CreateSharedContext() const {
return std::make_unique<SDLGLContext>();
return std::make_unique<SDLGLContext>(render_window);
}

View File

@@ -20,9 +20,6 @@ public:
std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override;
private:
/// Fake hidden window for the core context
SDL_Window* dummy_window{};
/// Whether the GPU and driver supports the OpenGL extension required
bool SupportsRequiredGLExtensions();