diff options
69 files changed, 740 insertions, 775 deletions
| diff --git a/CMakeLists.txt b/CMakeLists.txt index dcd4011a5..fe12f3d23 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -639,14 +639,18 @@ endif()  # =========================  # Install freedesktop.org metadata files, following those specifications: -# http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html -# http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html -# http://standards.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html +# https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html +# https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html +# https://specifications.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html +# https://www.freedesktop.org/software/appstream/docs/  if(ENABLE_QT AND UNIX AND NOT APPLE) -    install(FILES "${PROJECT_SOURCE_DIR}/dist/yuzu.desktop" -            DESTINATION "${CMAKE_INSTALL_PREFIX}/share/applications") -    install(FILES "${PROJECT_SOURCE_DIR}/dist/yuzu.svg" -            DESTINATION "${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps") -    install(FILES "${PROJECT_SOURCE_DIR}/dist/yuzu.xml" -            DESTINATION "${CMAKE_INSTALL_PREFIX}/share/mime/packages") +    install(FILES "dist/org.yuzu_emu.yuzu.desktop" +            DESTINATION "share/applications") +    install(FILES "dist/yuzu.svg" +            DESTINATION "share/icons/hicolor/scalable/apps" +            RENAME "org.yuzu_emu.yuzu.svg") +    install(FILES "dist/org.yuzu_emu.yuzu.xml" +            DESTINATION "share/mime/packages") +    install(FILES "dist/org.yuzu_emu.yuzu.metainfo.xml" +            DESTINATION "share/metainfo")  endif() diff --git a/dist/yuzu.desktop b/dist/org.yuzu_emu.yuzu.desktop index 6cc0704d2..3652a3abc 100644 --- a/dist/yuzu.desktop +++ b/dist/org.yuzu_emu.yuzu.desktop @@ -4,9 +4,9 @@ Type=Application  Name=yuzu  GenericName=Switch Emulator  Comment=Nintendo Switch video game console emulator -Icon=yuzu +Icon=org.yuzu_emu.yuzu  TryExec=yuzu  Exec=yuzu %f  Categories=Game;Emulator;Qt;  MimeType=application/x-nx-nro;application/x-nx-nso;application/x-nx-nsp;application/x-nx-xci; -Keywords=Switch;Nintendo;
\ No newline at end of file +Keywords=Nintendo;Switch; diff --git a/dist/org.yuzu_emu.yuzu.metainfo.xml b/dist/org.yuzu_emu.yuzu.metainfo.xml new file mode 100644 index 000000000..5f366137b --- /dev/null +++ b/dist/org.yuzu_emu.yuzu.metainfo.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<component type="desktop-application"> +  <id>org.yuzu_emu.yuzu</id> +  <metadata_license>CC0-1.0</metadata_license> +  <name>yuzu</name> +  <summary>Nintendo Switch emulator</summary> +  <description> +    <p>yuzu is the world's most popular, open-source, Nintendo Switch emulator — started by the creators of Citra.</p> +    <p>The emulator is capable of running most commercial games at full speed, provided you meet the necessary hardware requirements.</p> +    <p>For a full list of games yuzu support, please visit our Compatibility page.</p> +    <p>Check out our website for the latest news on exciting features, monthly progress reports, and more!</p> +  </description> +  <categories> +    <category>Game</category> +    <category>Emulator</category> +  </categories> +  <keywords> +    <keyword>switch</keyword> +    <keyword>emulator</keyword> +  </keywords> +  <url type="homepage">https://yuzu-emu.org/</url> +  <url type="bugtracker">https://github.com/yuzu-emu/yuzu/issues</url> +  <url type="faq">https://yuzu-emu.org/wiki/faq/</url> +  <url type="help">https://yuzu-emu.org/wiki/home/</url> +  <url type="donation">https://yuzu-emu.org/donate/</url> +  <url type="translate">https://www.transifex.com/projects/p/yuzu</url> +  <url type="contact">https://community.citra-emu.org/</url> +  <url type="vcs-browser">https://github.com/yuzu-emu/yuzu</url> +  <url type="contribute">https://yuzu-emu.org/wiki/contributing/</url> +  <launchable type="desktop-id">org.yuzu_emu.yuzu.desktop</launchable> +  <provides> +    <binary>yuzu</binary> +    <binary>yuzu-cmd</binary> +  </provides> +  <requires> +    <memory>8192</memory> +  </requires> +  <recommends> +    <memory>16384</memory> +  </recommends> +  <project_license>GPL-3.0-or-later</project_license> +  <developer_name>yuzu Emulator Team</developer_name> +  <content_rating type="oars-1.0"/> +  <screenshots> +    <screenshot type="default">https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/001-Super%20Mario%20Odyssey%20.png</screenshot> +    <screenshot>https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/004-The%20Legend%20of%20Zelda%20Skyward%20Sword%20HD.png</screenshot> +    <screenshot>https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/007-Pokemon%20Sword.png</screenshot> +    <screenshot>https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/010-Hyrule%20Warriors%20Age%20of%20Calamity.png</screenshot> +    <screenshot>https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/039-Pok%C3%A9mon%20Mystery%20Dungeon%20Rescue%20Team%20DX.png.png.png</screenshot> +  </screenshots> +</component> diff --git a/dist/yuzu.xml b/dist/org.yuzu_emu.yuzu.xml index dd1e30a6b..b52acecc4 100644 --- a/dist/yuzu.xml +++ b/dist/org.yuzu_emu.yuzu.xml @@ -3,7 +3,7 @@      <mime-type type="application/x-nx-nro">          <comment>Nintendo Switch homebrew executable</comment>          <acronym>NRO</acronym> -        <icon name="yuzu"/> +        <icon name="org.yuzu_emu.yuzu"/>          <glob pattern="*.nro"/>          <magic><match value="NRO" type="string" offset="16"/></magic>      </mime-type> @@ -11,7 +11,7 @@      <mime-type type="application/x-nx-nso">          <comment>Nintendo Switch homebrew executable</comment>          <acronym>NSO</acronym> -        <icon name="yuzu"/> +        <icon name="org.yuzu_emu.yuzu"/>          <glob pattern="*.nso"/>          <magic><match value="NSO" type="string" offset="0"/></magic>      </mime-type> @@ -19,7 +19,7 @@      <mime-type type="application/x-nx-nsp">          <comment>Nintendo Switch Package</comment>          <acronym>NSP</acronym> -        <icon name="yuzu"/> +        <icon name="org.yuzu_emu.yuzu"/>          <glob pattern="*.nsp"/>          <magic><match value="PFS" type="string" offset="0"/></magic>      </mime-type> @@ -27,7 +27,7 @@      <mime-type type="application/x-nx-xci">          <comment>Nintendo Switch Card Image</comment>          <acronym>XCI</acronym> -        <icon name="yuzu"/> +        <icon name="org.yuzu_emu.yuzu"/>          <glob pattern="*.xci"/>      </mime-type> -</mime-info>
\ No newline at end of file +</mime-info> diff --git a/externals/sirit b/externals/sirit -Subproject a39596358a3a5488c06554c0c15184a6af71e43 +Subproject b8f133bf631ace5a613bbd7e8329300358cacbd diff --git a/src/common/assert.h b/src/common/assert.h index 33060d865..dbfd8abaf 100644 --- a/src/common/assert.h +++ b/src/common/assert.h @@ -1,6 +1,6 @@ -// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later  #pragma once diff --git a/src/common/bit_field.h b/src/common/bit_field.h index 7f8620e7d..16d805694 100644 --- a/src/common/bit_field.h +++ b/src/common/bit_field.h @@ -1,32 +1,6 @@ -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -// Copyright 2014 Tony Wasserka -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -//     * Redistributions of source code must retain the above copyright -//       notice, this list of conditions and the following disclaimer. -//     * Redistributions in binary form must reproduce the above copyright -//       notice, this list of conditions and the following disclaimer in the -//       documentation and/or other materials provided with the distribution. -//     * Neither the name of the owner nor the names of its contributors may -//       be used to endorse or promote products derived from this software -//       without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// SPDX-FileCopyrightText: 2014 Tony Wasserka +// SPDX-FileCopyrightText: 2014 Dolphin Emulator Project +// SPDX-License-Identifier: BSD-3-Clause AND GPL-2.0-or-later  #pragma once diff --git a/src/common/cityhash.cpp b/src/common/cityhash.cpp index 66218fc21..d50ac9e6c 100644 --- a/src/common/cityhash.cpp +++ b/src/common/cityhash.cpp @@ -1,23 +1,8 @@ -// Copyright (c) 2011 Google, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// +// SPDX-FileCopyrightText: 2011 Google, Inc. +// SPDX-FileContributor: Geoff Pike +// SPDX-FileContributor: Jyrki Alakuijala +// SPDX-License-Identifier: MIT +  // CityHash, by Geoff Pike and Jyrki Alakuijala  //  // This file provides CityHash64() and related functions. diff --git a/src/common/cityhash.h b/src/common/cityhash.h index d74fc7639..627ba81cd 100644 --- a/src/common/cityhash.h +++ b/src/common/cityhash.h @@ -1,23 +1,8 @@ -// Copyright (c) 2011 Google, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// +// SPDX-FileCopyrightText: 2011 Google, Inc. +// SPDX-FileContributor: Geoff Pike +// SPDX-FileContributor: Jyrki Alakuijala +// SPDX-License-Identifier: MIT +  // CityHash, by Geoff Pike and Jyrki Alakuijala  //  // http://code.google.com/p/cityhash/ diff --git a/src/common/common_types.h b/src/common/common_types.h index 99bffc460..0fc225aff 100644 --- a/src/common/common_types.h +++ b/src/common/common_types.h @@ -1,3 +1,7 @@ +// SPDX-FileCopyrightText: 2012 Gekko Emulator +// SPDX-FileContributor: ShizZy <shizzy247@gmail.com> +// SPDX-License-Identifier: GPL-2.0-or-later +  /**   * Copyright (C) 2005-2012 Gekko Emulator   * diff --git a/src/common/dynamic_library.cpp b/src/common/dynamic_library.cpp index 11003e1d6..054277a2b 100644 --- a/src/common/dynamic_library.cpp +++ b/src/common/dynamic_library.cpp @@ -1,6 +1,5 @@ -// Copyright 2019 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2019 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later  #include <string>  #include <utility> diff --git a/src/common/dynamic_library.h b/src/common/dynamic_library.h index 3512da940..f42bdf441 100644 --- a/src/common/dynamic_library.h +++ b/src/common/dynamic_library.h @@ -1,6 +1,5 @@ -// Copyright 2019 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2019 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later  #pragma once diff --git a/src/common/hex_util.cpp b/src/common/hex_util.cpp index 74f52dd11..07053295c 100644 --- a/src/common/hex_util.cpp +++ b/src/common/hex_util.cpp @@ -1,6 +1,6 @@ -// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later  #include "common/hex_util.h" diff --git a/src/common/hex_util.h b/src/common/hex_util.h index 323c8fb33..a00904939 100644 --- a/src/common/hex_util.h +++ b/src/common/hex_util.h @@ -1,6 +1,6 @@ -// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later  #pragma once diff --git a/src/common/math_util.h b/src/common/math_util.h index 54485bf53..1f5928c15 100644 --- a/src/common/math_util.h +++ b/src/common/math_util.h @@ -1,6 +1,6 @@ -// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later  #pragma once diff --git a/src/common/settings.cpp b/src/common/settings.cpp index fdc012355..9a9c74a70 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -10,7 +10,7 @@  namespace Settings { -Values values = {}; +Values values;  static bool configuring_global = true;  std::string GetTimeZoneString() { diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 3695dae4d..703aa5db8 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -1,6 +1,6 @@ -// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later  #include <algorithm>  #include <cctype> diff --git a/src/common/string_util.h b/src/common/string_util.h index f0dd632ee..a33830aec 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h @@ -1,6 +1,6 @@ -// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later  #pragma once diff --git a/src/common/swap.h b/src/common/swap.h index a80e191dc..037b82781 100644 --- a/src/common/swap.h +++ b/src/common/swap.h @@ -1,16 +1,6 @@ -// Copyright (c) 2012- PPSSPP Project / Dolphin Project. - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, version 2.0 or later versions. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -// GNU General Public License 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ +// SPDX-FileCopyrightText: 2012 PPSSPP Project +// SPDX-FileCopyrightText: 2012 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later  // Official git repository and contact information can be found at  // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. diff --git a/src/common/thread.cpp b/src/common/thread.cpp index 946a1114d..f932a7290 100644 --- a/src/common/thread.cpp +++ b/src/common/thread.cpp @@ -1,6 +1,6 @@ -// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later  #include <string> diff --git a/src/common/thread.h b/src/common/thread.h index 626609372..a63122516 100644 --- a/src/common/thread.h +++ b/src/common/thread.h @@ -1,6 +1,6 @@ -// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later  #pragma once diff --git a/src/common/thread_queue_list.h b/src/common/thread_queue_list.h index def9e5d8d..ce48cec92 100644 --- a/src/common/thread_queue_list.h +++ b/src/common/thread_queue_list.h @@ -1,6 +1,6 @@ -// Copyright 2014 Citra Emulator Project / PPSSPP Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2012 PPSSPP Project +// SPDX-FileCopyrightText: 2014 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later  #pragma once diff --git a/src/common/threadsafe_queue.h b/src/common/threadsafe_queue.h index 7272ac6e8..f7ae9d8c2 100644 --- a/src/common/threadsafe_queue.h +++ b/src/common/threadsafe_queue.h @@ -1,6 +1,5 @@ -// Copyright 2010 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2010 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later  #pragma once diff --git a/src/common/tree.h b/src/common/tree.h index 28370e343..f77859209 100644 --- a/src/common/tree.h +++ b/src/common/tree.h @@ -1,32 +1,10 @@ +// SPDX-FileCopyrightText: 2002 Niels Provos <provos@citi.umich.edu> +// SPDX-License-Identifier: BSD-2-Clause +  /* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */  /* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */  /* $FreeBSD$ */ -/*- - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - *    notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - *    notice, this list of conditions and the following disclaimer in the - *    documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -  #pragma once  /* diff --git a/src/common/vector_math.h b/src/common/vector_math.h index ba7c363c1..e62eeea2e 100644 --- a/src/common/vector_math.h +++ b/src/common/vector_math.h @@ -1,32 +1,6 @@ -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -// Copyright 2014 Tony Wasserka -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -//     * Redistributions of source code must retain the above copyright -//       notice, this list of conditions and the following disclaimer. -//     * Redistributions in binary form must reproduce the above copyright -//       notice, this list of conditions and the following disclaimer in the -//       documentation and/or other materials provided with the distribution. -//     * Neither the name of the owner nor the names of its contributors may -//       be used to endorse or promote products derived from this software -//       without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// SPDX-FileCopyrightText: 2014 Tony Wasserka +// SPDX-FileCopyrightText: 2014 Dolphin Emulator Project +// SPDX-License-Identifier: BSD-3-Clause AND GPL-2.0-or-later  #pragma once diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h index df2b1dfc5..26ec1091b 100644 --- a/src/core/hid/hid_types.h +++ b/src/core/hid/hid_types.h @@ -316,27 +316,27 @@ static_assert(sizeof(TouchAttribute) == 0x4, "TouchAttribute is an invalid size"  // This is nn::hid::TouchState  struct TouchState { -    u64 delta_time; -    TouchAttribute attribute; -    u32 finger; -    Common::Point<u32> position; -    u32 diameter_x; -    u32 diameter_y; -    u32 rotation_angle; +    u64 delta_time{}; +    TouchAttribute attribute{}; +    u32 finger{}; +    Common::Point<u32> position{}; +    u32 diameter_x{}; +    u32 diameter_y{}; +    u32 rotation_angle{};  };  static_assert(sizeof(TouchState) == 0x28, "Touchstate is an invalid size");  // This is nn::hid::NpadControllerColor  struct NpadControllerColor { -    u32 body; -    u32 button; +    u32 body{}; +    u32 button{};  };  static_assert(sizeof(NpadControllerColor) == 8, "NpadControllerColor is an invalid size");  // This is nn::hid::AnalogStickState  struct AnalogStickState { -    s32 x; -    s32 y; +    s32 x{}; +    s32 y{};  };  static_assert(sizeof(AnalogStickState) == 8, "AnalogStickState is an invalid size"); @@ -354,10 +354,10 @@ static_assert(sizeof(NpadBatteryLevel) == 0x4, "NpadBatteryLevel is an invalid s  // This is nn::hid::system::NpadPowerInfo  struct NpadPowerInfo { -    bool is_powered; -    bool is_charging; +    bool is_powered{}; +    bool is_charging{};      INSERT_PADDING_BYTES(0x6); -    NpadBatteryLevel battery_level; +    NpadBatteryLevel battery_level{8};  };  static_assert(sizeof(NpadPowerInfo) == 0xC, "NpadPowerInfo is an invalid size"); @@ -474,8 +474,8 @@ static_assert(sizeof(DebugPadButton) == 0x4, "DebugPadButton is an invalid size"  // This is nn::hid::ConsoleSixAxisSensorHandle  struct ConsoleSixAxisSensorHandle { -    u8 unknown_1; -    u8 unknown_2; +    u8 unknown_1{}; +    u8 unknown_2{};      INSERT_PADDING_BYTES_NOINIT(2);  };  static_assert(sizeof(ConsoleSixAxisSensorHandle) == 4, @@ -483,9 +483,9 @@ static_assert(sizeof(ConsoleSixAxisSensorHandle) == 4,  // This is nn::hid::SixAxisSensorHandle  struct SixAxisSensorHandle { -    NpadStyleIndex npad_type; -    u8 npad_id; -    DeviceIndex device_index; +    NpadStyleIndex npad_type{NpadStyleIndex::None}; +    u8 npad_id{}; +    DeviceIndex device_index{DeviceIndex::None};      INSERT_PADDING_BYTES_NOINIT(1);  };  static_assert(sizeof(SixAxisSensorHandle) == 4, "SixAxisSensorHandle is an invalid size"); @@ -500,19 +500,19 @@ static_assert(sizeof(SixAxisSensorFusionParameters) == 8,  // This is nn::hid::VibrationDeviceHandle  struct VibrationDeviceHandle { -    NpadStyleIndex npad_type; -    u8 npad_id; -    DeviceIndex device_index; +    NpadStyleIndex npad_type{NpadStyleIndex::None}; +    u8 npad_id{}; +    DeviceIndex device_index{DeviceIndex::None};      INSERT_PADDING_BYTES_NOINIT(1);  };  static_assert(sizeof(VibrationDeviceHandle) == 4, "SixAxisSensorHandle is an invalid size");  // This is nn::hid::VibrationValue  struct VibrationValue { -    f32 low_amplitude; -    f32 low_frequency; -    f32 high_amplitude; -    f32 high_frequency; +    f32 low_amplitude{}; +    f32 low_frequency{}; +    f32 high_amplitude{}; +    f32 high_frequency{};  };  static_assert(sizeof(VibrationValue) == 0x10, "VibrationValue has incorrect size."); @@ -561,7 +561,7 @@ static_assert(sizeof(KeyboardAttribute) == 0x4, "KeyboardAttribute is an invalid  // This is nn::hid::KeyboardKey  struct KeyboardKey {      // This should be a 256 bit flag -    std::array<u8, 32> key; +    std::array<u8, 32> key{};  };  static_assert(sizeof(KeyboardKey) == 0x20, "KeyboardKey is an invalid size"); @@ -590,16 +590,16 @@ static_assert(sizeof(MouseAttribute) == 0x4, "MouseAttribute is an invalid size"  // This is nn::hid::detail::MouseState  struct MouseState { -    s64 sampling_number; -    s32 x; -    s32 y; -    s32 delta_x; -    s32 delta_y; +    s64 sampling_number{}; +    s32 x{}; +    s32 y{}; +    s32 delta_x{}; +    s32 delta_y{};      // Axis Order in HW is switched for the wheel -    s32 delta_wheel_y; -    s32 delta_wheel_x; -    MouseButton button; -    MouseAttribute attribute; +    s32 delta_wheel_y{}; +    s32 delta_wheel_x{}; +    MouseButton button{}; +    MouseAttribute attribute{};  };  static_assert(sizeof(MouseState) == 0x28, "MouseState is an invalid size"); diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 3807b9aa8..8d38d0030 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -154,6 +154,48 @@ constexpr ResultCode ResultSuccess(0);  constexpr ResultCode ResultUnknown(UINT32_MAX);  /** + * A ResultRange defines an inclusive range of error descriptions within an error module. + * This can be used to check whether the description of a given ResultCode falls within the range. + * The conversion function returns a ResultCode with its description set to description_start. + * + * An example of how it could be used: + * \code + * constexpr ResultRange ResultCommonError{ErrorModule::Common, 0, 9999}; + * + * ResultCode Example(int value) { + *     const ResultCode result = OtherExample(value); + * + *     // This will only evaluate to true if result.module is ErrorModule::Common and + *     // result.description is in between 0 and 9999 inclusive. + *     if (ResultCommonError.Includes(result)) { + *         // This returns ResultCode{ErrorModule::Common, 0}; + *         return ResultCommonError; + *     } + * + *     return ResultSuccess; + * } + * \endcode + */ +class ResultRange { +public: +    consteval ResultRange(ErrorModule module, u32 description_start, u32 description_end_) +        : code{module, description_start}, description_end{description_end_} {} + +    [[nodiscard]] consteval operator ResultCode() const { +        return code; +    } + +    [[nodiscard]] constexpr bool Includes(ResultCode other) const { +        return code.module == other.module && code.description <= other.description && +               other.description <= description_end; +    } + +private: +    ResultCode code; +    u32 description_end; +}; + +/**   * This is an optional value type. It holds a `ResultCode` and, if that code is ResultSuccess, it   * also holds a result of type `T`. If the code is an error code (not ResultSuccess), then trying   * to access the inner value with operator* is undefined behavior and will assert with Unwrap(). diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/console_sixaxis.cpp index f5a0b94dd..bb3cba910 100644 --- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp +++ b/src/core/hle/service/hid/controllers/console_sixaxis.cpp @@ -9,9 +9,14 @@  namespace Service::HID {  constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C200; -Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_) +Controller_ConsoleSixAxis::Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_, +                                                     u8* raw_shared_memory_)      : ControllerBase{hid_core_} {      console = hid_core.GetEmulatedConsole(); +    static_assert(SHARED_MEMORY_OFFSET + sizeof(ConsoleSharedMemory) < shared_memory_size, +                  "ConsoleSharedMemory is bigger than the shared memory"); +    shared_memory = std::construct_at( +        reinterpret_cast<ConsoleSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));  }  Controller_ConsoleSixAxis::~Controller_ConsoleSixAxis() = default; @@ -20,8 +25,7 @@ void Controller_ConsoleSixAxis::OnInit() {}  void Controller_ConsoleSixAxis::OnRelease() {} -void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, -                                         std::size_t size) { +void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) {      if (!IsControllerActivated() || !is_transfer_memory_set) {          seven_sixaxis_lifo.buffer_count = 0;          seven_sixaxis_lifo.buffer_tail = 0; @@ -48,13 +52,11 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti          -motion_status.quaternion.xyz.z,      }; -    console_six_axis.sampling_number++; -    console_six_axis.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest; -    console_six_axis.verticalization_error = motion_status.verticalization_error; -    console_six_axis.gyro_bias = motion_status.gyro_bias; +    shared_memory->sampling_number++; +    shared_memory->is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest; +    shared_memory->verticalization_error = motion_status.verticalization_error; +    shared_memory->gyro_bias = motion_status.gyro_bias; -    // Update console six axis shared memory -    std::memcpy(data + SHARED_MEMORY_OFFSET, &console_six_axis, sizeof(console_six_axis));      // Update seven six axis transfer memory      seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state);      std::memcpy(transfer_memory, &seven_sixaxis_lifo, sizeof(seven_sixaxis_lifo)); diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/console_sixaxis.h index 6da5e9454..2fd11538f 100644 --- a/src/core/hle/service/hid/controllers/console_sixaxis.h +++ b/src/core/hle/service/hid/controllers/console_sixaxis.h @@ -17,7 +17,7 @@ class EmulatedConsole;  namespace Service::HID {  class Controller_ConsoleSixAxis final : public ControllerBase {  public: -    explicit Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_); +    explicit Controller_ConsoleSixAxis(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);      ~Controller_ConsoleSixAxis() override;      // Called when the controller is initialized @@ -27,7 +27,7 @@ public:      void OnRelease() override;      // When the controller is requesting an update for the shared memory -    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, size_t size) override; +    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;      // Called on InitializeSevenSixAxisSensor      void SetTransferMemoryPointer(u8* t_mem); @@ -61,12 +61,13 @@ private:      Lifo<SevenSixAxisState, 0x21> seven_sixaxis_lifo{};      static_assert(sizeof(seven_sixaxis_lifo) == 0xA70, "SevenSixAxisState is an invalid size"); -    Core::HID::EmulatedConsole* console; +    SevenSixAxisState next_seven_sixaxis_state{};      u8* transfer_memory = nullptr; +    ConsoleSharedMemory* shared_memory = nullptr; +    Core::HID::EmulatedConsole* console = nullptr; +      bool is_transfer_memory_set = false;      u64 last_saved_timestamp{};      u64 last_global_timestamp{}; -    ConsoleSharedMemory console_six_axis{}; -    SevenSixAxisState next_seven_sixaxis_state{};  };  } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/controller_base.h b/src/core/hle/service/hid/controllers/controller_base.h index bb01ea643..d6f7a5073 100644 --- a/src/core/hle/service/hid/controllers/controller_base.h +++ b/src/core/hle/service/hid/controllers/controller_base.h @@ -26,12 +26,10 @@ public:      virtual void OnRelease() = 0;      // When the controller is requesting an update for the shared memory -    virtual void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, -                          std::size_t size) = 0; +    virtual void OnUpdate(const Core::Timing::CoreTiming& core_timing) = 0;      // When the controller is requesting a motion update for the shared memory -    virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, -                                std::size_t size) {} +    virtual void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) {}      void ActivateController(); @@ -40,6 +38,7 @@ public:      bool IsControllerActivated() const;      static const std::size_t hid_entry_count = 17; +    static const std::size_t shared_memory_size = 0x40000;  protected:      bool is_activated{false}; diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp index 73309d64e..8ec9f4a95 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.cpp +++ b/src/core/hle/service/hid/controllers/debug_pad.cpp @@ -13,8 +13,12 @@  namespace Service::HID {  constexpr std::size_t SHARED_MEMORY_OFFSET = 0x00000; -Controller_DebugPad::Controller_DebugPad(Core::HID::HIDCore& hid_core_) +Controller_DebugPad::Controller_DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)      : ControllerBase{hid_core_} { +    static_assert(SHARED_MEMORY_OFFSET + sizeof(DebugPadSharedMemory) < shared_memory_size, +                  "DebugPadSharedMemory is bigger than the shared memory"); +    shared_memory = std::construct_at( +        reinterpret_cast<DebugPadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));      controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Other);  } @@ -24,16 +28,14 @@ void Controller_DebugPad::OnInit() {}  void Controller_DebugPad::OnRelease() {} -void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, -                                   std::size_t size) { +void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {      if (!IsControllerActivated()) { -        debug_pad_lifo.buffer_count = 0; -        debug_pad_lifo.buffer_tail = 0; -        std::memcpy(data + SHARED_MEMORY_OFFSET, &debug_pad_lifo, sizeof(debug_pad_lifo)); +        shared_memory->debug_pad_lifo.buffer_count = 0; +        shared_memory->debug_pad_lifo.buffer_tail = 0;          return;      } -    const auto& last_entry = debug_pad_lifo.ReadCurrentEntry().state; +    const auto& last_entry = shared_memory->debug_pad_lifo.ReadCurrentEntry().state;      next_state.sampling_number = last_entry.sampling_number + 1;      if (Settings::values.debug_pad_enabled) { @@ -47,8 +49,7 @@ void Controller_DebugPad::OnUpdate(const Core::Timing::CoreTiming& core_timing,          next_state.r_stick = stick_state.right;      } -    debug_pad_lifo.WriteNextEntry(next_state); -    std::memcpy(data + SHARED_MEMORY_OFFSET, &debug_pad_lifo, sizeof(debug_pad_lifo)); +    shared_memory->debug_pad_lifo.WriteNextEntry(next_state);  }  } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h index 388d25b3c..68ff0ea79 100644 --- a/src/core/hle/service/hid/controllers/debug_pad.h +++ b/src/core/hle/service/hid/controllers/debug_pad.h @@ -17,7 +17,7 @@ struct AnalogStickState;  namespace Service::HID {  class Controller_DebugPad final : public ControllerBase {  public: -    explicit Controller_DebugPad(Core::HID::HIDCore& hid_core_); +    explicit Controller_DebugPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);      ~Controller_DebugPad() override;      // Called when the controller is initialized @@ -27,7 +27,7 @@ public:      void OnRelease() override;      // When the controller is requesting an update for the shared memory -    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; +    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;  private:      // This is nn::hid::DebugPadAttribute @@ -41,19 +41,24 @@ private:      // This is nn::hid::DebugPadState      struct DebugPadState { -        s64 sampling_number; -        DebugPadAttribute attribute; -        Core::HID::DebugPadButton pad_state; -        Core::HID::AnalogStickState r_stick; -        Core::HID::AnalogStickState l_stick; +        s64 sampling_number{}; +        DebugPadAttribute attribute{}; +        Core::HID::DebugPadButton pad_state{}; +        Core::HID::AnalogStickState r_stick{}; +        Core::HID::AnalogStickState l_stick{};      };      static_assert(sizeof(DebugPadState) == 0x20, "DebugPadState is an invalid state"); -    // This is nn::hid::detail::DebugPadLifo -    Lifo<DebugPadState, hid_entry_count> debug_pad_lifo{}; -    static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size"); -    DebugPadState next_state{}; +    struct DebugPadSharedMemory { +        // This is nn::hid::detail::DebugPadLifo +        Lifo<DebugPadState, hid_entry_count> debug_pad_lifo{}; +        static_assert(sizeof(debug_pad_lifo) == 0x2C8, "debug_pad_lifo is an invalid size"); +        INSERT_PADDING_WORDS(0x4E); +    }; +    static_assert(sizeof(DebugPadSharedMemory) == 0x400, "DebugPadSharedMemory is an invalid size"); -    Core::HID::EmulatedController* controller; +    DebugPadState next_state{}; +    DebugPadSharedMemory* shared_memory = nullptr; +    Core::HID::EmulatedController* controller = nullptr;  };  } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/gesture.cpp b/src/core/hle/service/hid/controllers/gesture.cpp index c8dd131dd..3eae1ae35 100644 --- a/src/core/hle/service/hid/controllers/gesture.cpp +++ b/src/core/hle/service/hid/controllers/gesture.cpp @@ -23,25 +23,28 @@ constexpr f32 Square(s32 num) {      return static_cast<f32>(num * num);  } -Controller_Gesture::Controller_Gesture(Core::HID::HIDCore& hid_core_) : ControllerBase(hid_core_) { +Controller_Gesture::Controller_Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) +    : ControllerBase(hid_core_) { +    static_assert(SHARED_MEMORY_OFFSET + sizeof(GestureSharedMemory) < shared_memory_size, +                  "GestureSharedMemory is bigger than the shared memory"); +    shared_memory = std::construct_at( +        reinterpret_cast<GestureSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));      console = hid_core.GetEmulatedConsole();  }  Controller_Gesture::~Controller_Gesture() = default;  void Controller_Gesture::OnInit() { -    gesture_lifo.buffer_count = 0; -    gesture_lifo.buffer_tail = 0; +    shared_memory->gesture_lifo.buffer_count = 0; +    shared_memory->gesture_lifo.buffer_tail = 0;      force_update = true;  }  void Controller_Gesture::OnRelease() {} -void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, -                                  std::size_t size) { +void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing) {      if (!IsControllerActivated()) { -        gesture_lifo.buffer_count = 0; -        gesture_lifo.buffer_tail = 0; -        std::memcpy(data + SHARED_MEMORY_OFFSET, &gesture_lifo, sizeof(gesture_lifo)); +        shared_memory->gesture_lifo.buffer_count = 0; +        shared_memory->gesture_lifo.buffer_tail = 0;          return;      } @@ -49,15 +52,15 @@ void Controller_Gesture::OnUpdate(const Core::Timing::CoreTiming& core_timing, u      GestureProperties gesture = GetGestureProperties();      f32 time_difference = -        static_cast<f32>(gesture_lifo.timestamp - last_update_timestamp) / (1000 * 1000 * 1000); +        static_cast<f32>(shared_memory->gesture_lifo.timestamp - last_update_timestamp) / +        (1000 * 1000 * 1000);      // Only update if necesary      if (!ShouldUpdateGesture(gesture, time_difference)) {          return;      } -    last_update_timestamp = gesture_lifo.timestamp; -    UpdateGestureSharedMemory(data, size, gesture, time_difference); +    last_update_timestamp = shared_memory->gesture_lifo.timestamp;  }  void Controller_Gesture::ReadTouchInput() { @@ -97,7 +100,7 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size,      GestureType type = GestureType::Idle;      GestureAttribute attributes{}; -    const auto& last_entry = gesture_lifo.ReadCurrentEntry().state; +    const auto& last_entry = shared_memory->gesture_lifo.ReadCurrentEntry().state;      // Reset next state to default      next_state.sampling_number = last_entry.sampling_number + 1; @@ -127,8 +130,7 @@ void Controller_Gesture::UpdateGestureSharedMemory(u8* data, std::size_t size,      next_state.points = gesture.points;      last_gesture = gesture; -    gesture_lifo.WriteNextEntry(next_state); -    std::memcpy(data + SHARED_MEMORY_OFFSET, &gesture_lifo, sizeof(gesture_lifo)); +    shared_memory->gesture_lifo.WriteNextEntry(next_state);  }  void Controller_Gesture::NewGesture(GestureProperties& gesture, GestureType& type, @@ -305,7 +307,7 @@ void Controller_Gesture::SetSwipeEvent(GestureProperties& gesture,  }  const Controller_Gesture::GestureState& Controller_Gesture::GetLastGestureEntry() const { -    return gesture_lifo.ReadCurrentEntry().state; +    return shared_memory->gesture_lifo.ReadCurrentEntry().state;  }  Controller_Gesture::GestureProperties Controller_Gesture::GetGestureProperties() { diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h index 7a9d28dc6..c62a341bf 100644 --- a/src/core/hle/service/hid/controllers/gesture.h +++ b/src/core/hle/service/hid/controllers/gesture.h @@ -14,7 +14,7 @@  namespace Service::HID {  class Controller_Gesture final : public ControllerBase {  public: -    explicit Controller_Gesture(Core::HID::HIDCore& hid_core_); +    explicit Controller_Gesture(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);      ~Controller_Gesture() override;      // Called when the controller is initialized @@ -24,7 +24,7 @@ public:      void OnRelease() override;      // When the controller is requesting an update for the shared memory -    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, size_t size) override; +    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;  private:      static constexpr size_t MAX_FINGERS = 16; @@ -66,19 +66,19 @@ private:      // This is nn::hid::GestureState      struct GestureState { -        s64 sampling_number; -        s64 detection_count; -        GestureType type; -        GestureDirection direction; -        Common::Point<s32> pos; -        Common::Point<s32> delta; -        f32 vel_x; -        f32 vel_y; -        GestureAttribute attributes; -        f32 scale; -        f32 rotation_angle; -        s32 point_count; -        std::array<Common::Point<s32>, 4> points; +        s64 sampling_number{}; +        s64 detection_count{}; +        GestureType type{GestureType::Idle}; +        GestureDirection direction{GestureDirection::None}; +        Common::Point<s32> pos{}; +        Common::Point<s32> delta{}; +        f32 vel_x{}; +        f32 vel_y{}; +        GestureAttribute attributes{}; +        f32 scale{}; +        f32 rotation_angle{}; +        s32 point_count{}; +        std::array<Common::Point<s32>, 4> points{};      };      static_assert(sizeof(GestureState) == 0x60, "GestureState is an invalid size"); @@ -92,6 +92,14 @@ private:          f32 angle{};      }; +    struct GestureSharedMemory { +        // This is nn::hid::detail::GestureLifo +        Lifo<GestureState, hid_entry_count> gesture_lifo{}; +        static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size"); +        INSERT_PADDING_WORDS(0x3E); +    }; +    static_assert(sizeof(GestureSharedMemory) == 0x800, "GestureSharedMemory is an invalid size"); +      // Reads input from all available input engines      void ReadTouchInput(); @@ -134,12 +142,9 @@ private:      // Returns the average distance, angle and middle point of the active fingers      GestureProperties GetGestureProperties(); -    // This is nn::hid::detail::GestureLifo -    Lifo<GestureState, hid_entry_count> gesture_lifo{}; -    static_assert(sizeof(gesture_lifo) == 0x708, "gesture_lifo is an invalid size");      GestureState next_state{}; - -    Core::HID::EmulatedConsole* console; +    GestureSharedMemory* shared_memory = nullptr; +    Core::HID::EmulatedConsole* console = nullptr;      std::array<Core::HID::TouchFinger, MAX_POINTS> fingers{};      GestureProperties last_gesture{}; diff --git a/src/core/hle/service/hid/controllers/keyboard.cpp b/src/core/hle/service/hid/controllers/keyboard.cpp index 8dc67757b..117d87433 100644 --- a/src/core/hle/service/hid/controllers/keyboard.cpp +++ b/src/core/hle/service/hid/controllers/keyboard.cpp @@ -12,8 +12,12 @@  namespace Service::HID {  constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3800; -Controller_Keyboard::Controller_Keyboard(Core::HID::HIDCore& hid_core_) +Controller_Keyboard::Controller_Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_)      : ControllerBase{hid_core_} { +    static_assert(SHARED_MEMORY_OFFSET + sizeof(KeyboardSharedMemory) < shared_memory_size, +                  "KeyboardSharedMemory is bigger than the shared memory"); +    shared_memory = std::construct_at( +        reinterpret_cast<KeyboardSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));      emulated_devices = hid_core.GetEmulatedDevices();  } @@ -23,16 +27,14 @@ void Controller_Keyboard::OnInit() {}  void Controller_Keyboard::OnRelease() {} -void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, -                                   std::size_t size) { +void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing) {      if (!IsControllerActivated()) { -        keyboard_lifo.buffer_count = 0; -        keyboard_lifo.buffer_tail = 0; -        std::memcpy(data + SHARED_MEMORY_OFFSET, &keyboard_lifo, sizeof(keyboard_lifo)); +        shared_memory->keyboard_lifo.buffer_count = 0; +        shared_memory->keyboard_lifo.buffer_tail = 0;          return;      } -    const auto& last_entry = keyboard_lifo.ReadCurrentEntry().state; +    const auto& last_entry = shared_memory->keyboard_lifo.ReadCurrentEntry().state;      next_state.sampling_number = last_entry.sampling_number + 1;      if (Settings::values.keyboard_enabled) { @@ -44,8 +46,7 @@ void Controller_Keyboard::OnUpdate(const Core::Timing::CoreTiming& core_timing,          next_state.attribute.is_connected.Assign(1);      } -    keyboard_lifo.WriteNextEntry(next_state); -    std::memcpy(data + SHARED_MEMORY_OFFSET, &keyboard_lifo, sizeof(keyboard_lifo)); +    shared_memory->keyboard_lifo.WriteNextEntry(next_state);  }  } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/keyboard.h b/src/core/hle/service/hid/controllers/keyboard.h index 39c6085f1..7532f53c6 100644 --- a/src/core/hle/service/hid/controllers/keyboard.h +++ b/src/core/hle/service/hid/controllers/keyboard.h @@ -16,7 +16,7 @@ struct KeyboardKey;  namespace Service::HID {  class Controller_Keyboard final : public ControllerBase {  public: -    explicit Controller_Keyboard(Core::HID::HIDCore& hid_core_); +    explicit Controller_Keyboard(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);      ~Controller_Keyboard() override;      // Called when the controller is initialized @@ -26,23 +26,28 @@ public:      void OnRelease() override;      // When the controller is requesting an update for the shared memory -    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; +    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;  private:      // This is nn::hid::detail::KeyboardState      struct KeyboardState { -        s64 sampling_number; -        Core::HID::KeyboardModifier modifier; -        Core::HID::KeyboardAttribute attribute; -        Core::HID::KeyboardKey key; +        s64 sampling_number{}; +        Core::HID::KeyboardModifier modifier{}; +        Core::HID::KeyboardAttribute attribute{}; +        Core::HID::KeyboardKey key{};      };      static_assert(sizeof(KeyboardState) == 0x30, "KeyboardState is an invalid size"); -    // This is nn::hid::detail::KeyboardLifo -    Lifo<KeyboardState, hid_entry_count> keyboard_lifo{}; -    static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size"); -    KeyboardState next_state{}; +    struct KeyboardSharedMemory { +        // This is nn::hid::detail::KeyboardLifo +        Lifo<KeyboardState, hid_entry_count> keyboard_lifo{}; +        static_assert(sizeof(keyboard_lifo) == 0x3D8, "keyboard_lifo is an invalid size"); +        INSERT_PADDING_WORDS(0xA); +    }; +    static_assert(sizeof(KeyboardSharedMemory) == 0x400, "KeyboardSharedMemory is an invalid size"); -    Core::HID::EmulatedDevices* emulated_devices; +    KeyboardState next_state{}; +    KeyboardSharedMemory* shared_memory = nullptr; +    Core::HID::EmulatedDevices* emulated_devices = nullptr;  };  } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/mouse.cpp b/src/core/hle/service/hid/controllers/mouse.cpp index a0292f586..b11cb438d 100644 --- a/src/core/hle/service/hid/controllers/mouse.cpp +++ b/src/core/hle/service/hid/controllers/mouse.cpp @@ -12,7 +12,12 @@  namespace Service::HID {  constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3400; -Controller_Mouse::Controller_Mouse(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} { +Controller_Mouse::Controller_Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) +    : ControllerBase{hid_core_} { +    static_assert(SHARED_MEMORY_OFFSET + sizeof(MouseSharedMemory) < shared_memory_size, +                  "MouseSharedMemory is bigger than the shared memory"); +    shared_memory = std::construct_at( +        reinterpret_cast<MouseSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));      emulated_devices = hid_core.GetEmulatedDevices();  } @@ -21,16 +26,14 @@ Controller_Mouse::~Controller_Mouse() = default;  void Controller_Mouse::OnInit() {}  void Controller_Mouse::OnRelease() {} -void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, -                                std::size_t size) { +void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing) {      if (!IsControllerActivated()) { -        mouse_lifo.buffer_count = 0; -        mouse_lifo.buffer_tail = 0; -        std::memcpy(data + SHARED_MEMORY_OFFSET, &mouse_lifo, sizeof(mouse_lifo)); +        shared_memory->mouse_lifo.buffer_count = 0; +        shared_memory->mouse_lifo.buffer_tail = 0;          return;      } -    const auto& last_entry = mouse_lifo.ReadCurrentEntry().state; +    const auto& last_entry = shared_memory->mouse_lifo.ReadCurrentEntry().state;      next_state.sampling_number = last_entry.sampling_number + 1;      next_state.attribute.raw = 0; @@ -50,8 +53,7 @@ void Controller_Mouse::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*          next_state.button = mouse_button_state;      } -    mouse_lifo.WriteNextEntry(next_state); -    std::memcpy(data + SHARED_MEMORY_OFFSET, &mouse_lifo, sizeof(mouse_lifo)); +    shared_memory->mouse_lifo.WriteNextEntry(next_state);  }  } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/mouse.h b/src/core/hle/service/hid/controllers/mouse.h index 62acdfb77..733d00577 100644 --- a/src/core/hle/service/hid/controllers/mouse.h +++ b/src/core/hle/service/hid/controllers/mouse.h @@ -16,7 +16,7 @@ struct AnalogStickState;  namespace Service::HID {  class Controller_Mouse final : public ControllerBase {  public: -    explicit Controller_Mouse(Core::HID::HIDCore& hid_core_); +    explicit Controller_Mouse(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);      ~Controller_Mouse() override;      // Called when the controller is initialized @@ -26,15 +26,20 @@ public:      void OnRelease() override;      // When the controller is requesting an update for the shared memory -    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; +    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;  private: -    // This is nn::hid::detail::MouseLifo -    Lifo<Core::HID::MouseState, hid_entry_count> mouse_lifo{}; -    static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size"); -    Core::HID::MouseState next_state{}; +    struct MouseSharedMemory { +        // This is nn::hid::detail::MouseLifo +        Lifo<Core::HID::MouseState, hid_entry_count> mouse_lifo{}; +        static_assert(sizeof(mouse_lifo) == 0x350, "mouse_lifo is an invalid size"); +        INSERT_PADDING_WORDS(0x2C); +    }; +    static_assert(sizeof(MouseSharedMemory) == 0x400, "MouseSharedMemory is an invalid size"); -    Core::HID::AnalogStickState last_mouse_wheel_state; -    Core::HID::EmulatedDevices* emulated_devices; +    Core::HID::MouseState next_state{}; +    Core::HID::AnalogStickState last_mouse_wheel_state{}; +    MouseSharedMemory* shared_memory = nullptr; +    Core::HID::EmulatedDevices* emulated_devices = nullptr;  };  } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 16e973b25..17f71beaf 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -61,11 +61,14 @@ bool Controller_NPad::IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle&      return npad_id && npad_type && device_index;  } -Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, +Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,                                   KernelHelpers::ServiceContext& service_context_)      : ControllerBase{hid_core_}, service_context{service_context_} { +    static_assert(NPAD_OFFSET + (NPAD_COUNT * sizeof(NpadInternalState)) < shared_memory_size);      for (std::size_t i = 0; i < controller_data.size(); ++i) {          auto& controller = controller_data[i]; +        controller.shared_memory = std::construct_at(reinterpret_cast<NpadInternalState*>( +            raw_shared_memory_ + NPAD_OFFSET + (i * sizeof(NpadInternalState))));          controller.device = hid_core.GetEmulatedControllerByIndex(i);          controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =              Core::HID::DEFAULT_VIBRATION_VALUE; @@ -115,11 +118,11 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,          if (!controller.device->IsConnected()) {              return;          } -        auto& shared_memory = controller.shared_memory_entry; +        auto* shared_memory = controller.shared_memory;          const auto& battery_level = controller.device->GetBattery(); -        shared_memory.battery_level_dual = battery_level.dual.battery_level; -        shared_memory.battery_level_left = battery_level.left.battery_level; -        shared_memory.battery_level_right = battery_level.right.battery_level; +        shared_memory->battery_level_dual = battery_level.dual.battery_level; +        shared_memory->battery_level_left = battery_level.left.battery_level; +        shared_memory->battery_level_right = battery_level.right.battery_level;          break;      }      default: @@ -134,99 +137,100 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {      }      LOG_DEBUG(Service_HID, "Npad connected {}", npad_id);      const auto controller_type = controller.device->GetNpadStyleIndex(); -    auto& shared_memory = controller.shared_memory_entry; +    auto* shared_memory = controller.shared_memory;      if (controller_type == Core::HID::NpadStyleIndex::None) {          controller.styleset_changed_event->GetWritableEvent().Signal();          return;      } -    shared_memory.style_tag.raw = Core::HID::NpadStyleSet::None; -    shared_memory.device_type.raw = 0; -    shared_memory.system_properties.raw = 0; +    shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None; +    shared_memory->device_type.raw = 0; +    shared_memory->system_properties.raw = 0;      switch (controller_type) {      case Core::HID::NpadStyleIndex::None:          UNREACHABLE();          break;      case Core::HID::NpadStyleIndex::ProController: -        shared_memory.style_tag.fullkey.Assign(1); -        shared_memory.device_type.fullkey.Assign(1); -        shared_memory.system_properties.is_vertical.Assign(1); -        shared_memory.system_properties.use_plus.Assign(1); -        shared_memory.system_properties.use_minus.Assign(1); -        shared_memory.applet_footer.type = AppletFooterUiType::SwitchProController; +        shared_memory->style_tag.fullkey.Assign(1); +        shared_memory->device_type.fullkey.Assign(1); +        shared_memory->system_properties.is_vertical.Assign(1); +        shared_memory->system_properties.use_plus.Assign(1); +        shared_memory->system_properties.use_minus.Assign(1); +        shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::SwitchProController;          break;      case Core::HID::NpadStyleIndex::Handheld: -        shared_memory.style_tag.handheld.Assign(1); -        shared_memory.device_type.handheld_left.Assign(1); -        shared_memory.device_type.handheld_right.Assign(1); -        shared_memory.system_properties.is_vertical.Assign(1); -        shared_memory.system_properties.use_plus.Assign(1); -        shared_memory.system_properties.use_minus.Assign(1); -        shared_memory.system_properties.use_directional_buttons.Assign(1); -        shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual; -        shared_memory.applet_footer.type = AppletFooterUiType::HandheldJoyConLeftJoyConRight; +        shared_memory->style_tag.handheld.Assign(1); +        shared_memory->device_type.handheld_left.Assign(1); +        shared_memory->device_type.handheld_right.Assign(1); +        shared_memory->system_properties.is_vertical.Assign(1); +        shared_memory->system_properties.use_plus.Assign(1); +        shared_memory->system_properties.use_minus.Assign(1); +        shared_memory->system_properties.use_directional_buttons.Assign(1); +        shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual; +        shared_memory->applet_nfc_xcd.applet_footer.type = +            AppletFooterUiType::HandheldJoyConLeftJoyConRight;          break;      case Core::HID::NpadStyleIndex::JoyconDual: -        shared_memory.style_tag.joycon_dual.Assign(1); +        shared_memory->style_tag.joycon_dual.Assign(1);          if (controller.is_dual_left_connected) { -            shared_memory.device_type.joycon_left.Assign(1); -            shared_memory.system_properties.use_minus.Assign(1); +            shared_memory->device_type.joycon_left.Assign(1); +            shared_memory->system_properties.use_minus.Assign(1);          }          if (controller.is_dual_right_connected) { -            shared_memory.device_type.joycon_right.Assign(1); -            shared_memory.system_properties.use_plus.Assign(1); +            shared_memory->device_type.joycon_right.Assign(1); +            shared_memory->system_properties.use_plus.Assign(1);          } -        shared_memory.system_properties.use_directional_buttons.Assign(1); -        shared_memory.system_properties.is_vertical.Assign(1); -        shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual; +        shared_memory->system_properties.use_directional_buttons.Assign(1); +        shared_memory->system_properties.is_vertical.Assign(1); +        shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual;          if (controller.is_dual_left_connected && controller.is_dual_right_connected) { -            shared_memory.applet_footer.type = AppletFooterUiType::JoyDual; +            shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDual;          } else if (controller.is_dual_left_connected) { -            shared_memory.applet_footer.type = AppletFooterUiType::JoyDualLeftOnly; +            shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDualLeftOnly;          } else { -            shared_memory.applet_footer.type = AppletFooterUiType::JoyDualRightOnly; +            shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDualRightOnly;          }          break;      case Core::HID::NpadStyleIndex::JoyconLeft: -        shared_memory.style_tag.joycon_left.Assign(1); -        shared_memory.device_type.joycon_left.Assign(1); -        shared_memory.system_properties.is_horizontal.Assign(1); -        shared_memory.system_properties.use_minus.Assign(1); -        shared_memory.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal; +        shared_memory->style_tag.joycon_left.Assign(1); +        shared_memory->device_type.joycon_left.Assign(1); +        shared_memory->system_properties.is_horizontal.Assign(1); +        shared_memory->system_properties.use_minus.Assign(1); +        shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal;          break;      case Core::HID::NpadStyleIndex::JoyconRight: -        shared_memory.style_tag.joycon_right.Assign(1); -        shared_memory.device_type.joycon_right.Assign(1); -        shared_memory.system_properties.is_horizontal.Assign(1); -        shared_memory.system_properties.use_plus.Assign(1); -        shared_memory.applet_footer.type = AppletFooterUiType::JoyRightHorizontal; +        shared_memory->style_tag.joycon_right.Assign(1); +        shared_memory->device_type.joycon_right.Assign(1); +        shared_memory->system_properties.is_horizontal.Assign(1); +        shared_memory->system_properties.use_plus.Assign(1); +        shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyRightHorizontal;          break;      case Core::HID::NpadStyleIndex::GameCube: -        shared_memory.style_tag.gamecube.Assign(1); -        shared_memory.device_type.fullkey.Assign(1); -        shared_memory.system_properties.is_vertical.Assign(1); -        shared_memory.system_properties.use_plus.Assign(1); +        shared_memory->style_tag.gamecube.Assign(1); +        shared_memory->device_type.fullkey.Assign(1); +        shared_memory->system_properties.is_vertical.Assign(1); +        shared_memory->system_properties.use_plus.Assign(1);          break;      case Core::HID::NpadStyleIndex::Pokeball: -        shared_memory.style_tag.palma.Assign(1); -        shared_memory.device_type.palma.Assign(1); +        shared_memory->style_tag.palma.Assign(1); +        shared_memory->device_type.palma.Assign(1);          break;      case Core::HID::NpadStyleIndex::NES: -        shared_memory.style_tag.lark.Assign(1); -        shared_memory.device_type.fullkey.Assign(1); +        shared_memory->style_tag.lark.Assign(1); +        shared_memory->device_type.fullkey.Assign(1);          break;      case Core::HID::NpadStyleIndex::SNES: -        shared_memory.style_tag.lucia.Assign(1); -        shared_memory.device_type.fullkey.Assign(1); -        shared_memory.applet_footer.type = AppletFooterUiType::Lucia; +        shared_memory->style_tag.lucia.Assign(1); +        shared_memory->device_type.fullkey.Assign(1); +        shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::Lucia;          break;      case Core::HID::NpadStyleIndex::N64: -        shared_memory.style_tag.lagoon.Assign(1); -        shared_memory.device_type.fullkey.Assign(1); -        shared_memory.applet_footer.type = AppletFooterUiType::Lagon; +        shared_memory->style_tag.lagoon.Assign(1); +        shared_memory->device_type.fullkey.Assign(1); +        shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::Lagon;          break;      case Core::HID::NpadStyleIndex::SegaGenesis: -        shared_memory.style_tag.lager.Assign(1); -        shared_memory.device_type.fullkey.Assign(1); +        shared_memory->style_tag.lager.Assign(1); +        shared_memory->device_type.fullkey.Assign(1);          break;      default:          break; @@ -234,23 +238,23 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {      const auto& body_colors = controller.device->GetColors(); -    shared_memory.fullkey_color.attribute = ColorAttribute::Ok; -    shared_memory.fullkey_color.fullkey = body_colors.fullkey; +    shared_memory->fullkey_color.attribute = ColorAttribute::Ok; +    shared_memory->fullkey_color.fullkey = body_colors.fullkey; -    shared_memory.joycon_color.attribute = ColorAttribute::Ok; -    shared_memory.joycon_color.left = body_colors.left; -    shared_memory.joycon_color.right = body_colors.right; +    shared_memory->joycon_color.attribute = ColorAttribute::Ok; +    shared_memory->joycon_color.left = body_colors.left; +    shared_memory->joycon_color.right = body_colors.right;      // TODO: Investigate when we should report all batery types      const auto& battery_level = controller.device->GetBattery(); -    shared_memory.battery_level_dual = battery_level.dual.battery_level; -    shared_memory.battery_level_left = battery_level.left.battery_level; -    shared_memory.battery_level_right = battery_level.right.battery_level; +    shared_memory->battery_level_dual = battery_level.dual.battery_level; +    shared_memory->battery_level_left = battery_level.left.battery_level; +    shared_memory->battery_level_right = battery_level.right.battery_level;      controller.is_connected = true;      controller.device->Connect();      SignalStyleSetChangedEvent(npad_id); -    WriteEmptyEntry(controller.shared_memory_entry); +    WriteEmptyEntry(controller.shared_memory);  }  void Controller_NPad::OnInit() { @@ -270,12 +274,12 @@ void Controller_NPad::OnInit() {      // Prefill controller buffers      for (auto& controller : controller_data) { -        auto& npad = controller.shared_memory_entry; -        npad.fullkey_color = { +        auto* npad = controller.shared_memory; +        npad->fullkey_color = {              .attribute = ColorAttribute::NoController,              .fullkey = {},          }; -        npad.joycon_color = { +        npad->joycon_color = {              .attribute = ColorAttribute::NoController,              .left = {},              .right = {}, @@ -287,25 +291,25 @@ void Controller_NPad::OnInit() {      }  } -void Controller_NPad::WriteEmptyEntry(NpadInternalState& npad) { +void Controller_NPad::WriteEmptyEntry(NpadInternalState* npad) {      NPadGenericState dummy_pad_state{};      NpadGcTriggerState dummy_gc_state{}; -    dummy_pad_state.sampling_number = npad.fullkey_lifo.ReadCurrentEntry().sampling_number + 1; -    npad.fullkey_lifo.WriteNextEntry(dummy_pad_state); -    dummy_pad_state.sampling_number = npad.handheld_lifo.ReadCurrentEntry().sampling_number + 1; -    npad.handheld_lifo.WriteNextEntry(dummy_pad_state); -    dummy_pad_state.sampling_number = npad.joy_dual_lifo.ReadCurrentEntry().sampling_number + 1; -    npad.joy_dual_lifo.WriteNextEntry(dummy_pad_state); -    dummy_pad_state.sampling_number = npad.joy_left_lifo.ReadCurrentEntry().sampling_number + 1; -    npad.joy_left_lifo.WriteNextEntry(dummy_pad_state); -    dummy_pad_state.sampling_number = npad.joy_right_lifo.ReadCurrentEntry().sampling_number + 1; -    npad.joy_right_lifo.WriteNextEntry(dummy_pad_state); -    dummy_pad_state.sampling_number = npad.palma_lifo.ReadCurrentEntry().sampling_number + 1; -    npad.palma_lifo.WriteNextEntry(dummy_pad_state); -    dummy_pad_state.sampling_number = npad.system_ext_lifo.ReadCurrentEntry().sampling_number + 1; -    npad.system_ext_lifo.WriteNextEntry(dummy_pad_state); -    dummy_gc_state.sampling_number = npad.gc_trigger_lifo.ReadCurrentEntry().sampling_number + 1; -    npad.gc_trigger_lifo.WriteNextEntry(dummy_gc_state); +    dummy_pad_state.sampling_number = npad->fullkey_lifo.ReadCurrentEntry().sampling_number + 1; +    npad->fullkey_lifo.WriteNextEntry(dummy_pad_state); +    dummy_pad_state.sampling_number = npad->handheld_lifo.ReadCurrentEntry().sampling_number + 1; +    npad->handheld_lifo.WriteNextEntry(dummy_pad_state); +    dummy_pad_state.sampling_number = npad->joy_dual_lifo.ReadCurrentEntry().sampling_number + 1; +    npad->joy_dual_lifo.WriteNextEntry(dummy_pad_state); +    dummy_pad_state.sampling_number = npad->joy_left_lifo.ReadCurrentEntry().sampling_number + 1; +    npad->joy_left_lifo.WriteNextEntry(dummy_pad_state); +    dummy_pad_state.sampling_number = npad->joy_right_lifo.ReadCurrentEntry().sampling_number + 1; +    npad->joy_right_lifo.WriteNextEntry(dummy_pad_state); +    dummy_pad_state.sampling_number = npad->palma_lifo.ReadCurrentEntry().sampling_number + 1; +    npad->palma_lifo.WriteNextEntry(dummy_pad_state); +    dummy_pad_state.sampling_number = npad->system_ext_lifo.ReadCurrentEntry().sampling_number + 1; +    npad->system_ext_lifo.WriteNextEntry(dummy_pad_state); +    dummy_gc_state.sampling_number = npad->gc_trigger_lifo.ReadCurrentEntry().sampling_number + 1; +    npad->gc_trigger_lifo.WriteNextEntry(dummy_gc_state);  }  void Controller_NPad::OnRelease() { @@ -371,23 +375,19 @@ void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {      }  } -void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, -                               std::size_t data_len) { +void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {      if (!IsControllerActivated()) {          return;      }      for (std::size_t i = 0; i < controller_data.size(); ++i) {          auto& controller = controller_data[i]; -        auto& npad = controller.shared_memory_entry; +        auto* npad = controller.shared_memory;          const auto& controller_type = controller.device->GetNpadStyleIndex();          if (controller_type == Core::HID::NpadStyleIndex::None ||              !controller.device->IsConnected()) { -            // Refresh shared memory -            std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)), -                        &controller.shared_memory_entry, sizeof(NpadInternalState));              continue;          } @@ -415,8 +415,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*              libnx_state.connection_status.is_wired.Assign(1);              pad_state.sampling_number = -                npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; -            npad.fullkey_lifo.WriteNextEntry(pad_state); +                npad->fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; +            npad->fullkey_lifo.WriteNextEntry(pad_state);              break;          case Core::HID::NpadStyleIndex::Handheld:              pad_state.connection_status.raw = 0; @@ -433,8 +433,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*              libnx_state.connection_status.is_left_wired.Assign(1);              libnx_state.connection_status.is_right_wired.Assign(1);              pad_state.sampling_number = -                npad.handheld_lifo.ReadCurrentEntry().state.sampling_number + 1; -            npad.handheld_lifo.WriteNextEntry(pad_state); +                npad->handheld_lifo.ReadCurrentEntry().state.sampling_number + 1; +            npad->handheld_lifo.WriteNextEntry(pad_state);              break;          case Core::HID::NpadStyleIndex::JoyconDual:              pad_state.connection_status.raw = 0; @@ -449,8 +449,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*              }              pad_state.sampling_number = -                npad.joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1; -            npad.joy_dual_lifo.WriteNextEntry(pad_state); +                npad->joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1; +            npad->joy_dual_lifo.WriteNextEntry(pad_state);              break;          case Core::HID::NpadStyleIndex::JoyconLeft:              pad_state.connection_status.raw = 0; @@ -459,8 +459,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*              libnx_state.connection_status.is_left_connected.Assign(1);              pad_state.sampling_number = -                npad.joy_left_lifo.ReadCurrentEntry().state.sampling_number + 1; -            npad.joy_left_lifo.WriteNextEntry(pad_state); +                npad->joy_left_lifo.ReadCurrentEntry().state.sampling_number + 1; +            npad->joy_left_lifo.WriteNextEntry(pad_state);              break;          case Core::HID::NpadStyleIndex::JoyconRight:              pad_state.connection_status.raw = 0; @@ -469,8 +469,8 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*              libnx_state.connection_status.is_right_connected.Assign(1);              pad_state.sampling_number = -                npad.joy_right_lifo.ReadCurrentEntry().state.sampling_number + 1; -            npad.joy_right_lifo.WriteNextEntry(pad_state); +                npad->joy_right_lifo.ReadCurrentEntry().state.sampling_number + 1; +            npad->joy_right_lifo.WriteNextEntry(pad_state);              break;          case Core::HID::NpadStyleIndex::GameCube:              pad_state.connection_status.raw = 0; @@ -479,18 +479,18 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*              libnx_state.connection_status.is_wired.Assign(1);              pad_state.sampling_number = -                npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; +                npad->fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;              trigger_state.sampling_number = -                npad.gc_trigger_lifo.ReadCurrentEntry().state.sampling_number + 1; -            npad.fullkey_lifo.WriteNextEntry(pad_state); -            npad.gc_trigger_lifo.WriteNextEntry(trigger_state); +                npad->gc_trigger_lifo.ReadCurrentEntry().state.sampling_number + 1; +            npad->fullkey_lifo.WriteNextEntry(pad_state); +            npad->gc_trigger_lifo.WriteNextEntry(trigger_state);              break;          case Core::HID::NpadStyleIndex::Pokeball:              pad_state.connection_status.raw = 0;              pad_state.connection_status.is_connected.Assign(1);              pad_state.sampling_number = -                npad.palma_lifo.ReadCurrentEntry().state.sampling_number + 1; -            npad.palma_lifo.WriteNextEntry(pad_state); +                npad->palma_lifo.ReadCurrentEntry().state.sampling_number + 1; +            npad->palma_lifo.WriteNextEntry(pad_state);              break;          default:              break; @@ -499,17 +499,13 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*          libnx_state.npad_buttons.raw = pad_state.npad_buttons.raw;          libnx_state.l_stick = pad_state.l_stick;          libnx_state.r_stick = pad_state.r_stick; -        npad.system_ext_lifo.WriteNextEntry(pad_state); +        npad->system_ext_lifo.WriteNextEntry(pad_state);          press_state |= static_cast<u64>(pad_state.npad_buttons.raw); - -        std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)), -                    &controller.shared_memory_entry, sizeof(NpadInternalState));      }  } -void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, -                                     std::size_t data_len) { +void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) {      if (!IsControllerActivated()) {          return;      } @@ -524,7 +520,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing              continue;          } -        auto& npad = controller.shared_memory_entry; +        auto* npad = controller.shared_memory;          const auto& motion_state = controller.device->GetMotions();          auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state;          auto& sixaxis_handheld_state = controller.sixaxis_handheld_state; @@ -610,32 +606,30 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing          }          sixaxis_fullkey_state.sampling_number = -            npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1; +            npad->sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;          sixaxis_handheld_state.sampling_number = -            npad.sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1; +            npad->sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;          sixaxis_dual_left_state.sampling_number = -            npad.sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1; +            npad->sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1;          sixaxis_dual_right_state.sampling_number = -            npad.sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1; +            npad->sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1;          sixaxis_left_lifo_state.sampling_number = -            npad.sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1; +            npad->sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1;          sixaxis_right_lifo_state.sampling_number = -            npad.sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1; +            npad->sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;          if (Core::HID::IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {              // This buffer only is updated on handheld on HW -            npad.sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state); +            npad->sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);          } else {              // Handheld doesn't update this buffer on HW -            npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state); +            npad->sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);          } -        npad.sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state); -        npad.sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state); -        npad.sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state); -        npad.sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state); -        std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)), -                    &controller.shared_memory_entry, sizeof(NpadInternalState)); +        npad->sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state); +        npad->sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state); +        npad->sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state); +        npad->sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state);      }  } @@ -713,8 +707,8 @@ void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceTy      }      auto& controller = GetControllerFromNpadIdType(npad_id); -    if (controller.shared_memory_entry.assignment_mode != assignment_mode) { -        controller.shared_memory_entry.assignment_mode = assignment_mode; +    if (controller.shared_memory->assignment_mode != assignment_mode) { +        controller.shared_memory->assignment_mode = assignment_mode;      }      if (!controller.device->IsConnected()) { @@ -981,32 +975,32 @@ void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {          controller.vibration[device_idx].device_mounted = false;      } -    auto& shared_memory_entry = controller.shared_memory_entry; -    // Don't reset shared_memory_entry.assignment_mode this value is persistent -    shared_memory_entry.style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out -    shared_memory_entry.device_type.raw = 0; -    shared_memory_entry.system_properties.raw = 0; -    shared_memory_entry.button_properties.raw = 0; -    shared_memory_entry.battery_level_dual = 0; -    shared_memory_entry.battery_level_left = 0; -    shared_memory_entry.battery_level_right = 0; -    shared_memory_entry.fullkey_color = { +    auto* shared_memory = controller.shared_memory; +    // Don't reset shared_memory->assignment_mode this value is persistent +    shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out +    shared_memory->device_type.raw = 0; +    shared_memory->system_properties.raw = 0; +    shared_memory->button_properties.raw = 0; +    shared_memory->battery_level_dual = 0; +    shared_memory->battery_level_left = 0; +    shared_memory->battery_level_right = 0; +    shared_memory->fullkey_color = {          .attribute = ColorAttribute::NoController,          .fullkey = {},      }; -    shared_memory_entry.joycon_color = { +    shared_memory->joycon_color = {          .attribute = ColorAttribute::NoController,          .left = {},          .right = {},      }; -    shared_memory_entry.applet_footer.type = AppletFooterUiType::None; +    shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::None;      controller.is_dual_left_connected = true;      controller.is_dual_right_connected = true;      controller.is_connected = false;      controller.device->Disconnect();      SignalStyleSetChangedEvent(npad_id); -    WriteEmptyEntry(controller.shared_memory_entry); +    WriteEmptyEntry(shared_memory);  }  ResultCode Controller_NPad::SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle, diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index b42532b68..0a96825a5 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -35,7 +35,7 @@ namespace Service::HID {  class Controller_NPad final : public ControllerBase {  public: -    explicit Controller_NPad(Core::HID::HIDCore& hid_core_, +    explicit Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,                               KernelHelpers::ServiceContext& service_context_);      ~Controller_NPad() override; @@ -46,11 +46,10 @@ public:      void OnRelease() override;      // When the controller is requesting an update for the shared memory -    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; +    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;      // When the controller is requesting a motion update for the shared memory -    void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, -                        std::size_t size) override; +    void OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) override;      // This is nn::hid::GyroscopeZeroDriftMode      enum class GyroscopeZeroDriftMode : u32 { @@ -188,6 +187,8 @@ public:      static bool IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle);  private: +    static constexpr std::size_t NPAD_COUNT = 10; +      // This is nn::hid::detail::ColorAttribute      enum class ColorAttribute : u32 {          Ok = 0, @@ -409,6 +410,13 @@ private:          U,      }; +    struct AppletNfcXcd { +        union { +            AppletFooterUi applet_footer{}; +            Lifo<NfcXcdDeviceHandleStateImpl, 0x2> nfc_xcd_device_lifo; +        }; +    }; +      // This is nn::hid::detail::NpadInternalState      struct NpadInternalState {          Core::HID::NpadStyleTag style_tag{Core::HID::NpadStyleSet::None}; @@ -435,10 +443,7 @@ private:          Core::HID::NpadBatteryLevel battery_level_dual{};          Core::HID::NpadBatteryLevel battery_level_left{};          Core::HID::NpadBatteryLevel battery_level_right{}; -        union { -            AppletFooterUi applet_footer{}; -            Lifo<NfcXcdDeviceHandleStateImpl, 0x2> nfc_xcd_device_lifo; -        }; +        AppletNfcXcd applet_nfc_xcd{};          INSERT_PADDING_BYTES(0x20); // Unknown          Lifo<NpadGcTriggerState, hid_entry_count> gc_trigger_lifo{};          NpadLarkType lark_type_l_and_main{}; @@ -465,9 +470,9 @@ private:      };      struct NpadControllerData { -        Core::HID::EmulatedController* device;          Kernel::KEvent* styleset_changed_event{}; -        NpadInternalState shared_memory_entry{}; +        NpadInternalState* shared_memory = nullptr; +        Core::HID::EmulatedController* device = nullptr;          std::array<VibrationData, 2> vibration{};          bool unintended_home_button_input_protection{}; @@ -497,15 +502,14 @@ private:          SixAxisSensorState sixaxis_dual_right_state{};          SixAxisSensorState sixaxis_left_lifo_state{};          SixAxisSensorState sixaxis_right_lifo_state{}; - -        int callback_key; +        int callback_key{};      };      void ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx);      void InitNewlyAddedController(Core::HID::NpadIdType npad_id);      bool IsControllerSupported(Core::HID::NpadStyleIndex controller) const;      void RequestPadStateUpdate(Core::HID::NpadIdType npad_id); -    void WriteEmptyEntry(NpadInternalState& npad); +    void WriteEmptyEntry(NpadInternalState* npad);      NpadControllerData& GetControllerFromHandle(          const Core::HID::SixAxisSensorHandle& device_handle); @@ -520,7 +524,7 @@ private:      std::atomic<u64> press_state{}; -    std::array<NpadControllerData, 10> controller_data{}; +    std::array<NpadControllerData, NPAD_COUNT> controller_data{};      KernelHelpers::ServiceContext& service_context;      std::mutex mutex;      std::vector<Core::HID::NpadIdType> supported_npad_id_types{}; diff --git a/src/core/hle/service/hid/controllers/stubbed.cpp b/src/core/hle/service/hid/controllers/stubbed.cpp index 4d3b9d2be..df9ee0c3f 100644 --- a/src/core/hle/service/hid/controllers/stubbed.cpp +++ b/src/core/hle/service/hid/controllers/stubbed.cpp @@ -9,15 +9,18 @@  namespace Service::HID { -Controller_Stubbed::Controller_Stubbed(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} +Controller_Stubbed::Controller_Stubbed(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) +    : ControllerBase{hid_core_} { +    raw_shared_memory = raw_shared_memory_; +} +  Controller_Stubbed::~Controller_Stubbed() = default;  void Controller_Stubbed::OnInit() {}  void Controller_Stubbed::OnRelease() {} -void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, -                                  std::size_t size) { +void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing) {      if (!smart_update) {          return;      } @@ -28,7 +31,7 @@ void Controller_Stubbed::OnUpdate(const Core::Timing::CoreTiming& core_timing, u      header.entry_count = 0;      header.last_entry_index = 0; -    std::memcpy(data + common_offset, &header, sizeof(CommonHeader)); +    std::memcpy(raw_shared_memory + common_offset, &header, sizeof(CommonHeader));  }  void Controller_Stubbed::SetCommonHeaderOffset(std::size_t off) { diff --git a/src/core/hle/service/hid/controllers/stubbed.h b/src/core/hle/service/hid/controllers/stubbed.h index 512066eb3..1483a968e 100644 --- a/src/core/hle/service/hid/controllers/stubbed.h +++ b/src/core/hle/service/hid/controllers/stubbed.h @@ -9,7 +9,7 @@  namespace Service::HID {  class Controller_Stubbed final : public ControllerBase {  public: -    explicit Controller_Stubbed(Core::HID::HIDCore& hid_core_); +    explicit Controller_Stubbed(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);      ~Controller_Stubbed() override;      // Called when the controller is initialized @@ -19,19 +19,20 @@ public:      void OnRelease() override;      // When the controller is requesting an update for the shared memory -    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; +    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;      void SetCommonHeaderOffset(std::size_t off);  private:      struct CommonHeader { -        s64 timestamp; -        s64 total_entry_count; -        s64 last_entry_index; -        s64 entry_count; +        s64 timestamp{}; +        s64 total_entry_count{}; +        s64 last_entry_index{}; +        s64 entry_count{};      };      static_assert(sizeof(CommonHeader) == 0x20, "CommonHeader is an invalid size"); +    u8* raw_shared_memory = nullptr;      bool smart_update{};      std::size_t common_offset{};  }; diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index 5b4b51a69..108ce5a41 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp @@ -15,8 +15,13 @@  namespace Service::HID {  constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400; -Controller_Touchscreen::Controller_Touchscreen(Core::HID::HIDCore& hid_core_) +Controller_Touchscreen::Controller_Touchscreen(Core::HID::HIDCore& hid_core_, +                                               u8* raw_shared_memory_)      : ControllerBase{hid_core_} { +    static_assert(SHARED_MEMORY_OFFSET + sizeof(TouchSharedMemory) < shared_memory_size, +                  "TouchSharedMemory is bigger than the shared memory"); +    shared_memory = std::construct_at( +        reinterpret_cast<TouchSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET));      console = hid_core.GetEmulatedConsole();  } @@ -26,14 +31,12 @@ void Controller_Touchscreen::OnInit() {}  void Controller_Touchscreen::OnRelease() {} -void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, -                                      std::size_t size) { -    touch_screen_lifo.timestamp = core_timing.GetCPUTicks(); +void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timing) { +    shared_memory->touch_screen_lifo.timestamp = core_timing.GetCPUTicks();      if (!IsControllerActivated()) { -        touch_screen_lifo.buffer_count = 0; -        touch_screen_lifo.buffer_tail = 0; -        std::memcpy(data, &touch_screen_lifo, sizeof(touch_screen_lifo)); +        shared_memory->touch_screen_lifo.buffer_count = 0; +        shared_memory->touch_screen_lifo.buffer_tail = 0;          return;      } @@ -74,7 +77,7 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin          static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter));      const u64 tick = core_timing.GetCPUTicks(); -    const auto& last_entry = touch_screen_lifo.ReadCurrentEntry().state; +    const auto& last_entry = shared_memory->touch_screen_lifo.ReadCurrentEntry().state;      next_state.sampling_number = last_entry.sampling_number + 1;      next_state.entry_count = static_cast<s32>(active_fingers_count); @@ -106,8 +109,7 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin          }      } -    touch_screen_lifo.WriteNextEntry(next_state); -    std::memcpy(data + SHARED_MEMORY_OFFSET, &touch_screen_lifo, sizeof(touch_screen_lifo)); +    shared_memory->touch_screen_lifo.WriteNextEntry(next_state);  }  } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index 424973b38..e57a3a80e 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h @@ -25,14 +25,14 @@ public:      // This is nn::hid::TouchScreenConfigurationForNx      struct TouchScreenConfigurationForNx { -        TouchScreenModeForNx mode; +        TouchScreenModeForNx mode{TouchScreenModeForNx::UseSystemSetting};          INSERT_PADDING_BYTES_NOINIT(0x7);          INSERT_PADDING_BYTES_NOINIT(0xF); // Reserved      };      static_assert(sizeof(TouchScreenConfigurationForNx) == 0x17,                    "TouchScreenConfigurationForNx is an invalid size"); -    explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_); +    explicit Controller_Touchscreen(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);      ~Controller_Touchscreen() override;      // Called when the controller is initialized @@ -42,26 +42,32 @@ public:      void OnRelease() override;      // When the controller is requesting an update for the shared memory -    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; +    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;  private:      static constexpr std::size_t MAX_FINGERS = 16;      // This is nn::hid::TouchScreenState      struct TouchScreenState { -        s64 sampling_number; -        s32 entry_count; +        s64 sampling_number{}; +        s32 entry_count{};          INSERT_PADDING_BYTES(4); // Reserved -        std::array<Core::HID::TouchState, MAX_FINGERS> states; +        std::array<Core::HID::TouchState, MAX_FINGERS> states{};      };      static_assert(sizeof(TouchScreenState) == 0x290, "TouchScreenState is an invalid size"); -    // This is nn::hid::detail::TouchScreenLifo -    Lifo<TouchScreenState, hid_entry_count> touch_screen_lifo{}; -    static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size"); +    struct TouchSharedMemory { +        // This is nn::hid::detail::TouchScreenLifo +        Lifo<TouchScreenState, hid_entry_count> touch_screen_lifo{}; +        static_assert(sizeof(touch_screen_lifo) == 0x2C38, "touch_screen_lifo is an invalid size"); +        INSERT_PADDING_WORDS(0xF2); +    }; +    static_assert(sizeof(TouchSharedMemory) == 0x3000, "TouchSharedMemory is an invalid size"); +      TouchScreenState next_state{}; +    TouchSharedMemory* shared_memory = nullptr; +    Core::HID::EmulatedConsole* console = nullptr; -    std::array<Core::HID::TouchFinger, MAX_FINGERS> fingers; -    Core::HID::EmulatedConsole* console; +    std::array<Core::HID::TouchFinger, MAX_FINGERS> fingers{};  };  } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/xpad.cpp b/src/core/hle/service/hid/controllers/xpad.cpp index fc6ac6457..62119e2c5 100644 --- a/src/core/hle/service/hid/controllers/xpad.cpp +++ b/src/core/hle/service/hid/controllers/xpad.cpp @@ -10,28 +10,31 @@  namespace Service::HID {  constexpr std::size_t SHARED_MEMORY_OFFSET = 0x3C00; -Controller_XPad::Controller_XPad(Core::HID::HIDCore& hid_core_) : ControllerBase{hid_core_} {} +Controller_XPad::Controller_XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_) +    : ControllerBase{hid_core_} { +    static_assert(SHARED_MEMORY_OFFSET + sizeof(XpadSharedMemory) < shared_memory_size, +                  "XpadSharedMemory is bigger than the shared memory"); +    shared_memory = std::construct_at( +        reinterpret_cast<XpadSharedMemory*>(raw_shared_memory_ + SHARED_MEMORY_OFFSET)); +}  Controller_XPad::~Controller_XPad() = default;  void Controller_XPad::OnInit() {}  void Controller_XPad::OnRelease() {} -void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, -                               std::size_t size) { +void Controller_XPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {      if (!IsControllerActivated()) { -        basic_xpad_lifo.buffer_count = 0; -        basic_xpad_lifo.buffer_tail = 0; -        std::memcpy(data + SHARED_MEMORY_OFFSET, &basic_xpad_lifo, sizeof(basic_xpad_lifo)); +        shared_memory->basic_xpad_lifo.buffer_count = 0; +        shared_memory->basic_xpad_lifo.buffer_tail = 0;          return;      } -    const auto& last_entry = basic_xpad_lifo.ReadCurrentEntry().state; +    const auto& last_entry = shared_memory->basic_xpad_lifo.ReadCurrentEntry().state;      next_state.sampling_number = last_entry.sampling_number + 1;      // TODO(ogniK): Update xpad states -    basic_xpad_lifo.WriteNextEntry(next_state); -    std::memcpy(data + SHARED_MEMORY_OFFSET, &basic_xpad_lifo, sizeof(basic_xpad_lifo)); +    shared_memory->basic_xpad_lifo.WriteNextEntry(next_state);  }  } // namespace Service::HID diff --git a/src/core/hle/service/hid/controllers/xpad.h b/src/core/hle/service/hid/controllers/xpad.h index 8211b6ee3..d01dee5fc 100644 --- a/src/core/hle/service/hid/controllers/xpad.h +++ b/src/core/hle/service/hid/controllers/xpad.h @@ -12,7 +12,7 @@  namespace Service::HID {  class Controller_XPad final : public ControllerBase {  public: -    explicit Controller_XPad(Core::HID::HIDCore& hid_core_); +    explicit Controller_XPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_);      ~Controller_XPad() override;      // Called when the controller is initialized @@ -22,7 +22,7 @@ public:      void OnRelease() override;      // When the controller is requesting an update for the shared memory -    void OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, std::size_t size) override; +    void OnUpdate(const Core::Timing::CoreTiming& core_timing) override;  private:      // This is nn::hid::BasicXpadAttributeSet @@ -90,17 +90,23 @@ private:      // This is nn::hid::detail::BasicXpadState      struct BasicXpadState { -        s64 sampling_number; -        BasicXpadAttributeSet attributes; -        BasicXpadButtonSet pad_states; -        Core::HID::AnalogStickState l_stick; -        Core::HID::AnalogStickState r_stick; +        s64 sampling_number{}; +        BasicXpadAttributeSet attributes{}; +        BasicXpadButtonSet pad_states{}; +        Core::HID::AnalogStickState l_stick{}; +        Core::HID::AnalogStickState r_stick{};      };      static_assert(sizeof(BasicXpadState) == 0x20, "BasicXpadState is an invalid size"); -    // This is nn::hid::detail::BasicXpadLifo -    Lifo<BasicXpadState, hid_entry_count> basic_xpad_lifo{}; -    static_assert(sizeof(basic_xpad_lifo) == 0x2C8, "basic_xpad_lifo is an invalid size"); +    struct XpadSharedMemory { +        // This is nn::hid::detail::BasicXpadLifo +        Lifo<BasicXpadState, hid_entry_count> basic_xpad_lifo{}; +        static_assert(sizeof(basic_xpad_lifo) == 0x2C8, "basic_xpad_lifo is an invalid size"); +        INSERT_PADDING_WORDS(0x4E); +    }; +    static_assert(sizeof(XpadSharedMemory) == 0x400, "XpadSharedMemory is an invalid size"); +      BasicXpadState next_state{}; +    XpadSharedMemory* shared_memory = nullptr;  };  } // namespace Service::HID diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index fb1ec52b2..eba44eda8 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -39,7 +39,6 @@ constexpr auto pad_update_ns = std::chrono::nanoseconds{4 * 1000 * 1000};  constexpr auto mouse_keyboard_update_ns = std::chrono::nanoseconds{8 * 1000 * 1000}; // (8ms, 125Hz)  // TODO: Correct update rate for motion is 5ms. Check why some games don't behave at that speed  constexpr auto motion_update_ns = std::chrono::nanoseconds{10 * 1000 * 1000}; // (10ms, 100Hz) -constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;  IAppletResource::IAppletResource(Core::System& system_,                                   KernelHelpers::ServiceContext& service_context_) @@ -48,20 +47,20 @@ IAppletResource::IAppletResource(Core::System& system_,          {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"},      };      RegisterHandlers(functions); - -    MakeController<Controller_DebugPad>(HidController::DebugPad); -    MakeController<Controller_Touchscreen>(HidController::Touchscreen); -    MakeController<Controller_Mouse>(HidController::Mouse); -    MakeController<Controller_Keyboard>(HidController::Keyboard); -    MakeController<Controller_XPad>(HidController::XPad); -    MakeController<Controller_Stubbed>(HidController::HomeButton); -    MakeController<Controller_Stubbed>(HidController::SleepButton); -    MakeController<Controller_Stubbed>(HidController::CaptureButton); -    MakeController<Controller_Stubbed>(HidController::InputDetector); -    MakeController<Controller_Stubbed>(HidController::UniquePad); -    MakeControllerWithServiceContext<Controller_NPad>(HidController::NPad); -    MakeController<Controller_Gesture>(HidController::Gesture); -    MakeController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor); +    u8* shared_memory = system.Kernel().GetHidSharedMem().GetPointer(); +    MakeController<Controller_DebugPad>(HidController::DebugPad, shared_memory); +    MakeController<Controller_Touchscreen>(HidController::Touchscreen, shared_memory); +    MakeController<Controller_Mouse>(HidController::Mouse, shared_memory); +    MakeController<Controller_Keyboard>(HidController::Keyboard, shared_memory); +    MakeController<Controller_XPad>(HidController::XPad, shared_memory); +    MakeController<Controller_Stubbed>(HidController::HomeButton, shared_memory); +    MakeController<Controller_Stubbed>(HidController::SleepButton, shared_memory); +    MakeController<Controller_Stubbed>(HidController::CaptureButton, shared_memory); +    MakeController<Controller_Stubbed>(HidController::InputDetector, shared_memory); +    MakeController<Controller_Stubbed>(HidController::UniquePad, shared_memory); +    MakeControllerWithServiceContext<Controller_NPad>(HidController::NPad, shared_memory); +    MakeController<Controller_Gesture>(HidController::Gesture, shared_memory); +    MakeController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor, shared_memory);      // Homebrew doesn't try to activate some controllers, so we activate them by default      GetController<Controller_NPad>(HidController::NPad).ActivateController(); @@ -135,8 +134,7 @@ void IAppletResource::UpdateControllers(std::uintptr_t user_data,          if (controller == controllers[static_cast<size_t>(HidController::Mouse)]) {              continue;          } -        controller->OnUpdate(core_timing, system.Kernel().GetHidSharedMem().GetPointer(), -                             SHARED_MEMORY_SIZE); +        controller->OnUpdate(core_timing);      }      // If ns_late is higher than the update rate ignore the delay @@ -151,10 +149,8 @@ void IAppletResource::UpdateMouseKeyboard(std::uintptr_t user_data,                                            std::chrono::nanoseconds ns_late) {      auto& core_timing = system.CoreTiming(); -    controllers[static_cast<size_t>(HidController::Mouse)]->OnUpdate( -        core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE); -    controllers[static_cast<size_t>(HidController::Keyboard)]->OnUpdate( -        core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE); +    controllers[static_cast<size_t>(HidController::Mouse)]->OnUpdate(core_timing); +    controllers[static_cast<size_t>(HidController::Keyboard)]->OnUpdate(core_timing);      // If ns_late is higher than the update rate ignore the delay      if (ns_late > mouse_keyboard_update_ns) { @@ -167,8 +163,7 @@ void IAppletResource::UpdateMouseKeyboard(std::uintptr_t user_data,  void IAppletResource::UpdateMotion(std::uintptr_t user_data, std::chrono::nanoseconds ns_late) {      auto& core_timing = system.CoreTiming(); -    controllers[static_cast<size_t>(HidController::NPad)]->OnMotionUpdate( -        core_timing, system.Kernel().GetHidSharedMem().GetPointer(), SHARED_MEMORY_SIZE); +    controllers[static_cast<size_t>(HidController::NPad)]->OnMotionUpdate(core_timing);      // If ns_late is higher than the update rate ignore the delay      if (ns_late > motion_update_ns) { @@ -362,7 +357,7 @@ Hid::Hid(Core::System& system_)          {1000, &Hid::SetNpadCommunicationMode, "SetNpadCommunicationMode"},          {1001, &Hid::GetNpadCommunicationMode, "GetNpadCommunicationMode"},          {1002, &Hid::SetTouchScreenConfiguration, "SetTouchScreenConfiguration"}, -        {1003, nullptr, "IsFirmwareUpdateNeededForNotification"}, +        {1003, &Hid::IsFirmwareUpdateNeededForNotification, "IsFirmwareUpdateNeededForNotification"},          {2000, nullptr, "ActivateDigitizer"},      };      // clang-format on @@ -1803,6 +1798,25 @@ void Hid::SetTouchScreenConfiguration(Kernel::HLERequestContext& ctx) {      rb.Push(ResultSuccess);  } +void Hid::IsFirmwareUpdateNeededForNotification(Kernel::HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    struct Parameters { +        s32 unknown; +        INSERT_PADDING_WORDS_NOINIT(1); +        u64 applet_resource_user_id; +    }; +    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size."); + +    const auto parameters{rp.PopRaw<Parameters>()}; + +    LOG_WARNING(Service_HID, "(STUBBED) called, unknown={}, applet_resource_user_id={}", +                parameters.unknown, parameters.applet_resource_user_id); + +    IPC::ResponseBuilder rb{ctx, 3}; +    rb.Push(ResultSuccess); +    rb.Push(false); +} +  class HidDbg final : public ServiceFramework<HidDbg> {  public:      explicit HidDbg(Core::System& system_) : ServiceFramework{system_, "hid:dbg"} { diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 95778e673..1be04c22b 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -58,13 +58,14 @@ public:  private:      template <typename T> -    void MakeController(HidController controller) { -        controllers[static_cast<std::size_t>(controller)] = std::make_unique<T>(system.HIDCore()); +    void MakeController(HidController controller, u8* shared_memory) { +        controllers[static_cast<std::size_t>(controller)] = +            std::make_unique<T>(system.HIDCore(), shared_memory);      }      template <typename T> -    void MakeControllerWithServiceContext(HidController controller) { +    void MakeControllerWithServiceContext(HidController controller, u8* shared_memory) {          controllers[static_cast<std::size_t>(controller)] = -            std::make_unique<T>(system.HIDCore(), service_context); +            std::make_unique<T>(system.HIDCore(), shared_memory, service_context);      }      void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); @@ -165,6 +166,7 @@ private:      void SetNpadCommunicationMode(Kernel::HLERequestContext& ctx);      void GetNpadCommunicationMode(Kernel::HLERequestContext& ctx);      void SetTouchScreenConfiguration(Kernel::HLERequestContext& ctx); +    void IsFirmwareUpdateNeededForNotification(Kernel::HLERequestContext& ctx);      std::shared_ptr<IAppletResource> applet_resource; diff --git a/src/core/hle/service/mii/raw_data.cpp b/src/core/hle/service/mii/raw_data.cpp index 9d3c8017a..1442280c8 100644 --- a/src/core/hle/service/mii/raw_data.cpp +++ b/src/core/hle/service/mii/raw_data.cpp @@ -1,22 +1,5 @@ -// MIT License -// -// Copyright (c) Ryujinx Team and Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -// associated documentation files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, publish, distribute, -// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// +// SPDX-FileCopyrightText: Ryujinx Team and Contributors +// SPDX-License-Identifier: MIT  #include "core/hle/service/mii/raw_data.h" diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index d0250bdb4..cf5933699 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -1,6 +1,6 @@ -// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later  #include <cstring>  #include <memory> diff --git a/src/core/loader/elf.h b/src/core/loader/elf.h index bff51ec17..acd33dc3d 100644 --- a/src/core/loader/elf.h +++ b/src/core/loader/elf.h @@ -1,6 +1,6 @@ -// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later  #pragma once diff --git a/src/input_common/drivers/gc_adapter.cpp b/src/input_common/drivers/gc_adapter.cpp index 8abd41726..27a0ffb0d 100644 --- a/src/input_common/drivers/gc_adapter.cpp +++ b/src/input_common/drivers/gc_adapter.cpp @@ -1,6 +1,5 @@ -// Copyright 2014 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2014 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later  #include <fmt/format.h>  #include <libusb.h> diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h index 894ab65a4..8682da847 100644 --- a/src/input_common/drivers/gc_adapter.h +++ b/src/input_common/drivers/gc_adapter.h @@ -1,6 +1,5 @@ -// Copyright 2014 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2014 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later  #pragma once diff --git a/src/shader_recompiler/ir_opt/verification_pass.cpp b/src/shader_recompiler/ir_opt/verification_pass.cpp index e2ef2b0b3..f89f4ac28 100644 --- a/src/shader_recompiler/ir_opt/verification_pass.cpp +++ b/src/shader_recompiler/ir_opt/verification_pass.cpp @@ -43,7 +43,7 @@ static void ValidateUses(const IR::Program& program) {              }          }      } -    for (const auto [inst, uses] : actual_uses) { +    for (const auto& [inst, uses] : actual_uses) {          if (inst->UseCount() != uses) {              throw LogicError("Invalid uses in block: {}", IR::DumpProgram(program));          } diff --git a/src/tests/core/core_timing.cpp b/src/tests/core/core_timing.cpp index e0c66fa2e..8358d36b5 100644 --- a/src/tests/core/core_timing.cpp +++ b/src/tests/core/core_timing.cpp @@ -1,6 +1,5 @@ -// Copyright 2016 Dolphin Emulator Project / 2017 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2016 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later  #include <catch2/catch.hpp> diff --git a/src/video_core/cdma_pusher.cpp b/src/video_core/cdma_pusher.cpp index 8dd840558..8e890a85e 100644 --- a/src/video_core/cdma_pusher.cpp +++ b/src/video_core/cdma_pusher.cpp @@ -1,22 +1,5 @@ -// MIT License -// -// Copyright (c) Ryujinx Team and Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -// associated documentation files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, publish, distribute, -// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// +// SPDX-FileCopyrightText: Ryujinx Team and Contributors +// SPDX-License-Identifier: MIT  #include <bit>  #include "command_classes/host1x.h" diff --git a/src/video_core/command_classes/codecs/h264.cpp b/src/video_core/command_classes/codecs/h264.cpp index 84f1fa938..e2acd54d4 100644 --- a/src/video_core/command_classes/codecs/h264.cpp +++ b/src/video_core/command_classes/codecs/h264.cpp @@ -1,22 +1,5 @@ -// MIT License -// -// Copyright (c) Ryujinx Team and Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -// associated documentation files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, publish, distribute, -// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// +// SPDX-FileCopyrightText: Ryujinx Team and Contributors +// SPDX-License-Identifier: MIT  #include <array>  #include <bit> diff --git a/src/video_core/command_classes/codecs/h264.h b/src/video_core/command_classes/codecs/h264.h index 1899d8e7f..261574364 100644 --- a/src/video_core/command_classes/codecs/h264.h +++ b/src/video_core/command_classes/codecs/h264.h @@ -1,22 +1,5 @@ -// MIT License -// -// Copyright (c) Ryujinx Team and Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -// associated documentation files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, publish, distribute, -// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// +// SPDX-FileCopyrightText: Ryujinx Team and Contributors +// SPDX-License-Identifier: MIT  #pragma once diff --git a/src/video_core/command_classes/sync_manager.cpp b/src/video_core/command_classes/sync_manager.cpp index 19dc9e0ab..67e58046f 100644 --- a/src/video_core/command_classes/sync_manager.cpp +++ b/src/video_core/command_classes/sync_manager.cpp @@ -1,22 +1,5 @@ -// MIT License -// -// Copyright (c) Ryujinx Team and Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -// associated documentation files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, publish, distribute, -// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// +// SPDX-FileCopyrightText: Ryujinx Team and Contributors +// SPDX-License-Identifier: MIT  #include <algorithm>  #include "sync_manager.h" diff --git a/src/video_core/command_classes/sync_manager.h b/src/video_core/command_classes/sync_manager.h index 2c321ec58..6dfaae080 100644 --- a/src/video_core/command_classes/sync_manager.h +++ b/src/video_core/command_classes/sync_manager.h @@ -1,22 +1,5 @@ -// MIT License -// -// Copyright (c) Ryujinx Team and Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -// associated documentation files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, publish, distribute, -// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// +// SPDX-FileCopyrightText: Ryujinx Team and Contributors +// SPDX-License-Identifier: MIT  #pragma once diff --git a/src/video_core/host_shaders/opengl_present_scaleforce.frag b/src/video_core/host_shaders/opengl_present_scaleforce.frag index 71ff9e1e3..a780373e3 100644 --- a/src/video_core/host_shaders/opengl_present_scaleforce.frag +++ b/src/video_core/host_shaders/opengl_present_scaleforce.frag @@ -1,24 +1,5 @@ -// MIT License -// -// Copyright (c) 2020 BreadFish64 -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. +// SPDX-FileCopyrightText: 2020 BreadFish64 +// SPDX-License-Identifier: MIT  // Adapted from https://github.com/BreadFish64/ScaleFish/tree/master/scaleforce diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 7a1d911eb..7c78d0299 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -127,6 +127,11 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {      if (!render_window.IsShown()) {          return;      } +    // Update screen info if the framebuffer size has changed. +    if (screen_info.width != framebuffer->width || screen_info.height != framebuffer->height) { +        screen_info.width = framebuffer->width; +        screen_info.height = framebuffer->height; +    }      const VAddr framebuffer_addr = framebuffer->address + framebuffer->offset;      const bool use_accelerated =          rasterizer.AccelerateDisplay(*framebuffer, framebuffer_addr, framebuffer->stride); diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp index a558f8deb..d469964f6 100644 --- a/src/video_core/shader_environment.cpp +++ b/src/video_core/shader_environment.cpp @@ -188,11 +188,11 @@ void GenericEnvironment::Serialize(std::ofstream& file) const {          .write(reinterpret_cast<const char*>(&cached_highest), sizeof(cached_highest))          .write(reinterpret_cast<const char*>(&stage), sizeof(stage))          .write(reinterpret_cast<const char*>(code.data()), code_size); -    for (const auto [key, type] : texture_types) { +    for (const auto& [key, type] : texture_types) {          file.write(reinterpret_cast<const char*>(&key), sizeof(key))              .write(reinterpret_cast<const char*>(&type), sizeof(type));      } -    for (const auto [key, type] : cbuf_values) { +    for (const auto& [key, type] : cbuf_values) {          file.write(reinterpret_cast<const char*>(&key), sizeof(key))              .write(reinterpret_cast<const char*>(&type), sizeof(type));      } diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp index 597382331..1820823b2 100644 --- a/src/video_core/texture_cache/util.cpp +++ b/src/video_core/texture_cache/util.cpp @@ -1,30 +1,11 @@  // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later +// SPDX-FileCopyrightText: Ryujinx Team and Contributors +// SPDX-License-Identifier: GPL-2.0-or-later AND MIT  // This files contains code from Ryujinx  // A copy of the code can be obtained from https://github.com/Ryujinx/Ryujinx  // The sections using code from Ryujinx are marked with a link to the original version -// MIT License -// -// Copyright (c) Ryujinx Team and Contributors -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -// associated documentation files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, publish, distribute, -// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// -  #include <algorithm>  #include <array>  #include <numeric> diff --git a/src/video_core/textures/astc.cpp b/src/video_core/textures/astc.cpp index 28e4beafd..e3f3d3c5d 100644 --- a/src/video_core/textures/astc.cpp +++ b/src/video_core/textures/astc.cpp @@ -1,17 +1,6 @@ -// Copyright 2016 The University of North Carolina at Chapel Hill -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -//    http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// +// SPDX-FileCopyrightText: 2016 The University of North Carolina at Chapel Hill +// SPDX-License-Identifier: Apache-2.0 +  // Please send all BUG REPORTS to <pavel@cs.unc.edu>.  // <http://gamma.cs.unc.edu/FasTC/> diff --git a/src/yuzu/configuration/configure_network.cpp b/src/yuzu/configuration/configure_network.cpp index f87d3d53a..8ed08fa6a 100644 --- a/src/yuzu/configuration/configure_network.cpp +++ b/src/yuzu/configuration/configure_network.cpp @@ -26,7 +26,15 @@ void ConfigureNetwork::ApplyConfiguration() {      Settings::values.network_interface = ui->network_interface->currentText().toStdString();  } -void ConfigureNetwork::RetranslateUi() { +void ConfigureNetwork::changeEvent(QEvent* event) { +    if (event->type() == QEvent::LanguageChange) { +        RetranslateUI(); +    } + +    QWidget::changeEvent(event); +} + +void ConfigureNetwork::RetranslateUI() {      ui->retranslateUi(this);  } diff --git a/src/yuzu/configuration/configure_network.h b/src/yuzu/configuration/configure_network.h index e8245cfdc..f666edbd1 100644 --- a/src/yuzu/configuration/configure_network.h +++ b/src/yuzu/configuration/configure_network.h @@ -18,9 +18,10 @@ public:      ~ConfigureNetwork() override;      void ApplyConfiguration(); -    void RetranslateUi();  private: +    void changeEvent(QEvent*) override; +    void RetranslateUI();      void SetConfiguration();      std::unique_ptr<Ui::ConfigureNetwork> ui; diff --git a/src/yuzu/configuration/configure_system.ui b/src/yuzu/configuration/configure_system.ui index 5b68dcb29..b234ea87b 100644 --- a/src/yuzu/configuration/configure_system.ui +++ b/src/yuzu/configuration/configure_system.ui @@ -474,9 +474,6 @@                <day>1</day>               </date>              </property> -            <property name="displayFormat"> -             <string>d MMM yyyy h:mm:ss AP</string> -            </property>             </widget>            </item>            <item row="6" column="1"> diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp index 46e5409db..d3a60cdd1 100644 --- a/src/yuzu/configuration/configure_ui.cpp +++ b/src/yuzu/configuration/configure_ui.cpp @@ -9,6 +9,7 @@  #include <QDirIterator>  #include "common/common_types.h"  #include "common/fs/path_util.h" +#include "common/logging/log.h"  #include "common/settings.h"  #include "core/core.h"  #include "ui_configure_ui.h" @@ -170,14 +171,74 @@ void ConfigureUi::RetranslateUI() {  }  void ConfigureUi::InitializeLanguageComboBox() { +    // This is a list of lexicographically sorted languages, only the available translations are +    // shown to the user. +    static const struct { +        const QString name; +        const char* id; +    } languages[] = { +        // clang-format off +        {QStringLiteral(u"Bahasa Indonesia"), "id"},                                 // Indonesian +        {QStringLiteral(u"Bahasa Melayu"), "ms"},                                    // Malay +        {QStringLiteral(u"Catal\u00E0"), "ca"},                                      // Catalan +        {QStringLiteral(u"\u010Ce\u0161tina"), "cs"},                                // Czech +        {QStringLiteral(u"Dansk"), "da"},                                            // Danish +        {QStringLiteral(u"Deutsch"), "de"},                                          // German +        {QStringLiteral(u"English"), "en"},                                          // English +        {QStringLiteral(u"Espa\u00F1ol"), "es"},                                     // Spanish +        {QStringLiteral(u"Fran\u00E7ais"), "fr"},                                    // French +        {QStringLiteral(u"Hrvatski"), "hr"},                                         // Croatian +        {QStringLiteral(u"Italiano"), "it"},                                         // Italian +        {QStringLiteral(u"Magyar"), "hu"},                                           // Hungarian +        {QStringLiteral(u"Nederlands"), "nl"},                                       // Dutch +        {QStringLiteral(u"Norsk bokm\u00E5l"), "nb"},                                // Norwegian +        {QStringLiteral(u"Polski"), "pl"},                                           // Polish +        {QStringLiteral(u"Portugu\u00EAs"), "pt_PT"},                                // Portuguese +        {QStringLiteral(u"Portugu\u00EAs (Brasil)"), "pt_BR"},                       // Portuguese (Brazil) +        {QStringLiteral(u"Rom\u00E2n\u0103"), "ro"},                                 // Romanian +        {QStringLiteral(u"Srpski"), "sr"},                                           // Serbian +        {QStringLiteral(u"Suomi"), "fi"},                                            // Finnish +        {QStringLiteral(u"Svenska"), "sv"},                                          // Swedish +        {QStringLiteral(u"Ti\u1EBFng Vi\u1EC7t"), "vi"},                             // Vietnamese +        {QStringLiteral(u"Ti\u1EBFng Vi\u1EC7t (Vi\u1EC7t Nam)"), "vi_VN"},          // Vietnamese +        {QStringLiteral(u"T\u00FCrk\u00E7e"), "tr_TR"},                              // Turkish +        {QStringLiteral(u"\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC"), "el"}, // Greek +        {QStringLiteral(u"\u0420\u0443\u0441\u0441\u043A\u0438\u0439"), "ru_RU"},    // Russian +        {QStringLiteral(u"\u0423\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430"), +         "uk"},                                                                      // Ukrainian +        {QStringLiteral(u"\u0627\u0644\u0639\u0631\u0628\u064A\u0629"), "ar"},       // Arabic +        {QStringLiteral(u"\u0641\u0627\u0631\u0633\u06CC"), "fa"},                   // Farsi +        {QStringLiteral(u"\uD55C\uAD6D\uC5B4"), "ko_KR"},                            // Korean +        {QStringLiteral(u"\u65E5\u672C\u8A9E"), "ja_JP"},                            // Japanese +        {QStringLiteral(u"\u7B80\u4F53\u4E2D\u6587"), "zh_CN"},                      // Simplified Chinese +        {QStringLiteral(u"\u7E41\u9AD4\u4E2D\u6587"), "zh_TW"},                      // Traditional Chinese +        // clang-format on +    };      ui->language_combobox->addItem(tr("<System>"), QString{}); -    ui->language_combobox->addItem(tr("English"), QStringLiteral("en")); -    QDirIterator it(QStringLiteral(":/languages"), QDirIterator::NoIteratorFlags); -    while (it.hasNext()) { -        QString locale = it.next(); +    QDir languages_dir{QStringLiteral(":/languages")}; +    QStringList language_files = languages_dir.entryList(); +    for (const auto& lang : languages) { +        if (QString::fromLatin1(lang.id) == QStringLiteral("en")) { +            ui->language_combobox->addItem(lang.name, QStringLiteral("en")); +            continue; +        } +        for (int i = 0; i < language_files.size(); ++i) { +            QString locale = language_files[i]; +            locale.truncate(locale.lastIndexOf(QLatin1Char{'.'})); +            if (QString::fromLatin1(lang.id) == locale) { +                ui->language_combobox->addItem(lang.name, locale); +                language_files.removeAt(i); +                break; +            } +        } +    } +    // Anything remaining will be at the bottom +    for (const QString& file : language_files) { +        LOG_CRITICAL(Frontend, "Unexpected Language File: {}", file.toStdString()); +        QString locale = file;          locale.truncate(locale.lastIndexOf(QLatin1Char{'.'})); -        locale.remove(0, locale.lastIndexOf(QLatin1Char{'/'}) + 1); -        const QString lang = QLocale::languageToString(QLocale(locale).language()); +        const QString language_name = QLocale::languageToString(QLocale(locale).language()); +        const QString lang = QStringLiteral("%1 [%2]").arg(language_name, locale);          ui->language_combobox->addItem(lang, locale);      } | 
