Compare commits
18 Commits
2024-04-28
...
2024-05-08
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bef55d43a5 | ||
|
|
08f47542e8 | ||
|
|
cdcbfdc837 | ||
|
|
036a7edb2c | ||
|
|
1df1841ad1 | ||
|
|
5097c6a0b9 | ||
|
|
4821698cd8 | ||
|
|
4ebd9dc2b5 | ||
|
|
12ccc468f4 | ||
|
|
82fce02827 | ||
|
|
bddfb77343 | ||
|
|
f7f1114ec1 | ||
|
|
c1449cca64 | ||
|
|
b242ac022c | ||
|
|
37e53d50bb | ||
|
|
b6e8e04533 | ||
|
|
f890dbb064 | ||
|
|
f05ffb6b05 |
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -55,9 +55,6 @@
|
||||
[submodule "externals/SPIRV-Headers"]
|
||||
path = externals/SPIRV-Headers
|
||||
url = https://github.com/KhronosGroup/SPIRV-Headers.git
|
||||
[submodule "externals/boost-headers"]
|
||||
path = externals/boost-headers
|
||||
url = https://github.com/boostorg/headers.git
|
||||
[submodule "externals/SPIRV-Tools"]
|
||||
path = externals/SPIRV-Tools
|
||||
url = https://github.com/KhronosGroup/SPIRV-Tools.git
|
||||
|
||||
@@ -275,8 +275,17 @@ endif()
|
||||
# Configure C++ standard
|
||||
# ===========================
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
# boost asio's concept usage doesn't play nicely with some compilers yet.
|
||||
add_definitions(-DBOOST_ASIO_DISABLE_CONCEPTS)
|
||||
if (MSVC)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:/std:c++20>)
|
||||
|
||||
# boost still makes use of deprecated result_of.
|
||||
add_definitions(-D_HAS_DEPRECATED_RESULT_OF)
|
||||
else()
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
endif()
|
||||
|
||||
# Output binaries to bin/
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
||||
@@ -285,6 +294,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
||||
# =======================================================================
|
||||
|
||||
# Enforce the search mode of non-required packages for better and shorter failure messages
|
||||
find_package(Boost 1.79.0 REQUIRED context)
|
||||
find_package(enet 1.3 MODULE)
|
||||
find_package(fmt 9 REQUIRED)
|
||||
find_package(LLVM 17.0.2 MODULE COMPONENTS Demangle)
|
||||
@@ -344,6 +354,11 @@ if (YUZU_TESTS)
|
||||
find_package(Catch2 3.0.1 REQUIRED)
|
||||
endif()
|
||||
|
||||
# boost:asio has functions that require AcceptEx et al
|
||||
if (MINGW)
|
||||
find_library(MSWSOCK_LIBRARY mswsock REQUIRED)
|
||||
endif()
|
||||
|
||||
if(ENABLE_OPENSSL)
|
||||
find_package(OpenSSL 1.1.1 REQUIRED)
|
||||
endif()
|
||||
@@ -669,6 +684,8 @@ function(create_target_directory_groups target_name)
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# Prevent boost from linking against libs when building
|
||||
target_link_libraries(Boost::headers INTERFACE Boost::disable_autolinking)
|
||||
# Adjustments for MSVC + Ninja
|
||||
if (MSVC AND CMAKE_GENERATOR STREQUAL "Ninja")
|
||||
add_compile_options(
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# prefix_var: name of a variable which will be set with the path to the extracted contents
|
||||
function(download_bundled_external remote_path lib_name prefix_var)
|
||||
|
||||
set(package_base_url "https://github.com/yuzu-emu/")
|
||||
set(package_base_url "https://github.com/yuzu-mirror/")
|
||||
set(package_repo "no_platform")
|
||||
set(package_extension "no_platform")
|
||||
if (WIN32)
|
||||
|
||||
39
README.md
39
README.md
@@ -5,13 +5,13 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
<h1 align="center">
|
||||
<br>
|
||||
<a href="http://y2nlvhmmk5jnsvechppxnbyzmmv3vbl7dvzn6ltwcdbpgxixp3clkgqd.onion/torzu-emu/torzu"><img src="https://raw.githubusercontent.com/litucks/torzu/master/dist/yuzu.svg" alt="torzu" width="200"></a>
|
||||
<a href="http://y2nlvhmmk5jnsvechppxnbyzmmv3vbl7dvzn6ltwcdbpgxixp3clkgqd.onion/torzu-emu/torzu"><img src="https://raw.githubusercontent.com/litucks/torzu/master/dist/yuzu.bmp" alt="torzu" width="200"></a>
|
||||
<br>
|
||||
<b>torzu</b>
|
||||
<br>
|
||||
</h1>
|
||||
|
||||
<h4 align="center"><b>torzu</b> is a fork of yuzu, the world's most popular, open-source, Nintendo Switch emulator — started by the creators of <a href="https://citra-emu.org" target="_blank">Citra</a>.
|
||||
<h4 align="center"><b>torzu</b> is a fork of yuzu, the world's most popular, open-source, Nintendo Switch emulator.
|
||||
<br>
|
||||
It is written in C++ with portability in mind, and I plan to actively maintain builds for Linux, Android and Windows.
|
||||
</h4>
|
||||
@@ -30,11 +30,33 @@ The emulator is capable of running most commercial games at full speed, provided
|
||||
|
||||
It runs most Nintendo Switch games released until the date of the Yuzu takedown.
|
||||
|
||||
## Changes
|
||||
|
||||
Following are the changes made since forking from Yuzu:
|
||||
|
||||
- Added option to optimize generated SPIR-V shaders via spirv-opt
|
||||
- Added option to synchronize CPU clock to render speed limit
|
||||
- Added option to launch home menu from Switch firmware
|
||||
- Fixed crash when switching away from null graphics per-game
|
||||
- Fixed controller UI being cut off at the bottom
|
||||
- Removed analytics and authentication as they'd be useless (perhaps even outright dangerous) now
|
||||
- Minor improvements and additions
|
||||
|
||||
## Goals
|
||||
|
||||
The first and foremost goal is long-term maintenance. Even if I stop commiting new features I will always do my best to keep the emulator functional and third party dependencies updated. This also means most of the changes made will eventually be bug fixes.
|
||||
Essentially, the main goal is that you can still use this emulator on modern systems in 20 years.
|
||||
It is very important to me that this project is going to be a good base to fork once grass has grown over the whole legal dilemma and people are willing to do real work on this emulator non-anonymously.
|
||||
|
||||
While the main platform is Linux as it is the main operating system I run on my personal and development desktops, Windows support is very near and will not be forgotten about. Android support is low priority but would be a nice bonus.
|
||||
|
||||
A secondary goal is the improvement of usability on low-end systems. This includes both improving the performance of the emulator as well as making games more playable below 100% speed whenever possible (the sync CPU to render speed limit option already helps with that in few cases).
|
||||
|
||||
## Development
|
||||
|
||||
Most of the development happens on [Dark Git](http://y2nlvhmmk5jnsvechppxnbyzmmv3vbl7dvzn6ltwcdbpgxixp3clkgqd.onion/). It's also where [our central repository](http://y2nlvhmmk5jnsvechppxnbyzmmv3vbl7dvzn6ltwcdbpgxixp3clkgqd.onion/torzu-emu/torzu) is hosted.
|
||||
|
||||
Currently, development is limited to external commits as I'm working on implementing a faster recompiler! This will increase emulation speed in CPU-bound scenarios.
|
||||
Currently, development is somewhat limited to external commits as I'm working on improvements in dynarmic! This will increase emulation speed in CPU-bound scenarios.
|
||||
|
||||
If you want to contribute, please take a look at the [Contributor's Guide](http://y2nlvhmmk5jnsvechppxnbyzmmv3vbl7dvzn6ltwcdbpgxixp3clkgqd.onion/torzu-emu/torzu/wiki/Contributing) and [Developer Information](http://y2nlvhmmk5jnsvechppxnbyzmmv3vbl7dvzn6ltwcdbpgxixp3clkgqd.onion/torzu-emu/torzu/wiki/Developer-Information).
|
||||
|
||||
@@ -48,22 +70,23 @@ Alternatively, you can clone from the [GitHub mirror repository](https://github.
|
||||
|
||||
git clone https://github.com/litucks/torzu.git --depth 1 --recursive
|
||||
|
||||
Note that above repository may be taken down any time. Do not rely on its existence in production.
|
||||
Note that above repository may be taken down any time. Do not rely on its existence in production. In case the GitHub mirror goes down, a mirror will be set up on Gitlab.
|
||||
|
||||
This project incorporates several commits from the [Suyu](https://suyu.dev) and [Sudachi](https://github.com/sudachi-emu/sudachi) forks (but cleaned up due to the typically mediocre code/commit quality from both projects) as well as some custom changes, including lowered minimum boost library version requirements and faster fibers.
|
||||
This project incorporates several commits from the [Suyu](https://suyu.dev) and [Sudachi](https://github.com/sudachi-emu/sudachi) forks (but cleaned up due to the typically mediocre code/commit quality from both projects) as well as changes listed in **Changes**.
|
||||
|
||||
## Building
|
||||
|
||||
* __Linux__: [Linux Build](http://y2nlvhmmk5jnsvechppxnbyzmmv3vbl7dvzn6ltwcdbpgxixp3clkgqd.onion/torzu-emu/torzu/wiki/Building-for-Linux)
|
||||
* ~~__Windows__: [Windows Build](http://y2nlvhmmk5jnsvechppxnbyzmmv3vbl7dvzn6ltwcdbpgxixp3clkgqd.onion/torzu-emu/torzu/wiki/Building-for-Windows)~~
|
||||
* __Windows__: [Windows Build](http://y2nlvhmmk5jnsvechppxnbyzmmv3vbl7dvzn6ltwcdbpgxixp3clkgqd.onion/torzu-emu/torzu/wiki/Building-for-Windows)
|
||||
* ~~__Android__: [Android Build](http://y2nlvhmmk5jnsvechppxnbyzmmv3vbl7dvzn6ltwcdbpgxixp3clkgqd.onion/torzu-emu/torzu/wiki/Building-For-Android)~~
|
||||
* ~~__macOS__: [macOS Build](http://y2nlvhmmk5jnsvechppxnbyzmmv3vbl7dvzn6ltwcdbpgxixp3clkgqd.onion/torzu-emu/torzu/wiki/Building-for-macOS)~~
|
||||
|
||||
(Only Linux builds are available for now. Next planned are Windows, then Android.)
|
||||
(Only Linux and Windows builds are available for now. Android is planned eventually.)
|
||||
|
||||
## Download
|
||||
|
||||
There are no precompiled releases available (yet).
|
||||
Precompiled build are available **in the releases section**.
|
||||
Windows builds have not been released yet but will very soon.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
2
dist/yuzu.svg
vendored
2
dist/yuzu.svg
vendored
@@ -1,2 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" version="1.1" viewBox="0 0 152 152" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><circle cx="75.585" cy="75.585" r="75.585" fill="url(#_Radial1)"/><clipPath id="_clip2"><circle cx="75.585" cy="75.585" r="75.585"/></clipPath><g clip-path="url(#_clip2)"><path d="m75.585 17.097c11.94-0 21.635 9.694 21.635 21.635s-9.695 21.635-21.635 21.635c-11.941 0-21.635-9.694-21.635-21.635s9.694-21.635 21.635-21.635zm-0 5.21c-9.066 0-16.425 7.36-16.425 16.425s7.359 16.425 16.425 16.425c9.065-0 16.424-7.36 16.424-16.425s-7.359-16.425-16.424-16.425z"/><path d="m75.585 27.343c6.285 0 11.388 5.103 11.388 11.389s-5.103 11.389-11.388 11.389c-6.286-0-11.389-5.103-11.389-11.389s5.103-11.389 11.389-11.389zm-0 5.21c-3.41 0-6.179 2.769-6.179 6.179s2.769 6.179 6.179 6.179 6.178-2.769 6.178-6.179-2.768-6.179-6.178-6.179z"/><path d="m112.44 53.95c11.941-0 21.635 9.694 21.635 21.635 0 11.94-9.694 21.635-21.635 21.635s-21.635-9.695-21.635-21.635c0-11.941 9.694-21.635 21.635-21.635zm0 5.21c-9.065-0-16.425 7.359-16.425 16.425 0 9.065 7.36 16.424 16.425 16.424s16.425-7.359 16.425-16.424c-0-9.066-7.36-16.425-16.425-16.425z"/><path d="m112.44 64.196c6.286-0 11.389 5.103 11.389 11.389-0 6.285-5.103 11.388-11.389 11.388s-11.389-5.103-11.389-11.388c0-6.286 5.103-11.389 11.389-11.389zm0 5.21c-3.41-0-6.178 2.769-6.178 6.179s2.768 6.178 6.178 6.178 6.179-2.768 6.179-6.178-2.769-6.179-6.179-6.179z"/><path d="m75.585 90.802c11.94 0 21.635 9.694 21.635 21.635s-9.695 21.635-21.635 21.635c-11.941 0-21.635-9.694-21.635-21.635s9.694-21.635 21.635-21.635zm-0 5.21c-9.066 0-16.425 7.36-16.425 16.425s7.359 16.425 16.425 16.425c9.065-0 16.424-7.36 16.424-16.425s-7.359-16.425-16.424-16.425z"/><path d="m75.585 101.05c6.285 0 11.388 5.103 11.388 11.389s-5.103 11.389-11.388 11.389c-6.286-0-11.389-5.103-11.389-11.389s5.103-11.389 11.389-11.389zm-0 5.211c-3.41-0-6.179 2.768-6.179 6.178s2.769 6.179 6.179 6.179 6.178-2.769 6.178-6.179-2.768-6.178-6.178-6.178z"/><path d="m38.732 53.95c11.941-0 21.635 9.694 21.635 21.635 0 11.94-9.694 21.635-21.635 21.635s-21.635-9.695-21.635-21.635c-0-11.941 9.694-21.635 21.635-21.635zm-0 5.21c-9.065-0-16.425 7.359-16.425 16.425 0 9.065 7.36 16.424 16.425 16.424s16.425-7.359 16.425-16.424c-0-9.066-7.36-16.425-16.425-16.425z"/><path d="m38.732 64.196c6.286-0 11.389 5.103 11.389 11.389-0 6.285-5.103 11.388-11.389 11.388s-11.389-5.103-11.389-11.388c0-6.286 5.103-11.389 11.389-11.389zm-0 5.21c-3.41-0-6.179 2.769-6.179 6.179s2.769 6.178 6.179 6.178 6.179-2.768 6.179-6.178-2.769-6.179-6.179-6.179z"/></g><defs><radialGradient id="_Radial1" cx="0" cy="0" r="1" gradientTransform="matrix(-81.196 -81.196 81.196 -81.196 114.32 116.87)" gradientUnits="userSpaceOnUse"><stop stop-color="#ff2088" offset="0"/><stop stop-color="#c24bac" offset=".44"/><stop stop-color="#37aeff" offset="1"/></radialGradient></defs></svg>
|
||||
<svg clip-rule="evenodd" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" version="1.1" viewBox="0 0 152 152" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><circle cx="75.585" cy="75.585" r="75.585" fill="url(#_Radial1)"/><clipPath id="_clip2"></clipPath><g clip-path="url(#_clip2)"><path d="m75.585 17.097c11.94-0 21.635 9.694 21.635 21.635s-9.695 21.635-21.635 21.635c-11.941 0-21.635-9.694-21.635-21.635s9.694-21.635 21.635-21.635zm-0 5.21c-9.066 0-16.425 7.36-16.425 16.425s7.359 16.425 16.425 16.425c9.065-0 16.424-7.36 16.424-16.425s-7.359-16.425-16.424-16.425z"/><path d="m75.585 27.343c6.285 0 11.388 5.103 11.388 11.389s-5.103 11.389-11.388 11.389c-6.286-0-11.389-5.103-11.389-11.389s5.103-11.389 11.389-11.389zm-0 5.21c-3.41 0-6.179 2.769-6.179 6.179s2.769 6.179 6.179 6.179 6.178-2.769 6.178-6.179-2.768-6.179-6.178-6.179z"/><path d="m112.44 53.95c11.941-0 21.635 9.694 21.635 21.635 0 11.94-9.694 21.635-21.635 21.635s-21.635-9.695-21.635-21.635c0-11.941 9.694-21.635 21.635-21.635zm0 5.21c-9.065-0-16.425 7.359-16.425 16.425 0 9.065 7.36 16.424 16.425 16.424s16.425-7.359 16.425-16.424c-0-9.066-7.36-16.425-16.425-16.425z"/><path d="m112.44 64.196c6.286-0 11.389 5.103 11.389 11.389-0 6.285-5.103 11.388-11.389 11.388s-11.389-5.103-11.389-11.388c0-6.286 5.103-11.389 11.389-11.389zm0 5.21c-3.41-0-6.178 2.769-6.178 6.179s2.768 6.178 6.178 6.178 6.179-2.768 6.179-6.178-2.769-6.179-6.179-6.179z"/><path d="m75.585 90.802c11.94 0 21.635 9.694 21.635 21.635s-9.695 21.635-21.635 21.635c-11.941 0-21.635-9.694-21.635-21.635s9.694-21.635 21.635-21.635zm-0 5.21c-9.066 0-16.425 7.36-16.425 16.425s7.359 16.425 16.425 16.425c9.065-0 16.424-7.36 16.424-16.425s-7.359-16.425-16.424-16.425z"/><path d="m75.585 101.05c6.285 0 11.388 5.103 11.388 11.389s-5.103 11.389-11.388 11.389c-6.286-0-11.389-5.103-11.389-11.389s5.103-11.389 11.389-11.389zm-0 5.211c-3.41-0-6.179 2.768-6.179 6.178s2.769 6.179 6.179 6.179 6.178-2.769 6.178-6.179-2.768-6.178-6.178-6.178z"/><path d="m38.732 53.95c11.941-0 21.635 9.694 21.635 21.635 0 11.94-9.694 21.635-21.635 21.635s-21.635-9.695-21.635-21.635c-0-11.941 9.694-21.635 21.635-21.635zm-0 5.21c-9.065-0-16.425 7.359-16.425 16.425 0 9.065 7.36 16.424 16.425 16.424s16.425-7.359 16.425-16.424c-0-9.066-7.36-16.425-16.425-16.425z"/><path d="m38.732 64.196c6.286-0 11.389 5.103 11.389 11.389-0 6.285-5.103 11.388-11.389 11.388s-11.389-5.103-11.389-11.388c0-6.286 5.103-11.389 11.389-11.389zm-0 5.21c-3.41-0-6.179 2.769-6.179 6.179s2.769 6.178 6.179 6.178 6.179-2.768 6.179-6.178-2.769-6.179-6.179-6.179z"/></g><defs><radialGradient id="_Radial1" cx="0" cy="0" r="1" gradientTransform="matrix(-81.196 -81.196 81.196 -81.196 114.32 116.87)" gradientUnits="userSpaceOnUse"><stop stop-color="#ff2088" offset="0"/><stop stop-color="#c24bac" offset=".44"/><stop stop-color="#37aeff" offset="1"/></radialGradient></defs></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
4
externals/CMakeLists.txt
vendored
4
externals/CMakeLists.txt
vendored
@@ -168,12 +168,10 @@ endif()
|
||||
|
||||
# SPIRV-Tools
|
||||
if (YUZU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS)
|
||||
set(SPIRV_SKIP_EXECUTABLES ON)
|
||||
add_subdirectory(SPIRV-Tools)
|
||||
endif()
|
||||
|
||||
# Boost headers
|
||||
add_subdirectory(boost-headers)
|
||||
|
||||
# TZDB (Time Zone Database)
|
||||
add_subdirectory(nx_tzdb)
|
||||
|
||||
|
||||
1
externals/boost-headers
vendored
1
externals/boost-headers
vendored
Submodule externals/boost-headers deleted from 0456900fad
@@ -62,12 +62,10 @@ if (MSVC)
|
||||
|
||||
# Warnings
|
||||
/W4
|
||||
/WX
|
||||
|
||||
/we4062 # Enumerator 'identifier' in a switch of enum 'enumeration' is not handled
|
||||
/we4189 # 'identifier': local variable is initialized but not referenced
|
||||
/we4265 # 'class': class has virtual functions, but destructor is not virtual
|
||||
/we4388 # 'expression': signed/unsigned mismatch
|
||||
/we4389 # 'operator': signed/unsigned mismatch
|
||||
/we4456 # Declaration of 'identifier' hides previous local declaration
|
||||
/we4457 # Declaration of 'identifier' hides function parameter
|
||||
|
||||
@@ -212,8 +212,6 @@ add_library(audio_core STATIC
|
||||
|
||||
if (MSVC)
|
||||
target_compile_options(audio_core PRIVATE
|
||||
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
|
||||
/we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data
|
||||
/we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch
|
||||
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
|
||||
/we4800 # Implicit conversion from 'type' to bool. Possible information loss
|
||||
|
||||
@@ -233,8 +233,6 @@ if (MSVC)
|
||||
_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
|
||||
)
|
||||
target_compile_options(common PRIVATE
|
||||
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
|
||||
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
|
||||
/we4800 # Implicit conversion from 'type' to bool. Possible information loss
|
||||
)
|
||||
else()
|
||||
@@ -261,7 +259,7 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(common PUBLIC Boost::headers fmt::fmt microprofile stb::headers Threads::Threads)
|
||||
target_link_libraries(common PUBLIC Boost::context Boost::headers fmt::fmt microprofile stb::headers Threads::Threads)
|
||||
target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle)
|
||||
|
||||
if (ANDROID)
|
||||
|
||||
@@ -5,46 +5,87 @@
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/fiber.h"
|
||||
#define MINICORO_IMPL
|
||||
#include "common/minicoro.h"
|
||||
#include "common/virtual_buffer.h"
|
||||
|
||||
#include <boost/context/detail/fcontext.hpp>
|
||||
|
||||
namespace Common {
|
||||
|
||||
constexpr std::size_t default_stack_size = 512 * 1024;
|
||||
|
||||
struct Fiber::FiberImpl {
|
||||
FiberImpl() {}
|
||||
FiberImpl() : stack{default_stack_size}, rewind_stack{default_stack_size} {}
|
||||
|
||||
VirtualBuffer<u8> stack;
|
||||
VirtualBuffer<u8> rewind_stack;
|
||||
|
||||
std::mutex guard;
|
||||
bool released{};
|
||||
bool is_thread_fiber{};
|
||||
Fiber* next_fiber{};
|
||||
Fiber** next_fiber_ptr;
|
||||
std::function<void()> entry_point;
|
||||
std::function<void()> rewind_point;
|
||||
std::shared_ptr<Fiber> previous_fiber;
|
||||
bool is_thread_fiber{};
|
||||
bool released{};
|
||||
|
||||
mco_coro* context;
|
||||
u8* stack_limit{};
|
||||
u8* rewind_stack_limit{};
|
||||
boost::context::detail::fcontext_t context{};
|
||||
boost::context::detail::fcontext_t rewind_context{};
|
||||
};
|
||||
|
||||
Fiber::Fiber() : impl{std::make_unique<FiberImpl>()} {
|
||||
impl->is_thread_fiber = true;
|
||||
void Fiber::SetRewindPoint(std::function<void()>&& rewind_func) {
|
||||
impl->rewind_point = std::move(rewind_func);
|
||||
}
|
||||
|
||||
void Fiber::Start(boost::context::detail::transfer_t& transfer) {
|
||||
ASSERT(impl->previous_fiber != nullptr);
|
||||
impl->previous_fiber->impl->context = transfer.fctx;
|
||||
impl->previous_fiber->impl->guard.unlock();
|
||||
impl->previous_fiber.reset();
|
||||
impl->entry_point();
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void Fiber::OnRewind([[maybe_unused]] boost::context::detail::transfer_t& transfer) {
|
||||
ASSERT(impl->context != nullptr);
|
||||
impl->context = impl->rewind_context;
|
||||
impl->rewind_context = nullptr;
|
||||
u8* tmp = impl->stack_limit;
|
||||
impl->stack_limit = impl->rewind_stack_limit;
|
||||
impl->rewind_stack_limit = tmp;
|
||||
impl->rewind_point();
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void Fiber::FiberStartFunc(boost::context::detail::transfer_t transfer) {
|
||||
auto* fiber = static_cast<Fiber*>(transfer.data);
|
||||
fiber->Start(transfer);
|
||||
}
|
||||
|
||||
void Fiber::RewindStartFunc(boost::context::detail::transfer_t transfer) {
|
||||
auto* fiber = static_cast<Fiber*>(transfer.data);
|
||||
fiber->OnRewind(transfer);
|
||||
}
|
||||
|
||||
Fiber::Fiber(std::function<void()>&& entry_point_func) : impl{std::make_unique<FiberImpl>()} {
|
||||
impl->entry_point = std::move(entry_point_func);
|
||||
auto desc = mco_desc_init(
|
||||
[](mco_coro* coro) { reinterpret_cast<Fiber*>(coro->user_data)->impl->entry_point(); }, 0);
|
||||
desc.user_data = this;
|
||||
mco_result res = mco_create(&impl->context, &desc);
|
||||
ASSERT(res == MCO_SUCCESS);
|
||||
impl->stack_limit = impl->stack.data();
|
||||
impl->rewind_stack_limit = impl->rewind_stack.data();
|
||||
u8* stack_base = impl->stack_limit + default_stack_size;
|
||||
impl->context =
|
||||
boost::context::detail::make_fcontext(stack_base, impl->stack.size(), FiberStartFunc);
|
||||
}
|
||||
|
||||
Fiber::Fiber() : impl{std::make_unique<FiberImpl>()} {}
|
||||
|
||||
Fiber::~Fiber() {
|
||||
if (impl->released) {
|
||||
return;
|
||||
}
|
||||
DestroyPre();
|
||||
if (impl->is_thread_fiber) {
|
||||
DestroyThreadFiber();
|
||||
} else {
|
||||
DestroyWorkFiber();
|
||||
// Make sure the Fiber is not being used
|
||||
const bool locked = impl->guard.try_lock();
|
||||
ASSERT_MSG(locked, "Destroying a fiber that's still running");
|
||||
if (locked) {
|
||||
impl->guard.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,66 +94,42 @@ void Fiber::Exit() {
|
||||
if (!impl->is_thread_fiber) {
|
||||
return;
|
||||
}
|
||||
DestroyPre();
|
||||
DestroyThreadFiber();
|
||||
}
|
||||
|
||||
void Fiber::DestroyPre() {
|
||||
// Make sure the Fiber is not being used
|
||||
const bool locked = impl->guard.try_lock();
|
||||
ASSERT_MSG(locked, "Destroying a fiber that's still running");
|
||||
if (locked) {
|
||||
impl->guard.unlock();
|
||||
}
|
||||
impl->guard.unlock();
|
||||
impl->released = true;
|
||||
}
|
||||
|
||||
void Fiber::DestroyWorkFiber() {
|
||||
mco_result res = mco_destroy(impl->context);
|
||||
ASSERT(res == MCO_SUCCESS);
|
||||
}
|
||||
|
||||
void Fiber::DestroyThreadFiber() {
|
||||
if (impl->next_fiber_ptr && *impl->next_fiber_ptr) {
|
||||
*impl->next_fiber_ptr = nullptr;
|
||||
}
|
||||
void Fiber::Rewind() {
|
||||
ASSERT(impl->rewind_point);
|
||||
ASSERT(impl->rewind_context == nullptr);
|
||||
u8* stack_base = impl->rewind_stack_limit + default_stack_size;
|
||||
impl->rewind_context =
|
||||
boost::context::detail::make_fcontext(stack_base, impl->stack.size(), RewindStartFunc);
|
||||
boost::context::detail::jump_fcontext(impl->rewind_context, this);
|
||||
}
|
||||
|
||||
void Fiber::YieldTo(std::weak_ptr<Fiber> weak_from, Fiber& to) {
|
||||
to.impl->guard.lock();
|
||||
to.impl->previous_fiber = weak_from.lock();
|
||||
|
||||
auto transfer = boost::context::detail::jump_fcontext(to.impl->context, &to);
|
||||
|
||||
// "from" might no longer be valid if the thread was killed
|
||||
if (auto from = weak_from.lock()) {
|
||||
if (!from->impl->is_thread_fiber) {
|
||||
// Set next fiber
|
||||
from->impl->next_fiber = &to;
|
||||
// Yield from thread
|
||||
if (!from->impl->released) {
|
||||
from->impl->guard.unlock();
|
||||
mco_yield(from->impl->context);
|
||||
}
|
||||
} else {
|
||||
from->impl->guard.lock();
|
||||
// Keep running next fiber until they've ran out
|
||||
auto& next_fiber_ptr = from->impl->next_fiber_ptr;
|
||||
next_fiber_ptr = &from->impl->next_fiber;
|
||||
*next_fiber_ptr = &to;
|
||||
while (*next_fiber_ptr) {
|
||||
auto next = *next_fiber_ptr;
|
||||
*next_fiber_ptr = nullptr;
|
||||
next_fiber_ptr = &next->impl->next_fiber;
|
||||
// Stop if new thread is thread fiber
|
||||
if (next->impl->is_thread_fiber)
|
||||
break;
|
||||
// Resume new thread
|
||||
next->impl->guard.lock();
|
||||
mco_result res = mco_resume(next->impl->context);
|
||||
ASSERT(res == MCO_SUCCESS);
|
||||
}
|
||||
from->impl->guard.unlock();
|
||||
if (from->impl->previous_fiber == nullptr) {
|
||||
ASSERT_MSG(false, "previous_fiber is nullptr!");
|
||||
return;
|
||||
}
|
||||
from->impl->previous_fiber->impl->context = transfer.fctx;
|
||||
from->impl->previous_fiber->impl->guard.unlock();
|
||||
from->impl->previous_fiber.reset();
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Fiber> Fiber::ThreadToFiber() {
|
||||
return std::shared_ptr<Fiber>{new Fiber()};
|
||||
std::shared_ptr<Fiber> fiber = std::shared_ptr<Fiber>{new Fiber()};
|
||||
fiber->impl->guard.lock();
|
||||
fiber->impl->is_thread_fiber = true;
|
||||
return fiber;
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include "common/minicoro.h"
|
||||
namespace boost::context::detail {
|
||||
struct transfer_t;
|
||||
}
|
||||
|
||||
namespace Common {
|
||||
|
||||
@@ -36,18 +38,25 @@ public:
|
||||
Fiber(Fiber&&) = default;
|
||||
Fiber& operator=(Fiber&&) = default;
|
||||
|
||||
/// Yields control from Fiber 'from' to Fiber 'to'
|
||||
/// Fiber 'from' must be the currently running fiber.
|
||||
static void YieldTo(std::weak_ptr<Fiber> weak_from, Fiber& to);
|
||||
[[nodiscard]] static std::shared_ptr<Fiber> ThreadToFiber();
|
||||
|
||||
void SetRewindPoint(std::function<void()>&& rewind_func);
|
||||
|
||||
void Rewind();
|
||||
|
||||
/// Only call from main thread's fiber
|
||||
void Exit();
|
||||
|
||||
private:
|
||||
Fiber();
|
||||
|
||||
void DestroyPre();
|
||||
void DestroyWorkFiber();
|
||||
void DestroyThreadFiber();
|
||||
void OnRewind(boost::context::detail::transfer_t& transfer);
|
||||
void Start(boost::context::detail::transfer_t& transfer);
|
||||
static void FiberStartFunc(boost::context::detail::transfer_t transfer);
|
||||
static void RewindStartFunc(boost::context::detail::transfer_t transfer);
|
||||
|
||||
struct FiberImpl;
|
||||
std::unique_ptr<FiberImpl> impl;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1144,8 +1144,6 @@ add_library(core STATIC
|
||||
|
||||
if (MSVC)
|
||||
target_compile_options(core PRIVATE
|
||||
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
|
||||
/we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data
|
||||
/we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch
|
||||
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
|
||||
/we4800 # Implicit conversion from 'type' to bool. Possible information loss
|
||||
|
||||
@@ -141,8 +141,6 @@ add_library(hid_core STATIC
|
||||
|
||||
if (MSVC)
|
||||
target_compile_options(hid_core PRIVATE
|
||||
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
|
||||
/we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data
|
||||
/we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch
|
||||
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
|
||||
/we4800 # Implicit conversion from 'type' to bool. Possible information loss
|
||||
|
||||
@@ -37,7 +37,6 @@ add_library(input_common STATIC
|
||||
|
||||
if (MSVC)
|
||||
target_compile_options(input_common PRIVATE
|
||||
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
|
||||
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
|
||||
/we4800 # Implicit conversion from 'type' to bool. Possible information loss
|
||||
)
|
||||
|
||||
@@ -252,7 +252,6 @@ target_link_libraries(shader_recompiler PUBLIC common fmt::fmt sirit ${SPIRV_TOO
|
||||
|
||||
if (MSVC)
|
||||
target_compile_options(shader_recompiler PRIVATE
|
||||
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
|
||||
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
|
||||
/we4800 # Implicit conversion from 'type' to bool. Possible information loss
|
||||
)
|
||||
|
||||
@@ -271,4 +271,43 @@ TEST_CASE("Fibers::StartRace", "[common]") {
|
||||
REQUIRE(test_control.value3 == 1);
|
||||
}
|
||||
|
||||
class TestControl4;
|
||||
|
||||
class TestControl4 {
|
||||
public:
|
||||
TestControl4() {
|
||||
fiber1 = std::make_shared<Fiber>([this] { DoWork(); });
|
||||
goal_reached = false;
|
||||
rewinded = false;
|
||||
}
|
||||
|
||||
void Execute() {
|
||||
thread_fiber = Fiber::ThreadToFiber();
|
||||
Fiber::YieldTo(thread_fiber, *fiber1);
|
||||
thread_fiber->Exit();
|
||||
}
|
||||
|
||||
void DoWork() {
|
||||
fiber1->SetRewindPoint([this] { DoWork(); });
|
||||
if (rewinded) {
|
||||
goal_reached = true;
|
||||
Fiber::YieldTo(fiber1, *thread_fiber);
|
||||
}
|
||||
rewinded = true;
|
||||
fiber1->Rewind();
|
||||
}
|
||||
|
||||
std::shared_ptr<Common::Fiber> fiber1;
|
||||
std::shared_ptr<Common::Fiber> thread_fiber;
|
||||
bool goal_reached;
|
||||
bool rewinded;
|
||||
};
|
||||
|
||||
TEST_CASE("Fibers::Rewind", "[common]") {
|
||||
TestControl4 test_control{};
|
||||
test_control.Execute();
|
||||
REQUIRE(test_control.goal_reached);
|
||||
REQUIRE(test_control.rewinded);
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -341,12 +341,7 @@ if (ENABLE_NSIGHT_AFTERMATH)
|
||||
target_include_directories(video_core PRIVATE "$ENV{NSIGHT_AFTERMATH_SDK}/include")
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
target_compile_options(video_core PRIVATE
|
||||
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
|
||||
/we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data
|
||||
)
|
||||
else()
|
||||
if (NOT MSVC)
|
||||
if (APPLE)
|
||||
# error: declaration shadows a typedef in 'interval_base_set<SubType, DomainT, Compare, Interval, Alloc>'
|
||||
# error: implicit conversion loses integer precision: 'int' to 'boost::icl::bound_type' (aka 'unsigned char')
|
||||
|
||||
@@ -382,7 +382,7 @@ elseif(WIN32)
|
||||
endif()
|
||||
|
||||
target_link_libraries(yuzu PRIVATE common core input_common frontend_common network video_core)
|
||||
target_link_libraries(yuzu PRIVATE Boost::headers glad Qt${QT_MAJOR_VERSION}::Widgets)
|
||||
target_link_libraries(yuzu PRIVATE Boost::headers glad Qt${QT_MAJOR_VERSION}::Widgets httplib::httplib)
|
||||
target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)
|
||||
|
||||
target_link_libraries(yuzu PRIVATE Vulkan::Headers)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,7 @@
|
||||
#include "common/linux/gamemode.h"
|
||||
#endif
|
||||
|
||||
#include <httplib.h>
|
||||
#include <boost/container/flat_set.hpp>
|
||||
|
||||
// VFS includes must be before glad as they will conflict with Windows file api, which uses defines.
|
||||
@@ -1520,10 +1521,7 @@ void GMainWindow::ConnectMenuEvents() {
|
||||
// Emulation
|
||||
connect_menu(ui->action_Pause, &GMainWindow::OnPauseContinueGame);
|
||||
connect_menu(ui->action_Stop, &GMainWindow::OnStopGame);
|
||||
connect_menu(ui->action_Report_Compatibility, &GMainWindow::OnMenuReportCompatibility);
|
||||
connect_menu(ui->action_Open_Mods_Page, &GMainWindow::OnOpenModsPage);
|
||||
connect_menu(ui->action_Open_Quickstart_Guide, &GMainWindow::OnOpenQuickstartGuide);
|
||||
connect_menu(ui->action_Open_FAQ, &GMainWindow::OnOpenFAQ);
|
||||
connect_menu(ui->action_Open_Mirror_Repo, &GMainWindow::OnOpenMirrorRepo);
|
||||
connect_menu(ui->action_Restart, &GMainWindow::OnRestartGame);
|
||||
connect_menu(ui->action_Configure, &GMainWindow::OnConfigure);
|
||||
connect_menu(ui->action_Configure_Current_Game, &GMainWindow::OnConfigurePerGame);
|
||||
@@ -3513,39 +3511,6 @@ void GMainWindow::ErrorDisplayRequestExit() {
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::OnMenuReportCompatibility() {
|
||||
#if defined(ARCHITECTURE_x86_64) && !defined(__APPLE__)
|
||||
const auto& caps = Common::GetCPUCaps();
|
||||
const bool has_fma = caps.fma || caps.fma4;
|
||||
const auto processor_count = std::thread::hardware_concurrency();
|
||||
const bool has_4threads = processor_count == 0 || processor_count >= 4;
|
||||
const bool has_8gb_ram = Common::GetMemInfo().TotalPhysicalMemory >= 8_GiB;
|
||||
const bool has_broken_vulkan = UISettings::values.has_broken_vulkan;
|
||||
|
||||
if (!has_fma || !has_4threads || !has_8gb_ram || has_broken_vulkan) {
|
||||
QMessageBox::critical(this, tr("Hardware requirements not met"),
|
||||
tr("Your system does not meet the recommended hardware requirements. "
|
||||
"Compatibility reporting has been disabled."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Settings::values.yuzu_token.GetValue().empty() &&
|
||||
!Settings::values.yuzu_username.GetValue().empty()) {
|
||||
} else {
|
||||
QMessageBox::critical(
|
||||
this, tr("Missing yuzu Account"),
|
||||
tr("In order to submit a game compatibility test case, you must link your yuzu "
|
||||
"account.<br><br/>To link your yuzu account, go to Emulation > Configuration "
|
||||
"> "
|
||||
"Web."));
|
||||
}
|
||||
#else
|
||||
QMessageBox::critical(this, tr("Hardware requirements not met"),
|
||||
tr("Your system does not meet the recommended hardware requirements. "
|
||||
"Compatibility reporting has been disabled."));
|
||||
#endif
|
||||
}
|
||||
|
||||
void GMainWindow::OpenURL(const QUrl& url) {
|
||||
const bool open = QDesktopServices::openUrl(url);
|
||||
if (!open) {
|
||||
@@ -3554,16 +3519,39 @@ void GMainWindow::OpenURL(const QUrl& url) {
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::OnOpenModsPage() {
|
||||
OpenURL(QUrl(QStringLiteral("https://github.com/yuzu-emu/yuzu/wiki/Switch-Mods")));
|
||||
}
|
||||
void GMainWindow::OnOpenMirrorRepo() {
|
||||
struct Mirror {
|
||||
const char *host, *path;
|
||||
};
|
||||
const std::initializer_list<Mirror> mirrors = {
|
||||
{"https://github.com", "/litucks/torzu"},
|
||||
{"https://gitlab.com", "/litucks/torzu"},
|
||||
{"https://bitbucket.org", "/litucks/torzu"},
|
||||
{"https://codeberg.org", "/litucks/torzu"},
|
||||
{"https://notabug.org", "/litucks/torzu"},
|
||||
{"https://gitea.com", "/litucks/torzu"},
|
||||
{"https://try.gitea.io", "/litucks/torzu"},
|
||||
{"https://git.math.hamburg", "/litucks/torzu"},
|
||||
{"https://gitea.sprint-pay.com", "/litucks/torzu"},
|
||||
{"https://gitea.djoe.ovh", "/litucks/torzu"},
|
||||
{"https://git.sheetjs.com", "/litucks/torzu"},
|
||||
{"https://gitea.cisetech.com", "/litucks/torzu"}
|
||||
};
|
||||
|
||||
void GMainWindow::OnOpenQuickstartGuide() {
|
||||
OpenURL(QUrl(QStringLiteral("https://yuzu-emu.org/help/quickstart/")));
|
||||
}
|
||||
for (const auto& mirror : mirrors) {
|
||||
httplib::Client cli(mirror.host);
|
||||
if (cli.Get(mirror.path)) {
|
||||
OpenURL(QUrl(QString::fromStdString(fmt::format("{}{}", mirror.host, mirror.path))));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void GMainWindow::OnOpenFAQ() {
|
||||
OpenURL(QUrl(QStringLiteral("https://yuzu-emu.org/wiki/faq/")));
|
||||
QMessageBox::warning(this, tr("Error locating mirror"), tr("There has been an error finding the current mirror repository.\n"
|
||||
"Your version may be so old the list has already been depleted\n"
|
||||
"or your network connectivity may be limited.\n"
|
||||
"Please either try again later, through a VPN or access the main\n"
|
||||
"repository via the Tor Browser:\n"
|
||||
"http://y2nlvhmmk5jnsvechppxnbyzmmv3vbl7dvzn6ltwcdbpgxixp3clkgqd.onion/torzu-emu/torzu"));
|
||||
}
|
||||
|
||||
void GMainWindow::ToggleFullscreen() {
|
||||
|
||||
@@ -333,10 +333,7 @@ private slots:
|
||||
void OnPauseContinueGame();
|
||||
void OnStopGame();
|
||||
void OnPrepareForSleep(bool prepare_sleep);
|
||||
void OnMenuReportCompatibility();
|
||||
void OnOpenModsPage();
|
||||
void OnOpenQuickstartGuide();
|
||||
void OnOpenFAQ();
|
||||
void OnOpenMirrorRepo();
|
||||
/// Called whenever a user selects a game in the game list widget.
|
||||
void OnGameListLoadFile(QString game_path, u64 program_id);
|
||||
void OnGameListOpenFolder(u64 program_id, GameListOpenTarget target,
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1280</width>
|
||||
<height>21</height>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_File">
|
||||
@@ -183,9 +183,7 @@
|
||||
<string>&Help</string>
|
||||
</property>
|
||||
<addaction name="action_Report_Compatibility"/>
|
||||
<addaction name="action_Open_Mods_Page"/>
|
||||
<addaction name="action_Open_Quickstart_Guide"/>
|
||||
<addaction name="action_Open_FAQ"/>
|
||||
<addaction name="action_Open_Mirror_Repo"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_About"/>
|
||||
</widget>
|
||||
@@ -481,6 +479,11 @@
|
||||
<string>Open Home Menu</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Open_Mirror_Repo">
|
||||
<property name="text">
|
||||
<string>Open current Mirror &Repo</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="yuzu.qrc"/>
|
||||
|
||||
Reference in New Issue
Block a user