Date: Mon, 13 Feb 2023 14:51:09 +0100
Subject: [PATCH 08/12] github: Improve Readme and add better issue templates
(#6276)
* README: Update with latest information and better design
* .github: Add better issue templates
* Readme: Address review comments
---
.../ISSUE_TEMPLATE/blank_issue_template.yml | 10 +++
.../bug-report-feature-request.md | 35 --------
.github/ISSUE_TEMPLATE/bug_report.yml | 64 +++++++++++++++
.github/ISSUE_TEMPLATE/config.yml | 3 -
.github/ISSUE_TEMPLATE/feature_request.yml | 28 +++++++
README.md | 79 ++++++++++++++-----
6 files changed, 162 insertions(+), 57 deletions(-)
create mode 100644 .github/ISSUE_TEMPLATE/blank_issue_template.yml
delete mode 100644 .github/ISSUE_TEMPLATE/bug-report-feature-request.md
create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml
create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml
diff --git a/.github/ISSUE_TEMPLATE/blank_issue_template.yml b/.github/ISSUE_TEMPLATE/blank_issue_template.yml
new file mode 100644
index 000000000..49b7f3822
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/blank_issue_template.yml
@@ -0,0 +1,10 @@
+name: New Issue (Developers Only)
+description: A blank issue template for developers only. If you are not a developer, do not use this issue template. Your issue WILL BE CLOSED if you do not use the appropriate issue template.
+body:
+ - type: markdown
+ attributes:
+ value: |
+ **If you are not a developer, do not use this issue template. Your issue WILL BE CLOSED if you do not use the appropriate issue template.**
+ - type: textarea
+ attributes:
+ label: "Issue"
diff --git a/.github/ISSUE_TEMPLATE/bug-report-feature-request.md b/.github/ISSUE_TEMPLATE/bug-report-feature-request.md
deleted file mode 100644
index 156c63858..000000000
--- a/.github/ISSUE_TEMPLATE/bug-report-feature-request.md
+++ /dev/null
@@ -1,35 +0,0 @@
----
-name: Bug Report / Feature Request
-about: Tech support does not belong here. You should only file an issue here if you think you have experienced an actual bug with Citra or you are requesting a feature you believe would make Citra better.
-title: ''
-labels: ''
-assignees: ''
-
----
-
-
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 000000000..944218654
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,64 @@
+name: Bug Report
+description: File a bug report
+body:
+ - type: markdown
+ attributes:
+ value: Tech support does not belong here. You should only file an issue here if you think you have experienced an actual bug with Citra.
+ - type: checkboxes
+ attributes:
+ label: Is there an existing issue for this?
+ description: Please search to see if an issue already exists for the bug you encountered.
+ options:
+ - label: I have searched the existing issues
+ required: true
+ - type: input
+ attributes:
+ label: Affected Build(s)
+ description: List the affected build(s) that this issue applies to.
+ placeholder: Nightly 1234 / Canary 1234
+ validations:
+ required: true
+ - type: textarea
+ id: issue-desc
+ attributes:
+ label: Description of Issue
+ description: A brief description of the issue encountered along with any images and/or videos.
+ validations:
+ required: true
+ - type: textarea
+ id: expected-behavior
+ attributes:
+ label: Expected Behavior
+ description: A brief description of how it is expected to work along with any images and/or videos.
+ validations:
+ required: true
+ - type: textarea
+ id: reproduction-steps
+ attributes:
+ label: Reproduction Steps
+ description: A brief explanation of how to reproduce this issue. If possible, provide a save file to aid in reproducing the issue.
+ validations:
+ required: true
+ - type: textarea
+ id: log
+ attributes:
+ label: Log File
+ description: A log file will help our developers to better diagnose and fix the issue.
+ validations:
+ required: true
+ - type: textarea
+ id: system-config
+ attributes:
+ label: System Configuration
+ placeholder: |
+ CPU: Intel i5-10400 / AMD Ryzen 5 3600
+ GPU/Driver: NVIDIA GeForce GTX 1060 (Driver 512.95)
+ RAM: 16GB DDR4-3200
+ OS: Windows 11 22H2 (Build 22621.819)
+ value: |
+ CPU:
+ GPU/Driver:
+ RAM:
+ OS:
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index e58da5502..88575a335 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -6,6 +6,3 @@ contact_links:
- name: Community forums
url: https://community.citra-emu.org
about: This is an alternative place for tech support, however helpers there are not as active.
- - name: Citra Android
- url: https://github.com/citra-emu/citra-android
- about: If you need tech support on Citra Android, you should use either of the above two options. If you want to file an issue, you should go to the Android repo linked here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 000000000..7ab8172e3
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,28 @@
+name: Feature Request
+description: File a feature request
+labels: "request"
+body:
+ - type: markdown
+ attributes:
+ value: Tech support does not belong here. You should only file an issue here if you are requesting a feature you believe would make Citra better.
+ - type: checkboxes
+ attributes:
+ label: Is there an existing issue for this?
+ description: Please search to see if an issue already exists for the feature you are requesting.
+ options:
+ - label: I have searched the existing issues
+ required: true
+ - type: textarea
+ id: what-feature
+ attributes:
+ label: What feature are you suggesting?
+ description: A brief description of the requested feature.
+ validations:
+ required: true
+ - type: textarea
+ id: why-feature
+ attributes:
+ label: Why would this feature be useful?
+ description: A brief description of why this feature would make Citra better.
+ validations:
+ required: true
diff --git a/README.md b/README.md
index 81d0f884f..402699093 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,49 @@
-**BEFORE FILING AN ISSUE, READ THE RELEVANT SECTION IN THE [CONTRIBUTING](https://github.com/citra-emu/citra/wiki/Contributing#reporting-issues) FILE!!!**
+
+
+
+
+ Citra
+
+
-# Citra
+Citra is the world's most popular, open-source, Nintendo 3DS emulator.
+
+It is written in C++ with portability in mind and builds are actively maintained for Windows, Linux, Android and macOS.
+
-[](https://github.com/citra-emu/citra/actions)
-[](https://app.bitrise.io/app/4ccd8e5720f0d13b)
-[](https://discord.gg/FAXfZV9)
+
+
+
+
+
+
+
+
-Citra is an experimental open-source Nintendo 3DS emulator/debugger written in C++. It is written with portability in mind, with builds actively maintained for Windows, Linux and macOS.
+
+ Compatibility |
+ Releases |
+ Development |
+ Building |
+ Support |
+ License
+
-Citra emulates a subset of 3DS hardware and therefore is useful for running/debugging homebrew applications, and it is also able to run many commercial games! Some of these do not run at a playable state, but we are working every day to advance the project forward. (Playable here means compatibility of at least "Okay" on our [game compatibility list](https://citra-emu.org/game).)
-Citra is licensed under the GPLv2 (or any later version). Refer to the license.txt file included. Please read the [FAQ](https://citra-emu.org/wiki/faq/) before getting started with the project.
+## Compatibility
-Check out our [website](https://citra-emu.org/)!
+The emulator is capable of running most commercial games at full speed, provided you meet the necessary hardware requirements.
+
+For a full list of games Citra supports, please visit our [Compatibility page](https://citra-emu.org/game/)
+
+Check out our [website](https://citra-emu.org/) for the latest news on exciting features, progress reports, and more!
+Please read the [FAQ](https://citra-emu.org/wiki/faq/) before getting started with the project.
Need help? Check out our [asking for help](https://citra-emu.org/help/reference/asking/) guide.
-For development discussion, please join us on our [Discord server](https://citra-emu.org/discord/) or at #citra-dev on libera.
-
-### Releases
+## Releases
Citra has two main release channels: Nightly and Canary.
@@ -28,30 +53,46 @@ The [Canary](https://github.com/citra-emu/citra-canary) build is based on the ma
Both builds can be installed with the installer provided on the [website](https://citra-emu.org/download/), but those looking for specific versions or standalone releases can find them in the release tabs of the [Nightly](https://github.com/citra-emu/citra-nightly/releases) and [Canary](https://github.com/citra-emu/citra-canary/releases) repositories.
-Currently, development and releases of the Android version are in [a separate repository](https://github.com/citra-emu/citra-android).
+Android builds can be downloaded from the Google Play Store.
A Flatpak for Citra is available on [Flathub](https://flathub.org/apps/details/org.citra_emu.citra). Details on the build process can be found in [our Flathub repository](https://github.com/flathub/org.citra_emu.citra).
-### Development
+## Development
Most of the development happens on GitHub. It's also where [our central repository](https://github.com/citra-emu/citra) is hosted.
+For development discussion, please join us on our [Discord server](https://citra-emu.org/discord/) or at #citra-dev on libera.
-If you want to contribute please take a look at the [Contributor's Guide](https://github.com/citra-emu/citra/wiki/Contributing) and [Developer Information](https://github.com/citra-emu/citra/wiki/Developer-Information). You should also contact any of the developers in the forum in order to know about the current state of the emulator because the [TODO list](https://docs.google.com/document/d/1SWIop0uBI9IW8VGg97TAtoT_CHNoP42FzYmvG1F4QDA) isn't maintained anymore.
+If you want to contribute please take a look at the [Contributor's Guide](https://github.com/citra-emu/citra/wiki/Contributing) and [Developer Information](https://github.com/citra-emu/citra/wiki/Developer-Information). You can also contact any of the developers on Discord in order to know about the current state of the emulator.
-If you want to contribute to the user interface translation, please check out the [citra project on transifex](https://www.transifex.com/citra/citra). We centralize the translation work there, and periodically upstream translations.
+If you want to contribute to the user interface translation, please check out the [Citra project on transifex](https://www.transifex.com/citra/citra). We centralize the translation work there, and periodically upstream translations.
-### Building
+## Building
* __Windows__: [Windows Build](https://github.com/citra-emu/citra/wiki/Building-For-Windows)
* __Linux__: [Linux Build](https://github.com/citra-emu/citra/wiki/Building-For-Linux)
* __macOS__: [macOS Build](https://github.com/citra-emu/citra/wiki/Building-for-macOS)
+* __Android__: [Android Build](https://github.com/citra-emu/citra/wiki/Building-for-Android)
-### Support
-We happily accept monetary donations or donated games and hardware. Please see our [donations page](https://citra-emu.org/donate/) for more information on how you can contribute to Citra. Any donations received will go towards things like:
+## Support
+
+If you enjoy the project and want to support us financially, check out our Patreon!
+
+
+
+
+
+We also happily accept donated games and hardware.
+Please see our [donations page](https://citra-emu.org/donate/) for more information on how you can contribute to Citra.
+Any donations received will go towards things like:
* 3DS consoles for developers to explore the hardware
* 3DS games for testing
* Any equipment required for homebrew
* Infrastructure setup
We also more than gladly accept used 3DS consoles! If you would like to give yours away, don't hesitate to join our [Discord server](https://citra-emu.org/discord/) and talk to bunnei.
+
+
+## License
+
+Citra is licensed under the GPLv2 (or any later version). Refer to the [LICENSE.txt](https://github.com/citra-emu/citra/blob/master/license.txt) file.
From a8e4e11cd5bbe35a12bfef7af0396c4193d784df Mon Sep 17 00:00:00 2001
From: SomeDudeOnDiscord <122324510+SomeDudeOnDiscord@users.noreply.github.com>
Date: Tue, 14 Feb 2023 16:06:11 -0500
Subject: [PATCH 09/12] Better Support for Picture-in-Picture Custom Layouts
(Based on #6127) (#6247)
---
src/citra/config.cpp | 2 +
src/citra/default_ini.h | 3 +
src/citra_qt/configuration/config.cpp | 3 +
src/common/settings.h | 1 +
src/core/frontend/emu_window.cpp | 2 +-
src/core/frontend/framebuffer_layout.cpp | 14 +-
src/core/frontend/framebuffer_layout.h | 2 +-
.../renderer_opengl/renderer_opengl.cpp | 279 ++++++++++--------
.../renderer_opengl/renderer_opengl.h | 6 +
9 files changed, 180 insertions(+), 132 deletions(-)
diff --git a/src/citra/config.cpp b/src/citra/config.cpp
index 64d33a930..cf8a1e01e 100644
--- a/src/citra/config.cpp
+++ b/src/citra/config.cpp
@@ -177,6 +177,8 @@ void Config::ReadValues() {
static_cast(sdl2_config->GetInteger("Layout", "custom_bottom_right", 360));
Settings::values.custom_bottom_bottom =
static_cast(sdl2_config->GetInteger("Layout", "custom_bottom_bottom", 480));
+ Settings::values.custom_second_layer_opacity =
+ static_cast(sdl2_config->GetInteger("Layout", "custom_second_layer_opacity", 100));
// Utility
Settings::values.dump_textures = sdl2_config->GetBoolean("Utility", "dump_textures", false);
diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h
index e84532a3c..9cc72ba09 100644
--- a/src/citra/default_ini.h
+++ b/src/citra/default_ini.h
@@ -204,6 +204,9 @@ custom_bottom_top =
custom_bottom_right =
custom_bottom_bottom =
+# Opacity of second layer when using custom layout option (bottom screen unless swapped)
+custom_second_layer_opacity =
+
# Swaps the prominent screen with the other screen.
# For example, if Single Screen is chosen, setting this to 1 will display the bottom screen instead of the top screen.
# 0 (default): Top Screen is prominent, 1: Bottom Screen is prominent
diff --git a/src/citra_qt/configuration/config.cpp b/src/citra_qt/configuration/config.cpp
index 5e5d41e83..bfccdbe18 100644
--- a/src/citra_qt/configuration/config.cpp
+++ b/src/citra_qt/configuration/config.cpp
@@ -9,6 +9,7 @@
#include
#include "citra_qt/configuration/config.h"
#include "common/file_util.h"
+#include "common/settings.h"
#include "core/frontend/mic.h"
#include "core/hle/service/service.h"
#include "input_common/main.h"
@@ -496,6 +497,7 @@ void Config::ReadLayoutValues() {
ReadBasicSetting(Settings::values.custom_bottom_top);
ReadBasicSetting(Settings::values.custom_bottom_right);
ReadBasicSetting(Settings::values.custom_bottom_bottom);
+ ReadBasicSetting(Settings::values.custom_second_layer_opacity);
}
qt_config->endGroup();
@@ -1006,6 +1008,7 @@ void Config::SaveLayoutValues() {
WriteBasicSetting(Settings::values.custom_bottom_top);
WriteBasicSetting(Settings::values.custom_bottom_right);
WriteBasicSetting(Settings::values.custom_bottom_bottom);
+ WriteBasicSetting(Settings::values.custom_second_layer_opacity);
}
qt_config->endGroup();
diff --git a/src/common/settings.h b/src/common/settings.h
index 7fec09ba0..a29123af1 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -464,6 +464,7 @@ struct Values {
Setting custom_bottom_top{240, "custom_bottom_top"};
Setting custom_bottom_right{360, "custom_bottom_right"};
Setting custom_bottom_bottom{480, "custom_bottom_bottom"};
+ Setting custom_second_layer_opacity{100, "custom_second_layer_opacity"};
SwitchableSetting bg_red{0.f, "bg_red"};
SwitchableSetting bg_green{0.f, "bg_green"};
diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp
index 2222ece02..acb81fdaa 100644
--- a/src/core/frontend/emu_window.cpp
+++ b/src/core/frontend/emu_window.cpp
@@ -178,7 +178,7 @@ void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height,
layout_option.GetValue(), Settings::values.upright_screen.GetValue());
if (Settings::values.custom_layout.GetValue() == true) {
- layout = Layout::CustomFrameLayout(width, height);
+ layout = Layout::CustomFrameLayout(width, height, Settings::values.swap_screen.GetValue());
} else {
width = std::max(width, min_size.first);
height = std::max(height, min_size.second);
diff --git a/src/core/frontend/framebuffer_layout.cpp b/src/core/frontend/framebuffer_layout.cpp
index 4b3512d6a..75f330f18 100644
--- a/src/core/frontend/framebuffer_layout.cpp
+++ b/src/core/frontend/framebuffer_layout.cpp
@@ -349,7 +349,7 @@ FramebufferLayout SeparateWindowsLayout(u32 width, u32 height, bool is_secondary
return SingleFrameLayout(width, height, is_secondary, upright);
}
-FramebufferLayout CustomFrameLayout(u32 width, u32 height) {
+FramebufferLayout CustomFrameLayout(u32 width, u32 height, bool is_swapped) {
ASSERT(width > 0);
ASSERT(height > 0);
@@ -364,8 +364,13 @@ FramebufferLayout CustomFrameLayout(u32 width, u32 height) {
Settings::values.custom_bottom_right.GetValue(),
Settings::values.custom_bottom_bottom.GetValue()};
- res.top_screen = top_screen;
- res.bottom_screen = bot_screen;
+ if (is_swapped) {
+ res.top_screen = bot_screen;
+ res.bottom_screen = top_screen;
+ } else {
+ res.top_screen = top_screen;
+ res.bottom_screen = bot_screen;
+ }
return res;
}
@@ -375,7 +380,8 @@ FramebufferLayout FrameLayoutFromResolutionScale(u32 res_scale, bool is_secondar
layout = CustomFrameLayout(std::max(Settings::values.custom_top_right.GetValue(),
Settings::values.custom_bottom_right.GetValue()),
std::max(Settings::values.custom_top_bottom.GetValue(),
- Settings::values.custom_bottom_bottom.GetValue()));
+ Settings::values.custom_bottom_bottom.GetValue()),
+ Settings::values.swap_screen.GetValue());
} else {
int width, height;
switch (Settings::values.layout_option.GetValue()) {
diff --git a/src/core/frontend/framebuffer_layout.h b/src/core/frontend/framebuffer_layout.h
index 92b43f285..763262663 100644
--- a/src/core/frontend/framebuffer_layout.h
+++ b/src/core/frontend/framebuffer_layout.h
@@ -114,7 +114,7 @@ FramebufferLayout SeparateWindowsLayout(u32 width, u32 height, bool is_secondary
* @param height Window framebuffer height in pixels
* @return Newly created FramebufferLayout object with default screen regions initialized
*/
-FramebufferLayout CustomFrameLayout(u32 width, u32 height);
+FramebufferLayout CustomFrameLayout(u32 width, u32 height, bool is_swapped);
/**
* Convenience method to get frame layout by resolution scale
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 5b8b7f060..89e58a9dc 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -1002,134 +1002,161 @@ void RendererOpenGL::DrawScreens(const Layout::FramebufferLayout& layout, bool f
}
glUniform1i(uniform_layer, 0);
- if (layout.top_screen_enabled) {
- if (layout.is_rotated) {
- if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) {
- int eye = static_cast(Settings::values.mono_render_option.GetValue());
- DrawSingleScreenRotated(screen_infos[eye], (float)top_screen.left,
- (float)top_screen.top, (float)top_screen.GetWidth(),
- (float)top_screen.GetHeight());
- } else if (Settings::values.render_3d.GetValue() ==
- Settings::StereoRenderOption::SideBySide) {
- DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left / 2,
- (float)top_screen.top, (float)top_screen.GetWidth() / 2,
- (float)top_screen.GetHeight());
- glUniform1i(uniform_layer, 1);
- DrawSingleScreenRotated(screen_infos[1],
- ((float)top_screen.left / 2) + ((float)layout.width / 2),
- (float)top_screen.top, (float)top_screen.GetWidth() / 2,
- (float)top_screen.GetHeight());
- } else if (Settings::values.render_3d.GetValue() ==
- Settings::StereoRenderOption::CardboardVR) {
- DrawSingleScreenRotated(screen_infos[0], layout.top_screen.left,
- layout.top_screen.top, layout.top_screen.GetWidth(),
- layout.top_screen.GetHeight());
- glUniform1i(uniform_layer, 1);
- DrawSingleScreenRotated(screen_infos[1],
- layout.cardboard.top_screen_right_eye +
- ((float)layout.width / 2),
- layout.top_screen.top, layout.top_screen.GetWidth(),
- layout.top_screen.GetHeight());
- } else if (stereo_single_screen) {
- DrawSingleScreenStereoRotated(
- screen_infos[0], screen_infos[1], (float)top_screen.left, (float)top_screen.top,
- (float)top_screen.GetWidth(), (float)top_screen.GetHeight());
- }
- } else {
- if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) {
- int eye = static_cast(Settings::values.mono_render_option.GetValue());
- DrawSingleScreen(screen_infos[eye], (float)top_screen.left, (float)top_screen.top,
- (float)top_screen.GetWidth(), (float)top_screen.GetHeight());
- } else if (Settings::values.render_3d.GetValue() ==
- Settings::StereoRenderOption::SideBySide) {
- DrawSingleScreen(screen_infos[0], (float)top_screen.left / 2, (float)top_screen.top,
- (float)top_screen.GetWidth() / 2, (float)top_screen.GetHeight());
- glUniform1i(uniform_layer, 1);
- DrawSingleScreen(screen_infos[1],
- ((float)top_screen.left / 2) + ((float)layout.width / 2),
- (float)top_screen.top, (float)top_screen.GetWidth() / 2,
- (float)top_screen.GetHeight());
- } else if (Settings::values.render_3d.GetValue() ==
- Settings::StereoRenderOption::CardboardVR) {
- DrawSingleScreen(screen_infos[0], layout.top_screen.left, layout.top_screen.top,
- layout.top_screen.GetWidth(), layout.top_screen.GetHeight());
- glUniform1i(uniform_layer, 1);
- DrawSingleScreen(screen_infos[1],
- layout.cardboard.top_screen_right_eye + ((float)layout.width / 2),
- layout.top_screen.top, layout.top_screen.GetWidth(),
- layout.top_screen.GetHeight());
- } else if (stereo_single_screen) {
- DrawSingleScreenStereo(screen_infos[0], screen_infos[1], (float)top_screen.left,
- (float)top_screen.top, (float)top_screen.GetWidth(),
- (float)top_screen.GetHeight());
- }
+ if (!Settings::values.swap_screen) {
+ DrawTopScreen(layout, top_screen, stereo_single_screen);
+ glUniform1i(uniform_layer, 0);
+ ApplySecondLayerOpacity();
+ DrawBottomScreen(layout, bottom_screen, stereo_single_screen);
+ } else {
+ DrawBottomScreen(layout, bottom_screen, stereo_single_screen);
+ glUniform1i(uniform_layer, 0);
+ ApplySecondLayerOpacity();
+ DrawTopScreen(layout, top_screen, stereo_single_screen);
+ }
+ state.blend.enabled = false;
+}
+
+void RendererOpenGL::ApplySecondLayerOpacity() {
+ if (Settings::values.custom_layout &&
+ Settings::values.custom_second_layer_opacity.GetValue() < 100) {
+ state.blend.enabled = true;
+ state.blend.src_rgb_func = GL_CONSTANT_ALPHA;
+ state.blend.src_a_func = GL_CONSTANT_ALPHA;
+ state.blend.dst_a_func = GL_ONE_MINUS_CONSTANT_ALPHA;
+ state.blend.dst_rgb_func = GL_ONE_MINUS_CONSTANT_ALPHA;
+ state.blend.color.alpha = Settings::values.custom_second_layer_opacity.GetValue() / 100.0f;
+ }
+}
+
+void RendererOpenGL::DrawTopScreen(const Layout::FramebufferLayout& layout,
+ const Common::Rectangle& top_screen,
+ const bool stereo_single_screen) {
+ if (!layout.top_screen_enabled) {
+ return;
+ }
+
+ if (layout.is_rotated) {
+ if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) {
+ DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left, (float)top_screen.top,
+ (float)top_screen.GetWidth(), (float)top_screen.GetHeight());
+ } else if (Settings::values.render_3d.GetValue() ==
+ Settings::StereoRenderOption::SideBySide) {
+ DrawSingleScreenRotated(screen_infos[0], (float)top_screen.left / 2,
+ (float)top_screen.top, (float)top_screen.GetWidth() / 2,
+ (float)top_screen.GetHeight());
+ glUniform1i(uniform_layer, 1);
+ DrawSingleScreenRotated(screen_infos[1],
+ ((float)top_screen.left / 2) + ((float)layout.width / 2),
+ (float)top_screen.top, (float)top_screen.GetWidth() / 2,
+ (float)top_screen.GetHeight());
+ } else if (Settings::values.render_3d.GetValue() ==
+ Settings::StereoRenderOption::CardboardVR) {
+ DrawSingleScreenRotated(screen_infos[0], layout.top_screen.left, layout.top_screen.top,
+ layout.top_screen.GetWidth(), layout.top_screen.GetHeight());
+ glUniform1i(uniform_layer, 1);
+ DrawSingleScreenRotated(
+ screen_infos[1], layout.cardboard.top_screen_right_eye + ((float)layout.width / 2),
+ layout.top_screen.top, layout.top_screen.GetWidth(), layout.top_screen.GetHeight());
+ } else if (stereo_single_screen) {
+ DrawSingleScreenStereoRotated(screen_infos[0], screen_infos[1], (float)top_screen.left,
+ (float)top_screen.top, (float)top_screen.GetWidth(),
+ (float)top_screen.GetHeight());
+ }
+ } else {
+ if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) {
+ DrawSingleScreen(screen_infos[0], (float)top_screen.left, (float)top_screen.top,
+ (float)top_screen.GetWidth(), (float)top_screen.GetHeight());
+ } else if (Settings::values.render_3d.GetValue() ==
+ Settings::StereoRenderOption::SideBySide) {
+ DrawSingleScreen(screen_infos[0], (float)top_screen.left / 2, (float)top_screen.top,
+ (float)top_screen.GetWidth() / 2, (float)top_screen.GetHeight());
+ glUniform1i(uniform_layer, 1);
+ DrawSingleScreen(screen_infos[1],
+ ((float)top_screen.left / 2) + ((float)layout.width / 2),
+ (float)top_screen.top, (float)top_screen.GetWidth() / 2,
+ (float)top_screen.GetHeight());
+ } else if (Settings::values.render_3d.GetValue() ==
+ Settings::StereoRenderOption::CardboardVR) {
+ DrawSingleScreen(screen_infos[0], layout.top_screen.left, layout.top_screen.top,
+ layout.top_screen.GetWidth(), layout.top_screen.GetHeight());
+ glUniform1i(uniform_layer, 1);
+ DrawSingleScreen(
+ screen_infos[1], layout.cardboard.top_screen_right_eye + ((float)layout.width / 2),
+ layout.top_screen.top, layout.top_screen.GetWidth(), layout.top_screen.GetHeight());
+ } else if (stereo_single_screen) {
+ DrawSingleScreenStereo(screen_infos[0], screen_infos[1], (float)top_screen.left,
+ (float)top_screen.top, (float)top_screen.GetWidth(),
+ (float)top_screen.GetHeight());
}
}
- glUniform1i(uniform_layer, 0);
- if (layout.bottom_screen_enabled) {
- if (layout.is_rotated) {
- if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) {
- DrawSingleScreenRotated(screen_infos[2], (float)bottom_screen.left,
- (float)bottom_screen.top, (float)bottom_screen.GetWidth(),
- (float)bottom_screen.GetHeight());
- } else if (Settings::values.render_3d.GetValue() ==
- Settings::StereoRenderOption::SideBySide) {
- DrawSingleScreenRotated(
- screen_infos[2], (float)bottom_screen.left / 2, (float)bottom_screen.top,
- (float)bottom_screen.GetWidth() / 2, (float)bottom_screen.GetHeight());
- glUniform1i(uniform_layer, 1);
- DrawSingleScreenRotated(
- screen_infos[2], ((float)bottom_screen.left / 2) + ((float)layout.width / 2),
- (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2,
- (float)bottom_screen.GetHeight());
- } else if (Settings::values.render_3d.GetValue() ==
- Settings::StereoRenderOption::CardboardVR) {
- DrawSingleScreenRotated(screen_infos[2], layout.bottom_screen.left,
- layout.bottom_screen.top, layout.bottom_screen.GetWidth(),
- layout.bottom_screen.GetHeight());
- glUniform1i(uniform_layer, 1);
- DrawSingleScreenRotated(screen_infos[2],
- layout.cardboard.bottom_screen_right_eye +
- ((float)layout.width / 2),
- layout.bottom_screen.top, layout.bottom_screen.GetWidth(),
- layout.bottom_screen.GetHeight());
- } else if (stereo_single_screen) {
- DrawSingleScreenStereoRotated(screen_infos[2], screen_infos[2],
- (float)bottom_screen.left, (float)bottom_screen.top,
- (float)bottom_screen.GetWidth(),
- (float)bottom_screen.GetHeight());
- }
- } else {
- if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) {
- DrawSingleScreen(screen_infos[2], (float)bottom_screen.left,
- (float)bottom_screen.top, (float)bottom_screen.GetWidth(),
- (float)bottom_screen.GetHeight());
- } else if (Settings::values.render_3d.GetValue() ==
- Settings::StereoRenderOption::SideBySide) {
- DrawSingleScreen(screen_infos[2], (float)bottom_screen.left / 2,
- (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2,
- (float)bottom_screen.GetHeight());
- glUniform1i(uniform_layer, 1);
- DrawSingleScreen(screen_infos[2],
- ((float)bottom_screen.left / 2) + ((float)layout.width / 2),
- (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2,
- (float)bottom_screen.GetHeight());
- } else if (Settings::values.render_3d.GetValue() ==
- Settings::StereoRenderOption::CardboardVR) {
- DrawSingleScreen(screen_infos[2], layout.bottom_screen.left,
- layout.bottom_screen.top, layout.bottom_screen.GetWidth(),
- layout.bottom_screen.GetHeight());
- glUniform1i(uniform_layer, 1);
- DrawSingleScreen(screen_infos[2],
- layout.cardboard.bottom_screen_right_eye +
- ((float)layout.width / 2),
- layout.bottom_screen.top, layout.bottom_screen.GetWidth(),
- layout.bottom_screen.GetHeight());
- } else if (stereo_single_screen) {
- DrawSingleScreenStereo(screen_infos[2], screen_infos[2], (float)bottom_screen.left,
- (float)bottom_screen.top, (float)bottom_screen.GetWidth(),
- (float)bottom_screen.GetHeight());
- }
+}
+
+void RendererOpenGL::DrawBottomScreen(const Layout::FramebufferLayout& layout,
+ const Common::Rectangle& bottom_screen,
+ const bool stereo_single_screen) {
+ if (!layout.bottom_screen_enabled) {
+ return;
+ }
+
+ if (layout.is_rotated) {
+ if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) {
+ DrawSingleScreenRotated(screen_infos[2], (float)bottom_screen.left,
+ (float)bottom_screen.top, (float)bottom_screen.GetWidth(),
+ (float)bottom_screen.GetHeight());
+ } else if (Settings::values.render_3d.GetValue() ==
+ Settings::StereoRenderOption::SideBySide) {
+ DrawSingleScreenRotated(screen_infos[2], (float)bottom_screen.left / 2,
+ (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2,
+ (float)bottom_screen.GetHeight());
+ glUniform1i(uniform_layer, 1);
+ DrawSingleScreenRotated(screen_infos[2],
+ ((float)bottom_screen.left / 2) + ((float)layout.width / 2),
+ (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2,
+ (float)bottom_screen.GetHeight());
+ } else if (Settings::values.render_3d.GetValue() ==
+ Settings::StereoRenderOption::CardboardVR) {
+ DrawSingleScreenRotated(screen_infos[2], layout.bottom_screen.left,
+ layout.bottom_screen.top, layout.bottom_screen.GetWidth(),
+ layout.bottom_screen.GetHeight());
+ glUniform1i(uniform_layer, 1);
+ DrawSingleScreenRotated(screen_infos[2],
+ layout.cardboard.bottom_screen_right_eye +
+ ((float)layout.width / 2),
+ layout.bottom_screen.top, layout.bottom_screen.GetWidth(),
+ layout.bottom_screen.GetHeight());
+ } else if (stereo_single_screen) {
+ DrawSingleScreenStereoRotated(screen_infos[2], screen_infos[2],
+ (float)bottom_screen.left, (float)bottom_screen.top,
+ (float)bottom_screen.GetWidth(),
+ (float)bottom_screen.GetHeight());
+ }
+ } else {
+ if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Off) {
+ DrawSingleScreen(screen_infos[2], (float)bottom_screen.left, (float)bottom_screen.top,
+ (float)bottom_screen.GetWidth(), (float)bottom_screen.GetHeight());
+ } else if (Settings::values.render_3d.GetValue() ==
+ Settings::StereoRenderOption::SideBySide) {
+ DrawSingleScreen(screen_infos[2], (float)bottom_screen.left / 2,
+ (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2,
+ (float)bottom_screen.GetHeight());
+ glUniform1i(uniform_layer, 1);
+ DrawSingleScreen(screen_infos[2],
+ ((float)bottom_screen.left / 2) + ((float)layout.width / 2),
+ (float)bottom_screen.top, (float)bottom_screen.GetWidth() / 2,
+ (float)bottom_screen.GetHeight());
+ } else if (Settings::values.render_3d.GetValue() ==
+ Settings::StereoRenderOption::CardboardVR) {
+ DrawSingleScreen(screen_infos[2], layout.bottom_screen.left, layout.bottom_screen.top,
+ layout.bottom_screen.GetWidth(), layout.bottom_screen.GetHeight());
+ glUniform1i(uniform_layer, 1);
+ DrawSingleScreen(screen_infos[2],
+ layout.cardboard.bottom_screen_right_eye + ((float)layout.width / 2),
+ layout.bottom_screen.top, layout.bottom_screen.GetWidth(),
+ layout.bottom_screen.GetHeight());
+ } else if (stereo_single_screen) {
+ DrawSingleScreenStereo(screen_infos[2], screen_infos[2], (float)bottom_screen.left,
+ (float)bottom_screen.top, (float)bottom_screen.GetWidth(),
+ (float)bottom_screen.GetHeight());
}
}
}
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h
index 0cd2e7089..a168b055e 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.h
+++ b/src/video_core/renderer_opengl/renderer_opengl.h
@@ -89,6 +89,12 @@ private:
void ConfigureFramebufferTexture(TextureInfo& texture,
const GPU::Regs::FramebufferConfig& framebuffer);
void DrawScreens(const Layout::FramebufferLayout& layout, bool flipped);
+ void ApplySecondLayerOpacity();
+ void DrawBottomScreen(const Layout::FramebufferLayout& layout,
+ const Common::Rectangle& bottom_screen,
+ const bool stereo_single_screen);
+ void DrawTopScreen(const Layout::FramebufferLayout& layout,
+ const Common::Rectangle& top_screen, const bool stereo_single_screen);
void DrawSingleScreenRotated(const ScreenInfo& screen_info, float x, float y, float w, float h);
void DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h);
void DrawSingleScreenStereoRotated(const ScreenInfo& screen_info_l,
From 68162c29b479fcb6567bc2ba86010b0b6b1b46e0 Mon Sep 17 00:00:00 2001
From: Steveice10 <1269164+Steveice10@users.noreply.github.com>
Date: Tue, 14 Feb 2023 13:10:07 -0800
Subject: [PATCH 10/12] cfg: Initialize backlight controls config blocks.
(#6291)
---
src/core/hle/service/cfg/cfg.cpp | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp
index 0b37c5d56..14ab57f49 100644
--- a/src/core/hle/service/cfg/cfg.cpp
+++ b/src/core/hle/service/cfg/cfg.cpp
@@ -153,6 +153,20 @@ struct ConsoleCountryInfo {
u8 country_code; ///< The country code of the console
};
static_assert(sizeof(ConsoleCountryInfo) == 4, "ConsoleCountryInfo must be exactly 4 bytes");
+
+struct BacklightControls {
+ u8 power_saving_enabled; ///< Whether power saving mode is enabled.
+ u8 brightness_level; ///< The configured brightness level.
+};
+static_assert(sizeof(BacklightControls) == 2, "BacklightControls must be exactly 2 bytes");
+
+struct New3dsBacklightControls {
+ u8 unknown_1[4]; ///< Unknown data
+ u8 auto_brightness_enabled; ///< Whether auto brightness is enabled.
+ u8 unknown_2[3]; ///< Unknown data
+};
+static_assert(sizeof(New3dsBacklightControls) == 8,
+ "New3dsBacklightControls must be exactly 8 bytes");
} // namespace
constexpr EULAVersion MAX_EULA_VERSION{0x7F, 0x7F};
@@ -166,6 +180,8 @@ constexpr u8 UNITED_STATES_COUNTRY_ID = 49;
constexpr u8 WASHINGTON_DC_STATE_ID = 2;
/// TODO(Subv): Find what the other bytes are
constexpr ConsoleCountryInfo COUNTRY_INFO{{0, 0}, WASHINGTON_DC_STATE_ID, UNITED_STATES_COUNTRY_ID};
+constexpr BacklightControls BACKLIGHT_CONTROLS{0, 2};
+constexpr New3dsBacklightControls NEW_3DS_BACKLIGHT_CONTROLS{{0, 0, 0, 0}, 0, {0, 0, 0}};
/**
* TODO(Subv): Find out what this actually is, these values fix some NaN uniforms in some games,
@@ -508,11 +524,23 @@ ResultCode Module::FormatConfig() {
if (!res.IsSuccess())
return res;
+ // 0x00050001 - Backlight controls
+ res = CreateConfigInfoBlk(BacklightControlsBlockID, sizeof(BACKLIGHT_CONTROLS), 0xC,
+ &BACKLIGHT_CONTROLS);
+ if (!res.IsSuccess())
+ return res;
+
res = CreateConfigInfoBlk(StereoCameraSettingsBlockID, sizeof(STEREO_CAMERA_SETTINGS), 0xE,
STEREO_CAMERA_SETTINGS.data());
if (!res.IsSuccess())
return res;
+ // 0x00050009 - New 3DS backlight controls
+ res = CreateConfigInfoBlk(BacklightControlNew3dsBlockID, sizeof(NEW_3DS_BACKLIGHT_CONTROLS),
+ 0xC, &NEW_3DS_BACKLIGHT_CONTROLS);
+ if (!res.IsSuccess())
+ return res;
+
res = CreateConfigInfoBlk(SoundOutputModeBlockID, sizeof(SOUND_OUTPUT_MODE), 0xE,
&SOUND_OUTPUT_MODE);
if (!res.IsSuccess())
From 5215468ff61cc7e1f1773db4068aa84303e2f298 Mon Sep 17 00:00:00 2001
From: SachinVin <26602104+SachinVin@users.noreply.github.com>
Date: Wed, 15 Feb 2023 02:49:45 +0530
Subject: [PATCH 11/12] core\file_sys\archive_sdmc.cpp: Log error message if
file failed to open. (#6284)
---
src/common/misc.cpp | 11 +++++++----
src/core/file_sys/archive_sdmc.cpp | 2 +-
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/src/common/misc.cpp b/src/common/misc.cpp
index 68cb86cd1..59258749b 100644
--- a/src/common/misc.cpp
+++ b/src/common/misc.cpp
@@ -16,16 +16,19 @@
// Call directly after the command or use the error num.
// This function might change the error code.
std::string GetLastErrorMsg() {
- static const std::size_t buff_size = 255;
+ constexpr std::size_t buff_size = 255;
char err_str[buff_size];
+ std::size_t msg_len;
#ifdef _WIN32
- FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, GetLastError(),
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err_str, buff_size, nullptr);
+ msg_len =
+ FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), err_str, buff_size, nullptr);
#else
// Thread safe (XSI-compliant)
strerror_r(errno, err_str, buff_size);
+ msg_len = strnlen(err_str, buff_size);
#endif
- return std::string(err_str, buff_size);
+ return std::string(err_str, msg_len);
}
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp
index a68e6bf34..9164d48c6 100644
--- a/src/core/file_sys/archive_sdmc.cpp
+++ b/src/core/file_sys/archive_sdmc.cpp
@@ -106,7 +106,7 @@ ResultVal> SDMCArchive::OpenFileBase(const Path& pa
FileUtil::IOFile file(full_path, mode.write_flag ? "r+b" : "rb");
if (!file.IsOpen()) {
- LOG_CRITICAL(Service_FS, "(unreachable) Unknown error opening {}", full_path);
+ LOG_CRITICAL(Service_FS, "Error opening {}: {}", full_path, GetLastErrorMsg());
return ERROR_NOT_FOUND;
}
From 5aa80873e2c24719ef0081d638179e4e52ed04b3 Mon Sep 17 00:00:00 2001
From: Steveice10 <1269164+Steveice10@users.noreply.github.com>
Date: Wed, 15 Feb 2023 12:24:54 -0800
Subject: [PATCH 12/12] qt: Enable application options for system applications.
(#6286)
---
src/citra_qt/game_list.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/citra_qt/game_list.cpp b/src/citra_qt/game_list.cpp
index 4a3771bf8..f9dbcdfee 100644
--- a/src/citra_qt/game_list.cpp
+++ b/src/citra_qt/game_list.cpp
@@ -501,8 +501,8 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, u64 progra
QAction* delete_opengl_disk_shader_cache =
shader_menu->addAction(tr("Delete OpenGL Shader Cache"));
- const bool is_application =
- 0x0004000000000000 <= program_id && program_id <= 0x00040000FFFFFFFF;
+ const u32 program_id_high = (program_id >> 32) & 0xFFFFFFFF;
+ const bool is_application = program_id_high == 0x00040000 || program_id_high == 0x00040010;
bool opengl_cache_exists = false;
ForEachOpenGLCacheFile(