Compare commits

...

73 Commits

Author SHA1 Message Date
ReinUsesLisp 76f178ba6e shader/video: Partially implement VMNMX
Implements the common usages for VMNMX. Inputs with a different size
than 32 bits are not supported and sign mismatches aren't supported
either.

VMNMX works as follows:
It grabs Ra and Rb and applies a maximum/minimum on them (this is
defined by .MX), having in mind the input sign. This result can then be
saturated. After the intermediate result is calculated, it applies
another operation on it using Rc. These operations are merges,
accumulations or another min/max pass.

This instruction allows to implement with a more flexible approach GCN's
min3 and max3 instructions (for instance).
2020-04-12 00:34:42 -03:00
ReinUsesLisp 08470d261d shader_bytecode: Fix I2I_IMM encoding 2020-03-28 18:49:07 -03:00
bunnei ffe1e2b5ec Merge pull request #3562 from perillamint/vrsvc
am: Implement VR related APIs
2020-03-28 13:32:52 -04:00
bunnei 997a802bd6 Merge pull request #3569 from bunnei/hid-stub
services: hid: Stub InitializeSevenSixAxisSensor.
2020-03-28 04:10:45 -04:00
bunnei 75795a9a63 Merge pull request #3573 from FearlessTobi/port-5089
Port citra-emu/citra#5089: "Set render window's focus policy to Qt::StrongFocus"
2020-03-28 01:48:46 -04:00
bunnei 9bd9980372 Merge pull request #3576 from FearlessTobi/port-4906
Port citra-emu/citra#4906: "citra_qt: fix the stuck in fullscreen mode"
2020-03-28 00:28:31 -04:00
bunnei 6286b8dedd Merge pull request #3574 from FearlessTobi/port-5093
Port citra-emu/citra#5093: "Replace non-commercial icons"
2020-03-27 21:43:30 -04:00
FearlessTobi 8ba06aa4e1 yuzu: fix the stuck in fullscreen mode bug
Co-Authored-By: Valentin Vanelslande <vvanelslandedev@gmail.com>
2020-03-28 02:31:35 +01:00
Guo Yunhe dd236c6c1d Replace non-commercial icons with free icons from icons8 (#5093) 2020-03-27 22:31:54 +01:00
Vitor K 10ba8d16be Set render window to also accept focus via tabbing (Qt::StrongFocus) (#5089) 2020-03-27 22:25:01 +01:00
Fernando Sahmkow 7a2f60df26 Merge pull request #3565 from ReinUsesLisp/image-format
engines/const_buffer_engine_interface: Store image format and types
2020-03-27 14:08:54 -04:00
bunnei 8a6a25e4b6 services: hid: Stub InitializeSevenSixAxisSensor.
- Used by Super Smash Bros. Ultimate v7.0.0.
2020-03-27 10:48:01 -04:00
perillamint a429644672 am: Implement VR related APIs
Implement (and stub) VR related APIs in AM sysmodule.

This fixes issue #2938
2020-03-27 18:22:28 +09:00
ReinUsesLisp cedbe925cd engines/const_buffer_engine_interface: Store image format type
This information is required to properly implement SULD.B. It might also
be handy for all image operations, since it would allow us to implement
them on devices that require the image format to be specified (on
desktop, this would be AMD on OpenGL and Intel on OpenGL and Vulkan).
2020-03-27 00:36:22 -03:00
Mat M e84b760016 Merge pull request #3564 from makigumo/maxwell_to_vk_sscaled
maxwell_to_vk: implement signedscaled vertex formats
2020-03-26 21:05:52 -04:00
Dan 744b207d92 maxwell_to_vk: implement signedscaled vertex formats 2020-03-27 00:14:19 +01:00
bunnei 950b6dbc80 Merge pull request #3453 from FearlessTobi/remove-pause-lock
yuzu: Remove exit lock for game pausing
2020-03-26 16:42:57 -04:00
bunnei 3194f14aca Merge pull request #3550 from hughesjs/hughesjs-readme-changes-1
Minor Readme Changes
2020-03-26 00:50:56 -04:00
bunnei 8244536f7a Merge pull request #3548 from jroweboy/use-plugins-dir
Use the correct directory for Qt Plugins
2020-03-26 00:50:06 -04:00
bunnei 23c7dda710 Merge pull request #3544 from makigumo/myfork/patch-2
xmad: fix clang build error
2020-03-25 19:29:16 -04:00
bunnei e6aff11057 Merge pull request #3520 from ReinUsesLisp/legacy-varyings
gl_shader_decompiler: Implement legacy varyings
2020-03-25 19:27:51 -04:00
James Hughes aa41fcc04e Update README.md 2020-03-24 22:30:37 +00:00
James Hughes ac4154bfde Minor ReadMe Changes
Added Discord shield and direct link to contribution guide
2020-03-24 22:26:07 +00:00
bunnei f8382c9d9d Merge pull request #3524 from FearlessTobi/port-5106
Port citra-emu/citra#5106: "gdbstub: Ensure gdbstub doesn't drop packets crucial to initialization"
2020-03-24 16:50:58 -04:00
James Rowe 6ca8637d4c Use the correct directory for Qt Plugins 2020-03-23 18:51:46 -06:00
Fernando Sahmkow 497f593525 Merge pull request #3543 from ReinUsesLisp/gl-depth-range
gl_rasterizer: Use transformed viewport for depth ranges
2020-03-23 12:00:21 -04:00
Fernando Sahmkow 7981910746 Merge pull request #3542 from namkazt/patch-10
Implement MME shadow RAM
2020-03-23 12:00:01 -04:00
bunnei dc4415811c Merge pull request #3546 from FearlessTobi/pointer-buffer-size
sm/controller: Increase PointerBufferSize
2020-03-22 23:31:08 -04:00
FearlessTobi 4afebf26b6 sm/controller: Increase PointerBufferSize
This increases the PointerBufferSize as a lager one is required by some services.
This change is still not hw-accurate, but it is proven to work in Ryujinx.

Instead of using a hardcoded size, we should figure out the specific values for each service in the future. Some of them can be taken from Atmosphere: https://github.com/Atmosphere-NX/Atmosphere/search?q=PointerBufferSize.
2020-03-23 03:19:30 +01:00
makigumo 5a5c6d4ed8 xmad: fix clang build error 2020-03-23 00:09:31 +01:00
bunnei e731c4b991 Merge pull request #3477 from FearlessTobi/webapplet-shit
core/web_browser: Allow WebApplet to exit gracefully when an error occurs
2020-03-22 13:11:02 -04:00
namkazy fc37672f26 apply replay logic to all writes. remove replay from MacroInterpreter::Send (@fincs) 2020-03-22 22:25:44 +07:00
FearlessTobi 977418c65b core/web_browser: Allow WebApplet to exit gracefully when an error occurs
Currently, yuzu just freezes when an error occurs while Initializing the WebApplet.
From a user perspective, this obviously isn't great as the game just softlocks.
With this change, yuzu will call the Finalize method, so to the game it seems like as the user just exited the WebApplet normally.

This works around https://github.com/yuzu-emu/yuzu/issues/2852.
2020-03-22 16:01:13 +01:00
namkazy f66743cd0c maxwell_3d: change declaration order 2020-03-22 13:41:16 +07:00
namkazy d4e93cf38c maxwell_3d: init shadow_state 2020-03-22 13:35:11 +07:00
ReinUsesLisp bdcedc8506 gl_rasterizer: Use transformed viewport for depth ranges
Implement depth ranges using the transformed viewport instead of the
generic one. This matches the current Vulkan implementation but doesn't
support negative depth ranges. An update to glad is required for this.
2020-03-22 03:26:07 -03:00
namkazy 22f4268c2f maxwell_3d: this seem more correct. 2020-03-22 12:02:54 +07:00
namkazy 7051dc1902 maxwell_3d: update comments for shadow ram usage 2020-03-22 11:35:26 +07:00
Nguyen Dac Nam 01af036c1f marco_interpreter: write hw value when shadow ram requested 2020-03-22 10:53:41 +07:00
Nguyen Dac Nam 63c2635e6f maxwell_3d: track shadow ram ctrl and hw reg value 2020-03-22 10:53:41 +07:00
Nguyen Dac Nam dbfbe352e0 maxwell_3d: implement MME shadow RAM 2020-03-22 10:53:35 +07:00
bunnei e5bb5d13c4 Merge pull request #3531 from makigumo/yuzu_master
set: implement GetRegionCode
2020-03-21 22:49:28 -04:00
bunnei e70451d967 Merge pull request #3525 from FearlessTobi/linux-compile-error
input_common/udp: Fix Linux build by using a backwards compatible way of error checking
2020-03-21 16:04:45 -04:00
bunnei 81fa492825 Merge pull request #3526 from FearlessTobi/bcat-disable
bcat: Disable Boxcat backend by default
2020-03-20 13:01:28 -04:00
bunnei bdddbe2daa Merge pull request #3505 from namkazt/patch-8
shader_decode: implement XMAD mode CSfu
2020-03-19 17:41:01 -04:00
Dan 06dea163fa set: implement GetRegionCode 2020-03-19 10:37:42 +01:00
bunnei bc681dc555 Merge pull request #3527 from FearlessTobi/output-mode
yuzu: Save sound output mode and set it to Stereo by default
2020-03-18 23:19:22 -04:00
Mat M 9418b983bd Merge pull request #3535 from ReinUsesLisp/gcc-warnings
video_core: Silence misc warnings
2020-03-18 20:09:32 -04:00
bunnei 76d6178e4a Merge pull request #3534 from ReinUsesLisp/oob-time-zone
time_zone_content_manager: Fix out of bounds read
2020-03-18 19:12:05 -04:00
ReinUsesLisp 38c1e77f01 vk_texture_cache: Silence misc warnings 2020-03-18 20:03:19 -03:00
ReinUsesLisp b6b2e31e5e vk_staging_buffer_pool: Silence unused constant warning 2020-03-18 20:03:19 -03:00
ReinUsesLisp fc51ece7bf vk_rasterizer: Remove unused variable 2020-03-18 20:03:19 -03:00
ReinUsesLisp 98d85cdc20 vk_pipeline_cache: Remove unused variable 2020-03-18 20:03:19 -03:00
ReinUsesLisp dab450ec46 maxwell_to_vk: Sielence -Wswitch warning 2020-03-18 20:03:19 -03:00
ReinUsesLisp 351816ac38 gl_shader_decompiler: Remove deprecated function and its usages 2020-03-18 20:03:19 -03:00
ReinUsesLisp acf328a71f gl_rasterizer: Silence misc warnings 2020-03-18 20:03:19 -03:00
ReinUsesLisp 9f46066bda kepler_compute: Remove unused variables 2020-03-18 20:03:19 -03:00
ReinUsesLisp ba9674862d microprofile: Silence sign comparison warning 2020-03-18 20:03:19 -03:00
ReinUsesLisp ac7ee21331 time_zone_content_manager: Fix out of bounds read
There were cases where raw_data didn't contain enough
space to hold the zero terminator.

This was caught with -fsanitize=address.
2020-03-18 19:06:16 -03:00
Mat M 56ea0f8acb Merge pull request #3530 from ReinUsesLisp/fix-clang
astc/input_common: Fix clang build issues
2020-03-18 04:28:55 -04:00
ReinUsesLisp f5658a9fda gl_shader_decompiler: Don't redeclare gl_VertexID and gl_InstanceID 2020-03-18 01:28:41 -03:00
FearlessTobi cdeadd448b yuzu: Save sound output mode and set it to Stereo by default 2020-03-17 19:03:00 +01:00
FearlessTobi 2fd3b328ae bcat: Disable Boxcat backend by default
This commit disables the Boxcat backend by default for new users of yuzu.

There's several reasons as to why this is done:
1. Boxcat currently only actually has an impact on 3 games and doesn't influence any core mechanics of them
2. It causes a plethora of issues when enabled such as games like Crash Team Racing, Diablo 3 and Tales of Vesperia not booting at all or hanging
3. It causes https://github.com/yuzu-emu/yuzu/issues/2957 to happen. This makes the configuration menu totally unusable for many Linux users of yuzu

I think those points show that currently the negative impact of Boxcat outweighs its benefits and should therefore be disabled by default.
For users who are eager to use the extra features provided by it, they can still just turn it on in the settings.
2020-03-17 15:24:26 +01:00
FearlessTobi 230ac6a4e8 input_common/udp: Fix Linux build by using a backwards compatible way of error checking
Should fix https://github.com/yuzu-emu/yuzu/issues/3487.

error_code::failed is a function which has been introduced in Boost 1.69.
This version of boost hasn't landed in most major distros yet.
2020-03-17 12:29:25 +01:00
Gauvain "GovanifY" Roussel-Tarbouriech eae2ed6b07 gdbstub: small logic bug fix with defer_start 2020-03-17 11:18:39 +01:00
Gauvain "GovanifY" Roussel-Tarbouriech 38036eb1c8 gdbstub: Ensure gdbstub doesn't drop packets crucial to initialization 2020-03-17 11:18:13 +01:00
ReinUsesLisp 5afc397d52 gl_shader_decompiler: Implement legacy varyings
Legacy varyings are special attributes carried over in hardware from
the OpenGL 1 and OpenGL 2 days. These were generally used instead of the
generic attributes we use today. They are deprecated or removed from
most APIs, but Nvidia still ships them in hardware.

To implement these, this commit maps them 1:1 to OpenGL compatibility.
2020-03-15 21:03:59 -03:00
ReinUsesLisp 6442e02c5d shader/shader_ir: Track usage in input attribute and of legacy varyings 2020-03-15 21:01:52 -03:00
ReinUsesLisp 8e6e55d6f8 shader/shader_ir: Fix clip distance usage stores 2020-03-15 20:53:14 -03:00
ReinUsesLisp 464bd5fad7 shader/shader_ir: Change declare output attribute to a switch 2020-03-15 20:49:35 -03:00
Nguyen Dac Nam 829f424618 nit & remove some optional param 2020-03-13 20:47:38 +07:00
Nguyen Dac Nam a166217480 shader_decode: implement XMAD mode CSfu 2020-03-13 19:01:49 +07:00
FearlessTobi 7cbe6748c3 yuzu: Remove exit lock for game pausing
This removes the "exit lock" popup from yuzu when pausing a game.

Motivation
The exit lock feature is broken in many ways and doesn't work properly in a lot of games, causing it to appear every time you want to pause the game or stop it, even in places where it wouldn't on Switch.

Additionally, the feature of pausing a game doesn't exist like this on Switch and yuzu should be guaranteed to be deterministic anyway, so pausing the emulation shouldn't be able to interrupt any critical processes in any way.
2020-02-24 17:51:17 +01:00
44 changed files with 564 additions and 152 deletions
+8 -4
View File
@@ -6,9 +6,9 @@ function(copy_yuzu_Qt5_deps target_dir)
set(Qt5_STYLES_DIR "${Qt5_DIR}/../../../plugins/styles/")
set(Qt5_IMAGEFORMATS_DIR "${Qt5_DIR}/../../../plugins/imageformats/")
set(Qt5_RESOURCES_DIR "${Qt5_DIR}/../../../resources/")
set(PLATFORMS ${DLL_DEST}platforms/)
set(STYLES ${DLL_DEST}styles/)
set(IMAGEFORMATS ${DLL_DEST}imageformats/)
set(PLATFORMS ${DLL_DEST}plugins/platforms/)
set(STYLES ${DLL_DEST}plugins/styles/)
set(IMAGEFORMATS ${DLL_DEST}plugins/imageformats/)
windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}
icudt*.dll
icuin*.dll
@@ -42,11 +42,15 @@ function(copy_yuzu_Qt5_deps target_dir)
icudtl.dat
)
endif ()
windows_copy_files(yuzu ${Qt5_PLATFORMS_DIR} ${PLATFORMS} qwindows$<$<CONFIG:Debug>:d>.*)
windows_copy_files(yuzu ${Qt5_STYLES_DIR} ${STYLES} qwindowsvistastyle$<$<CONFIG:Debug>:d>.*)
windows_copy_files(yuzu ${Qt5_IMAGEFORMATS_DIR} ${IMAGEFORMATS}
qjpeg$<$<CONFIG:Debug>:d>.*
qgif$<$<CONFIG:Debug>:d>.*
)
# Create an empty qt.conf file. Qt will detect that this file exists, and use the folder that its in as the root folder.
# This way it'll look for plugins in the root/plugins/ folder
add_custom_command(TARGET yuzu POST_BUILD
COMMAND ${CMAKE_COMMAND} -E touch ${DLL_DEST}qt.conf
)
endfunction(copy_yuzu_Qt5_deps)
+2 -1
View File
@@ -2,6 +2,7 @@ yuzu emulator
=============
[![Travis CI Build Status](https://travis-ci.com/yuzu-emu/yuzu.svg?branch=master)](https://travis-ci.com/yuzu-emu/yuzu)
[![Azure Mainline CI Build Status](https://dev.azure.com/yuzu-emu/yuzu/_apis/build/status/yuzu%20mainline?branchName=master)](https://dev.azure.com/yuzu-emu/yuzu/)
[![Discord](https://img.shields.io/discord/398318088170242053?color=%237289DA&label=yuzu&logo=discord&logoColor=white)](https://discord.gg/XQV6dn9)
yuzu is an experimental open-source emulator for the Nintendo Switch from the creators of [Citra](https://citra-emu.org/).
@@ -21,7 +22,7 @@ For development discussion, please join us on [Discord](https://discord.gg/XQV6d
Most of the development happens on GitHub. It's also where [our central repository](https://github.com/yuzu-emu/yuzu) is hosted.
If you want to contribute please take a look at the [Contributor's Guide](CONTRIBUTING.md) and [Developer Information](https://github.com/yuzu-emu/yuzu/wiki/Developer-Information). You should also contact any of the developers on Discord in order to know about the current state of the emulator.
If you want to contribute please take a look at the [Contributor's Guide](https://github.com/yuzu-emu/yuzu/wiki/Contributing) and [Developer Information](https://github.com/yuzu-emu/yuzu/wiki/Developer-Information). You should also contact any of the developers on Discord in order to know about the current state of the emulator.
### Building
+2 -4
View File
@@ -2,8 +2,8 @@ The icons in this folder and its subfolders have the following licenses:
Icon Name | License | Origin/Author
--- | --- | ---
qt_themes/default/icons/16x16/checked.png | Free for non-commercial use
qt_themes/default/icons/16x16/failed.png | Free for non-commercial use
qt_themes/default/icons/16x16/checked.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/default/icons/16x16/failed.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/default/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/default/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/default/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com
@@ -11,8 +11,6 @@ qt_themes/default/icons/48x48/chip.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/default/icons/48x48/folder.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/default/icons/48x48/plus.png | CC0 1.0 | Designed by BreadFish64 from the Citra team
qt_themes/default/icons/48x48/sd_card.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/qdarkstyle/icons/16x16/checked.png | Free for non-commercial use
qt_themes/qdarkstyle/icons/16x16/failed.png | Free for non-commercial use
qt_themes/qdarkstyle/icons/16x16/lock.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/qdarkstyle/icons/256x256/plus_folder.png | CC BY-ND 3.0 | https://icons8.com
qt_themes/qdarkstyle/icons/48x48/bad_folder.png | CC BY-ND 3.0 | https://icons8.com
Binary file not shown.

Before

Width:  |  Height:  |  Size: 451 B

After

Width:  |  Height:  |  Size: 657 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 428 B

After

Width:  |  Height:  |  Size: 524 B

+3 -3
View File
@@ -828,7 +828,7 @@ inline MicroProfileLogEntry MicroProfileMakeLogIndex(uint64_t nBegin, MicroProfi
MicroProfileLogEntry Entry = (nBegin<<62) | ((0x3fff&nToken)<<48) | (MP_LOG_TICK_MASK&nTick);
int t = MicroProfileLogType(Entry);
uint64_t nTimerIndex = MicroProfileLogTimerIndex(Entry);
MP_ASSERT(t == nBegin);
MP_ASSERT((uint64_t)t == nBegin);
MP_ASSERT(nTimerIndex == (nToken&0x3fff));
return Entry;
@@ -1556,10 +1556,10 @@ void MicroProfileFlip()
pFramePut->nFrameStartCpu = MP_TICK();
pFramePut->nFrameStartGpu = (uint32_t)MicroProfileGpuInsertTimeStamp();
if(pFrameNext->nFrameStartGpu != (uint64_t)-1)
if(pFrameNext->nFrameStartGpu != -1)
pFrameNext->nFrameStartGpu = MicroProfileGpuGetTimeStamp((uint32_t)pFrameNext->nFrameStartGpu);
if(pFrameCurrent->nFrameStartGpu == (uint64_t)-1)
if(pFrameCurrent->nFrameStartGpu == -1)
pFrameCurrent->nFrameStartGpu = pFrameNext->nFrameStartGpu + 1;
uint64_t nFrameStartCpu = pFrameCurrent->nFrameStartCpu;
+2 -2
View File
@@ -343,8 +343,8 @@ The icons used in this project have the following licenses:
Icon Name | License | Origin/Author
--- | --- | ---
checked.png | Free for non-commercial use
failed.png | Free for non-commercial use
checked.png | CC BY-ND 3.0 | https://icons8.com
failed.png | CC BY-ND 3.0 | https://icons8.com
lock.png | CC BY-ND 3.0 | https://icons8.com
plus_folder.png (Default, Dark) | CC BY-ND 3.0 | https://icons8.com
bad_folder.png (Default, Dark) | CC BY-ND 3.0 | https://icons8.com
+1 -1
View File
@@ -166,7 +166,7 @@ struct System::Impl {
service_manager = std::make_shared<Service::SM::ServiceManager>();
Service::Init(service_manager, system);
GDBStub::Init();
GDBStub::DeferStart();
renderer = VideoCore::CreateRenderer(emu_window, system);
if (!renderer->Init()) {
+9
View File
@@ -141,6 +141,7 @@ constexpr char target_xml[] =
)";
int gdbserver_socket = -1;
bool defer_start = false;
u8 command_buffer[GDB_BUFFER_SIZE];
u32 command_length;
@@ -1166,6 +1167,9 @@ static void RemoveBreakpoint() {
void HandlePacket() {
if (!IsConnected()) {
if (defer_start) {
ToggleServer(true);
}
return;
}
@@ -1256,6 +1260,10 @@ void ToggleServer(bool status) {
}
}
void DeferStart() {
defer_start = true;
}
static void Init(u16 port) {
if (!server_enabled) {
// Set the halt loop to false in case the user enabled the gdbstub mid-execution.
@@ -1341,6 +1349,7 @@ void Shutdown() {
if (!server_enabled) {
return;
}
defer_start = false;
LOG_INFO(Debug_GDBStub, "Stopping GDB ...");
if (gdbserver_socket != -1) {
+7
View File
@@ -43,6 +43,13 @@ void ToggleServer(bool status);
/// Start the gdbstub server.
void Init();
/**
* Defer initialization of the gdbstub to the first packet processing functions.
* This avoids a case where the gdbstub thread is frozen after initialization
* and fails to respond in time to packets.
*/
void DeferStart();
/// Stop gdbstub server.
void Shutdown();
+39 -3
View File
@@ -52,6 +52,11 @@ enum class LaunchParameterKind : u32 {
AccountPreselectedUser = 2,
};
enum class VrMode : u8 {
Disabled = 0,
Enabled = 1,
};
constexpr u32 LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC = 0xC79497CA;
struct LaunchParameterAccountPreselectedUser {
@@ -605,11 +610,11 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system,
{30, nullptr, "GetHomeButtonReaderLockAccessor"},
{31, nullptr, "GetReaderLockAccessorEx"},
{40, nullptr, "GetCradleFwVersion"},
{50, nullptr, "IsVrModeEnabled"},
{51, nullptr, "SetVrModeEnabled"},
{50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"},
{51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"},
{52, &ICommonStateGetter::SetLcdBacklighOffEnabled, "SetLcdBacklighOffEnabled"},
{53, nullptr, "BeginVrModeEx"},
{54, nullptr, "EndVrModeEx"},
{54, &ICommonStateGetter::EndVrModeEx, "EndVrModeEx"},
{55, nullptr, "IsInControllerFirmwareUpdateSection"},
{60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
{61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"},
@@ -672,6 +677,30 @@ void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
rb.Push(static_cast<u8>(FocusState::InFocus));
}
void ICommonStateGetter::IsVrModeEnabled(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.PushEnum(VrMode::Disabled);
}
void ICommonStateGetter::SetVrModeEnabled(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto is_vr_mode_enabled = rp.Pop<bool>();
LOG_WARNING(Service_AM, "(STUBBED) called. is_vr_mode_enabled={}", is_vr_mode_enabled);
IPC::ResponseBuilder rb{ctx, 2};
if (!is_vr_mode_enabled) {
rb.Push(RESULT_SUCCESS);
} else {
// TODO: Find better error code for this
UNIMPLEMENTED_MSG("is_vr_mode_enabled={}", is_vr_mode_enabled);
rb.Push(RESULT_UNKNOWN);
}
}
void ICommonStateGetter::SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto is_lcd_backlight_off_enabled = rp.Pop<bool>();
@@ -683,6 +712,13 @@ void ICommonStateGetter::SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx
rb.Push(RESULT_SUCCESS);
}
void ICommonStateGetter::EndVrModeEx(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AM, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called");
+3
View File
@@ -182,7 +182,10 @@ private:
void GetOperationMode(Kernel::HLERequestContext& ctx);
void GetPerformanceMode(Kernel::HLERequestContext& ctx);
void GetBootMode(Kernel::HLERequestContext& ctx);
void IsVrModeEnabled(Kernel::HLERequestContext& ctx);
void SetVrModeEnabled(Kernel::HLERequestContext& ctx);
void SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx);
void EndVrModeEx(Kernel::HLERequestContext& ctx);
void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx);
void SetCpuBoostMode(Kernel::HLERequestContext& ctx);
@@ -254,6 +254,12 @@ void WebBrowser::Execute() {
if (status != RESULT_SUCCESS) {
complete = true;
// This is a workaround in order not to softlock yuzu when an error happens during the
// webapplet init. In order to avoid an svcBreak, the status is set to RESULT_SUCCESS
Finalize();
status = RESULT_SUCCESS;
return;
}
+8 -1
View File
@@ -235,7 +235,7 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) {
{303, nullptr, "ActivateSevenSixAxisSensor"},
{304, nullptr, "StartSevenSixAxisSensor"},
{305, nullptr, "StopSevenSixAxisSensor"},
{306, nullptr, "InitializeSevenSixAxisSensor"},
{306, &Hid::InitializeSevenSixAxisSensor, "InitializeSevenSixAxisSensor"},
{307, nullptr, "FinalizeSevenSixAxisSensor"},
{308, nullptr, "SetSevenSixAxisSensorFusionStrength"},
{309, nullptr, "GetSevenSixAxisSensorFusionStrength"},
@@ -853,6 +853,13 @@ void Hid::SetPalmaBoostMode(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
}
void Hid::InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_HID, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
class HidDbg final : public ServiceFramework<HidDbg> {
public:
explicit HidDbg() : ServiceFramework{"hid:dbg"} {
+1
View File
@@ -128,6 +128,7 @@ private:
void StopSixAxisSensor(Kernel::HLERequestContext& ctx);
void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx);
void SetPalmaBoostMode(Kernel::HLERequestContext& ctx);
void InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx);
std::shared_ptr<IAppletResource> applet_resource;
Core::System& system;
+9 -1
View File
@@ -111,6 +111,14 @@ void SET::GetLanguageCode(Kernel::HLERequestContext& ctx) {
rb.PushEnum(available_language_codes[Settings::values.language_index]);
}
void SET::GetRegionCode(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(Settings::values.region_index);
}
SET::SET() : ServiceFramework("set") {
// clang-format off
static const FunctionInfo functions[] = {
@@ -118,7 +126,7 @@ SET::SET() : ServiceFramework("set") {
{1, &SET::GetAvailableLanguageCodes, "GetAvailableLanguageCodes"},
{2, &SET::MakeLanguageCode, "MakeLanguageCode"},
{3, &SET::GetAvailableLanguageCodeCount, "GetAvailableLanguageCodeCount"},
{4, nullptr, "GetRegionCode"},
{4, &SET::GetRegionCode, "GetRegionCode"},
{5, &SET::GetAvailableLanguageCodes2, "GetAvailableLanguageCodes2"},
{6, &SET::GetAvailableLanguageCodeCount2, "GetAvailableLanguageCodeCount2"},
{7, nullptr, "GetKeyCodeMap"},
+1
View File
@@ -43,6 +43,7 @@ private:
void GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx);
void GetAvailableLanguageCodeCount2(Kernel::HLERequestContext& ctx);
void GetQuestFlag(Kernel::HLERequestContext& ctx);
void GetRegionCode(Kernel::HLERequestContext& ctx);
};
} // namespace Service::Set
+1 -1
View File
@@ -44,7 +44,7 @@ void Controller::QueryPointerBufferSize(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u16>(0x500);
rb.Push<u16>(0x1000);
}
Controller::Controller() : ServiceFramework("IpcController") {
@@ -53,7 +53,7 @@ static std::vector<std::string> BuildLocationNameCache(Core::System& system) {
return {};
}
std::vector<char> raw_data(binary_list->GetSize());
std::vector<char> raw_data(binary_list->GetSize() + 1);
binary_list->ReadBytes<char>(raw_data.data(), binary_list->GetSize());
std::stringstream data_stream{raw_data.data()};
+1
View File
@@ -86,6 +86,7 @@ void LogSettings() {
LogSetting("System_RngSeed", Settings::values.rng_seed.value_or(0));
LogSetting("System_CurrentUser", Settings::values.current_user);
LogSetting("System_LanguageIndex", Settings::values.language_index);
LogSetting("System_RegionIndex", Settings::values.region_index);
LogSetting("Core_UseMultiCore", Settings::values.use_multi_core);
LogSetting("Renderer_UseResolutionFactor", Settings::values.resolution_factor);
LogSetting("Renderer_UseFrameLimit", Settings::values.use_frame_limit);
+2
View File
@@ -387,6 +387,8 @@ struct Values {
s32 current_user;
s32 language_index;
s32 region_index;
s32 sound_index;
// Controls
std::array<PlayerInput, 10> players;
+1 -1
View File
@@ -35,7 +35,7 @@ public:
pad_index(pad_index) {
boost::system::error_code ec{};
auto ipv4 = boost::asio::ip::make_address_v4(host, ec);
if (ec.failed()) {
if (ec.value() != boost::system::errc::success) {
LOG_ERROR(Input, "Invalid IPv4 address \"{}\" provided to socket", host);
ipv4 = boost::asio::ip::address_v4{};
}
@@ -18,10 +18,14 @@ struct SamplerDescriptor {
union {
u32 raw = 0;
BitField<0, 2, Tegra::Shader::TextureType> texture_type;
BitField<2, 3, Tegra::Texture::ComponentType> component_type;
BitField<2, 3, Tegra::Texture::ComponentType> r_type;
BitField<5, 1, u32> is_array;
BitField<6, 1, u32> is_buffer;
BitField<7, 1, u32> is_shadow;
BitField<8, 3, Tegra::Texture::ComponentType> g_type;
BitField<11, 3, Tegra::Texture::ComponentType> b_type;
BitField<14, 3, Tegra::Texture::ComponentType> a_type;
BitField<17, 7, Tegra::Texture::TextureFormat> format;
};
bool operator==(const SamplerDescriptor& rhs) const noexcept {
@@ -36,9 +40,11 @@ struct SamplerDescriptor {
using Tegra::Shader::TextureType;
SamplerDescriptor result;
// This is going to be used to determine the shading language type.
// Because of that we don't care about all component types on color textures.
result.component_type.Assign(tic.r_type.Value());
result.format.Assign(tic.format.Value());
result.r_type.Assign(tic.r_type.Value());
result.g_type.Assign(tic.g_type.Value());
result.b_type.Assign(tic.b_type.Value());
result.a_type.Assign(tic.a_type.Value());
switch (tic.texture_type.Value()) {
case Tegra::Texture::TextureType::Texture1D:
@@ -119,14 +119,6 @@ Texture::TICEntry KeplerCompute::GetTICEntry(u32 tic_index) const {
Texture::TICEntry tic_entry;
memory_manager.ReadBlockUnsafe(tic_address_gpu, &tic_entry, sizeof(Texture::TICEntry));
const auto r_type{tic_entry.r_type.Value()};
const auto g_type{tic_entry.g_type.Value()};
const auto b_type{tic_entry.b_type.Value()};
const auto a_type{tic_entry.a_type.Value()};
// TODO(Subv): Different data types for separate components are not supported
DEBUG_ASSERT(r_type == g_type && r_type == b_type && r_type == a_type);
return tic_entry;
}
+20 -5
View File
@@ -98,6 +98,8 @@ void Maxwell3D::InitializeRegisterDefaults() {
regs.framebuffer_srgb = 1;
regs.front_face = Maxwell3D::Regs::FrontFace::ClockWise;
shadow_state = regs;
mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_end_gl)] = true;
mme_inline[MAXWELL3D_REG_INDEX(draw.vertex_begin_gl)] = true;
mme_inline[MAXWELL3D_REG_INDEX(vertex_buffer.count)] = true;
@@ -160,8 +162,17 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) {
ASSERT_MSG(method < Regs::NUM_REGS,
"Invalid Maxwell3D register, increase the size of the Regs structure");
if (regs.reg_array[method] != method_call.argument) {
regs.reg_array[method] = method_call.argument;
u32 arg = method_call.argument;
// Keep track of the register value in shadow_state when requested.
if (shadow_state.shadow_ram_control == Regs::ShadowRamControl::Track ||
shadow_state.shadow_ram_control == Regs::ShadowRamControl::TrackWithFilter) {
shadow_state.reg_array[method] = arg;
} else if (shadow_state.shadow_ram_control == Regs::ShadowRamControl::Replay) {
arg = shadow_state.reg_array[method];
}
if (regs.reg_array[method] != arg) {
regs.reg_array[method] = arg;
for (const auto& table : dirty.tables) {
dirty.flags[table[method]] = true;
@@ -169,12 +180,16 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) {
}
switch (method) {
case MAXWELL3D_REG_INDEX(shadow_ram_control): {
shadow_state.shadow_ram_control = static_cast<Regs::ShadowRamControl>(method_call.argument);
break;
}
case MAXWELL3D_REG_INDEX(macros.data): {
ProcessMacroUpload(method_call.argument);
ProcessMacroUpload(arg);
break;
}
case MAXWELL3D_REG_INDEX(macros.bind): {
ProcessMacroBind(method_call.argument);
ProcessMacroBind(arg);
break;
}
case MAXWELL3D_REG_INDEX(firmware[4]): {
@@ -250,7 +265,7 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) {
}
case MAXWELL3D_REG_INDEX(data_upload): {
const bool is_last_call = method_call.IsLastCall();
upload_state.ProcessData(method_call.argument, is_last_call);
upload_state.ProcessData(arg, is_last_call);
if (is_last_call) {
OnMemoryWrite();
}
+21 -2
View File
@@ -531,6 +531,17 @@ public:
Fill = 0x1b02,
};
enum class ShadowRamControl : u32 {
// write value to shadow ram
Track = 0,
// write value to shadow ram ( with validation ??? )
TrackWithFilter = 1,
// only write to real hw register
Passthrough = 2,
// write value from shadow ram to real hw register
Replay = 3,
};
struct RenderTargetConfig {
u32 address_high;
u32 address_low;
@@ -674,7 +685,9 @@ public:
u32 bind;
} macros;
INSERT_UNION_PADDING_WORDS(0x17);
ShadowRamControl shadow_ram_control;
INSERT_UNION_PADDING_WORDS(0x16);
Upload::Registers upload;
struct {
@@ -1263,7 +1276,12 @@ public:
};
std::array<u32, NUM_REGS> reg_array;
};
} regs{};
};
Regs regs{};
/// Store temporary hw register values, used by some calls to restore state after a operation
Regs shadow_state;
static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32), "Maxwell3D Regs has wrong size");
static_assert(std::is_trivially_copyable_v<Regs>, "Maxwell3D Regs must be trivially copyable");
@@ -1458,6 +1476,7 @@ private:
"Field " #field_name " has invalid position")
ASSERT_REG_POSITION(macros, 0x45);
ASSERT_REG_POSITION(shadow_ram_control, 0x49);
ASSERT_REG_POSITION(upload, 0x60);
ASSERT_REG_POSITION(exec_upload, 0x6C);
ASSERT_REG_POSITION(data_upload, 0x6D);
+62 -1
View File
@@ -82,6 +82,10 @@ union Attribute {
Position = 7,
Attribute_0 = 8,
Attribute_31 = 39,
FrontColor = 40,
FrontSecondaryColor = 41,
BackColor = 42,
BackSecondaryColor = 43,
ClipDistances0123 = 44,
ClipDistances4567 = 45,
PointCoord = 46,
@@ -89,6 +93,8 @@ union Attribute {
// shader, and a tuple of (TessCoord.x, TessCoord.y, TessCoord.z, ~) when inside a Tess Eval
// shader.
TessCoordInstanceIDVertexID = 47,
TexCoord_0 = 48,
TexCoord_7 = 55,
// This attribute contains a tuple of (Unk, Unk, Unk, gl_FrontFacing) when inside a fragment
// shader. It is unknown what the other values contain.
FrontFacing = 63,
@@ -296,6 +302,23 @@ enum class VmadShr : u64 {
Shr15 = 2,
};
enum class VmnmxType : u64 {
Bits8,
Bits16,
Bits32,
};
enum class VmnmxOperation : u64 {
Mrg_16H = 0,
Mrg_16L = 1,
Mrg_8B0 = 2,
Mrg_8B2 = 3,
Acc = 4,
Min = 5,
Max = 6,
Nop = 7,
};
enum class XmadMode : u64 {
None = 0,
CLo = 1,
@@ -1656,6 +1679,42 @@ union Instruction {
BitField<47, 1, u64> cc;
} vmad;
union {
BitField<54, 1, u64> is_dest_signed;
BitField<48, 1, u64> is_src_a_signed;
BitField<49, 1, u64> is_src_b_signed;
BitField<37, 2, u64> src_format_a;
BitField<29, 2, u64> src_format_b;
BitField<56, 1, u64> mx;
BitField<55, 1, u64> sat;
BitField<36, 2, u64> selector_a;
BitField<28, 2, u64> selector_b;
BitField<50, 1, u64> is_op_b_register;
BitField<51, 3, VmnmxOperation> operation;
VmnmxType SourceFormatA() const {
switch (src_format_a) {
case 0b11:
return VmnmxType::Bits32;
case 0b10:
return VmnmxType::Bits16;
default:
return VmnmxType::Bits8;
}
}
VmnmxType SourceFormatB() const {
switch (src_format_b) {
case 0b11:
return VmnmxType::Bits32;
case 0b10:
return VmnmxType::Bits16;
default:
return VmnmxType::Bits8;
}
}
} vmnmx;
union {
BitField<20, 16, u64> imm20_16;
BitField<35, 1, u64> high_b_rr; // used on RR
@@ -1767,6 +1826,7 @@ public:
MEMBAR,
VMAD,
VSETP,
VMNMX,
FFMA_IMM, // Fused Multiply and Add
FFMA_CR,
FFMA_RC,
@@ -2072,6 +2132,7 @@ private:
INST("1110111110011---", Id::MEMBAR, Type::Trivial, "MEMBAR"),
INST("01011111--------", Id::VMAD, Type::Video, "VMAD"),
INST("0101000011110---", Id::VSETP, Type::Video, "VSETP"),
INST("0011101---------", Id::VMNMX, Type::Video, "VMNMX"),
INST("0011001-1-------", Id::FFMA_IMM, Type::Ffma, "FFMA_IMM"),
INST("010010011-------", Id::FFMA_CR, Type::Ffma, "FFMA_CR"),
INST("010100011-------", Id::FFMA_RC, Type::Ffma, "FFMA_RC"),
@@ -2172,7 +2233,7 @@ private:
INST("0011011-11111---", Id::SHF_LEFT_IMM, Type::Shift, "SHF_LEFT_IMM"),
INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"),
INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"),
INST("0011101-11100---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"),
INST("0011100-11100---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"),
INST("0100110010111---", Id::I2F_C, Type::Conversion, "I2F_C"),
INST("0101110010111---", Id::I2F_R, Type::Conversion, "I2F_R"),
INST("0011100-10111---", Id::I2F_IMM, Type::Conversion, "I2F_IMM"),
@@ -93,10 +93,6 @@ void oglEnable(GLenum cap, bool state) {
(state ? glEnable : glDisable)(cap);
}
void oglEnablei(GLenum cap, bool state, GLuint index) {
(state ? glEnablei : glDisablei)(cap, index);
}
} // Anonymous namespace
RasterizerOpenGL::RasterizerOpenGL(Core::System& system, Core::Frontend::EmuWindow& emu_window,
@@ -478,7 +474,6 @@ void RasterizerOpenGL::Clear() {
void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
MICROPROFILE_SCOPE(OpenGL_Drawing);
auto& gpu = system.GPU().Maxwell3D();
const auto& regs = gpu.regs;
query_cache.UpdateCounters();
@@ -529,7 +524,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
// Upload vertex and index data.
SetupVertexBuffer();
SetupVertexInstances();
GLintptr index_buffer_offset;
GLintptr index_buffer_offset = 0;
if (is_indexed) {
index_buffer_offset = SetupIndexBuffer();
}
@@ -555,7 +550,7 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) {
ConfigureFramebuffers();
// Signal the buffer cache that we are not going to upload more things.
const bool invalidate = buffer_cache.Unmap();
buffer_cache.Unmap();
// Now that we are no longer uploading data, we can safely bind the buffers to OpenGL.
vertex_array_pushbuffer.Bind();
@@ -938,13 +933,15 @@ void RasterizerOpenGL::SyncViewport() {
}
flags[Dirty::Viewport0 + i] = false;
const Common::Rectangle<f32> rect{regs.viewport_transform[i].GetRect()};
const auto& src = regs.viewport_transform[i];
const Common::Rectangle<f32> rect{src.GetRect()};
glViewportIndexedf(static_cast<GLuint>(i), rect.left, rect.bottom, rect.GetWidth(),
rect.GetHeight());
const auto& src = regs.viewports[i];
glDepthRangeIndexed(static_cast<GLuint>(i), static_cast<GLdouble>(src.depth_range_near),
static_cast<GLdouble>(src.depth_range_far));
const GLdouble reduce_z = regs.depth_mode == Maxwell::DepthMode::MinusOneToOne;
const GLdouble near_depth = src.translate_z - src.scale_z * reduce_z;
const GLdouble far_depth = src.translate_z + src.scale_z;
glDepthRangeIndexed(static_cast<GLuint>(i), near_depth, far_depth);
}
}
}
@@ -366,10 +366,19 @@ constexpr bool IsGenericAttribute(Attribute::Index index) {
return index >= Attribute::Index::Attribute_0 && index <= Attribute::Index::Attribute_31;
}
constexpr bool IsLegacyTexCoord(Attribute::Index index) {
return static_cast<int>(index) >= static_cast<int>(Attribute::Index::TexCoord_0) &&
static_cast<int>(index) <= static_cast<int>(Attribute::Index::TexCoord_7);
}
constexpr Attribute::Index ToGenericAttribute(u64 value) {
return static_cast<Attribute::Index>(value + static_cast<u64>(Attribute::Index::Attribute_0));
}
constexpr int GetLegacyTexCoordIndex(Attribute::Index index) {
return static_cast<int>(index) - static_cast<int>(Attribute::Index::TexCoord_0);
}
u32 GetGenericAttributeIndex(Attribute::Index index) {
ASSERT(IsGenericAttribute(index));
return static_cast<u32>(index) - static_cast<u32>(Attribute::Index::Attribute_0);
@@ -393,10 +402,6 @@ std::string FlowStackTopName(MetaStackClass stack) {
return fmt::format("{}_flow_stack_top", GetFlowStackPrefix(stack));
}
[[deprecated]] constexpr bool IsVertexShader(ShaderType stage) {
return stage == ShaderType::Vertex;
}
struct GenericVaryingDescription {
std::string name;
u8 first_element = 0;
@@ -502,7 +507,7 @@ private:
if (!identifier.empty()) {
code.AddLine("// {}", identifier);
}
code.AddLine("#version 440 core");
code.AddLine("#version 440 {}", ir.UsesLegacyVaryings() ? "compatibility" : "core");
code.AddLine("#extension GL_ARB_separate_shader_objects : enable");
if (device.HasShaderBallot()) {
code.AddLine("#extension GL_ARB_shader_ballot : require");
@@ -529,8 +534,9 @@ private:
}
void DeclareVertex() {
if (!IsVertexShader(stage))
if (stage != ShaderType::Vertex) {
return;
}
DeclareVertexRedeclarations();
}
@@ -564,6 +570,16 @@ private:
if (stage != ShaderType::Fragment) {
return;
}
if (ir.UsesLegacyVaryings()) {
code.AddLine("in gl_PerFragment {{");
++code.scope;
code.AddLine("vec4 gl_TexCoord[8];");
code.AddLine("vec4 gl_Color;");
code.AddLine("vec4 gl_SecondaryColor;");
--code.scope;
code.AddLine("}};");
}
for (u32 rt = 0; rt < Maxwell::NumRenderTargets; ++rt) {
code.AddLine("layout (location = {}) out vec4 frag_color{};", rt, rt);
}
@@ -602,14 +618,14 @@ private:
break;
}
}
if (!IsVertexShader(stage) || device.HasVertexViewportLayer()) {
if (stage != ShaderType::Vertex || device.HasVertexViewportLayer()) {
if (ir.UsesLayer()) {
code.AddLine("int gl_Layer;");
}
if (ir.UsesViewportIndex()) {
code.AddLine("int gl_ViewportIndex;");
}
} else if ((ir.UsesLayer() || ir.UsesViewportIndex()) && IsVertexShader(stage) &&
} else if ((ir.UsesLayer() || ir.UsesViewportIndex()) && stage == ShaderType::Vertex &&
!device.HasVertexViewportLayer()) {
LOG_ERROR(
Render_OpenGL,
@@ -620,12 +636,12 @@ private:
code.AddLine("float gl_PointSize;");
}
if (ir.UsesInstanceId()) {
code.AddLine("int gl_InstanceID;");
}
if (ir.UsesVertexId()) {
code.AddLine("int gl_VertexID;");
if (ir.UsesLegacyVaryings()) {
code.AddLine("vec4 gl_TexCoord[8];");
code.AddLine("vec4 gl_FrontColor;");
code.AddLine("vec4 gl_FrontSecondaryColor;");
code.AddLine("vec4 gl_BackColor;");
code.AddLine("vec4 gl_BackSecondaryColor;");
}
--code.scope;
@@ -1131,6 +1147,10 @@ private:
default:
UNREACHABLE();
}
case Attribute::Index::FrontColor:
return {"gl_Color"s + GetSwizzle(element), Type::Float};
case Attribute::Index::FrontSecondaryColor:
return {"gl_SecondaryColor"s + GetSwizzle(element), Type::Float};
case Attribute::Index::PointCoord:
switch (element) {
case 0:
@@ -1147,7 +1167,7 @@ private:
// TODO(Subv): Find out what the values are for the first two elements when inside a
// vertex shader, and what's the value of the fourth element when inside a Tess Eval
// shader.
ASSERT(IsVertexShader(stage));
ASSERT(stage == ShaderType::Vertex);
switch (element) {
case 2:
// Config pack's first value is instance_id.
@@ -1171,6 +1191,12 @@ private:
return {GeometryPass(GetGenericInputAttribute(attribute)) + GetSwizzle(element),
Type::Float};
}
if (IsLegacyTexCoord(attribute)) {
UNIMPLEMENTED_IF(stage == ShaderType::Geometry);
return {fmt::format("gl_TexCoord[{}]{}", GetLegacyTexCoordIndex(attribute),
GetSwizzle(element)),
Type::Float};
}
break;
}
UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute));
@@ -1209,21 +1235,22 @@ private:
}
std::optional<Expression> GetOutputAttribute(const AbufNode* abuf) {
const u32 element = abuf->GetElement();
switch (const auto attribute = abuf->GetIndex()) {
case Attribute::Index::Position:
return {{"gl_Position"s + GetSwizzle(abuf->GetElement()), Type::Float}};
return {{"gl_Position"s + GetSwizzle(element), Type::Float}};
case Attribute::Index::LayerViewportPointSize:
switch (abuf->GetElement()) {
switch (element) {
case 0:
UNIMPLEMENTED();
return {};
case 1:
if (IsVertexShader(stage) && !device.HasVertexViewportLayer()) {
if (stage == ShaderType::Vertex && !device.HasVertexViewportLayer()) {
return {};
}
return {{"gl_Layer", Type::Int}};
case 2:
if (IsVertexShader(stage) && !device.HasVertexViewportLayer()) {
if (stage == ShaderType::Vertex && !device.HasVertexViewportLayer()) {
return {};
}
return {{"gl_ViewportIndex", Type::Int}};
@@ -1231,13 +1258,26 @@ private:
return {{"gl_PointSize", Type::Float}};
}
return {};
case Attribute::Index::FrontColor:
return {{"gl_FrontColor"s + GetSwizzle(element), Type::Float}};
case Attribute::Index::FrontSecondaryColor:
return {{"gl_FrontSecondaryColor"s + GetSwizzle(element), Type::Float}};
case Attribute::Index::BackColor:
return {{"gl_BackColor"s + GetSwizzle(element), Type::Float}};
case Attribute::Index::BackSecondaryColor:
return {{"gl_BackSecondaryColor"s + GetSwizzle(element), Type::Float}};
case Attribute::Index::ClipDistances0123:
return {{fmt::format("gl_ClipDistance[{}]", abuf->GetElement()), Type::Float}};
return {{fmt::format("gl_ClipDistance[{}]", element), Type::Float}};
case Attribute::Index::ClipDistances4567:
return {{fmt::format("gl_ClipDistance[{}]", abuf->GetElement() + 4), Type::Float}};
return {{fmt::format("gl_ClipDistance[{}]", element + 4), Type::Float}};
default:
if (IsGenericAttribute(attribute)) {
return {{GetGenericOutputAttribute(attribute, abuf->GetElement()), Type::Float}};
return {{GetGenericOutputAttribute(attribute, element), Type::Float}};
}
if (IsLegacyTexCoord(attribute)) {
return {{fmt::format("gl_TexCoord[{}]{}", GetLegacyTexCoordIndex(attribute),
GetSwizzle(element)),
Type::Float}};
}
UNIMPLEMENTED_MSG("Unhandled output attribute: {}", static_cast<u32>(attribute));
return {};
@@ -2532,7 +2572,7 @@ private:
}
u32 GetNumPhysicalInputAttributes() const {
return IsVertexShader(stage) ? GetNumPhysicalAttributes() : GetNumPhysicalVaryings();
return stage == ShaderType::Vertex ? GetNumPhysicalAttributes() : GetNumPhysicalVaryings();
}
u32 GetNumPhysicalAttributes() const {
@@ -257,6 +257,8 @@ vk::ShaderStageFlagBits ShaderStage(Tegra::Engines::ShaderType stage) {
return vk::ShaderStageFlagBits::eGeometry;
case Tegra::Engines::ShaderType::Fragment:
return vk::ShaderStageFlagBits::eFragment;
case Tegra::Engines::ShaderType::Compute:
return vk::ShaderStageFlagBits::eCompute;
}
UNIMPLEMENTED_MSG("Unimplemented shader stage={}", static_cast<u32>(stage));
return {};
@@ -399,6 +401,26 @@ vk::Format VertexFormat(Maxwell::VertexAttribute::Type type, Maxwell::VertexAttr
}
break;
case Maxwell::VertexAttribute::Type::SignedScaled:
switch (size) {
case Maxwell::VertexAttribute::Size::Size_8:
return vk::Format::eR8Sscaled;
case Maxwell::VertexAttribute::Size::Size_8_8:
return vk::Format::eR8G8Sscaled;
case Maxwell::VertexAttribute::Size::Size_8_8_8:
return vk::Format::eR8G8B8Sscaled;
case Maxwell::VertexAttribute::Size::Size_8_8_8_8:
return vk::Format::eR8G8B8A8Sscaled;
case Maxwell::VertexAttribute::Size::Size_16:
return vk::Format::eR16Sscaled;
case Maxwell::VertexAttribute::Size::Size_16_16:
return vk::Format::eR16G16Sscaled;
case Maxwell::VertexAttribute::Size::Size_16_16_16:
return vk::Format::eR16G16B16Sscaled;
case Maxwell::VertexAttribute::Size::Size_16_16_16_16:
return vk::Format::eR16G16B16A16Sscaled;
default:
break;
}
break;
case Maxwell::VertexAttribute::Type::Float:
switch (size) {
@@ -192,7 +192,6 @@ std::array<Shader, Maxwell::MaxShaderProgram> VKPipelineCache::GetShaders() {
std::array<Shader, Maxwell::MaxShaderProgram> shaders;
for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
const auto& shader_config = gpu.regs.shader_config[index];
const auto program{static_cast<Maxwell::ShaderProgram>(index)};
// Skip stages that are not enabled
@@ -548,8 +548,6 @@ bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config,
// Verify that the cached surface is the same size and format as the requested framebuffer
const auto& params{surface->GetSurfaceParams()};
const auto& pixel_format{
VideoCore::Surface::PixelFormatFromGPUPixelFormat(config.pixel_format)};
ASSERT_MSG(params.width == config.width, "Framebuffer width is different");
ASSERT_MSG(params.height == config.height, "Framebuffer height is different");
@@ -100,7 +100,6 @@ void VKStagingBufferPool::ReleaseCache(bool host_visible) {
}
u64 VKStagingBufferPool::ReleaseLevel(StagingBuffersCache& cache, std::size_t log2) {
static constexpr u64 epochs_to_destroy = 180;
static constexpr std::size_t deletions_per_tick = 16;
auto& staging = cache[log2];
@@ -108,6 +107,7 @@ u64 VKStagingBufferPool::ReleaseLevel(StagingBuffersCache& cache, std::size_t lo
const std::size_t old_size = entries.size();
const auto is_deleteable = [this](const auto& entry) {
static constexpr u64 epochs_to_destroy = 180;
return entry.last_epoch + epochs_to_destroy < epoch && !entry.watch.IsUsed();
};
const std::size_t begin_offset = staging.delete_index;
@@ -52,6 +52,9 @@ vk::ImageType SurfaceTargetToImage(SurfaceTarget target) {
return vk::ImageType::e2D;
case SurfaceTarget::Texture3D:
return vk::ImageType::e3D;
case SurfaceTarget::TextureBuffer:
UNREACHABLE();
return {};
}
UNREACHABLE_MSG("Unknown texture target={}", static_cast<u32>(target));
return {};
@@ -273,7 +276,6 @@ void CachedSurface::UploadImage(const std::vector<u8>& staging_buffer) {
for (u32 level = 0; level < params.num_levels; ++level) {
vk::BufferImageCopy copy = GetBufferImageCopy(level);
const auto& dld = device.GetDispatchLoader();
if (image->GetAspectMask() ==
(vk::ImageAspectFlagBits::eDepth | vk::ImageAspectFlagBits::eStencil)) {
vk::BufferImageCopy depth = copy;
@@ -422,7 +424,6 @@ void VKTextureCache::ImageCopy(Surface& src_surface, Surface& dst_surface,
dst_base_layer, num_layers, copy_params.dest_level, 1, vk::PipelineStageFlagBits::eTransfer,
vk::AccessFlagBits::eTransferWrite, vk::ImageLayout::eTransferDstOptimal);
const auto& dld{device.GetDispatchLoader()};
const vk::ImageSubresourceLayers src_subresource(
src_surface->GetAspectMask(), copy_params.source_level, copy_params.source_z, num_layers);
const vk::ImageSubresourceLayers dst_subresource(
@@ -458,7 +459,6 @@ void VKTextureCache::ImageBlit(View& src_view, View& dst_view,
dst_view->GetImageSubresourceLayers(), {dst_top_left, dst_bot_right});
const bool is_linear = copy_config.filter == Tegra::Engines::Fermi2D::Filter::Linear;
const auto& dld{device.GetDispatchLoader()};
scheduler.Record([src_image = src_view->GetImage(), dst_image = dst_view->GetImage(), blit,
is_linear](auto cmdbuf, auto& dld) {
cmdbuf.blitImage(src_image, vk::ImageLayout::eTransferSrcOptimal, dst_image,
+58
View File
@@ -10,16 +10,24 @@
namespace VideoCommon::Shader {
using std::move;
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
using Tegra::Shader::Pred;
using Tegra::Shader::VideoType;
using Tegra::Shader::VmadShr;
using Tegra::Shader::VmnmxOperation;
using Tegra::Shader::VmnmxType;
u32 ShaderIR::DecodeVideo(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);
if (opcode->get().GetId() == OpCode::Id::VMNMX) {
DecodeVMNMX(bb, instr);
return pc;
}
const Node op_a =
GetVideoOperand(GetRegister(instr.gpr8), instr.video.is_byte_chunk_a, instr.video.signed_a,
instr.video.type_a, instr.video.byte_height_a);
@@ -109,4 +117,54 @@ Node ShaderIR::GetVideoOperand(Node op, bool is_chunk, bool is_signed,
}
}
void ShaderIR::DecodeVMNMX(NodeBlock& bb, Tegra::Shader::Instruction instr) {
UNIMPLEMENTED_IF(!instr.vmnmx.is_op_b_register);
UNIMPLEMENTED_IF(instr.vmnmx.SourceFormatA() != VmnmxType::Bits32);
UNIMPLEMENTED_IF(instr.vmnmx.SourceFormatB() != VmnmxType::Bits32);
UNIMPLEMENTED_IF(instr.vmnmx.is_src_a_signed != instr.vmnmx.is_src_b_signed);
UNIMPLEMENTED_IF(instr.vmnmx.sat);
UNIMPLEMENTED_IF(instr.generates_cc);
Node op_a = GetRegister(instr.gpr8);
Node op_b = GetRegister(instr.gpr20);
Node op_c = GetRegister(instr.gpr39);
const bool is_oper1_signed = instr.vmnmx.is_src_a_signed; // Stubbed
const bool is_oper2_signed = instr.vmnmx.is_dest_signed;
const auto operation_a = instr.vmnmx.mx ? OperationCode::IMax : OperationCode::IMin;
Node value = SignedOperation(operation_a, is_oper1_signed, move(op_a), move(op_b));
switch (instr.vmnmx.operation) {
case VmnmxOperation::Mrg_16H:
value = BitfieldInsert(move(op_c), move(value), 16, 16);
break;
case VmnmxOperation::Mrg_16L:
value = BitfieldInsert(move(op_c), move(value), 0, 16);
break;
case VmnmxOperation::Mrg_8B0:
value = BitfieldInsert(move(op_c), move(value), 0, 8);
break;
case VmnmxOperation::Mrg_8B2:
value = BitfieldInsert(move(op_c), move(value), 16, 8);
break;
case VmnmxOperation::Acc:
value = Operation(OperationCode::IAdd, move(value), move(op_c));
break;
case VmnmxOperation::Min:
value = SignedOperation(OperationCode::IMin, is_oper2_signed, move(value), move(op_c));
break;
case VmnmxOperation::Max:
value = SignedOperation(OperationCode::IMax, is_oper2_signed, move(value), move(op_c));
break;
case VmnmxOperation::Nop:
break;
default:
UNREACHABLE();
break;
}
SetRegister(bb, instr.gpr0, move(value));
}
} // namespace VideoCommon::Shader
+51 -17
View File
@@ -12,6 +12,7 @@ namespace VideoCommon::Shader {
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
using Tegra::Shader::PredCondition;
u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
@@ -30,7 +31,7 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
const bool is_signed_b = instr.xmad.sign_b == 1;
const bool is_signed_c = is_signed_a;
auto [is_merge, is_psl, is_high_b, mode, op_b,
auto [is_merge, is_psl, is_high_b, mode, op_b_binding,
op_c] = [&]() -> std::tuple<bool, bool, bool, Tegra::Shader::XmadMode, Node, Node> {
switch (opcode->get().GetId()) {
case OpCode::Id::XMAD_CR:
@@ -63,15 +64,19 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
}
}();
op_a = BitfieldExtract(op_a, instr.xmad.high_a ? 16 : 0, 16);
op_a = SignedOperation(OperationCode::IBitfieldExtract, is_signed_a, std::move(op_a),
instr.xmad.high_a ? Immediate(16) : Immediate(0), Immediate(16));
const Node original_b = op_b;
op_b = BitfieldExtract(op_b, is_high_b ? 16 : 0, 16);
const Node original_b = op_b_binding;
const Node op_b =
SignedOperation(OperationCode::IBitfieldExtract, is_signed_b, std::move(op_b_binding),
is_high_b ? Immediate(16) : Immediate(0), Immediate(16));
// TODO(Rodrigo): Use an appropiate sign for this operation
Node product = Operation(OperationCode::IMul, NO_PRECISE, op_a, op_b);
// we already check sign_a and sign_b is difference or not before so just use one in here.
Node product = SignedOperation(OperationCode::IMul, is_signed_a, op_a, op_b);
if (is_psl) {
product = Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, product, Immediate(16));
product =
SignedOperation(OperationCode::ILogicalShiftLeft, is_signed_a, product, Immediate(16));
}
SetTemporary(bb, 0, product);
product = GetTemporary(0);
@@ -88,12 +93,40 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
return BitfieldExtract(original_c, 16, 16);
case Tegra::Shader::XmadMode::CBcc: {
const Node shifted_b = SignedOperation(OperationCode::ILogicalShiftLeft, is_signed_b,
NO_PRECISE, original_b, Immediate(16));
return SignedOperation(OperationCode::IAdd, is_signed_c, NO_PRECISE, original_c,
shifted_b);
original_b, Immediate(16));
return SignedOperation(OperationCode::IAdd, is_signed_c, original_c, shifted_b);
}
case Tegra::Shader::XmadMode::CSfu: {
const Node comp_a = GetPredicateComparisonInteger(PredCondition::Equal, is_signed_a,
op_a, Immediate(0));
const Node comp_b = GetPredicateComparisonInteger(PredCondition::Equal, is_signed_b,
op_b, Immediate(0));
const Node comp = Operation(OperationCode::LogicalOr, comp_a, comp_b);
const Node comp_minus_a = GetPredicateComparisonInteger(
PredCondition::NotEqual, is_signed_a,
SignedOperation(OperationCode::IBitwiseAnd, is_signed_a, op_a,
Immediate(0x80000000)),
Immediate(0));
const Node comp_minus_b = GetPredicateComparisonInteger(
PredCondition::NotEqual, is_signed_b,
SignedOperation(OperationCode::IBitwiseAnd, is_signed_b, op_b,
Immediate(0x80000000)),
Immediate(0));
Node new_c = Operation(
OperationCode::Select, comp_minus_a,
SignedOperation(OperationCode::IAdd, is_signed_c, original_c, Immediate(-65536)),
original_c);
new_c = Operation(
OperationCode::Select, comp_minus_b,
SignedOperation(OperationCode::IAdd, is_signed_c, new_c, Immediate(-65536)),
std::move(new_c));
return Operation(OperationCode::Select, comp, original_c, std::move(new_c));
}
default:
UNIMPLEMENTED_MSG("Unhandled XMAD mode: {}", static_cast<u32>(instr.xmad.mode.Value()));
UNREACHABLE();
return Immediate(0);
}
}();
@@ -102,18 +135,19 @@ u32 ShaderIR::DecodeXmad(NodeBlock& bb, u32 pc) {
op_c = GetTemporary(1);
// TODO(Rodrigo): Use an appropiate sign for this operation
Node sum = Operation(OperationCode::IAdd, product, op_c);
Node sum = SignedOperation(OperationCode::IAdd, is_signed_a, product, std::move(op_c));
SetTemporary(bb, 2, sum);
sum = GetTemporary(2);
if (is_merge) {
const Node a = BitfieldExtract(sum, 0, 16);
const Node b =
Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, original_b, Immediate(16));
sum = Operation(OperationCode::IBitwiseOr, NO_PRECISE, a, b);
const Node a = SignedOperation(OperationCode::IBitfieldExtract, is_signed_a, std::move(sum),
Immediate(0), Immediate(16));
const Node b = SignedOperation(OperationCode::ILogicalShiftLeft, is_signed_b, original_b,
Immediate(16));
sum = SignedOperation(OperationCode::IBitwiseOr, is_signed_a, a, b);
}
SetInternalFlagsFromInteger(bb, sum, instr.generates_cc);
SetRegister(bb, instr.gpr0, sum);
SetRegister(bb, instr.gpr0, std::move(sum));
return pc;
}
+50 -35
View File
@@ -96,6 +96,7 @@ Node ShaderIR::GetPredicate(bool immediate) {
}
Node ShaderIR::GetInputAttribute(Attribute::Index index, u64 element, Node buffer) {
MarkAttributeUsage(index, element);
used_input_attributes.emplace(index);
return MakeNode<AbufNode>(index, static_cast<u32>(element), std::move(buffer));
}
@@ -106,42 +107,8 @@ Node ShaderIR::GetPhysicalInputAttribute(Tegra::Shader::Register physical_addres
}
Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) {
if (index == Attribute::Index::LayerViewportPointSize) {
switch (element) {
case 0:
UNIMPLEMENTED();
break;
case 1:
uses_layer = true;
break;
case 2:
uses_viewport_index = true;
break;
case 3:
uses_point_size = true;
break;
}
}
if (index == Attribute::Index::TessCoordInstanceIDVertexID) {
switch (element) {
case 2:
uses_instance_id = true;
break;
case 3:
uses_vertex_id = true;
break;
default:
break;
}
}
if (index == Attribute::Index::ClipDistances0123 ||
index == Attribute::Index::ClipDistances4567) {
const auto clip_index =
static_cast<u32>((index == Attribute::Index::ClipDistances4567 ? 1 : 0) + element);
used_clip_distances.at(clip_index) = true;
}
MarkAttributeUsage(index, element);
used_output_attributes.insert(index);
return MakeNode<AbufNode>(index, static_cast<u32>(element), std::move(buffer));
}
@@ -452,6 +419,54 @@ Node ShaderIR::BitfieldInsert(Node base, Node insert, u32 offset, u32 bits) {
Immediate(bits));
}
void ShaderIR::MarkAttributeUsage(Attribute::Index index, u64 element) {
switch (index) {
case Attribute::Index::LayerViewportPointSize:
switch (element) {
case 0:
UNIMPLEMENTED();
break;
case 1:
uses_layer = true;
break;
case 2:
uses_viewport_index = true;
break;
case 3:
uses_point_size = true;
break;
}
break;
case Attribute::Index::TessCoordInstanceIDVertexID:
switch (element) {
case 2:
uses_instance_id = true;
break;
case 3:
uses_vertex_id = true;
break;
}
break;
case Attribute::Index::ClipDistances0123:
case Attribute::Index::ClipDistances4567: {
const u64 clip_index = (index == Attribute::Index::ClipDistances4567 ? 4 : 0) + element;
used_clip_distances.at(clip_index) = true;
break;
}
case Attribute::Index::FrontColor:
case Attribute::Index::FrontSecondaryColor:
case Attribute::Index::BackColor:
case Attribute::Index::BackSecondaryColor:
uses_legacy_varyings = true;
break;
default:
if (index >= Attribute::Index::TexCoord_0 && index <= Attribute::Index::TexCoord_7) {
uses_legacy_varyings = true;
}
break;
}
}
std::size_t ShaderIR::DeclareAmend(Node new_amend) {
const std::size_t id = amend_code.size();
amend_code.push_back(new_amend);
+11
View File
@@ -137,6 +137,10 @@ public:
return uses_vertex_id;
}
bool UsesLegacyVaryings() const {
return uses_legacy_varyings;
}
bool UsesWarps() const {
return uses_warps;
}
@@ -343,6 +347,12 @@ private:
/// Inserts a sequence of bits from a node
Node BitfieldInsert(Node base, Node insert, u32 offset, u32 bits);
/// Marks the usage of a input or output attribute.
void MarkAttributeUsage(Tegra::Shader::Attribute::Index index, u64 element);
/// Decodes VMNMX instruction and inserts its code into the passed basic block.
void DecodeVMNMX(NodeBlock& bb, Tegra::Shader::Instruction instr);
void WriteTexInstructionFloat(NodeBlock& bb, Tegra::Shader::Instruction instr,
const Node4& components);
@@ -443,6 +453,7 @@ private:
bool uses_physical_attributes{}; // Shader uses AL2P or physical attribute read/writes
bool uses_instance_id{};
bool uses_vertex_id{};
bool uses_legacy_varyings{};
bool uses_warps{};
bool uses_indexed_samplers{};
+8 -1
View File
@@ -539,7 +539,7 @@ void Config::ReadDebuggingValues() {
void Config::ReadServiceValues() {
qt_config->beginGroup(QStringLiteral("Services"));
Settings::values.bcat_backend =
ReadSetting(QStringLiteral("bcat_backend"), QStringLiteral("boxcat"))
ReadSetting(QStringLiteral("bcat_backend"), QStringLiteral("null"))
.toString()
.toStdString();
Settings::values.bcat_boxcat_local =
@@ -682,6 +682,8 @@ void Config::ReadSystemValues() {
Settings::values.language_index = ReadSetting(QStringLiteral("language_index"), 1).toInt();
Settings::values.region_index = ReadSetting(QStringLiteral("region_index"), 1).toInt();
const auto rng_seed_enabled = ReadSetting(QStringLiteral("rng_seed_enabled"), false).toBool();
if (rng_seed_enabled) {
Settings::values.rng_seed = ReadSetting(QStringLiteral("rng_seed"), 0).toULongLong();
@@ -698,6 +700,8 @@ void Config::ReadSystemValues() {
Settings::values.custom_rtc = std::nullopt;
}
Settings::values.sound_index = ReadSetting(QStringLiteral("sound_index"), 1).toInt();
qt_config->endGroup();
}
@@ -1114,6 +1118,7 @@ void Config::SaveSystemValues() {
WriteSetting(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false);
WriteSetting(QStringLiteral("current_user"), Settings::values.current_user, 0);
WriteSetting(QStringLiteral("language_index"), Settings::values.language_index, 1);
WriteSetting(QStringLiteral("region_index"), Settings::values.region_index, 1);
WriteSetting(QStringLiteral("rng_seed_enabled"), Settings::values.rng_seed.has_value(), false);
WriteSetting(QStringLiteral("rng_seed"), Settings::values.rng_seed.value_or(0), 0);
@@ -1125,6 +1130,8 @@ void Config::SaveSystemValues() {
Settings::values.custom_rtc.value_or(std::chrono::seconds{}).count()),
0);
WriteSetting(QStringLiteral("sound_index"), Settings::values.sound_index, 1);
qt_config->endGroup();
}
@@ -56,6 +56,8 @@ void ConfigureSystem::SetConfiguration() {
enabled = !Core::System::GetInstance().IsPoweredOn();
ui->combo_language->setCurrentIndex(Settings::values.language_index);
ui->combo_region->setCurrentIndex(Settings::values.region_index);
ui->combo_sound->setCurrentIndex(Settings::values.sound_index);
ui->rng_seed_checkbox->setChecked(Settings::values.rng_seed.has_value());
ui->rng_seed_edit->setEnabled(Settings::values.rng_seed.has_value());
@@ -81,6 +83,8 @@ void ConfigureSystem::ApplyConfiguration() {
}
Settings::values.language_index = ui->combo_language->currentIndex();
Settings::values.region_index = ui->combo_region->currentIndex();
Settings::values.sound_index = ui->combo_sound->currentIndex();
if (ui->rng_seed_checkbox->isChecked()) {
Settings::values.rng_seed = ui->rng_seed_edit->text().toULongLong(nullptr, 16);
@@ -36,5 +36,6 @@ private:
bool enabled = false;
int language_index = 0;
int region_index = 0;
int sound_index = 0;
};
+54 -8
View File
@@ -22,14 +22,14 @@
<string>System Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<item row="2" column="0">
<widget class="QLabel" name="label_sound">
<property name="text">
<string>Sound output mode</string>
</property>
</widget>
</item>
<item row="2" column="0">
<item row="3" column="0">
<widget class="QLabel" name="label_console_id">
<property name="text">
<string>Console ID:</string>
@@ -128,14 +128,60 @@
</item>
</widget>
</item>
<item row="4" column="0">
<item row="1" column="0">
<widget class="QLabel" name="label_region">
<property name="text">
<string>Region:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="combo_region">
<item>
<property name="text">
<string>Japan</string>
</property>
</item>
<item>
<property name="text">
<string>USA</string>
</property>
</item>
<item>
<property name="text">
<string>Europe</string>
</property>
</item>
<item>
<property name="text">
<string>Australia</string>
</property>
</item>
<item>
<property name="text">
<string>China</string>
</property>
</item>
<item>
<property name="text">
<string>Korea</string>
</property>
</item>
<item>
<property name="text">
<string>Taiwan</string>
</property>
</item>
</widget>
</item>
<item row="5" column="0">
<widget class="QCheckBox" name="rng_seed_checkbox">
<property name="text">
<string>RNG Seed</string>
</property>
</widget>
</item>
<item row="1" column="1">
<item row="2" column="1">
<widget class="QComboBox" name="combo_sound">
<item>
<property name="text">
@@ -161,7 +207,7 @@
</property>
</widget>
</item>
<item row="2" column="1">
<item row="3" column="1">
<widget class="QPushButton" name="button_regenerate_console_id">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
@@ -177,14 +223,14 @@
</property>
</widget>
</item>
<item row="3" column="0">
<item row="4" column="0">
<widget class="QCheckBox" name="custom_rtc_checkbox">
<property name="text">
<string>Custom RTC</string>
</property>
</widget>
</item>
<item row="3" column="1">
<item row="4" column="1">
<widget class="QDateTimeEdit" name="custom_rtc_edit">
<property name="minimumDate">
<date>
@@ -198,7 +244,7 @@
</property>
</widget>
</item>
<item row="4" column="1">
<item row="5" column="1">
<widget class="QLineEdit" name="rng_seed_edit">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+9 -6
View File
@@ -1034,6 +1034,14 @@ void GMainWindow::BootGame(const QString& filename) {
}
void GMainWindow::ShutdownGame() {
if (!emulation_running) {
return;
}
if (ui.action_Fullscreen->isChecked()) {
HideFullscreen();
}
AllowOSSleep();
discord_rpc->Pause();
@@ -1716,11 +1724,6 @@ void GMainWindow::OnStartGame() {
}
void GMainWindow::OnPauseGame() {
Core::System& system{Core::System::GetInstance()};
if (system.GetExitLock() && !ConfirmForceLockedExit()) {
return;
}
emu_thread->SetRunning(false);
ui.action_Start->setEnabled(true);
@@ -1803,7 +1806,7 @@ void GMainWindow::ToggleWindowMode() {
// Render in the main window...
render_window->BackupGeometry();
ui.horizontalLayout->addWidget(render_window);
render_window->setFocusPolicy(Qt::ClickFocus);
render_window->setFocusPolicy(Qt::StrongFocus);
if (emulation_running) {
render_window->setVisible(true);
render_window->setFocus();
+1 -1
View File
@@ -452,7 +452,7 @@ void Config::ReadValues() {
Settings::values.yuzu_token = sdl2_config->Get("WebService", "yuzu_token", "");
// Services
Settings::values.bcat_backend = sdl2_config->Get("Services", "bcat_backend", "boxcat");
Settings::values.bcat_backend = sdl2_config->Get("Services", "bcat_backend", "null");
Settings::values.bcat_boxcat_local =
sdl2_config->GetBoolean("Services", "bcat_boxcat_local", false);
}