Compare commits

...

28 Commits

Author SHA1 Message Date
PabloMK7 b5126f979c
renderer_vulkan: Use proper image view on LCD fills (#91) 2024-04-23 21:42:19 +02:00
PabloMK7 a8e601ae7d
Fix showing color console if debugger attached on windows. (#88) 2024-04-22 23:37:59 +02:00
PabloMK7 d063f26efc
Remove resource limit checks for now. (#89) 2024-04-22 23:37:45 +02:00
PabloMK7 b1e5485058
Allow loading IPS files from Luma3DS folders. (#87) 2024-04-22 23:37:30 +02:00
Reg Tiangha de65b15dde
renderer_vulkan: Rewrite descriptor set management and various small fixes (#77)
* renderer_vulkan: Remove vulkan prefix in SetObjectName

* renderer_vulkan: Rename renderpass cache to render manager

* It is no longer just a cache

* renderer_vulkan: Rewrite descriptor management

* Switch to batched vkUpdateDescriptorSets from cached descriptor sets with templates

* vk_master_semaphore: Remove waitable atomic

* These are buggy on some platforms and regular condition_variables are faster most of the time

* vk_texture_runtime.cpp: remove outdated references

* vk_render_manager: Minor cleanups and rename to RenderManager

* It is no longer just a renderpass cache
* Revert variable name change from render_manager back to renderpass_cache

---------

Co-authored-by: GPUCode <geoster3d@gmail.com>
2024-04-22 22:43:36 +02:00
Malachi e26ceabfd1
vk_instance.cpp: fix getting driver_id for vulkan device (#67)
* vk_instance.cpp: fix getting driver_id for vulkan device

* apply clang-format (fixed)
2024-04-10 23:05:35 +03:00
GPUCode 9dfe3eb4bc
rasterizer_cache: Improve validation skip heuristic (#69) 2024-04-10 23:00:53 +03:00
GPUCode f5cf180cee
Merge pull request #59 from GPUCode/y2r
y2r: Delay completion event
2024-04-10 01:38:47 +03:00
GPUCode db3da09d85 y2r: Remove goto 2024-04-10 01:23:31 +03:00
GPUCode 5691cf7e91 y2r: Delay completion event 2024-04-07 00:15:18 +03:00
PabloMK7 0c2f076dc4
Add svcs to get and set the emulation speed. (#57) 2024-04-06 13:00:58 +02:00
PabloMK7 775ceac27d
Reduce log levels for some FS functions and stub cache svcs (#51) 2024-04-05 13:49:36 +02:00
Reg Tiangha 7fc382479d
Delete unused files (#52) 2024-04-05 13:48:37 +02:00
Miguel 8e35df1a6c
Remove the telemetry (#45)
* remove the telemetry except from the renderers as I'm not being capable to remove it from there

* remove the telemetry except from the renderers as I'm not being capable to remove it from there

* Remove remainder of non-functional Telemetry and Citra Web Services

Squashed commit of the following:

commit f6dd4d4579c91db323877f0d08b9c01c82e1bb32
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 14:02:26 2024 -0600

    gl_driver.h: add back missing functions

commit 8f14384e7a7b763c3f2ccb3af6b5a59df641d9ee
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 13:56:16 2024 -0600

    gl_driver.cpp: add back missing functions

commit 5c802524b01a6eb05952d88ccf9dd78d63baee0a
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 13:39:46 2024 -0600

    apply clang-format

commit e8f62a7d3ee8a3da885a28bce21bcfcb84f13a84
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 13:16:22 2024 -0600

    remove web_tab

commit ced7f1e4909ae7b2714a96e3c3fa0500e8c62968
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 13:13:47 2024 -0600

    remove unused call?

commit f10e05da887e4570853fae2bd55a71087b4bcc77
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 13:03:47 2024 -0600

    fix build errors

commit 0489c1770b4b48d51f626145ae9235d3c81029fc
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 12:54:35 2024 -0600

    Remove deleted files

commit b2eb56f5a1f01663cc9874d99fe77ee64b48622b
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 12:43:17 2024 -0600

    Remove ConfigureWeb

commit b96f7c724006b2c5ee2272becaa70584fe90d012
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 11:49:51 2024 -0600

    remove unused DebugHandler

commit 91ddf16f63f9ae07b0cb2768171728dc878d1653
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 11:41:31 2024 -0600

    remove CollectToolingInfo() reference

commit 3909ac0502f23f8fb54944b53d5072b6986f8ffd
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 11:33:39 2024 -0600

    Fix "clean renderer_vulkan.cpp"

    This reverts commit 8a882658da9fabca40d71d73bfaf3bb5702acd72.

commit f4a10c4e4f27471b0a263ac363a6fa2abc9d6dc9
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 11:25:12 2024 -0600

    remove Core() references

commit 5593b8484e7c9f525ea218902dd2c13148d86b37
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 11:09:26 2024 -0600

    clean core/core.cpp

commit 55bbd8ad283297ef79db11e19ca6303fdfba6626
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 11:03:45 2024 -0600

    apply clang-format

commit 3707a0b2705dd415876130c9c90b0916bdea11db
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 11:02:16 2024 -0600

    citra_qt/main.h

commit ddbdea9be4d8179a333e04e7c302e215868715a9
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 11:01:30 2024 -0600

    clean common/detached_tasks.h

commit b513ba3b91ebc81bddd634b5690b6434824e1c7a
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 10:58:51 2024 -0600

    clean android/app/src/main/jni/default_ini.h

commit b6ba7d7cd730393883fdca294c651a4186727b55
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 10:58:14 2024 -0600

    clean android/app/src/main/jni/native.cpp

commit 2351305bb24b005920af0f3f7bb6bbb5bb3124bd
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 10:56:59 2024 -0600

    network/network_settings.h

commit 5b4c1ebb97c7fad5daf7789e1d3640041c2412fb
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 10:55:53 2024 -0600

    clean citra_qt/configuration/configure_web.ui

commit 9526d5122995c2e9c52b4d93b6e836a2ea4c80ef
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 10:54:53 2024 -0600

    citra_qt/configuration/config.cpp

commit ec6fe57412ce97e06096fc07f8b86dd080b7b944
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 10:53:50 2024 -0600

    clean citra/default_ini.h

commit acba1cf7e94de2fa87174e9f6d7c7c4554146352
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 10:52:47 2024 -0600

    clean citra/config.cpp

commit 02888777590d4e4bf1423e168a672ca0c5e140e5
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 10:50:42 2024 -0600

    clean vk_instance.cpp

commit eae451d5825b3601382c3a6dd08a3bde5c7a9460
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 10:48:53 2024 -0600

    clean vk_instanch.h

commit 8a882658da9fabca40d71d73bfaf3bb5702acd72
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 10:47:11 2024 -0600

    clean renderer_vulkan.cpp

commit ea6df111bc447913d2999acd86de984acced7eeb
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 10:45:51 2024 -0600

    clean renderer_opengl.cpp

commit 6b1bea0ef8cf8831c520d1c4e90b9d73d421c764
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 10:44:17 2024 -0600

    clean pica_to_gl.h

commit c12e984045a430cb10500241ada68701f73c85ac
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 10:42:48 2024 -0600

    clean gl_driver.h

commit ca3fe7801fff125a1ab8706bfc3998ca2928bded
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 10:40:14 2024 -0600

    clean gl_driver.cpp

commit d57381c38b217a423a7039bc7b413d79f59c2ff1
Author: Reg Tiangha <rtiangha@users.noreply.github.com>
Date:   Fri Mar 29 10:38:44 2024 -0600

    delete telemetry files

commit 1af826d1a045c5568a0d9ef4ca423514f298aee2
Author: Miguel <81558772+Miguel-hrvs@users.noreply.github.com>
Date:   Wed Mar 27 16:17:58 2024 +0100

    remove the telemetry except from the renderers as I'm not being capable to remove it from there

* rebase renderer_vulkan

* clean up renderer_vulkan

* bring back vulkan gpu logging

* clang-format vk_instance.h

* fix-formatting

---------

Co-authored-by: Reg Tiangha <rtiangha@users.noreply.github.com>
2024-04-02 20:25:36 +02:00
GPUCode a442389a60
Merge pull request #41 from rtiangha/build-fixes
Some build fixes for GCC 13.2.0 and Clang 18.1.1
2024-03-24 13:43:48 +02:00
Reg Tiangha 12b30be45e
apply clang-format 2024-03-23 09:53:04 -06:00
Reg Tiangha b90569700c
fix build error with modern openal-soft 2024-03-22 16:52:23 -06:00
Reg Tiangha 0500b993e0
Copilot AI suggestions to comply with LLVM 19 2024-03-22 16:51:41 -06:00
Reg Tiangha 69eba0d295
fix build issue with gcc 13.2.0 2024-03-22 16:51:16 -06:00
GPUCode 8433057909
renderer_vulkan: Disable dynamic index conditionally (#20) 2024-03-07 12:12:21 +01:00
PabloMK7 c4c90f0190
Remove dependencies to old docker containers (#21)
* Fix CI

* Change missing yml
2024-03-06 18:38:51 +01:00
PabloMK7 813d0c2a30
Add console unique data (SecureInfo, LocalFriendCodeSeed, CTCert) (#6)
* Add console unique secure data

* Add CTCert and DeviceID support

* Fix AM_U::GetDeviceID

Co-authored-by: Daniel López Guimaraes <112760654+DaniElectra@users.noreply.github.com>

* Update to latest master changes.

---------

Co-authored-by: Daniel López Guimaraes <112760654+DaniElectra@users.noreply.github.com>
2024-03-05 14:52:17 +01:00
PabloMK7 f112d975b9
Add log regex filter (#9) 2024-03-05 14:51:58 +01:00
PabloMK7 bf0127d0ae
Add HOST_TICK and BUILD_PLATFORM to svcGetSystemInfo CITRA_INFORMATION type (#8)
* Add HOST_TICK to svcGetSystemInfo CITRA_INFORMATION type

* Add BUILD_PLATFORM
2024-03-05 14:07:04 +01:00
PabloMK7 c710c0009f
Implement plugin loader Mode3 mem strategy (#7) 2024-03-05 14:06:50 +01:00
PabloMK7 f5316532e6
Revert "Implement some missing/wrong AC functionality." (#5)
* Revert "Implement some missing/wrong AC functionality."

* Remove setting wifi level from nwm
2024-03-05 13:26:48 +01:00
PabloMK7 cb75e1d637 Update README.md 2024-03-05 12:39:15 +01:00
PabloMK7 06b3bed49a Update .gitmodules 2024-03-05 09:43:31 +01:00
156 changed files with 1976 additions and 5910 deletions

View File

@ -9,7 +9,7 @@ COMPAT_LIST='dist/compatibility_list/compatibility_list.json'
mkdir artifacts
pip3 install git-archive-all
wget -q https://api.citra-emu.org/gamedb -O "${COMPAT_LIST}"
touch "${COMPAT_LIST}"
git describe --abbrev=0 --always HEAD > GIT-COMMIT
git describe --tags HEAD > GIT-TAG || echo 'unknown' > GIT-TAG
git archive-all --include "${COMPAT_LIST}" --include GIT-COMMIT --include GIT-TAG --force-submodules artifacts/"${REV_NAME}.tar"

View File

@ -28,7 +28,7 @@ jobs:
matrix:
target: ["appimage", "fresh"]
container:
image: citraemu/build-environments:linux-${{ matrix.target }}
image: pablomk7/build-environments:linux-${{ matrix.target }}
options: -u 1001
env:
CCACHE_DIR: ${{ github.workspace }}/.ccache

View File

@ -200,7 +200,7 @@ async function mergebot(github, context, execa) {
}
console.info("The following pull requests will be merged:");
console.table(displayList);
await fetchPullRequests(pulls, "https://github.com/citra-emu/citra", execa);
await fetchPullRequests(pulls, "https://github.com/PabloMK7/citra", execa);
const mergeResults = await mergePullRequests(pulls, execa);
await generateReadme(pulls, context, mergeResults, execa);
await tagAndPush(github, context.repo.owner, `${context.repo.repo}-canary`, execa, true);

View File

@ -10,7 +10,7 @@ jobs:
clang-format:
runs-on: ubuntu-latest
container:
image: citraemu/build-environments:linux-fresh
image: pablomk7/build-environments:linux-fresh
options: -u 1001
steps:
- uses: actions/checkout@v4

View File

@ -1,100 +0,0 @@
name: citra-publish
on:
schedule:
- cron: '7 0 * * *'
workflow_dispatch:
inputs:
nightly:
description: 'Whether to trigger a nightly build (true/false/auto)'
required: false
default: 'true'
canary:
description: 'Whether to trigger a canary build (true/false/auto)'
required: false
default: 'true'
jobs:
nightly:
runs-on: ubuntu-latest
if: ${{ github.event.inputs.nightly != 'false' && github.repository == 'citra-emu/citra' }}
steps:
# this checkout is required to make sure the GitHub Actions scripts are available
- uses: actions/checkout@v4
name: Pre-checkout
with:
submodules: false
- uses: actions/github-script@v7
id: check-changes
name: 'Check for new changes'
env:
# 24 hours
DETECTION_TIME_FRAME: 86400000
with:
result-encoding: string
script: |
if (context.payload.inputs && context.payload.inputs.nightly === 'true') return true;
const checkBaseChanges = require('./.github/workflows/ci-merge.js').checkBaseChanges;
return checkBaseChanges(github, context);
- run: npm install execa@5
if: ${{ steps.check-changes.outputs.result == 'true' }}
- uses: actions/checkout@v4
name: Checkout
if: ${{ steps.check-changes.outputs.result == 'true' }}
with:
path: 'citra-merge'
fetch-depth: 0
submodules: true
token: ${{ secrets.ALT_GITHUB_TOKEN }}
- uses: actions/github-script@v7
name: 'Update and tag new commits'
if: ${{ steps.check-changes.outputs.result == 'true' }}
env:
ALT_GITHUB_TOKEN: ${{ secrets.ALT_GITHUB_TOKEN }}
with:
script: |
const execa = require("execa");
const tagAndPush = require('./.github/workflows/ci-merge.js').tagAndPush;
process.chdir('${{ github.workspace }}/citra-merge');
tagAndPush(github, context.repo.owner, `${context.repo.repo}-nightly`, execa);
canary:
runs-on: ubuntu-latest
if: ${{ github.event.inputs.canary != 'false' && github.repository == 'citra-emu/citra' }}
steps:
# this checkout is required to make sure the GitHub Actions scripts are available
- uses: actions/checkout@v4
name: Pre-checkout
with:
submodules: false
- uses: actions/github-script@v7
id: check-changes
name: 'Check for new changes'
env:
# 24 hours
DETECTION_TIME_FRAME: 86400000
with:
script: |
if (context.payload.inputs && context.payload.inputs.canary === 'true') return true;
const checkCanaryChanges = require('./.github/workflows/ci-merge.js').checkCanaryChanges;
return checkCanaryChanges(github, context);
- run: npm install execa@5
if: ${{ steps.check-changes.outputs.result == 'true' }}
- uses: actions/checkout@v4
name: Checkout
if: ${{ steps.check-changes.outputs.result == 'true' }}
with:
path: 'citra-merge'
fetch-depth: 0
submodules: true
token: ${{ secrets.ALT_GITHUB_TOKEN }}
- uses: actions/github-script@v7
name: 'Check and merge canary changes'
if: ${{ steps.check-changes.outputs.result == 'true' }}
env:
ALT_GITHUB_TOKEN: ${{ secrets.ALT_GITHUB_TOKEN }}
with:
script: |
const execa = require("execa");
const mergebot = require('./.github/workflows/ci-merge.js').mergebot;
process.chdir('${{ github.workspace }}/citra-merge');
mergebot(github, context, execa);

View File

@ -7,7 +7,7 @@ on:
jobs:
transifex:
runs-on: ubuntu-latest
container: citraemu/build-environments:linux-fresh
container: pablomk7/build-environments:linux-fresh
if: ${{ github.repository == 'citra-emu/citra' }}
steps:
- uses: actions/checkout@v4

12
.gitmodules vendored
View File

@ -1,6 +1,6 @@
[submodule "boost"]
path = externals/boost
url = https://github.com/citra-emu/ext-boost.git
url = https://github.com/PabloMK7/ext-boost.git
[submodule "nihstro"]
path = externals/nihstro
url = https://github.com/neobrain/nihstro.git
@ -12,7 +12,7 @@
url = https://github.com/catchorg/Catch2
[submodule "dynarmic"]
path = externals/dynarmic
url = https://github.com/merryhime/dynarmic.git
url = https://github.com/PabloMK7/dynarmic.git
[submodule "xbyak"]
path = externals/xbyak
url = https://github.com/herumi/xbyak.git
@ -27,7 +27,7 @@
url = https://github.com/benhoyt/inih.git
[submodule "libressl"]
path = externals/libressl
url = https://github.com/citra-emu/ext-libressl-portable.git
url = https://github.com/PabloMK7/ext-libressl-portable.git
[submodule "libusb"]
path = externals/libusb/libusb
url = https://github.com/libusb/libusb.git
@ -36,7 +36,7 @@
url = https://github.com/mozilla/cubeb
[submodule "discord-rpc"]
path = externals/discord-rpc
url = https://github.com/yuzu-emu/discord-rpc.git
url = https://github.com/PabloMK7/discord-rpc.git
[submodule "cpp-jwt"]
path = externals/cpp-jwt
url = https://github.com/arun11299/cpp-jwt.git
@ -78,13 +78,13 @@
url = https://github.com/KhronosGroup/Vulkan-Headers
[submodule "sirit"]
path = externals/sirit
url = https://github.com/yuzu-emu/sirit
url = https://github.com/PabloMK7/sirit
[submodule "faad2"]
path = externals/faad2/faad2
url = https://github.com/knik0/faad2
[submodule "library-headers"]
path = externals/library-headers
url = https://github.com/citra-emu/ext-library-headers.git
url = https://github.com/PabloMK7/ext-library-headers.git
[submodule "libadrenotools"]
path = externals/libadrenotools
url = https://github.com/bylaws/libadrenotools

View File

@ -1,98 +1 @@
<h1 align="center">
<br>
<a href="https://citra-emu.org/"><img src="https://raw.githubusercontent.com/citra-emu/citra-assets/master/Main/citra_logo.svg" alt="Citra" width="200"></a>
<br>
<b>Citra</b>
<br>
</h1>
<h4 align="center"><b>Citra</b> is the world's most popular, open-source, Nintendo 3DS emulator.
<br>
It is written in C++ with portability in mind and builds are actively maintained for Windows, Linux, Android and macOS.
</h4>
<p align="center">
<a href="https://github.com/citra-emu/citra/actions/">
<img src="https://github.com/citra-emu/citra/workflows/citra-ci/badge.svg"
alt="GitHub Actions Build Status">
</a>
<a href="https://discord.gg/FAXfZV9">
<img src="https://img.shields.io/discord/220740965957107713?color=%237289DA&label=Citra&logo=discord&logoColor=white"
alt="Discord">
</a>
</p>
<p align="center">
<a href="#compatibility">Compatibility</a> |
<a href="#releases">Releases</a> |
<a href="#development">Development</a> |
<a href="#building">Building</a> |
<a href="#support">Support</a> |
<a href="#license">License</a>
</p>
## Compatibility
The emulator is capable of running most commercial games at full speed, provided you meet the necessary hardware requirements.
For a full list of games Citra supports, please visit our [Compatibility page](https://citra-emu.org/game/)
Check out our [website](https://citra-emu.org/) for the latest news on exciting features, progress reports, and more!
Please read the [FAQ](https://citra-emu.org/wiki/faq/) before getting started with the project.
Need help? Check out our [asking for help](https://citra-emu.org/help/reference/asking/) guide.
## Releases
Citra has two main release channels: Nightly and Canary.
The [Nightly](https://github.com/citra-emu/citra-nightly) build is based on the master branch, and contains already reviewed and tested features.
The [Canary](https://github.com/citra-emu/citra-canary) build is based on the master branch, but with additional features still under review. PRs tagged `canary-merge` are merged only into the Canary builds.
Both builds can be installed with the installer provided on the [website](https://citra-emu.org/download/), but those looking for specific versions or standalone releases can find them in the release tabs of the [Nightly](https://github.com/citra-emu/citra-nightly/releases) and [Canary](https://github.com/citra-emu/citra-canary/releases) repositories.
Android builds can be downloaded from the Google Play Store.
A Flatpak for Citra is available on [Flathub](https://flathub.org/apps/details/org.citra_emu.citra). Details on the build process can be found in [our Flathub repository](https://github.com/flathub/org.citra_emu.citra).
## Development
Most of the development happens on GitHub. It's also where [our central repository](https://github.com/citra-emu/citra) is hosted.
For development discussion, please join us on our [Discord server](https://citra-emu.org/discord/) or at #citra-dev on libera.
If you want to contribute please take a look at the [Contributor's Guide](https://github.com/citra-emu/citra/wiki/Contributing) and [Developer Information](https://github.com/citra-emu/citra/wiki/Developer-Information). You can also contact any of the developers on Discord in order to know about the current state of the emulator.
If you want to contribute to the user interface translation, please check out the [Citra project on transifex](https://www.transifex.com/citra/citra). We centralize the translation work there, and periodically upstream translations.
## Building
* __Windows__: [Windows Build](https://github.com/citra-emu/citra/wiki/Building-For-Windows)
* __Linux__: [Linux Build](https://github.com/citra-emu/citra/wiki/Building-For-Linux)
* __macOS__: [macOS Build](https://github.com/citra-emu/citra/wiki/Building-for-macOS)
* __Android__: [Android Build](https://github.com/citra-emu/citra/wiki/Building-for-Android)
## Support
If you enjoy the project and want to support us financially, check out our Patreon!
<a href="https://www.patreon.com/citraemu">
<img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" width="160">
</a>
We also happily accept donated games and hardware.
Please see our [donations page](https://citra-emu.org/donate/) for more information on how you can contribute to Citra.
Any donations received will go towards things like:
* 3DS consoles for developers to explore the hardware
* 3DS games for testing
* Any equipment required for homebrew
* Infrastructure setup
We also more than gladly accept used 3DS consoles! If you would like to give yours away, don't hesitate to join our [Discord server](https://citra-emu.org/discord/) and talk to bunnei.
## License
Citra is licensed under the GPLv2 (or any later version). Refer to the [LICENSE.txt](https://github.com/citra-emu/citra/blob/master/license.txt) file.
ñ

View File

@ -3583,142 +3583,6 @@ Drag points to change position, or double-click table cells to edit values.</sou
<translation>Engelsk</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation>Form</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Citras webservice</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation>Ved at give dit brugernavn og token, accepterer du at Citra indsamler yderligere brugsdata, som måske kan indeholde brugeridentificerende information.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation>Bekræft</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation>Opret konto</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation>Token:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation>Brugernavn:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation>Hvad er min token?</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation>Konfiguration af webservicen kan kun ændres mens du ikke er vært af et offentligt rum.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation>Telemetri</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Del anonym brugsdata med udviklerne af Citra</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation>Lær mere</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation>Telemetri-id:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation>Generer nyt</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Discord-presence</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation>Vis kørende spil som din Discord-status</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Lær mere&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Opret bruger&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Hvad er min token?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation>Telemetri-id: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>Godkender...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation>Bekræftelse mislykkedes</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation type="unfinished"/>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -6997,4 +6861,4 @@ They may have left the room.</source>
<translation>Afventningstræ</translation>
</message>
</context>
</TS>
</TS>

138
dist/languages/de.ts vendored
View File

@ -3585,142 +3585,6 @@ Ziehe Punkte, um ihre Position zu verändern, oder doppelklicke auf Zellen in de
<translation>Englisch</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation>Form</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Citra Web Service</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation>Mit dem Bereitstellen Ihres Nutzernamens und Tokens, erlauben Sie Citra, zusätzliche Nutzungsdaten zu sammeln. Die Nutzungsdaten können auch Daten zur Nutzeridentifikation beinhalten.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation>Verifizieren</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation>Registrieren</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation>Token: </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation>Nutzername:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation>Was ist mein Token?</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation>Die Web-Service-Konfiguration kann nur geändert werden, wenn kein öffentlicher Raum gehostet wird.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation>Telemetrie</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Anonyme Nutzungsdaten an das Citra-Team senden</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation>Mehr erfahren</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation>Telemetrie-ID:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation>Regenerieren</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Discord Presence</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation>Aktuelles Spiel in Ihrem Discordstatus anzeigen</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Mehr erfahren&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Anmelden&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Was ist mein Token?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation>Nicht spezifiziert</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation>Telemetrie-ID: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation>Token nicht verifiziert</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation>Der Token wurde nicht verifiziert. Die Änderung zu dem Token wurde nicht gespeichert.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>Verifizieren...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation>Verifizierung fehlgeschlagen</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation>Verifizierung fehlgeschlagen. Stellen Sie sicher, dass Sie sowohl Ihren Token korrekt eingegeben haben und dass Sie mit dem Internet verbunden sind.</translation>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -7004,4 +6868,4 @@ They may have left the room.</source>
<translation>Wait Tree</translation>
</message>
</context>
</TS>
</TS>

138
dist/languages/el.ts vendored
View File

@ -3584,142 +3584,6 @@ Drag points to change position, or double-click table cells to edit values.</sou
<translation>Αγγλικά</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation>Φόρμα</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Citra Web Service</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation>Παρέχοντας το όνομα χρήστη και το αναγνωριστικό σας, επιτρέπετε στο Citra να συλλέξει περισσότερα δεδομένα χρήσης, που ενδέχεται να περιέχουν αναγνωριστικές πληροφορίες χρήστη.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation>Επαλήθευση</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation>Εγγραφή</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation>Αναγνωριστικό: </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation>Όνομα χρήστη:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation>Ποιο είναι το αναγνωριστικό μου;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation>Η ρύθμιση της διαδικτυακής υπηρεσίας μπορεί να αλλάξει μόνο όταν δεν είναι σε λειτουργία κάποιο δημόσιο δωμάτιο.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation>Τηλεμετρία</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Κοινοποίηση ανώνυμων δεδομένων χρήσης στην ομάδα του Citra</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation>Μάθετε περισσότερα</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation>ID τηλεμετρίας:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation>Επαναδημιουργία</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Παρουσία Discord</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation>Εμφάνιση τρέχοντος παιχνιδιού στην κατάσταση Discord σας</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Μάθετε περισσότερα&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Εγγραφή&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Ποιο είναι το αναγνωριστικό μου;&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation>Δεν έχει καθοριστεί</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation>ID τηλεμετρίας: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation>Μη επαληθευμένο αναγνωριστικό</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation>Το αναγνωριστικό δεν επαληθεύτηκε. Η αλλαγή στο αναγνωριστικό σας δεν έχει αποθηκευτεί.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>Επαλήθευση...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation>Αποτυχία επαλήθευσης</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation>Αποτυχία επαλήθευσης. Βεβαιωθείτε ότι έχετε εισαγάγει σωστά το αναγνωστικό σας και ότι λειτουργεί η σύνδεσή σας στο διαδίκτυο.</translation>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -7001,4 +6865,4 @@ They may have left the room.</source>
<translation>Δένδρο αναμονής</translation>
</message>
</context>
</TS>
</TS>

View File

@ -3585,142 +3585,6 @@ Mueve los puntos para cambiar la posición, o haz doble click en las celdas de l
<translation>Inglés (English)</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation>Formulario</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Servicio Web de Citra</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation>Al dar tu nombre de usuario y tu token, das tu consentimiento a que Citra recopile datos de uso adicionales, que pueden incluir información que identifique al usuario.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation>Verificar</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation>Registrarse</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation>Token:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation>Nombre de usuario:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation>¿Cuál es mi token?</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation>La configuración del Servicio Web sólo puede ser cambiada cuando una sala pública no está siendo alojada.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation>Telemetría</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Compartir datos de uso anónimos con el equipo de Citra</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation>Más Información</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation>ID de Telemetría:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation>Regenerar</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Presencia en Discord</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation>Mostrar Juego Actual en el Estado de Discord</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Más información&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Regístrate&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;¿Cuál es mi token?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation>Sin especificar</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation>ID de Telemetría: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation>Token no verificado</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation>El token no ha sido verificado. El cambio a tu token no se ha guardado.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>Verificando...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation>La verificación falló</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation>La verificación ha fallado. Comprueba que has introducido tu token correctamente y que tu conexión a Internet funcione correctamente.</translation>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -7014,4 +6878,4 @@ Puede que haya dejado la sala.</translation>
<translation>Árbol de Espera</translation>
</message>
</context>
</TS>
</TS>

138
dist/languages/fi.ts vendored
View File

@ -3583,142 +3583,6 @@ Drag points to change position, or double-click table cells to edit values.</sou
<translation>Englanti</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation>Muot</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Citran Nettipalvelu</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation>Todenna</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation>Rekisteröidy</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation>Avain:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation>Käyttäjänimi</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation>Mikä on avaimeni?</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation>Telemetria</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Jaa anonyymejä käyttötietoja Citran tekiöiden kanssa</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation>Opi lisää</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation>Telemetria tunnus:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation>Uudista</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Discord läsnäolo</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation>Näytä nykyinen peli Discord tilassa</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Lue lisää&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Kirjaudu&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Mikä on avaimeni?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation>Telemetria tunnus: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>Varmennetaan...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation>Varmennus epäonnistui</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation type="unfinished"/>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -6981,4 +6845,4 @@ They may have left the room.</source>
<translation type="unfinished"/>
</message>
</context>
</TS>
</TS>

138
dist/languages/fr.ts vendored
View File

@ -3585,142 +3585,6 @@ Glissez les points pour modifier la position, ou double-cliquez les cellules pou
<translation>Anglais</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation>Forme</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Service web de Citra</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation>En fournissant votre nom d&apos;utilisateur et votre jeton, vous acceptez d&apos;autoriser Citra à collecter des données d&apos;utilisation supplémentaires, qui peuvent inclure des informations d&apos;identification de l&apos;utilisateur.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation>Vérifier</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation>S&apos;inscrire</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation>Jeton :</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation>Nom d&apos;utilisateur</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation>Quel est mon jeton ?</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation>La configuration du service Web ne peut être modifiée que si un salon publique n&apos;est pas en cours d&apos;hébergement.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation>Télémétrie</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Partage des données d&apos;utilisation anonymes avec l&apos;équipe Citra</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation>En savoir plus</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation>ID de télémétrie :</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation>Régénérer</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Présence sur Discord</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation>Afficher votre jeu en cours dans votre statut Discord</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;En savoir plus&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;S&apos;inscrire&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Quel est mon jeton ?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation>Non spécifié</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation>ID de télémétrie: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation>Jeton non vérifié</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation>Jeton non vérifié. La modification de votre jeton n&apos;a pas é sauvegardée.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>Vérification en cours...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation>Échec de la vérification</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation>Échec de la vérification. Vérifiez que le jeton a é écris correctement et que votre connexion internet fonctionne.</translation>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -7009,4 +6873,4 @@ Il a peut-être quitté la salon.</translation>
<translation>Arbre d&apos;instructions</translation>
</message>
</context>
</TS>
</TS>

View File

@ -3582,190 +3582,6 @@ Drag points to change position, or double-click table cells to edit values.</sou
<translation>Angol</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation>Forma</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Citra Web-szolgáltatás</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation>A felhasználóneved és tokened megadásával, belegyezel abba, hogy a Citra használati adatokat gyűjtsön, ami felhasználó azonosító információt tartalmazhat.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation>Ellenőrzés</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation>Regisztráció</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation>Token:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation>Felhasználónév:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation>Mi a tokenem?</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation>Telemetria</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Névtelen használati adat megosztása a Citra csapatával</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation>Tudj meg többet</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation>Telemetria ID:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation>Regeneráció</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Discord jelenlét</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation>Jelenlegi játék megjelenítése a Discord állapotodban</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Tudj meg többet&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Regisztráció&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Mi a tokenem?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation>Nem meghatározott</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation>Telemetria ID: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation>Token nincs megerősítve</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation>Token nincs megerősítve. A változtatások nem lettek elmentve.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>Megerősítés...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation>Ellenőrzés sikertelen</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation>Sikertelen megerősítés. Győződj meg róla, hogy helyesen írtad be a tokened, és van internetkapcsolatod.</translation>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
<location filename="../../src/citra_qt/multiplayer/direct_connect.ui" line="14"/>
<source>Direct Connect</source>
<translation>Közvetlen Kapcsolódás</translation>
</message>
<message>
<location filename="../../src/citra_qt/multiplayer/direct_connect.ui" line="47"/>
<source>Server Address</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/multiplayer/direct_connect.ui" line="54"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Server address of the host&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/multiplayer/direct_connect.ui" line="64"/>
<source>Port</source>
<translation>Port</translation>
</message>
<message>
<location filename="../../src/citra_qt/multiplayer/direct_connect.ui" line="71"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Port number the host is listening on&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Annak a portnak a száma, amire a gazda figyel&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/multiplayer/direct_connect.ui" line="77"/>
<source>24872</source>
<translation>24872</translation>
</message>
<message>
<location filename="../../src/citra_qt/multiplayer/direct_connect.ui" line="97"/>
<source>Nickname</source>
<translation>Becenév</translation>
</message>
<message>
<location filename="../../src/citra_qt/multiplayer/direct_connect.ui" line="111"/>
<source>Password</source>
<translation>Jelszó</translation>
</message>
<message>
<location filename="../../src/citra_qt/multiplayer/direct_connect.ui" line="153"/>
<source>Connect</source>
<translation>Kapcsolás</translation>
</message>
</context>
<context>
<name>DirectConnectWindow</name>
<message>
@ -6991,4 +6807,4 @@ They may have left the room.</source>
<translation>Várakozási Fa</translation>
</message>
</context>
</TS>
</TS>

139
dist/languages/id.ts vendored
View File

@ -3584,143 +3584,6 @@ Drag points to change position, or double-click table cells to edit values.</sou
<translation>Inggris</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation>Formulir</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Layanan Web Citra</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation>Dengan memberikan nama user dan token, Anda menyetujui Citra untuk mengumpulkan data penggunaan tambahan, mungkin termaksud informasi identifikasi pengguna.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation>Verifikasi</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation>Daftar</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation>Token: </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation>Nama User:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation>Apa token Saya?</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation>Konfigurasi Servis Web hanya bisa di ubah ketika ruangan publik sedang tidak digunakan</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation>Telemetri</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Bagikan data penggunaan anonim dengan tim Citra</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation>Pelajari lebih Banyak</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation>ID Telemetri:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation>Memperbarui</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Status Discord</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation>Tampilkan Game Saat Ini ke Status Discord Anda</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Pelajari lebih banyak&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Daftar&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Apa token saya ?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation>Tidak di spesifikasi</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation>ID Telemetri: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation>Token tidak ter-verifikasi</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation>Token tidak di verifikasi.
Perubahan pada token anda belum tersimpan.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>Mem-verifikasi...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation>Verifikasi gagal</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation>Verifikasi gagal. Pastikan nama user dan token yang Anda masukkan benar dan koneksi internet Anda menyala.</translation>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -6998,4 +6861,4 @@ They may have left the room.</source>
<translation>Tunggu Tree</translation>
</message>
</context>
</TS>
</TS>

138
dist/languages/it.ts vendored
View File

@ -3585,142 +3585,6 @@ Trascina i punti per cambiarne la posizione, o fai doppio clic sulla tabella per
<translation>Inglese</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation>Modulo</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Servizio web di Citra</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation>Fornendo i tuoi nome utente e token, permetti a Citra di raccogliere dati di utilizzo aggiuntivi, che potrebbero contenere informazioni identificative dell&apos;utente.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation>Verifica</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation>Registrati</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation>Token:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation>Nome utente</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation>Qual è il mio token?</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation>La configurazione del servizio web può essere cambiata solo quando non si sta ospitando una stanza pubblica.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation>Telemetria</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Condividi dati anonimi sull&apos;utilizzo con il team di Citra</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation>Per saperne di più</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation>ID telemetria:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation>Rigenera</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Discord Presence</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation>Mostra il gioco attuale nel tuo stato di Discord</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Per saperne di più&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Registrati&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Qual è il mio token?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation>Non specificato</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation>ID telemetria: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation>Token non verificato</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation>Il token non è stato verificato. La modifica al token non è stata salvata.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>Verifica...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation>Verifica fallita</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation>Verifica fallita. Controlla di aver inserito il token correttamente, e che la tua connessione a internet sia funzionante.</translation>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -7010,4 +6874,4 @@ Potrebbe aver lasciato la stanza.</translation>
<translation>Wait Tree</translation>
</message>
</context>
</TS>
</TS>

View File

@ -3587,142 +3587,6 @@ Drag points to change position, or double-click table cells to edit values.</sou
<translation></translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Citra Webサービス</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation>Citraへの追加の情報データの収集</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation>Web設定はPublicなルームをホスティング中は変更できません</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Citraチームに匿名で使用データを共有する</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation>ID</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Discord Presence</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation>Discordに表示</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;もっと詳しく&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;サインアップ&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;トークンの取得&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation>テレメトリーID: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation></translation>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -7002,4 +6866,4 @@ They may have left the room.</source>
<translation>Wait Tree</translation>
</message>
</context>
</TS>
</TS>

View File

@ -3585,142 +3585,6 @@ Drag points to change position, or double-click table cells to edit values.</sou
<translation>English</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Citra </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation> Citra가 .</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation>:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation> :</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation> ?</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation> .</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Citra팀과 </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation> </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation> ID:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation> </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation> </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;자세히 알아보기&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;가입&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;나의 토큰이 무엇인가요?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation> ID: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation> </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation> . .</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation> </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation> . .</translation>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -7004,4 +6868,4 @@ They may have left the room.</source>
<translation>Wait Tree</translation>
</message>
</context>
</TS>
</TS>

View File

@ -3581,142 +3581,6 @@ Drag points to change position, or double-click table cells to edit values.</sou
<translation>Anglų k.</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation>Forma</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Citra interneto tarnyba</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation>Įrašydami jūsų vartotojo vardą ir simbolinį ID, jūs sutinkate, kad Citra rinktų papildomus naudojimo duomenis, tarp kurių gali būti informacija, skirta atpažinti vartotoją.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation>Patikrinti</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation>Užsiregistruoti</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation>Simbolinis ID:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation>Vartotojo vardas:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation>Koks yra mano simbolinis ID?</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation>Telemetrija</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Pasidalinti anonimiškais naudojimo duomenimis su Citra komanda</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation>Sužinoti daugiau</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation>Telemetrijos ID:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation>Regeneruoti</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Discord nustatymai</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation>Rodyti jūsų žaidžiamą žaidimą Discord&apos;e</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sužinoti daugiau&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Užsiregistruoti&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Koks yra mano simbolinis ID?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation>Telemetrijos ID: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>Tikrinama...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation>Tikrinimas nepavyko</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation type="unfinished"/>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -6989,4 +6853,4 @@ They may have left the room.</source>
<translation>Laukimo gijų medis</translation>
</message>
</context>
</TS>
</TS>

138
dist/languages/nb.ts vendored
View File

@ -3584,142 +3584,6 @@ Dra punkter for å endre posisjon, eller dobbeltklikk på tabellceller for å re
<translation>Engelsk</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation>Form</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Citra Web Tjenester</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation>Ved å gi brukernavn og nøkkel, samtykker du i å tillate Citra å samle inn brukerdata, som kan inneholde bruker indentifiserende informasjon.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation>Verifisere</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation>Registrer deg</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation>Nøkkel: </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation>Brukernavn:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation>Hva er min nøkkel?</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation>Web Service-konfigurasjon kan bare endres når et offentlig rom ikke blir hostet.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation>Telemetri</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Del anonyme brukerdata med Citra-teamet</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation>Lær mer</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation>Telemetri ID:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation>Regenerere</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Discord tilstedeværelse</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation>Vis Gjeldende Spill i Discord Statusen din.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Lær mer&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Registrer deg&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Hva er min nøkkel?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation>Uspesifisert</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation>Telemetri ID: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation>Nøkkel ikke bekreftet</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation>Nøkkel ble ikke bekreftet. Endringen til nøkelen ditt er ikke lagret.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>Verifiserer...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation>Verifikasjon misslyktes</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation>Bekreftelsen mislyktes. Sjekk at du har lagt inn nøkkelen riktig, og at internettforbindelsen din fungerer.</translation>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -7001,4 +6865,4 @@ They may have left the room.</source>
<translation>Wait Tree</translation>
</message>
</context>
</TS>
</TS>

138
dist/languages/nl.ts vendored
View File

@ -3585,142 +3585,6 @@ Sleep punten om de positie te wijzigen of dubbelklik op tabelcellen om waarden t
<translation>Engels</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation>Formulier</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Citra-webdienst</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation>Door het voorzien van je gebruikersnaam en token, ga je akkoord dat Citra aanvullende gebruiksdata verzameld, waaronder informatie waarmee de gebruiker zou kunnen worden geïdentificeerd.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation>Verifiëren </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation>Registreren</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation>Token:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation>Gebruikersnaam:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation>Wat is mijn token?</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation>De webserviceconfiguratie kan alleen worden gewijzigd als er geen publieke ruimte wordt gehost.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation>Telemetrie</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Deel anonieme gebruiksdata met het Citra team</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation>Meer leren</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation>Telemetrie ID:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation>Regenereren</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Discord Presence</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation>Toon Huidige Spel in je Discord Status</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Meer leren&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Registreren&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Wat is mijn token?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation>Ongespecificeerd</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation>Telemetrie ID: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation>Token niet geverifieerd</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation>Token is niet geverifieerd. De wijziging van uw token is niet opgeslagen.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>Verifiëren...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation>Verificatie mislukt</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation>Verificatie mislukt. Controleer of je je token correct hebt ingevoerd en of uw internetverbinding werkt.</translation>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -7012,4 +6876,4 @@ Misschien hebben ze de kamer verlaten.</translation>
<translation>Wait Tree</translation>
</message>
</context>
</TS>
</TS>

View File

@ -3583,142 +3583,6 @@ Drag points to change position, or double-click table cells to edit values.</sou
<translation>Angielski (English)</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation>Formularz</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Usługa Sieciowa Citra</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation>Poprzez wprowadzenia nazwy użytkownika i tokenu, wyrażasz zgodę na wysłanie dodatkowych danych do Citra. Dane te mogą zawierać informacje identyfikujące użytkownika.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation>Zweryfikuj</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation>Zarejestruj się</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation>Token: </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation>Nazwa Użytkownika:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation>Czym jest mój token?</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation>Telemetria</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Udostępnij anonimowe dane użytkowania zespołowi Citra</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation>Dowiedz się więcej</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation>ID Telemetrii:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation>Regeneruj</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Widoczność na Discordzie</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation>Pokaż obecnie włączoną grę w statusie na Discrodzie</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Dowiedz się więcej&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Czym jest mój token?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation>ID Telemetrii: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation>Token nie zweryfikowany</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>Weryfikowanie...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation>Weryfikacja nieudana</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation type="unfinished"/>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -6992,4 +6856,4 @@ They may have left the room.</source>
<translation>Kolejka Oczekiwania</translation>
</message>
</context>
</TS>
</TS>

View File

@ -3585,142 +3585,6 @@ Arraste os pontos para alterar a posição ou clique duas vezes nas células da
<translation>Inglês (English)</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation>Formulário</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Citra Web Service</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation>Ao informar o seu usuário e token, você concorda em permitir ao Citra recolher dados de utilização adicionais, que podem incluir informações de identificação de usuário.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation>Verificar</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation>Registrar-se</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation>Token:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation>Nome de usuário</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation>Qual é o meu token?</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation>As configurações do Web Service não podem ser alteradas quando uma sala pública criada por você estiver em operação.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation>Telemetria</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Compartilhar anonimamente dados de utilização com a equipe do Citra</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation>Saiba mais</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation>ID de telemetria:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation>Gerar um novo</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Presença no Discord</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation>Mostrar o jogo atual no seu perfil do Discord</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Saber mais&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Registrar-se&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Qual é o meu token?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation>Não especificado</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation>ID de telemetria: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation>Token não verificado</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation>O token não foi verificado. A alteração no seu token não foi salva.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>Verificando...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation>Falha na verificação</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation>Falha na verificação. Verifique se o token foi inserido corretamente e se a conexão à internet está funcionando.</translation>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -7005,4 +6869,4 @@ They may have left the room.</source>
<translation>Árvore de espera</translation>
</message>
</context>
</TS>
</TS>

View File

@ -3584,142 +3584,6 @@ Drag points to change position, or double-click table cells to edit values.</sou
<translation>Engleză</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation>Model</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Citra Serviciu Web</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation>Furnizând numele de utilizator și token-ul, sunteți de acord permiți companiei Citra colecteze date suplimentare de utilizare, care pot include informații de identificare a utilizatorului.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation>Verificați</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation>Înregistrare</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation>Token: </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation>Nume de utilizator:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation>Care este token-ul meu?</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation>Configurarea de săli publice poate fi modificată doar când o sală publică nu este găzduită.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation>Telemetrie</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Distribuiți date de utilizare anonime cu echipa Citra</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation>Mai multe informații</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation>ID telemetrie:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation>Regenerează</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Prezență pe Discord</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation>Afișează Jocul Prezent pe Statusul Discord</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Mai multe informații&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Înregistrare&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Care este token-ul meu?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation>Nespecificat</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation>ID de Telemetrie: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>Verificănd...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation>Verificare eșuată</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation type="unfinished"/>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -6999,4 +6863,4 @@ They may have left the room.</source>
<translation>Copac de Așteptare</translation>
</message>
</context>
</TS>
</TS>

View File

@ -3587,143 +3587,6 @@ Drag points to change position, or double-click table cells to edit values.</sou
<translation>Английский</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation>Форма</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Веб-сервис Citra</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation>Отправка имени пользователя и токена означает согласие на сбор приложением Citra дополнительных данных об использовании,
которые могут включать сведения, идентифицирующие пользователя.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation>Подтвердить</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation>Регистрация</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation>Токен:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation>Имя пользователя:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation>Что такое токен?</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation>Настройки веб-сервиса можно изменять только в том случае, если на компьютере не размещается публичная комната чата.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation>Телеметрия</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Поделиться анонимными данными использования с командой Citra</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation>Дополнительная информация</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation>ID телеметрии:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation>Пересоздать</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Интеграция с Discord</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation>Показывать текущую игру в статусе Discord</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Дополнительная информация&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Зарегистрироваться&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Что такое токен?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation>Не указано</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation>ID телеметрии: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation>Токен не проверен</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation>Токен не был проверен. Изменения к токену сохранены не были.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>Проверка...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation>Сбой проверки</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation>Сбой проверки. Убедитесь в том, что токен введён верно и подключение к Интернету работает.</translation>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -7005,4 +6868,4 @@ They may have left the room.</source>
<translation>Дерево цепочки ожидания</translation>
</message>
</context>
</TS>
</TS>

View File

@ -3583,142 +3583,6 @@ Drag points to change position, or double-click table cells to edit values.</sou
<translation>İngilizce</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation>Form</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Citra Servisi</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation>Kullanıcı adınızı ve tokeninizi sağlayarak Citra&apos;nın ek kullanım verilerini toplamasına izin vermeyi kabul ediyorsunuz, bu kullanıcı tanımlayıcı bilgileri de içerebilir.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation>Doğrula</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation>Kaydol</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation>Token:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation>Kullanıcı Adı:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation>Tokenim nedir?</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation>Web servisi yapılandırması yalnızca Herkese ık Oda sunulmadığı sürece değiştirilebilir.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation>Telemetri</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Citra ekibiyle anonim kullanım verilerini paylaş</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation>Daha fazla bilgi edinin</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation>Telemetri ID:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation>Yeniden Oluştur</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Discord Görünümü</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation>Şu Anki Oyunu Discord Durumunda Göster</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Daha fazla bilgi edinin&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Kaydol&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Tokenim nedir?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation>Belirtilmemiş</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation>Telemetri ID: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation>Token doğrulanmadı</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation>Token doğrulanmadı. Token&apos;inizdeki değişiklikler kaydedilmeyecektir.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>Doğrulanıyor...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation>Doğrulama başarısız oldu</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation>Doğrulama başarısız oldu. Token&apos;inizi doğru girdiğinizden ve internet bağlantınızın çalıştığından emin olun.</translation>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -7001,4 +6865,4 @@ They may have left the room.</source>
<translation>Wait Tree</translation>
</message>
</context>
</TS>
</TS>

View File

@ -3583,142 +3583,6 @@ Drag points to change position, or double-click table cells to edit values.</sou
<translation>Tiếng Anh</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation>Đnh dạng</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Dịch vụ Web Citra</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation>Bằng việc cung cấp tên tài khoản token, bạn đã cho phép Citra thu thập các thông tin liên quan đến giả lập, cũng như bao gồm các thông tin đnh danh người dùng.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation>Xác thực</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation>Đăng </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation>Token: </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation>Tên người dùng:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation>Token của tôi ?</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation>Thiết lập cho Dịch vụ web chỉ thay đi đưc khi đang không tổ chức phòng công khai nào.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation>Theo dõi từ xa</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>Gửi các dữ liệu sử dụng nặc danh cho đi ngũ Citra</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation>Tìm hiểu thêm</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation> theo dõi:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation>Tạo mới</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation>Hiển thị game đang chơi trên trạng thái Discord</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Tìm hiểu thêm&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Đăng ký&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Token là gì?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation>Chưa đnh nghĩa</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation> theo dõi: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation>Token không đưc xác thực</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation>Token này chưa đưc xác thực. Thay đi về token chưa đưc lưu.</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>Đang xác thực...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation>Xác thực thất bại</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation>Xác thực thất bại. Vui lòng kiểm tra token đã nhập vào đúng, hiện thiết bị đang kết nối đến mạng.</translation>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -6997,4 +6861,4 @@ They may have left the room.</source>
<translation>Wait Tree</translation>
</message>
</context>
</TS>
</TS>

View File

@ -3585,142 +3585,6 @@ Drag points to change position, or double-click table cells to edit values.</sou
<translation></translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Citra </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation> Citra 使</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation>使</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation> Citra 使</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation> ID:</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Discord </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation> Discord </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;了解更多&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;注册&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;我的令牌是?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation> ID: 0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation>...</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation></translation>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -7009,4 +6873,4 @@ They may have left the room.</source>
<translation></translation>
</message>
</context>
</TS>
</TS>

View File

@ -3584,142 +3584,6 @@ Drag points to change position, or double-click table cells to edit values.</sou
<translation>English</translation>
</message>
</context>
<context>
<name>ConfigureWeb</name>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="14"/>
<source>Form</source>
<translation>Form</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="22"/>
<source>Citra Web Service</source>
<translation>Citra </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="28"/>
<source>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</source>
<translation>使 Citra 使使</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="46"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="140"/>
<source>Verify</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="53"/>
<source>Sign up</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="63"/>
<source>Token: </source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="73"/>
<source>Username: </source>
<translation>使</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="90"/>
<source>What is my token?</source>
<translation> Citra </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="115"/>
<source>Web Service configuration can only be changed when a public room isn&apos;t being hosted.</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="125"/>
<source>Telemetry</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="131"/>
<source>Share anonymous usage data with the Citra team</source>
<translation>使 Citra </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="138"/>
<source>Learn more</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="147"/>
<source>Telemetry ID:</source>
<translation> ID</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="163"/>
<source>Regenerate</source>
<translation> ID</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="177"/>
<source>Discord Presence</source>
<translation>Discord </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.ui" line="183"/>
<source>Show Current Game in your Discord Status</source>
<translation> Discord </translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="58"/>
<source>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Learn more&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;了解更多&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="66"/>
<source>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;Sign up&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://profile.citra-emu.org/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;註冊&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="70"/>
<source>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;What is my token?&lt;/span&gt;&lt;/a&gt;</source>
<translation>&lt;a href=&apos;https://citra-emu.org/wiki/citra-web-service/&apos;&gt;&lt;span style=&quot;text-decoration: underline; color:#039be5;&quot;&gt;什麼是 Citra 權杖?&lt;/span&gt;&lt;/a&gt;</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="76"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="151"/>
<source>Unspecified</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="87"/>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="111"/>
<source>Telemetry ID: 0x%1</source>
<translation> ID0x%1</translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="103"/>
<source>Token not verified</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="104"/>
<source>Token was not verified. The change to your token has not been saved.</source>
<translation type="unfinished"/>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="130"/>
<source>Verifying...</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="152"/>
<source>Verification failed</source>
<translation></translation>
</message>
<message>
<location filename="../../src/citra_qt/configuration/configure_web.cpp" line="153"/>
<source>Verification failed. Check that you have entered your token correctly, and that your internet connection is working.</source>
<translation type="unfinished"/>
</message>
</context>
<context>
<name>DirectConnect</name>
<message>
@ -7001,4 +6865,4 @@ They may have left the room.</source>
<translation></translation>
</message>
</context>
</TS>
</TS>

@ -1 +1 @@
Subproject commit 217e93c664ec6704ec2d8c36fa116c1a4a1e2d40
Subproject commit 5a5c9a643484d888873e32c5d7d484fae8e71d3d

View File

@ -244,12 +244,14 @@ void Config::ReadValues() {
// Miscellaneous
ReadSetting("Miscellaneous", Settings::values.log_filter);
ReadSetting("Miscellaneous", Settings::values.log_regex_filter);
// Apply the log_filter setting as the logger has already been initialized
// and doesn't pick up the filter on its own.
Common::Log::Filter filter;
filter.ParseFilterString(Settings::values.log_filter.GetValue());
Common::Log::SetGlobalFilter(filter);
Common::Log::SetRegexFilter(Settings::values.log_regex_filter.GetValue());
// Debugging
Settings::values.record_frame_times =
@ -264,8 +266,6 @@ void Config::ReadValues() {
}
// Web Service
NetSettings::values.enable_telemetry =
sdl2_config->GetBoolean("WebService", "enable_telemetry", false);
NetSettings::values.web_api_url =
sdl2_config->GetString("WebService", "web_api_url", "https://api.citra-emu.org");
NetSettings::values.citra_username = sdl2_config->GetString("WebService", "citra_username", "");

View File

@ -353,9 +353,6 @@ gdbstub_port=24689
# To LLE a service module add "LLE\<module name>=true"
[WebService]
# Whether or not to enable telemetry
# 0 (default): No, 1: Yes
enable_telemetry =
# URL for Web API
web_api_url = https://api.citra-emu.org
# Username and token for Citra Web Service

View File

@ -38,7 +38,6 @@
#include "core/hle/service/nfc/nfc.h"
#include "core/loader/loader.h"
#include "core/savestate.h"
#include "core/telemetry_session.h"
#include "jni/android_common/android_common.h"
#include "jni/applets/mii_selector.h"
#include "jni/applets/swkbd.h"
@ -207,9 +206,6 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
return load_result;
}
auto& telemetry_session = system.TelemetrySession();
telemetry_session.AddField(Common::Telemetry::FieldType::App, "Frontend", "Android");
stop_run = false;
pause_emulation = false;

View File

@ -73,8 +73,9 @@ OpenALSink::OpenALSink(std::string device_name) : impl(std::make_unique<Impl>())
auto alBufferCallbackSOFT =
reinterpret_cast<LPALBUFFERCALLBACKSOFT>(alGetProcAddress("alBufferCallbackSOFT"));
alBufferCallbackSOFT(impl->buffer, AL_FORMAT_STEREO16, native_sample_rate, &Impl::Callback,
impl.get());
alBufferCallbackSOFT(impl->buffer, AL_FORMAT_STEREO16, native_sample_rate,
reinterpret_cast<ALBUFFERCALLBACKTYPESOFT>(&Impl::Callback), impl.get());
if (alGetError() != AL_NO_ERROR) {
LOG_CRITICAL(Audio_Sink, "alBufferCallbackSOFT failed: {}", alGetError());
Close();

View File

@ -39,7 +39,6 @@
#include "core/hle/service/am/am.h"
#include "core/hle/service/cfg/cfg.h"
#include "core/movie.h"
#include "core/telemetry_session.h"
#include "input_common/main.h"
#include "network/network.h"
#include "video_core/gpu.h"
@ -436,8 +435,6 @@ int main(int argc, char** argv) {
break;
}
system.TelemetrySession().AddField(Common::Telemetry::FieldType::App, "Frontend", "SDL");
if (use_multiplayer) {
if (auto member = Network::GetRoomMember().lock()) {
member->BindOnChatMessageRecieved(OnMessageReceived);

View File

@ -306,12 +306,14 @@ void Config::ReadValues() {
// Miscellaneous
ReadSetting("Miscellaneous", Settings::values.log_filter);
ReadSetting("Miscellaneous", Settings::values.log_regex_filter);
// Apply the log_filter setting as the logger has already been initialized
// and doesn't pick up the filter on its own.
Common::Log::Filter filter;
filter.ParseFilterString(Settings::values.log_filter.GetValue());
Common::Log::SetGlobalFilter(filter);
Common::Log::SetRegexFilter(Settings::values.log_regex_filter.GetValue());
// Debugging
Settings::values.record_frame_times =
@ -326,8 +328,6 @@ void Config::ReadValues() {
}
// Web Service
NetSettings::values.enable_telemetry =
sdl2_config->GetBoolean("WebService", "enable_telemetry", false);
NetSettings::values.web_api_url =
sdl2_config->GetString("WebService", "web_api_url", "https://api.citra-emu.org");
NetSettings::values.citra_username = sdl2_config->GetString("WebService", "citra_username", "");

View File

@ -361,9 +361,6 @@ renderer_debug =
# To LLE a service module add "LLE\<module name>=true"
[WebService]
# Whether or not to enable telemetry
# 0 (default): No, 1: Yes
enable_telemetry =
# URL for Web API
web_api_url = https://api.citra-emu.org
# Username and token for Citra Web Service

View File

@ -81,9 +81,6 @@ add_executable(citra-qt
configuration/configure_ui.cpp
configuration/configure_ui.h
configuration/configure_ui.ui
configuration/configure_web.cpp
configuration/configure_web.h
configuration/configure_web.ui
configuration/configure_cheats.cpp
configuration/configure_cheats.h
configuration/configure_cheats.ui

View File

@ -7,14 +7,12 @@
#include <QPushButton>
#include <QtConcurrent/qtconcurrentrun.h>
#include "citra_qt/compatdb.h"
#include "common/telemetry.h"
#include "core/core.h"
#include "core/telemetry_session.h"
#include "ui_compatdb.h"
CompatDB::CompatDB(Core::TelemetrySession& telemetry_session_, QWidget* parent)
CompatDB::CompatDB(QWidget* parent)
: QWizard(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
ui{std::make_unique<Ui::CompatDB>()}, telemetry_session{telemetry_session_} {
ui{std::make_unique<Ui::CompatDB>()} {
ui->setupUi(this);
connect(ui->radioButton_Perfect, &QRadioButton::clicked, this, &CompatDB::EnableNext);
connect(ui->radioButton_Great, &QRadioButton::clicked, this, &CompatDB::EnableNext);
@ -52,15 +50,11 @@ void CompatDB::Submit() {
case CompatDBPage::Final:
back();
LOG_DEBUG(Frontend, "Compatibility Rating: {}", compatibility->checkedId());
telemetry_session.AddField(Common::Telemetry::FieldType::UserFeedback, "Compatibility",
compatibility->checkedId());
button(NextButton)->setEnabled(false);
button(NextButton)->setText(tr("Submitting"));
button(CancelButton)->setVisible(false);
testcase_watcher.setFuture(
QtConcurrent::run([this] { return telemetry_session.SubmitTestcase(); }));
break;
default:
LOG_ERROR(Frontend, "Unexpected page: {}", currentId());

View File

@ -8,10 +8,6 @@
#include <QFutureWatcher>
#include <QWizard>
namespace Core {
class TelemetrySession;
}
namespace Ui {
class CompatDB;
}
@ -20,7 +16,7 @@ class CompatDB : public QWizard {
Q_OBJECT
public:
explicit CompatDB(Core::TelemetrySession& telemetry_session_, QWidget* parent = nullptr);
explicit CompatDB(QWidget* parent = nullptr);
~CompatDB();
private:
@ -31,6 +27,4 @@ private:
void Submit();
void OnTestcaseSubmitted();
void EnableNext();
Core::TelemetrySession& telemetry_session;
};

View File

@ -536,6 +536,7 @@ void Config::ReadMiscellaneousValues() {
qt_config->beginGroup(QStringLiteral("Miscellaneous"));
ReadBasicSetting(Settings::values.log_filter);
ReadBasicSetting(Settings::values.log_regex_filter);
ReadBasicSetting(Settings::values.enable_gamemode);
qt_config->endGroup();
@ -836,8 +837,6 @@ void Config::ReadUpdaterValues() {
void Config::ReadWebServiceValues() {
qt_config->beginGroup(QStringLiteral("WebService"));
NetSettings::values.enable_telemetry =
ReadSetting(QStringLiteral("enable_telemetry"), false).toBool();
NetSettings::values.web_api_url =
ReadSetting(QStringLiteral("web_api_url"), QStringLiteral("https://api.citra-emu.org"))
.toString()
@ -1068,6 +1067,7 @@ void Config::SaveMiscellaneousValues() {
qt_config->beginGroup(QStringLiteral("Miscellaneous"));
WriteBasicSetting(Settings::values.log_filter);
WriteBasicSetting(Settings::values.log_regex_filter);
WriteBasicSetting(Settings::values.enable_gamemode);
qt_config->endGroup();
@ -1317,7 +1317,6 @@ void Config::SaveUpdaterValues() {
void Config::SaveWebServiceValues() {
qt_config->beginGroup(QStringLiteral("WebService"));
WriteSetting(QStringLiteral("enable_telemetry"), NetSettings::values.enable_telemetry, false);
WriteSetting(QStringLiteral("web_api_url"),
QString::fromStdString(NetSettings::values.web_api_url),
QStringLiteral("https://api.citra-emu.org"));

View File

@ -97,12 +97,6 @@
<header>configuration/configure_enhancements.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ConfigureWeb</class>
<extends>QWidget</extends>
<header>configuration/configure_web.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ConfigureUi</class>
<extends>QWidget</extends>

View File

@ -97,6 +97,8 @@ void ConfigureDebug::SetConfiguration() {
ui->toggle_console->setEnabled(!is_powered_on);
ui->toggle_console->setChecked(UISettings::values.show_console.GetValue());
ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter.GetValue()));
ui->log_regex_filter_edit->setText(
QString::fromStdString(Settings::values.log_regex_filter.GetValue()));
ui->toggle_cpu_jit->setChecked(Settings::values.use_cpu_jit.GetValue());
ui->delay_start_for_lle_modules->setChecked(
Settings::values.delay_start_for_lle_modules.GetValue());
@ -126,10 +128,12 @@ void ConfigureDebug::ApplyConfiguration() {
Settings::values.gdbstub_port = ui->gdbport_spinbox->value();
UISettings::values.show_console = ui->toggle_console->isChecked();
Settings::values.log_filter = ui->log_filter_edit->text().toStdString();
Settings::values.log_regex_filter = ui->log_regex_filter_edit->text().toStdString();
Debugger::ToggleConsole();
Common::Log::Filter filter;
filter.ParseFilterString(Settings::values.log_filter.GetValue());
Common::Log::SetGlobalFilter(filter);
Common::Log::SetRegexFilter(Settings::values.log_regex_filter.GetValue());
Settings::values.use_cpu_jit = ui->toggle_cpu_jit->isChecked();
Settings::values.delay_start_for_lle_modules = ui->delay_start_for_lle_modules->isChecked();
Settings::values.renderer_debug = ui->toggle_renderer_debug->isChecked();

View File

@ -85,6 +85,20 @@
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Regex Log Filter</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="log_regex_filter_edit"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>

View File

@ -16,7 +16,6 @@
#include "citra_qt/configuration/configure_storage.h"
#include "citra_qt/configuration/configure_system.h"
#include "citra_qt/configuration/configure_ui.h"
#include "citra_qt/configuration/configure_web.h"
#include "citra_qt/hotkeys.h"
#include "common/settings.h"
#include "core/core.h"
@ -38,7 +37,7 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, Cor
camera_tab{std::make_unique<ConfigureCamera>(this)},
debug_tab{std::make_unique<ConfigureDebug>(is_powered_on, this)},
storage_tab{std::make_unique<ConfigureStorage>(is_powered_on, this)},
web_tab{std::make_unique<ConfigureWeb>(this)}, ui_tab{std::make_unique<ConfigureUi>(this)} {
ui_tab{std::make_unique<ConfigureUi>(this)} {
Settings::SetConfiguringGlobal(true);
ui->setupUi(this);
@ -53,11 +52,9 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, Cor
ui->tabWidget->addTab(camera_tab.get(), tr("Camera"));
ui->tabWidget->addTab(debug_tab.get(), tr("Debug"));
ui->tabWidget->addTab(storage_tab.get(), tr("Storage"));
ui->tabWidget->addTab(web_tab.get(), tr("Web"));
ui->tabWidget->addTab(ui_tab.get(), tr("UI"));
hotkeys_tab->Populate(registry);
web_tab->SetWebServiceConfigEnabled(enable_web_config);
PopulateSelectionList();
@ -90,7 +87,6 @@ void ConfigureDialog::SetConfiguration() {
audio_tab->SetConfiguration();
camera_tab->SetConfiguration();
debug_tab->SetConfiguration();
web_tab->SetConfiguration();
ui_tab->SetConfiguration();
storage_tab->SetConfiguration();
}
@ -106,7 +102,6 @@ void ConfigureDialog::ApplyConfiguration() {
audio_tab->ApplyConfiguration();
camera_tab->ApplyConfiguration();
debug_tab->ApplyConfiguration();
web_tab->ApplyConfiguration();
ui_tab->ApplyConfiguration();
storage_tab->ApplyConfiguration();
system.ApplySettings();
@ -119,7 +114,7 @@ void ConfigureDialog::PopulateSelectionList() {
ui->selectorList->clear();
const std::array<std::pair<QString, QList<QWidget*>>, 5> items{
{{tr("General"), {general_tab.get(), web_tab.get(), debug_tab.get(), ui_tab.get()}},
{{tr("General"), {general_tab.get(), debug_tab.get(), ui_tab.get()}},
{tr("System"), {system_tab.get(), camera_tab.get(), storage_tab.get()}},
{tr("Graphics"), {enhancements_tab.get(), graphics_tab.get()}},
{tr("Audio"), {audio_tab.get()}},
@ -159,7 +154,6 @@ void ConfigureDialog::RetranslateUI() {
audio_tab->RetranslateUI();
camera_tab->RetranslateUI();
debug_tab->RetranslateUI();
web_tab->RetranslateUI();
ui_tab->RetranslateUI();
storage_tab->RetranslateUI();
}
@ -179,7 +173,6 @@ void ConfigureDialog::UpdateVisibleTabs() {
{camera_tab.get(), tr("Camera")},
{debug_tab.get(), tr("Debug")},
{storage_tab.get(), tr("Storage")},
{web_tab.get(), tr("Web")},
{ui_tab.get(), tr("UI")}};
ui->tabWidget->clear();

View File

@ -29,7 +29,6 @@ class ConfigureAudio;
class ConfigureCamera;
class ConfigureDebug;
class ConfigureStorage;
class ConfigureWeb;
class ConfigureUi;
class ConfigureDialog : public QDialog {
@ -70,6 +69,5 @@ private:
std::unique_ptr<ConfigureCamera> camera_tab;
std::unique_ptr<ConfigureDebug> debug_tab;
std::unique_ptr<ConfigureStorage> storage_tab;
std::unique_ptr<ConfigureWeb> web_tab;
std::unique_ptr<ConfigureUi> ui_tab;
};

View File

@ -3,12 +3,14 @@
// Refer to the license.txt file included.
#include <cstring>
#include <QFileDialog>
#include <QFutureWatcher>
#include <QMessageBox>
#include <QProgressDialog>
#include <QtConcurrent/QtConcurrentMap>
#include "citra_qt/configuration/configuration_shared.h"
#include "citra_qt/configuration/configure_system.h"
#include "common/file_util.h"
#include "common/settings.h"
#include "core/core.h"
#include "core/hle/service/am/am.h"
@ -236,6 +238,32 @@ ConfigureSystem::ConfigureSystem(Core::System& system_, QWidget* parent)
&ConfigureSystem::RefreshConsoleID);
connect(ui->button_start_download, &QPushButton::clicked, this,
&ConfigureSystem::DownloadFromNUS);
connect(ui->button_secure_info, &QPushButton::clicked, this, [this] {
ui->button_secure_info->setEnabled(false);
const QString file_path_qtstr = QFileDialog::getOpenFileName(
this, tr("Select SecureInfo_A/B"), QString(),
tr("SecureInfo_A/B (SecureInfo_A SecureInfo_B);;All Files (*.*)"));
ui->button_secure_info->setEnabled(true);
InstallSecureData(file_path_qtstr.toStdString(), cfg->GetSecureInfoAPath());
});
connect(ui->button_friend_code_seed, &QPushButton::clicked, this, [this] {
ui->button_friend_code_seed->setEnabled(false);
const QString file_path_qtstr =
QFileDialog::getOpenFileName(this, tr("Select LocalFriendCodeSeed_A/B"), QString(),
tr("LocalFriendCodeSeed_A/B (LocalFriendCodeSeed_A "
"LocalFriendCodeSeed_B);;All Files (*.*)"));
ui->button_friend_code_seed->setEnabled(true);
InstallSecureData(file_path_qtstr.toStdString(), cfg->GetLocalFriendCodeSeedBPath());
});
connect(ui->button_ct_cert, &QPushButton::clicked, this, [this] {
ui->button_ct_cert->setEnabled(false);
const QString file_path_qtstr = QFileDialog::getOpenFileName(
this, tr("Select CTCert"), QString(), tr("CTCert.bin (*.bin);;All Files (*.*)"));
ui->button_ct_cert->setEnabled(true);
InstallCTCert(file_path_qtstr.toStdString());
});
for (u8 i = 0; i < country_names.size(); i++) {
if (std::strcmp(country_names.at(i), "") != 0) {
ui->combo_country->addItem(tr(country_names.at(i)), i);
@ -304,6 +332,7 @@ void ConfigureSystem::SetConfiguration() {
ReadSystemSettings();
ui->group_system_settings->setEnabled(enabled);
ui->group_real_console_unique_data->setEnabled(enabled);
if (enabled) {
ui->label_disable_info->hide();
}
@ -354,6 +383,9 @@ void ConfigureSystem::ReadSystemSettings() {
// set firmware download region
ui->combo_download_region->setCurrentIndex(static_cast<int>(cfg->GetRegionValue()));
// Refresh secure data status
RefreshSecureDataStatus();
}
void ConfigureSystem::ApplyConfiguration() {
@ -522,6 +554,59 @@ void ConfigureSystem::RefreshConsoleID() {
tr("Console ID: 0x%1").arg(QString::number(console_id, 16).toUpper()));
}
void ConfigureSystem::InstallSecureData(const std::string& from_path, const std::string& to_path) {
std::string from =
FileUtil::SanitizePath(from_path, FileUtil::DirectorySeparator::PlatformDefault);
std::string to = FileUtil::SanitizePath(to_path, FileUtil::DirectorySeparator::PlatformDefault);
if (from.empty() || from == to) {
return;
}
FileUtil::CreateFullPath(to_path);
FileUtil::Copy(from, to);
cfg->InvalidateSecureData();
RefreshSecureDataStatus();
}
void ConfigureSystem::InstallCTCert(const std::string& from_path) {
std::string from =
FileUtil::SanitizePath(from_path, FileUtil::DirectorySeparator::PlatformDefault);
std::string to = FileUtil::SanitizePath(Service::AM::Module::GetCTCertPath(),
FileUtil::DirectorySeparator::PlatformDefault);
if (from.empty() || from == to) {
return;
}
FileUtil::Copy(from, to);
RefreshSecureDataStatus();
}
void ConfigureSystem::RefreshSecureDataStatus() {
auto status_to_str = [](Service::CFG::SecureDataLoadStatus status) {
switch (status) {
case Service::CFG::SecureDataLoadStatus::Loaded:
return "Loaded";
case Service::CFG::SecureDataLoadStatus::NotFound:
return "Not Found";
case Service::CFG::SecureDataLoadStatus::Invalid:
return "Invalid";
case Service::CFG::SecureDataLoadStatus::IOError:
return "IO Error";
default:
return "";
}
};
Service::AM::CTCert ct_cert;
ui->label_secure_info_status->setText(
tr((std::string("Status: ") + status_to_str(cfg->LoadSecureInfoAFile())).c_str()));
ui->label_friend_code_seed_status->setText(
tr((std::string("Status: ") + status_to_str(cfg->LoadLocalFriendCodeSeedBFile())).c_str()));
ui->label_ct_cert_status->setText(
tr((std::string("Status: ") + status_to_str(static_cast<Service::CFG::SecureDataLoadStatus>(
Service::AM::Module::LoadCTCertFile(ct_cert))))
.c_str()));
}
void ConfigureSystem::RetranslateUI() {
ui->retranslateUi(this);
}

View File

@ -20,6 +20,12 @@ namespace Core {
class System;
}
namespace Service {
namespace AM {
class Module;
} // namespace AM
} // namespace Service
namespace Service {
namespace CFG {
class Module;
@ -46,6 +52,10 @@ private:
void UpdateInitTicks(int init_ticks_type);
void RefreshConsoleID();
void InstallSecureData(const std::string& from_path, const std::string& to_path);
void InstallCTCert(const std::string& from_path);
void RefreshSecureDataStatus();
void SetupPerGameUI();
void DownloadFromNUS();

View File

@ -506,6 +506,123 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="group_real_console_unique_data">
<property name="title">
<string>Real Console Unique Data</string>
</property>
<layout class="QGridLayout" name="gridLayout1">
<item row="1" column="0">
<widget class="QLabel" name="label_secure_info">
<property name="text">
<string>SecureInfo_A/B</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QWidget" name="secure_info">
<layout class="QHBoxLayout" name="horizontalLayout_secure_info">
<item>
<widget class="QLabel" name="label_secure_info_status">
<property name="text">
<string></string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="button_secure_info">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Choose</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_friend_code_seed">
<property name="text">
<string>LocalFriendCodeSeed_A/B</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QWidget" name="friend_code_seed">
<layout class="QHBoxLayout" name="horizontalLayout_friend_code_seed">
<item>
<widget class="QLabel" name="label_friend_code_seed_status">
<property name="text">
<string></string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="button_friend_code_seed">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Choose</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_ct_cert">
<property name="text">
<string>CTCert</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QWidget" name="ct_cert">
<layout class="QHBoxLayout" name="horizontalLayout_ct_cert">
<item>
<widget class="QLabel" name="label_ct_cert_status">
<property name="text">
<string></string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="button_ct_cert">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Choose</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="label_disable_info">
<property name="text">

View File

@ -1,165 +0,0 @@
// Copyright 2017 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <QIcon>
#include <QMessageBox>
#include <QtConcurrent/QtConcurrentRun>
#include "citra_qt/configuration/configure_web.h"
#include "citra_qt/uisettings.h"
#include "core/telemetry_session.h"
#include "network/network_settings.h"
#include "ui_configure_web.h"
static constexpr char token_delimiter{':'};
static std::string GenerateDisplayToken(const std::string& username, const std::string& token) {
if (username.empty() || token.empty()) {
return {};
}
const std::string unencoded_display_token{username + token_delimiter + token};
QByteArray b{unencoded_display_token.c_str()};
QByteArray b64 = b.toBase64();
return b64.toStdString();
}
static std::string UsernameFromDisplayToken(const std::string& display_token) {
const std::string unencoded_display_token{
QByteArray::fromBase64(display_token.c_str()).toStdString()};
return unencoded_display_token.substr(0, unencoded_display_token.find(token_delimiter));
}
static std::string TokenFromDisplayToken(const std::string& display_token) {
const std::string unencoded_display_token{
QByteArray::fromBase64(display_token.c_str()).toStdString()};
return unencoded_display_token.substr(unencoded_display_token.find(token_delimiter) + 1);
}
ConfigureWeb::ConfigureWeb(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureWeb>()) {
ui->setupUi(this);
connect(ui->button_regenerate_telemetry_id, &QPushButton::clicked, this,
&ConfigureWeb::RefreshTelemetryID);
connect(ui->button_verify_login, &QPushButton::clicked, this, &ConfigureWeb::VerifyLogin);
connect(&verify_watcher, &QFutureWatcher<bool>::finished, this, &ConfigureWeb::OnLoginVerified);
#ifndef USE_DISCORD_PRESENCE
ui->discord_group->setVisible(false);
#endif
SetConfiguration();
}
ConfigureWeb::~ConfigureWeb() = default;
void ConfigureWeb::SetConfiguration() {
ui->web_credentials_disclaimer->setWordWrap(true);
ui->telemetry_learn_more->setOpenExternalLinks(true);
ui->telemetry_learn_more->setText(tr("<a "
"href='https://citra-emu.org/entry/"
"telemetry-and-why-thats-a-good-thing/'><span "
"style=\"text-decoration: underline; "
"color:#039be5;\">Learn more</span></a>"));
ui->web_signup_link->setOpenExternalLinks(true);
ui->web_signup_link->setText(
tr("<a href='https://profile.citra-emu.org/'><span style=\"text-decoration: underline; "
"color:#039be5;\">Sign up</span></a>"));
ui->web_token_info_link->setOpenExternalLinks(true);
ui->web_token_info_link->setText(
tr("<a href='https://citra-emu.org/wiki/citra-web-service/'><span style=\"text-decoration: "
"underline; color:#039be5;\">What is my token?</span></a>"));
ui->toggle_telemetry->setChecked(NetSettings::values.enable_telemetry);
if (NetSettings::values.citra_username.empty()) {
ui->username->setText(tr("Unspecified"));
} else {
ui->username->setText(QString::fromStdString(NetSettings::values.citra_username));
}
ui->edit_token->setText(QString::fromStdString(
GenerateDisplayToken(NetSettings::values.citra_username, NetSettings::values.citra_token)));
// Connect after setting the values, to avoid calling OnLoginChanged now
connect(ui->edit_token, &QLineEdit::textChanged, this, &ConfigureWeb::OnLoginChanged);
ui->label_telemetry_id->setText(
tr("Telemetry ID: 0x%1").arg(QString::number(Core::GetTelemetryId(), 16).toUpper()));
user_verified = true;
ui->toggle_discordrpc->setChecked(UISettings::values.enable_discord_presence.GetValue());
}
void ConfigureWeb::ApplyConfiguration() {
NetSettings::values.enable_telemetry = ui->toggle_telemetry->isChecked();
UISettings::values.enable_discord_presence = ui->toggle_discordrpc->isChecked();
if (user_verified) {
NetSettings::values.citra_username =
UsernameFromDisplayToken(ui->edit_token->text().toStdString());
NetSettings::values.citra_token =
TokenFromDisplayToken(ui->edit_token->text().toStdString());
} else {
QMessageBox::warning(
this, tr("Token not verified"),
tr("Token was not verified. The change to your token has not been saved."));
}
}
void ConfigureWeb::RefreshTelemetryID() {
const u64 new_telemetry_id{Core::RegenerateTelemetryId()};
ui->label_telemetry_id->setText(
tr("Telemetry ID: 0x%1").arg(QString::number(new_telemetry_id, 16).toUpper()));
}
void ConfigureWeb::OnLoginChanged() {
if (ui->edit_token->text().isEmpty()) {
user_verified = true;
const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("checked")).pixmap(16);
ui->label_token_verified->setPixmap(pixmap);
} else {
user_verified = false;
const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("failed")).pixmap(16);
ui->label_token_verified->setPixmap(pixmap);
}
}
void ConfigureWeb::VerifyLogin() {
ui->button_verify_login->setDisabled(true);
ui->button_verify_login->setText(tr("Verifying..."));
verify_watcher.setFuture(QtConcurrent::run(
[username = UsernameFromDisplayToken(ui->edit_token->text().toStdString()),
token = TokenFromDisplayToken(ui->edit_token->text().toStdString())] {
return Core::VerifyLogin(username, token);
}));
}
void ConfigureWeb::OnLoginVerified() {
ui->button_verify_login->setEnabled(true);
ui->button_verify_login->setText(tr("Verify"));
if (verify_watcher.result()) {
user_verified = true;
const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("checked")).pixmap(16);
ui->label_token_verified->setPixmap(pixmap);
ui->username->setText(
QString::fromStdString(UsernameFromDisplayToken(ui->edit_token->text().toStdString())));
} else {
const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("failed")).pixmap(16);
ui->label_token_verified->setPixmap(pixmap);
ui->username->setText(tr("Unspecified"));
QMessageBox::critical(this, tr("Verification failed"),
tr("Verification failed. Check that you have entered your token "
"correctly, and that your internet connection is working."));
}
}
void ConfigureWeb::RetranslateUI() {
ui->retranslateUi(this);
}
void ConfigureWeb::SetWebServiceConfigEnabled(bool enabled) {
ui->label_disable_info->setVisible(!enabled);
ui->groupBoxWebConfig->setEnabled(enabled);
}

View File

@ -1,37 +0,0 @@
// Copyright 2017 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include <QFutureWatcher>
#include <QWidget>
namespace Ui {
class ConfigureWeb;
}
class ConfigureWeb : public QWidget {
Q_OBJECT
public:
explicit ConfigureWeb(QWidget* parent = nullptr);
~ConfigureWeb() override;
void ApplyConfiguration();
void RetranslateUI();
void SetConfiguration();
void SetWebServiceConfigEnabled(bool enabled);
private:
void RefreshTelemetryID();
void OnLoginChanged();
void VerifyLogin();
void OnLoginVerified();
bool user_verified = true;
QFutureWatcher<bool> verify_watcher;
std::unique_ptr<Ui::ConfigureWeb> ui;
};

View File

@ -1,214 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConfigureWeb</class>
<widget class="QWidget" name="ConfigureWeb">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>996</width>
<height>561</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="groupBoxWebConfig">
<property name="title">
<string>Citra Web Service</string>
</property>
<layout class="QVBoxLayout" name="verticalLayoutCitraWebService">
<item>
<widget class="QLabel" name="web_credentials_disclaimer">
<property name="text">
<string>By providing your username and token, you agree to allow Citra to collect additional usage data, which may include user identifying information.</string>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayoutCitraUsername">
<item row="2" column="3">
<widget class="QPushButton" name="button_verify_login">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Verify</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="web_signup_link">
<property name="text">
<string>Sign up</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QLabel" name="username"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_token">
<property name="text">
<string>Token: </string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="label_token_verified"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_username">
<property name="text">
<string>Username: </string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="3">
<widget class="QLineEdit" name="edit_token">
<property name="maxLength">
<number>80</number>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="web_token_info_link">
<property name="text">
<string>What is my token?</string>
</property>
</widget>
</item>
<item row="2" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="label_disable_info">
<property name="text">
<string>Web Service configuration can only be changed when a public room isn't being hosted.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Telemetry</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="toggle_telemetry">
<property name="text">
<string>Share anonymous usage data with the Citra team</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="telemetry_learn_more">
<property name="text">
<string>Learn more</string>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayoutTelemetryId">
<item row="0" column="0">
<widget class="QLabel" name="label_telemetry_id">
<property name="text">
<string>Telemetry ID:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="button_regenerate_telemetry_id">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Regenerate</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="discord_group">
<property name="title">
<string>Discord Presence</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_21">
<item>
<widget class="QCheckBox" name="toggle_discordrpc">
<property name="text">
<string>Show Current Game in your Discord Status</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<tabstops>
<tabstop>edit_token</tabstop>
<tabstop>button_verify_login</tabstop>
<tabstop>toggle_telemetry</tabstop>
<tabstop>button_regenerate_telemetry_id</tabstop>
<tabstop>toggle_discordrpc</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View File

@ -25,7 +25,14 @@ void ToggleConsole() {
#ifdef _WIN32
FILE* temp;
if (UISettings::values.show_console) {
if (AllocConsole()) {
BOOL alloc_console_res = AllocConsole();
DWORD last_error = 0;
if (!alloc_console_res) {
last_error = GetLastError();
}
// If the windows debugger already opened a console, calling AllocConsole again
// will cause ERROR_ACCESS_DENIED. If that's the case assume a console is open.
if (alloc_console_res || last_error == ERROR_ACCESS_DENIED) {
// The first parameter for freopen_s is a out parameter, so we can just ignore it
freopen_s(&temp, "CONIN$", "r", stdin);
freopen_s(&temp, "CONOUT$", "w", stdout);

View File

@ -15,7 +15,6 @@
#include <QtGui>
#include <QtWidgets>
#include <fmt/format.h>
#include "core/telemetry_session.h"
#ifdef __APPLE__
#include <unistd.h> // for chdir
#endif
@ -128,27 +127,6 @@ constexpr int default_mouse_timeout = 2500;
* is a bitfield "callout_flags" options, used to track if a message has already been shown to the
* user. This is 32-bits - if we have more than 32 callouts, we should retire and recycle old ones.
*/
enum class CalloutFlag : uint32_t {
Telemetry = 0x1,
};
void GMainWindow::ShowTelemetryCallout() {
if (UISettings::values.callout_flags.GetValue() &
static_cast<uint32_t>(CalloutFlag::Telemetry)) {
return;
}
UISettings::values.callout_flags =
UISettings::values.callout_flags.GetValue() | static_cast<uint32_t>(CalloutFlag::Telemetry);
const QString telemetry_message =
tr("<a href='https://citra-emu.org/entry/telemetry-and-why-thats-a-good-thing/'>Anonymous "
"data is collected</a> to help improve Citra. "
"<br/><br/>Would you like to share your usage data with us?");
if (QMessageBox::question(this, tr("Telemetry"), telemetry_message) == QMessageBox::Yes) {
NetSettings::values.enable_telemetry = true;
system.ApplySettings();
}
}
const int GMainWindow::max_recent_files_item;
@ -263,9 +241,6 @@ GMainWindow::GMainWindow(Core::System& system_)
game_list->LoadCompatibilityList();
game_list->PopulateAsync(UISettings::values.game_dirs);
// Show one-time "callout" messages to the user
ShowTelemetryCallout();
mouse_hide_timer.setInterval(default_mouse_timeout);
connect(&mouse_hide_timer, &QTimer::timeout, this, &GMainWindow::HideMouseCursor);
connect(ui->menubar, &QMenuBar::hovered, this, &GMainWindow::OnMouseActivity);
@ -1244,7 +1219,6 @@ bool GMainWindow::LoadROM(const QString& filename) {
game_path = filename;
system.TelemetrySession().AddField(Common::Telemetry::FieldType::App, "Frontend", "Qt");
return true;
}
@ -1988,7 +1962,7 @@ void GMainWindow::OnLoadComplete() {
void GMainWindow::OnMenuReportCompatibility() {
if (!NetSettings::values.citra_token.empty() && !NetSettings::values.citra_username.empty()) {
CompatDB compatdb{system.TelemetrySession(), this};
CompatDB compatdb{this};
compatdb.exec();
} else {
QMessageBox::critical(this, tr("Missing Citra Account"),

View File

@ -152,7 +152,6 @@ private:
void BootGame(const QString& filename);
void ShutdownGame();
void ShowTelemetryCallout();
void SetDiscordEnabled(bool state);
void LoadAmiibo(const QString& filename);

View File

@ -22,7 +22,8 @@ QString GetOpenGLRenderer() {
QOpenGLContext context;
if (context.create()) {
context.makeCurrent(&surface);
return QString::fromUtf8(context.functions()->glGetString(GL_RENDERER));
return QString::fromUtf8(
reinterpret_cast<const char*>(context.functions()->glGetString(GL_RENDERER)));
} else {
return QStringLiteral("");
}

View File

@ -130,8 +130,6 @@ add_library(citra_common STATIC
string_util.cpp
string_util.h
swap.h
telemetry.cpp
telemetry.h
texture.cpp
texture.h
thread.cpp

View File

@ -12,10 +12,10 @@ namespace Common {
/**
* A background manager which ensures that all detached task is finished before program exits.
*
* Some tasks, telemetry submission for example, prefer executing asynchronously and don't care
* about the result. These tasks are suitable for std::thread::detach(). However, this is unsafe if
* the task is launched just before the program exits (which is a common case for telemetry), so we
* need to block on these tasks on program exit.
* Some tasks prefer executing asynchronously and don't care
* about the result. These tasks are suitable for std::thread::detach().
* However, this is unsafe if the task is launched just before the program exits
* so we need to block on these tasks on program exit.
*
* To make detached task safe, a single DetachedTasks object should be placed in the main(), and
* call WaitForAllTasks() after all program execution but before global/static variable destruction.

View File

@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include <chrono>
#include <boost/regex.hpp>
#include <fmt/format.h>
@ -234,6 +235,19 @@ public:
filter = f;
}
bool SetRegexFilter(const std::string& regex) {
if (regex.empty()) {
regex_filter = boost::regex();
return true;
}
regex_filter = boost::regex(regex, boost::regex_constants::no_except);
if (regex_filter.status() != 0) {
regex_filter = boost::regex();
return false;
}
return true;
}
void SetColorConsoleBackendEnabled(bool enabled) {
color_console_backend.SetEnabled(enabled);
}
@ -243,8 +257,13 @@ public:
if (!filter.CheckMessage(log_class, log_level)) {
return;
}
message_queue.EmplaceWait(
CreateEntry(log_class, log_level, filename, line_num, function, std::move(message)));
Entry new_entry =
CreateEntry(log_class, log_level, filename, line_num, function, std::move(message));
if (!regex_filter.empty() &&
!boost::regex_search(FormatLogMessage(new_entry), regex_filter)) {
return;
}
message_queue.EmplaceWait(new_entry);
}
private:
@ -406,6 +425,7 @@ private:
static inline std::unique_ptr<Impl, decltype(&Deleter)> instance{nullptr, Deleter};
Filter filter;
boost::regex regex_filter;
DebuggerBackend debugger_backend{};
ColorConsoleBackend color_console_backend{};
FileBackend file_backend;
@ -446,6 +466,10 @@ void SetGlobalFilter(const Filter& filter) {
Impl::Instance().SetGlobalFilter(filter);
}
bool SetRegexFilter(const std::string& regex) {
return Impl::Instance().SetRegexFilter(regex);
}
void SetColorConsoleBackendEnabled(bool enabled) {
Impl::Instance().SetColorConsoleBackendEnabled(enabled);
}

View File

@ -26,5 +26,11 @@ void DisableLoggingInTests();
*/
void SetGlobalFilter(const Filter& filter);
/**
* Only allow messages that match the specified regex. The regex is matched against the final log
* text.
*/
bool SetRegexFilter(const std::string& regex);
void SetColorConsoleBackendEnabled(bool enabled);
} // namespace Common::Log

View File

@ -542,6 +542,7 @@ struct Values {
// Miscellaneous
Setting<std::string> log_filter{"*:Info", "log_filter"};
Setting<std::string> log_regex_filter{"", "log_regex_filter"};
// Video Dumping
std::string output_format;

View File

@ -1,92 +0,0 @@
// Copyright 2017 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include <cstring>
#include "common/arch.h"
#include "common/assert.h"
#include "common/scm_rev.h"
#include "common/telemetry.h"
#if CITRA_ARCH(x86_64)
#include "common/x64/cpu_detect.h"
#endif
namespace Common::Telemetry {
void FieldCollection::Accept(VisitorInterface& visitor) const {
for (const auto& field : fields) {
field.second->Accept(visitor);
}
}
void FieldCollection::AddField(std::unique_ptr<FieldInterface> field) {
fields[field->GetName()] = std::move(field);
}
template <class T>
void Field<T>::Accept(VisitorInterface& visitor) const {
visitor.Visit(*this);
}
template class Field<bool>;
template class Field<double>;
template class Field<float>;
template class Field<u8>;
template class Field<u16>;
template class Field<u32>;
template class Field<u64>;
template class Field<s8>;
template class Field<s16>;
template class Field<s32>;
template class Field<s64>;
template class Field<std::string>;
template class Field<const char*>;
template class Field<std::chrono::microseconds>;
void AppendBuildInfo(FieldCollection& fc) {
const bool is_git_dirty{std::strstr(Common::g_scm_desc, "dirty") != nullptr};
fc.AddField(FieldType::App, "Git_IsDirty", is_git_dirty);
fc.AddField(FieldType::App, "Git_Branch", Common::g_scm_branch);
fc.AddField(FieldType::App, "Git_Revision", Common::g_scm_rev);
fc.AddField(FieldType::App, "BuildDate", Common::g_build_date);
fc.AddField(FieldType::App, "BuildName", Common::g_build_name);
}
void AppendCPUInfo(FieldCollection& fc) {
#if CITRA_ARCH(x86_64)
fc.AddField(FieldType::UserSystem, "CPU_Model", Common::GetCPUCaps().cpu_string);
fc.AddField(FieldType::UserSystem, "CPU_BrandString", Common::GetCPUCaps().brand_string);
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AES", Common::GetCPUCaps().aes);
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AVX", Common::GetCPUCaps().avx);
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AVX2", Common::GetCPUCaps().avx2);
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AVX512", Common::GetCPUCaps().avx512);
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_BMI1", Common::GetCPUCaps().bmi1);
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_BMI2", Common::GetCPUCaps().bmi2);
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_FMA", Common::GetCPUCaps().fma);
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_FMA4", Common::GetCPUCaps().fma4);
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_SSE", Common::GetCPUCaps().sse);
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_SSE2", Common::GetCPUCaps().sse2);
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_SSE3", Common::GetCPUCaps().sse3);
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_SSSE3", Common::GetCPUCaps().ssse3);
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_SSE41", Common::GetCPUCaps().sse4_1);
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_SSE42", Common::GetCPUCaps().sse4_2);
#else
fc.AddField(FieldType::UserSystem, "CPU_Model", "Other");
#endif
}
void AppendOSInfo(FieldCollection& fc) {
#ifdef __APPLE__
fc.AddField(FieldType::UserSystem, "OsPlatform", "Apple");
#elif defined(_WIN32)
fc.AddField(FieldType::UserSystem, "OsPlatform", "Windows");
#elif defined(__linux__) || defined(linux) || defined(__linux)
fc.AddField(FieldType::UserSystem, "OsPlatform", "Linux");
#else
fc.AddField(FieldType::UserSystem, "OsPlatform", "Unknown");
#endif
}
} // namespace Common::Telemetry

View File

@ -1,199 +0,0 @@
// Copyright 2017 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <chrono>
#include <map>
#include <memory>
#include <string>
#include "common/common_types.h"
namespace Common::Telemetry {
/// Field type, used for grouping fields together in the final submitted telemetry log
enum class FieldType : u8 {
None = 0, ///< No specified field group
App, ///< Citra application fields (e.g. version, branch, etc.)
Session, ///< Emulated session fields (e.g. title ID, log, etc.)
Performance, ///< Emulated performance (e.g. fps, emulated CPU speed, etc.)
UserFeedback, ///< User submitted feedback (e.g. star rating, user notes, etc.)
UserConfig, ///< User configuration fields (e.g. emulated CPU core, renderer, etc.)
UserSystem, ///< User system information (e.g. host CPU type, RAM, etc.)
};
struct VisitorInterface;
/**
* Interface class for telemetry data fields.
*/
class FieldInterface : NonCopyable {
public:
virtual ~FieldInterface() = default;
/**
* Accept method for the visitor pattern.
* @param visitor Reference to the visitor that will visit this field.
*/
virtual void Accept(VisitorInterface& visitor) const = 0;
/**
* Gets the name of this field.
* @returns Name of this field as a string.
*/
virtual const std::string& GetName() const = 0;
};
/**
* Represents a telemetry data field, i.e. a unit of data that gets logged and submitted to our
* telemetry web service.
*/
template <typename T>
class Field : public FieldInterface {
public:
Field(FieldType type, std::string name, T value)
: name(std::move(name)), type(type), value(std::move(value)) {}
Field(const Field&) = default;
Field& operator=(const Field&) = default;
Field(Field&&) = default;
Field& operator=(Field&& other) = default;
void Accept(VisitorInterface& visitor) const override;
[[nodiscard]] const std::string& GetName() const override {
return name;
}
/**
* Returns the type of the field.
*/
[[nodiscard]] FieldType GetType() const {
return type;
}
/**
* Returns the value of the field.
*/
[[nodiscard]] const T& GetValue() const {
return value;
}
[[nodiscard]] bool operator==(const Field& other) const {
return (type == other.type) && (name == other.name) && (value == other.value);
}
[[nodiscard]] bool operator!=(const Field& other) const {
return !operator==(other);
}
private:
std::string name; ///< Field name, must be unique
FieldType type{}; ///< Field type, used for grouping fields together
T value; ///< Field value
};
/**
* Collection of data fields that have been logged.
*/
class FieldCollection final : NonCopyable {
public:
FieldCollection() = default;
/**
* Accept method for the visitor pattern, visits each field in the collection.
* @param visitor Reference to the visitor that will visit each field.
*/
void Accept(VisitorInterface& visitor) const;
/**
* Creates a new field and adds it to the field collection.
* @param type Type of the field to add.
* @param name Name of the field to add.
* @param value Value for the field to add.
*/
template <typename T>
void AddField(FieldType type, const char* name, T value) {
return AddField(std::make_unique<Field<T>>(type, name, std::move(value)));
}
/**
* Adds a new field to the field collection.
* @param field Field to add to the field collection.
*/
void AddField(std::unique_ptr<FieldInterface> field);
private:
std::map<std::string, std::unique_ptr<FieldInterface>> fields;
};
/**
* Telemetry fields visitor interface class. A backend to log to a web service should implement
* this interface.
*/
struct VisitorInterface : NonCopyable {
virtual ~VisitorInterface() = default;
virtual void Visit(const Field<bool>& field) = 0;
virtual void Visit(const Field<double>& field) = 0;
virtual void Visit(const Field<float>& field) = 0;
virtual void Visit(const Field<u8>& field) = 0;
virtual void Visit(const Field<u16>& field) = 0;
virtual void Visit(const Field<u32>& field) = 0;
virtual void Visit(const Field<u64>& field) = 0;
virtual void Visit(const Field<s8>& field) = 0;
virtual void Visit(const Field<s16>& field) = 0;
virtual void Visit(const Field<s32>& field) = 0;
virtual void Visit(const Field<s64>& field) = 0;
virtual void Visit(const Field<std::string>& field) = 0;
virtual void Visit(const Field<const char*>& field) = 0;
virtual void Visit(const Field<std::chrono::microseconds>& field) = 0;
/// Completion method, called once all fields have been visited
virtual void Complete() = 0;
virtual bool SubmitTestcase() = 0;
};
/**
* Empty implementation of VisitorInterface that drops all fields. Used when a functional
* backend implementation is not available.
*/
struct NullVisitor : public VisitorInterface {
~NullVisitor() = default;
void Visit(const Field<bool>& /*field*/) override {}
void Visit(const Field<double>& /*field*/) override {}
void Visit(const Field<float>& /*field*/) override {}
void Visit(const Field<u8>& /*field*/) override {}
void Visit(const Field<u16>& /*field*/) override {}
void Visit(const Field<u32>& /*field*/) override {}
void Visit(const Field<u64>& /*field*/) override {}
void Visit(const Field<s8>& /*field*/) override {}
void Visit(const Field<s16>& /*field*/) override {}
void Visit(const Field<s32>& /*field*/) override {}
void Visit(const Field<s64>& /*field*/) override {}
void Visit(const Field<std::string>& /*field*/) override {}
void Visit(const Field<const char*>& /*field*/) override {}
void Visit(const Field<std::chrono::microseconds>& /*field*/) override {}
void Complete() override {}
bool SubmitTestcase() override {
return false;
}
};
/// Appends build-specific information to the given FieldCollection,
/// such as branch name, revision hash, etc.
void AppendBuildInfo(FieldCollection& fc);
/// Appends CPU-specific information to the given FieldCollection,
/// such as instruction set extensions, etc.
void AppendCPUInfo(FieldCollection& fc);
/// Appends OS-specific information to the given FieldCollection,
/// such as platform name, etc.
void AppendOSInfo(FieldCollection& fc);
} // namespace Common::Telemetry

View File

@ -467,8 +467,6 @@ add_library(citra_core STATIC
savestate_data.h
system_titles.cpp
system_titles.h
telemetry_session.cpp
telemetry_session.h
tracer/citrace.h
tracer/recorder.cpp
tracer/recorder.h

View File

@ -47,7 +47,6 @@
#ifdef ENABLE_SCRIPTING
#include "core/rpc/server.h"
#endif
#include "core/telemetry_session.h"
#include "network/network.h"
#include "video_core/custom_textures/custom_tex_manager.h"
#include "video_core/gpu.h"
@ -263,6 +262,18 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st
return ResultStatus::ErrorGetLoader;
}
if (restore_plugin_context.has_value() && restore_plugin_context->is_enabled &&
restore_plugin_context->use_user_load_parameters) {
u64_le program_id = 0;
app_loader->ReadProgramId(program_id);
if (restore_plugin_context->user_load_parameters.low_title_Id ==
static_cast<u32_le>(program_id) &&
restore_plugin_context->user_load_parameters.plugin_memory_strategy ==
Service::PLGLDR::PLG_LDR::PluginMemoryStrategy::PLG_STRATEGY_MODE3) {
app_loader->SetKernelMemoryModeOverride(Kernel::MemoryMode::Dev2);
}
}
auto memory_mode = app_loader->LoadKernelMemoryMode();
if (memory_mode.second != Loader::ResultStatus::Success) {
LOG_CRITICAL(Core, "Failed to determine system mode (Error {})!",
@ -310,7 +321,6 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st
restore_plugin_context.reset();
}
telemetry_session->AddInitialInfo(*app_loader);
std::shared_ptr<Kernel::Process> process;
const Loader::ResultStatus load_result{app_loader->Load(process)};
if (Loader::ResultStatus::Success != load_result) {
@ -440,8 +450,6 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window,
Settings::values.output_device.GetValue());
dsp_core->EnableStretching(Settings::values.enable_audio_stretching.GetValue());
telemetry_session = std::make_unique<Core::TelemetrySession>();
#ifdef ENABLE_SCRIPTING
rpc_server = std::make_unique<RPC::Server>(*this);
#endif
@ -566,16 +574,6 @@ void System::RegisterImageInterface(std::shared_ptr<Frontend::ImageInterface> im
}
void System::Shutdown(bool is_deserializing) {
// Log last frame performance stats
const auto perf_results = GetAndResetPerfStats();
constexpr auto performance = Common::Telemetry::FieldType::Performance;
telemetry_session->AddField(performance, "Shutdown_EmulationSpeed",
perf_results.emulation_speed * 100.0);
telemetry_session->AddField(performance, "Shutdown_Framerate", perf_results.game_fps);
telemetry_session->AddField(performance, "Shutdown_Frametime", perf_results.frametime * 1000.0);
telemetry_session->AddField(performance, "Mean_Frametime_MS",
perf_stats ? perf_stats->GetMeanFrametime() : 0);
// Shutdown emulation session
is_powered_on = false;
@ -587,7 +585,6 @@ void System::Shutdown(bool is_deserializing) {
app_loader.reset();
}
custom_tex_manager.reset();
telemetry_session.reset();
#ifdef ENABLE_SCRIPTING
rpc_server.reset();
#endif

View File

@ -72,7 +72,6 @@ class AppLoader;
namespace Core {
class ARM_Interface;
class TelemetrySession;
class ExclusiveMonitor;
class Timing;
@ -165,14 +164,6 @@ public:
return is_powered_on;
}
/**
* Returns a reference to the telemetry session for this emulation session.
* @returns Reference to the telemetry session.
*/
[[nodiscard]] Core::TelemetrySession& TelemetrySession() const {
return *telemetry_session;
}
/// Prepare the core emulation for a reschedule
void PrepareReschedule();
@ -385,9 +376,6 @@ private:
/// When true, signals that a reschedule should happen
bool reschedule_pending{};
/// Telemetry session for this emulation session
std::unique_ptr<Core::TelemetrySession> telemetry_session;
std::unique_ptr<VideoCore::GPU> gpu;
/// Service manager

View File

@ -128,14 +128,14 @@ public:
LOG_CRITICAL(Service_FS, "(unreachable) Invalid mount point {}", mount_point);
return ResultFileNotFound;
case PathParser::PathNotFound:
LOG_ERROR(Service_FS, "Path not found {}", full_path);
LOG_DEBUG(Service_FS, "Path not found {}", full_path);
return ResultPathNotFound;
case PathParser::FileInPath:
case PathParser::DirectoryFound:
LOG_ERROR(Service_FS, "Unexpected file or directory in {}", full_path);
LOG_DEBUG(Service_FS, "Unexpected file or directory in {}", full_path);
return ResultUnexpectedFileOrDirectory;
case PathParser::NotFound:
LOG_ERROR(Service_FS, "{} not found", full_path);
LOG_DEBUG(Service_FS, "{} not found", full_path);
return ResultFileNotFound;
case PathParser::FileFound:
break; // Expected 'success' case

View File

@ -83,14 +83,14 @@ ResultVal<std::unique_ptr<FileBackend>> SDMCArchive::OpenFileBase(const Path& pa
return ResultNotFound;
case PathParser::PathNotFound:
case PathParser::FileInPath:
LOG_ERROR(Service_FS, "Path not found {}", full_path);
LOG_DEBUG(Service_FS, "Path not found {}", full_path);
return ResultNotFound;
case PathParser::DirectoryFound:
LOG_ERROR(Service_FS, "{} is not a file", full_path);
LOG_DEBUG(Service_FS, "{} is not a file", full_path);
return ResultUnexpectedFileOrDirectorySdmc;
case PathParser::NotFound:
if (!mode.create_flag) {
LOG_ERROR(Service_FS, "Non-existing file {} can't be open without mode create.",
LOG_DEBUG(Service_FS, "Non-existing file {} can't be open without mode create.",
full_path);
return ResultNotFound;
} else {
@ -348,10 +348,10 @@ ResultVal<std::unique_ptr<DirectoryBackend>> SDMCArchive::OpenDirectory(const Pa
case PathParser::PathNotFound:
case PathParser::NotFound:
case PathParser::FileFound:
LOG_ERROR(Service_FS, "{} not found", full_path);
LOG_DEBUG(Service_FS, "{} not found", full_path);
return ResultNotFound;
case PathParser::FileInPath:
LOG_ERROR(Service_FS, "Unexpected file in path {}", full_path);
LOG_DEBUG(Service_FS, "Unexpected file in path {}", full_path);
return ResultUnexpectedFileOrDirectorySdmc;
case PathParser::DirectoryFound:
break; // Expected 'success' case

View File

@ -577,11 +577,26 @@ Loader::ResultStatus NCCHContainer::ApplyCodePatch(std::vector<u8>& code) const
const auto mods_path =
fmt::format("{}mods/{:016X}/", FileUtil::GetUserPath(FileUtil::UserPath::LoadDir),
GetModId(ncch_header.program_id));
const std::array<PatchLocation, 6> patch_paths{{
constexpr u32 system_module_tid_high = 0x00040130;
std::string luma_ips_location;
if ((static_cast<u32>(ncch_header.program_id >> 32) & system_module_tid_high) ==
system_module_tid_high) {
luma_ips_location =
fmt::format("{}luma/sysmodules/{:016X}.ips",
FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), ncch_header.program_id);
} else {
luma_ips_location =
fmt::format("{}luma/titles/{:016X}/code.ips",
FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), ncch_header.program_id);
}
const std::array<PatchLocation, 7> patch_paths{{
{mods_path + "exefs/code.ips", Patch::ApplyIpsPatch},
{mods_path + "exefs/code.bps", Patch::ApplyBpsPatch},
{mods_path + "code.ips", Patch::ApplyIpsPatch},
{mods_path + "code.bps", Patch::ApplyBpsPatch},
{luma_ips_location, Patch::ApplyIpsPatch},
{filepath + ".exefsdir/code.ips", Patch::ApplyIpsPatch},
{filepath + ".exefsdir/code.bps", Patch::ApplyBpsPatch},
}};

View File

@ -45,10 +45,10 @@ bool ResourceLimit::Reserve(ResourceLimitType type, s32 amount) {
const auto index = static_cast<std::size_t>(type);
const s32 limit = m_limit_values[index];
const s32 new_value = m_current_values[index] + amount;
// TODO(PabloMK7): Fix all resource limit bugs and return an error, instead of ignoring it.
if (new_value > limit) {
LOG_ERROR(Kernel, "New value {} exceeds limit {} for resource type {}", new_value, limit,
type);
return false;
}
m_current_values[index] = new_value;
return true;
@ -57,10 +57,10 @@ bool ResourceLimit::Reserve(ResourceLimitType type, s32 amount) {
bool ResourceLimit::Release(ResourceLimitType type, s32 amount) {
const auto index = static_cast<std::size_t>(type);
const s32 value = m_current_values[index];
// TODO(PabloMK7): Fix all resource limit bugs and return an error, instead of ignoring it.
if (amount > value) {
LOG_ERROR(Kernel, "Amount {} exceeds current value {} for resource type {}", amount, value,
type);
return false;
}
m_current_values[index] = value - amount;
return true;

View File

@ -4,11 +4,13 @@
#include <algorithm>
#include <array>
#include <chrono>
#include <fmt/format.h>
#include "common/archives.h"
#include "common/logging/log.h"
#include "common/microprofile.h"
#include "common/scm_rev.h"
#include "common/settings.h"
#include "core/arm/arm_interface.h"
#include "core/core.h"
#include "core/core_timing.h"
@ -73,6 +75,12 @@ enum class KernelState {
* Reboots the console
*/
KERNEL_STATE_REBOOT = 7,
// Special Citra only states.
/**
* Sets the emulation speed percentage. A value of 0 means unthrottled.
*/
KERNEL_STATE_CITRA_EMULATION_SPEED = 0x20000 ///
};
struct PageInfo {
@ -268,8 +276,11 @@ enum class SystemInfoMemUsageRegion {
*/
enum class SystemInfoCitraInformation {
IS_CITRA = 0, // Always set the output to 1, signaling the app is running on Citra.
HOST_TICK = 1, // Tick reference from the host in ns, unaffected by lag or cpu speed.
EMULATION_SPEED = 2, // Gets the emulation speed set by the user or by KernelSetState.
BUILD_NAME = 10, // (ie: Nightly, Canary).
BUILD_VERSION = 11, // Build version.
BUILD_PLATFORM = 12, // Build platform, see SystemInfoCitraPlatform.
BUILD_DATE_PART1 = 20, // Build date first 7 characters.
BUILD_DATE_PART2 = 21, // Build date next 7 characters.
BUILD_DATE_PART3 = 22, // Build date next 7 characters.
@ -280,6 +291,17 @@ enum class SystemInfoCitraInformation {
BUILD_GIT_DESCRIPTION_PART2 = 41, // Git description (commit) last 7 characters.
};
/**
* Current officially supported platforms.
*/
enum class SystemInfoCitraPlatform {
PLATFORM_UNKNOWN = 0,
PLATFORM_WINDOWS = 1,
PLATFORM_LINUX = 2,
PLATFORM_APPLE = 3,
PLATFORM_ANDROID = 4,
};
/**
* Accepted by the custom svcControlProcess.
*/
@ -382,6 +404,9 @@ private:
s64 nano_seconds);
Result ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_count,
Handle reply_target);
Result InvalidateProcessDataCache(Handle process_handle, VAddr address, u32 size);
Result StoreProcessDataCache(Handle process_handle, VAddr address, u32 size);
Result FlushProcessDataCache(Handle process_handle, VAddr address, u32 size);
Result CreateAddressArbiter(Handle* out_handle);
Result ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value, s64 nanoseconds);
void Break(u8 break_reason);
@ -1005,6 +1030,39 @@ Result SVC::ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_count,
return ResultSuccess;
}
/// Invalidates the specified cache range (stubbed as we do not emulate cache).
Result SVC::InvalidateProcessDataCache(Handle process_handle, VAddr address, u32 size) {
const std::shared_ptr<Process> process =
kernel.GetCurrentProcess()->handle_table.Get<Process>(process_handle);
R_UNLESS(process, ResultInvalidHandle);
LOG_DEBUG(Kernel_SVC, "called address=0x{:08X}, size=0x{:08X}", address, size);
return ResultSuccess;
}
/// Stores the specified cache range (stubbed as we do not emulate cache).
Result SVC::StoreProcessDataCache(Handle process_handle, VAddr address, u32 size) {
const std::shared_ptr<Process> process =
kernel.GetCurrentProcess()->handle_table.Get<Process>(process_handle);
R_UNLESS(process, ResultInvalidHandle);
LOG_DEBUG(Kernel_SVC, "called address=0x{:08X}, size=0x{:08X}", address, size);
return ResultSuccess;
}
/// Flushes the specified cache range (stubbed as we do not emulate cache).
Result SVC::FlushProcessDataCache(Handle process_handle, VAddr address, u32 size) {
const std::shared_ptr<Process> process =
kernel.GetCurrentProcess()->handle_table.Get<Process>(process_handle);
R_UNLESS(process, ResultInvalidHandle);
LOG_DEBUG(Kernel_SVC, "called address=0x{:08X}, size=0x{:08X}", address, size);
return ResultSuccess;
}
/// Create an address arbiter (to allocate access to shared resources)
Result SVC::CreateAddressArbiter(Handle* out_handle) {
// Update address arbiter count in resource limit.
@ -1370,6 +1428,12 @@ Result SVC::KernelSetState(u32 kernel_state, u32 varg1, u32 varg2) {
case KernelState::KERNEL_STATE_REBOOT:
system.RequestShutdown();
break;
// Citra specific states.
case KernelState::KERNEL_STATE_CITRA_EMULATION_SPEED: {
u16 new_value = static_cast<u16>(varg1);
Settings::values.frame_limit.SetValue(new_value);
} break;
default:
LOG_ERROR(Kernel_SVC, "Unknown KernelSetState state={} varg1={} varg2={}", kernel_state,
varg1, varg2);
@ -1740,12 +1804,34 @@ Result SVC::GetSystemInfo(s64* out, u32 type, s32 param) {
case SystemInfoCitraInformation::IS_CITRA:
*out = 1;
break;
case SystemInfoCitraInformation::HOST_TICK:
*out = static_cast<s64>(std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::steady_clock::now().time_since_epoch())
.count());
break;
case SystemInfoCitraInformation::EMULATION_SPEED:
*out = static_cast<s64>(Settings::values.frame_limit.GetValue());
break;
case SystemInfoCitraInformation::BUILD_NAME:
CopyStringPart(reinterpret_cast<char*>(out), Common::g_build_name, 0, sizeof(s64));
break;
case SystemInfoCitraInformation::BUILD_VERSION:
CopyStringPart(reinterpret_cast<char*>(out), Common::g_build_version, 0, sizeof(s64));
break;
case SystemInfoCitraInformation::BUILD_PLATFORM: {
#if defined(_WIN32)
*out = static_cast<s64>(SystemInfoCitraPlatform::PLATFORM_WINDOWS);
#elif defined(ANDROID)
*out = static_cast<s64>(SystemInfoCitraPlatform::PLATFORM_ANDROID);
#elif defined(__linux__)
*out = static_cast<s64>(SystemInfoCitraPlatform::PLATFORM_LINUX);
#elif defined(__APPLE__)
*out = static_cast<s64>(SystemInfoCitraPlatform::PLATFORM_APPLE);
#else
*out = static_cast<s64>(SystemInfoCitraPlatform::PLATFORM_UNKNOWN);
#endif
break;
}
case SystemInfoCitraInformation::BUILD_DATE_PART1:
CopyStringPart(reinterpret_cast<char*>(out), Common::g_build_date,
(sizeof(s64) - 1) * 0, sizeof(s64));
@ -2124,9 +2210,9 @@ const std::array<SVC::FunctionDef, 180> SVC::SVC_Table{{
{0x4F, &SVC::Wrap<&SVC::ReplyAndReceive>, "ReplyAndReceive"},
{0x50, nullptr, "BindInterrupt"},
{0x51, nullptr, "UnbindInterrupt"},
{0x52, nullptr, "InvalidateProcessDataCache"},
{0x53, nullptr, "StoreProcessDataCache"},
{0x54, nullptr, "FlushProcessDataCache"},
{0x52, &SVC::Wrap<&SVC::InvalidateProcessDataCache>, "InvalidateProcessDataCache"},
{0x53, &SVC::Wrap<&SVC::StoreProcessDataCache>, "StoreProcessDataCache"},
{0x54, &SVC::Wrap<&SVC::FlushProcessDataCache>, "FlushProcessDataCache"},
{0x55, nullptr, "StartInterProcessDma"},
{0x56, nullptr, "StopDma"},
{0x57, nullptr, "GetDmaState"},

View File

@ -13,7 +13,6 @@
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/shared_page.h"
#include "core/hle/result.h"
#include "core/hle/service/ac/ac.h"
#include "core/hle/service/ac/ac_i.h"
@ -41,143 +40,76 @@ void Module::Interface::CreateDefaultConfig(Kernel::HLERequestContext& ctx) {
void Module::Interface::ConnectAsync(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
const u32 pid = rp.PopPID();
rp.Skip(2, false); // ProcessId descriptor
ac->connect_event = rp.PopObject<Kernel::Event>();
rp.Skip(2, false); // Buffer descriptor
ac->Connect(pid);
if (ac->connect_event) {
ac->connect_event->SetName("AC:connect_event");
ac->connect_event->Signal();
ac->ac_connected = true;
}
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(ResultSuccess);
LOG_WARNING(Service_AC, "(STUBBED) called, pid={}", pid);
LOG_WARNING(Service_AC, "(STUBBED) called");
}
void Module::Interface::GetConnectResult(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
[[maybe_unused]] const u32 pid = rp.PopPID();
rp.Skip(2, false); // ProcessId descriptor
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(ac->connect_result);
}
void Module::Interface::CancelConnectAsync(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
const u32 pid = rp.PopPID();
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(ac->ac_connected ? ErrorAlreadyConnected : ErrorNotConnected);
LOG_WARNING(Service_AC, "(STUBBED) called, pid={}", pid);
rb.Push(ResultSuccess);
}
void Module::Interface::CloseAsync(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
const u32 pid = rp.PopPID();
rp.Skip(2, false); // ProcessId descriptor
ac->close_event = rp.PopObject<Kernel::Event>();
ac->Disconnect(pid);
if (ac->ac_connected && ac->disconnect_event) {
ac->disconnect_event->Signal();
}
if (ac->close_event) {
ac->close_event->SetName("AC:close_event");
ac->close_event->Signal();
}
ac->ac_connected = false;
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(ResultSuccess);
LOG_WARNING(Service_AC, "(STUBBED) called, pid={}", pid);
}
void Module::Interface::GetCloseResult(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
[[maybe_unused]] const u32 pid = rp.PopPID();
rp.Skip(2, false); // ProcessId descriptor
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(ac->close_result);
rb.Push(ResultSuccess);
LOG_WARNING(Service_AC, "(STUBBED) called");
}
void Module::Interface::GetWifiStatus(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
bool can_reach_internet = false;
if (!ac->ac_connected) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(ErrorNotConnected);
return;
std::shared_ptr<SOC::SOC_U> socu_module = SOC::GetService(ac->system);
if (socu_module) {
can_reach_internet = socu_module->GetDefaultInterfaceInfo().has_value();
}
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
rb.Push(ResultSuccess);
rb.Push<u32>(static_cast<u32>(WifiStatus::STATUS_CONNECTED_SLOT1));
LOG_WARNING(Service_AC, "(STUBBED) called");
}
void Module::Interface::GetCurrentAPInfo(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
const u32 len = rp.Pop<u32>();
const u32 pid = rp.PopPID();
if (!ac->ac_connected) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(ErrorNotConnected);
return;
}
constexpr const char* citra_ap = "Citra_AP";
constexpr s16 good_signal_strength = 60;
constexpr u8 unknown1_value = 6;
constexpr u8 unknown2_value = 5;
constexpr u8 unknown3_value = 5;
constexpr u8 unknown4_value = 0;
SharedPage::Handler& shared_page = ac->system.Kernel().GetSharedPageHandler();
SharedPage::MacAddress mac = shared_page.GetMacAddress();
APInfo info{
.ssid_len = static_cast<u32>(std::strlen(citra_ap)),
.bssid = mac,
.padding = 0,
.signal_strength = good_signal_strength,
.link_level = static_cast<u8>(shared_page.GetWifiLinkLevel()),
.unknown1 = unknown1_value,
.unknown2 = unknown2_value,
.unknown3 = unknown3_value,
.unknown4 = unknown4_value,
};
std::strncpy(info.ssid.data(), citra_ap, info.ssid.size());
std::vector<u8> out_info(len);
std::memcpy(out_info.data(), &info, std::min(len, static_cast<u32>(sizeof(info))));
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(ResultSuccess);
rb.PushStaticBuffer(out_info, 0);
LOG_WARNING(Service_AC, "(STUBBED) called, pid={}", pid);
}
void Module::Interface::GetConnectingInfraPriority(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
if (!ac->ac_connected) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(ErrorNotConnected);
return;
}
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
rb.Push(ResultSuccess);
rb.Push<u32>(static_cast<u32>(InfraPriority::PRIORITY_HIGH));
LOG_WARNING(Service_AC, "(STUBBED) called");
}
void Module::Interface::GetStatus(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
rb.Push(ResultSuccess);
rb.Push<u32>(static_cast<u32>(ac->ac_connected ? NetworkStatus::STATUS_INTERNET
: NetworkStatus::STATUS_DISCONNECTED));
LOG_WARNING(Service_AC, "(STUBBED) called");
rb.Push<u32>(static_cast<u32>(can_reach_internet ? (Settings::values.is_new_3ds
? WifiStatus::STATUS_CONNECTED_N3DS
: WifiStatus::STATUS_CONNECTED_O3DS)
: WifiStatus::STATUS_DISCONNECTED));
}
void Module::Interface::GetInfraPriority(Kernel::HLERequestContext& ctx) {
@ -186,28 +118,16 @@ void Module::Interface::GetInfraPriority(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
rb.Push(ResultSuccess);
rb.Push<u32>(static_cast<u32>(InfraPriority::PRIORITY_HIGH));
rb.Push<u32>(0); // Infra Priority, default 0
LOG_WARNING(Service_AC, "(STUBBED) called");
}
void Module::Interface::SetFromApplication(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
const u32 unknown = rp.Pop<u32>();
auto config = rp.PopStaticBuffer();
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(ResultSuccess);
rb.PushStaticBuffer(config, 0);
LOG_WARNING(Service_AC, "(STUBBED) called, unknown={}", unknown);
}
void Module::Interface::SetRequestEulaVersion(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
const u32 major = rp.Pop<u8>();
const u32 minor = rp.Pop<u8>();
u32 major = rp.Pop<u8>();
u32 minor = rp.Pop<u8>();
const std::vector<u8>& ac_config = rp.PopStaticBuffer();
@ -220,19 +140,6 @@ void Module::Interface::SetRequestEulaVersion(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AC, "(STUBBED) called, major={}, minor={}", major, minor);
}
void Module::Interface::GetNZoneBeaconNotFoundEvent(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
rp.PopPID();
auto event = rp.PopObject<Kernel::Event>();
event->Signal();
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(ResultSuccess);
LOG_WARNING(Service_AC, "(STUBBED) called");
}
void Module::Interface::RegisterDisconnectEvent(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
rp.Skip(2, false); // ProcessId descriptor
@ -261,93 +168,30 @@ void Module::Interface::GetConnectingProxyEnable(Kernel::HLERequestContext& ctx)
void Module::Interface::IsConnected(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
const u32 unk = rp.Pop<u32>();
const u32 pid = rp.PopPID();
u32 unk = rp.Pop<u32>();
u32 unk_descriptor = rp.Pop<u32>();
u32 unk_param = rp.Pop<u32>();
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
rb.Push(ResultSuccess);
rb.Push(ac->ac_connected);
LOG_DEBUG(Service_AC, "(STUBBED) called unk=0x{:08X} pid={}", unk, pid);
LOG_WARNING(Service_AC, "(STUBBED) called unk=0x{:08X} descriptor=0x{:08X} param=0x{:08X}", unk,
unk_descriptor, unk_param);
}
void Module::Interface::SetClientVersion(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
const u32 version = rp.Pop<u32>();
rp.PopPID();
u32 version = rp.Pop<u32>();
rp.Skip(2, false); // ProcessId descriptor
LOG_DEBUG(Service_AC, "(STUBBED) called, version: 0x{:08X}", version);
LOG_WARNING(Service_AC, "(STUBBED) called, version: 0x{:08X}", version);
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(ResultSuccess);
}
void Module::Connect(u32 pid) {
if (connect_event) {
connect_event->SetName("AC:connect_event");
connect_event->Signal();
}
if (connected_pids.size() == 0) {
// TODO(PabloMK7) Publish to subscriber 0x300
ac_connected = true;
// TODO(PabloMK7) Move shared page modification to NWM once it is implemented.
SharedPage::Handler& shared_page = system.Kernel().GetSharedPageHandler();
const bool can_access_internet = CanAccessInternet();
if (can_access_internet) {
shared_page.SetWifiState(SharedPage::WifiState::Internet);
shared_page.SetWifiLinkLevel(SharedPage::WifiLinkLevel::Best);
} else {
shared_page.SetWifiState(SharedPage::WifiState::Enabled);
shared_page.SetWifiLinkLevel(SharedPage::WifiLinkLevel::Off);
}
}
if (connected_pids.find(pid) == connected_pids.end()) {
connected_pids.insert(pid);
connect_result = ResultSuccess;
} else {
connect_result = ErrorAlreadyConnected;
}
}
void Module::Disconnect(u32 pid) {
if (close_event) {
close_event->SetName("AC:close_event");
close_event->Signal();
}
if (connected_pids.find(pid) != connected_pids.end()) {
connected_pids.erase(pid);
close_result = ResultSuccess;
} else {
close_result = ErrorNotConnected;
}
if (connected_pids.size() == 0) {
ac_connected = false;
if (disconnect_event) {
disconnect_event->Signal();
}
// TODO(PabloMK7) Move shared page modification to NWM once it is implemented.
SharedPage::Handler& shared_page = system.Kernel().GetSharedPageHandler();
shared_page.SetWifiState(SharedPage::WifiState::Enabled);
shared_page.SetWifiLinkLevel(SharedPage::WifiLinkLevel::Off);
}
}
bool Module::CanAccessInternet() {
std::shared_ptr<SOC::SOC_U> socu_module = SOC::GetService(system);
if (socu_module) {
return socu_module->GetDefaultInterfaceInfo().has_value();
}
return false;
}
Module::Interface::Interface(std::shared_ptr<Module> ac, const char* name, u32 max_session)
: ServiceFramework(name, max_session), ac(std::move(ac)) {}
@ -358,10 +202,6 @@ void InstallInterfaces(Core::System& system) {
std::make_shared<AC_U>(ac)->InstallAsService(service_manager);
}
std::shared_ptr<AC_U> GetService(Core::System& system) {
return system.ServiceManager().GetService<AC_U>("ac:u");
}
Module::Module(Core::System& system_) : system(system_) {}
template <class Archive>
@ -370,13 +210,6 @@ void Module::serialize(Archive& ar, const unsigned int) {
ar& close_event;
ar& connect_event;
ar& disconnect_event;
u32 connect_result_32 = connect_result.raw;
ar& connect_result_32;
connect_result.raw = connect_result_32;
u32 close_result_32 = close_result.raw;
ar& close_result_32;
close_result.raw = close_result_32;
ar& connected_pids;
// default_config is never written to
}
SERIALIZE_IMPL(Module)

View File

@ -17,7 +17,6 @@ class Event;
}
namespace Service::AC {
class AC_U;
class Module final {
public:
explicit Module(Core::System& system_);
@ -59,15 +58,6 @@ public:
*/
void GetConnectResult(Kernel::HLERequestContext& ctx);
/**
* AC::CancelConnectAsync service function
* Inputs:
* 1 : ProcessId Header
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void CancelConnectAsync(Kernel::HLERequestContext& ctx);
/**
* AC::CloseAsync service function
* Inputs:
@ -88,40 +78,14 @@ public:
*/
void GetCloseResult(Kernel::HLERequestContext& ctx);
/**
* AC::GetStatus service function
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
* 2 : Output status
*/
void GetStatus(Kernel::HLERequestContext& ctx);
/**
* AC::GetWifiStatus service function
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
* 2 : Output wifi status
* 2 : Output connection type, 0 = none, 1 = Old3DS Internet, 2 = New3DS Internet.
*/
void GetWifiStatus(Kernel::HLERequestContext& ctx);
/**
* AC::GetCurrentAPInfo service function
* Inputs:
* 1 : Size
* 2-3 : ProcessID
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void GetCurrentAPInfo(Kernel::HLERequestContext& ctx);
/**
* AC::GetConnectingInfraPriority service function
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
* 2 : Output connecting priority
*/
void GetConnectingInfraPriority(Kernel::HLERequestContext& ctx);
/**
* AC::GetInfraPriority service function
* Inputs:
@ -133,15 +97,6 @@ public:
*/
void GetInfraPriority(Kernel::HLERequestContext& ctx);
/**
* AC::SetFromApplication service function
* Inputs:
* 1-2 : Input config
* Outputs:
* 1-2 : Output config
*/
void SetFromApplication(Kernel::HLERequestContext& ctx);
/**
* AC::SetRequestEulaVersion service function
* Inputs:
@ -157,17 +112,6 @@ public:
*/
void SetRequestEulaVersion(Kernel::HLERequestContext& ctx);
/**
* AC::GetNZoneBeaconNotFoundEvent service function
* Inputs:
* 1 : ProcessId Header
* 3 : Copy Handle Header
* 4 : Event handle, should be signaled when AC cannot find NZone
* Outputs:
* 1 : Result of function, 0 on success, otherwise error code
*/
void GetNZoneBeaconNotFoundEvent(Kernel::HLERequestContext& ctx);
/**
* AC::RegisterDisconnectEvent service function
* Inputs:
@ -209,46 +153,12 @@ public:
};
protected:
static constexpr Result ErrorNotConnected =
Result(302, ErrorModule::AC, ErrorSummary::InvalidState, ErrorLevel::Usage);
static constexpr Result ErrorAlreadyConnected =
Result(301, ErrorModule::AC, ErrorSummary::InvalidState, ErrorLevel::Usage);
enum class NetworkStatus {
STATUS_DISCONNECTED = 0,
STATUS_ENABLED = 1,
STATUS_LOCAL = 2,
STATUS_INTERNET = 3,
};
enum class WifiStatus {
STATUS_DISCONNECTED = 0,
STATUS_CONNECTED_SLOT1 = (1 << 0),
STATUS_CONNECTED_SLOT2 = (1 << 1),
STATUS_CONNECTED_SLOT3 = (1 << 2),
STATUS_CONNECTED_O3DS = 1,
STATUS_CONNECTED_N3DS = 2,
};
enum class InfraPriority {
PRIORITY_HIGH = 0,
PRIORITY_LOW = 1,
PRIORITY_NONE = 2,
};
struct APInfo {
u32 ssid_len;
std::array<char, 0x20> ssid;
std::array<u8, 0x6> bssid;
u16 padding;
s16 signal_strength;
u8 link_level;
u8 unknown1;
u8 unknown2;
u8 unknown3;
u16 unknown4;
};
static_assert(sizeof(APInfo) == 0x34, "Invalid APInfo size");
struct ACConfig {
std::array<u8, 0x200> data;
};
@ -260,15 +170,6 @@ protected:
std::shared_ptr<Kernel::Event> close_event;
std::shared_ptr<Kernel::Event> connect_event;
std::shared_ptr<Kernel::Event> disconnect_event;
Result connect_result = ResultSuccess;
Result close_result = ResultSuccess;
std::set<u32> connected_pids;
void Connect(u32 pid);
void Disconnect(u32 pid);
bool CanAccessInternet();
private:
Core::System& system;
@ -280,8 +181,6 @@ private:
void InstallInterfaces(Core::System& system);
std::shared_ptr<AC_U> GetService(Core::System& system);
} // namespace Service::AC
BOOST_CLASS_EXPORT_KEY(Service::AC::Module)

View File

@ -13,22 +13,19 @@ AC_I::AC_I(std::shared_ptr<Module> ac) : Module::Interface(std::move(ac), "ac:i"
{0x0001, &AC_I::CreateDefaultConfig, "CreateDefaultConfig"},
{0x0004, &AC_I::ConnectAsync, "ConnectAsync"},
{0x0005, &AC_I::GetConnectResult, "GetConnectResult"},
{0x0007, &AC_I::CancelConnectAsync, "CancelConnectAsync"},
{0x0007, nullptr, "CancelConnectAsync"},
{0x0008, &AC_I::CloseAsync, "CloseAsync"},
{0x0009, &AC_I::GetCloseResult, "GetCloseResult"},
{0x000A, nullptr, "GetLastErrorCode"},
{0x000C, &AC_I::GetStatus, "GetStatus"},
{0x000C, nullptr, "GetStatus"},
{0x000D, &AC_I::GetWifiStatus, "GetWifiStatus"},
{0x000E, &AC_I::GetCurrentAPInfo, "GetCurrentAPInfo"},
{0x000F, &AC_I::GetConnectingInfraPriority, "GetConnectingInfraPriority"},
{0x000E, nullptr, "GetCurrentAPInfo"},
{0x0010, nullptr, "GetCurrentNZoneInfo"},
{0x0011, nullptr, "GetNZoneApNumService"},
{0x001D, nullptr, "ScanAPs"},
{0x0024, nullptr, "AddDenyApType"},
{0x0027, &AC_I::GetInfraPriority, "GetInfraPriority"},
{0x002C, &AC_I::SetFromApplication, "SetFromApplication"},
{0x002D, &AC_I::SetRequestEulaVersion, "SetRequestEulaVersion"},
{0x002F, &AC_I::GetNZoneBeaconNotFoundEvent, "GetNZoneBeaconNotFoundEvent"},
{0x0030, &AC_I::RegisterDisconnectEvent, "RegisterDisconnectEvent"},
{0x0036, &AC_I::GetConnectingProxyEnable, "GetConnectingProxyEnable"},
{0x003C, nullptr, "GetAPSSIDList"},

View File

@ -13,22 +13,19 @@ AC_U::AC_U(std::shared_ptr<Module> ac) : Module::Interface(std::move(ac), "ac:u"
{0x0001, &AC_U::CreateDefaultConfig, "CreateDefaultConfig"},
{0x0004, &AC_U::ConnectAsync, "ConnectAsync"},
{0x0005, &AC_U::GetConnectResult, "GetConnectResult"},
{0x0007, &AC_U::CancelConnectAsync, "CancelConnectAsync"},
{0x0007, nullptr, "CancelConnectAsync"},
{0x0008, &AC_U::CloseAsync, "CloseAsync"},
{0x0009, &AC_U::GetCloseResult, "GetCloseResult"},
{0x000A, nullptr, "GetLastErrorCode"},
{0x000C, &AC_U::GetStatus, "GetStatus"},
{0x000C, nullptr, "GetStatus"},
{0x000D, &AC_U::GetWifiStatus, "GetWifiStatus"},
{0x000E, &AC_U::GetCurrentAPInfo, "GetCurrentAPInfo"},
{0x000F, &AC_U::GetConnectingInfraPriority, "GetConnectingInfraPriority"},
{0x000E, nullptr, "GetCurrentAPInfo"},
{0x0010, nullptr, "GetCurrentNZoneInfo"},
{0x0011, nullptr, "GetNZoneApNumService"},
{0x001D, nullptr, "ScanAPs"},
{0x0024, nullptr, "AddDenyApType"},
{0x0027, &AC_U::GetInfraPriority, "GetInfraPriority"},
{0x002C, &AC_U::SetFromApplication, "SetFromApplication"},
{0x002D, &AC_U::SetRequestEulaVersion, "SetRequestEulaVersion"},
{0x002F, &AC_U::GetNZoneBeaconNotFoundEvent, "GetNZoneBeaconNotFoundEvent"},
{0x0030, &AC_U::RegisterDisconnectEvent, "RegisterDisconnectEvent"},
{0x0036, &AC_U::GetConnectingProxyEnable, "GetConnectingProxyEnable"},
{0x003C, nullptr, "GetAPSSIDList"},

View File

@ -80,6 +80,35 @@ struct TicketInfo {
static_assert(sizeof(TicketInfo) == 0x18, "Ticket info structure size is wrong");
bool CTCert::IsValid() const {
constexpr std::string_view expected_issuer_prod = "Nintendo CA - G3_NintendoCTR2prod";
constexpr std::string_view expected_issuer_dev = "Nintendo CA - G3_NintendoCTR2dev";
constexpr u32 expected_signature_type = 0x010005;
return signature_type == expected_signature_type &&
(std::string(issuer.data()) == expected_issuer_prod ||
std::string(issuer.data()) == expected_issuer_dev);
return false;
}
u32 CTCert::GetDeviceID() const {
constexpr std::string_view key_id_prefix = "CT";
const std::string key_id_str(key_id.data());
if (key_id_str.starts_with(key_id_prefix)) {
const std::string device_id =
key_id_str.substr(key_id_prefix.size(), key_id_str.find('-') - key_id_prefix.size());
char* end_ptr;
const u32 device_id_value = std::strtoul(device_id.c_str(), &end_ptr, 16);
if (*end_ptr == '\0') {
return device_id_value;
}
}
// Error
return 0;
}
class CIAFile::DecryptionState {
public:
std::vector<CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption> content;
@ -1213,6 +1242,21 @@ void Module::Interface::GetTicketList(Kernel::HLERequestContext& ctx) {
ticket_list_count, ticket_index);
}
void Module::Interface::GetDeviceID(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
const u32 deviceID = am->ct_cert.IsValid() ? am->ct_cert.GetDeviceID() : 0;
if (deviceID == 0) {
LOG_ERROR(Service_AM, "Invalid or missing CTCert");
}
IPC::RequestBuilder rb = rp.MakeBuilder(3, 0);
rb.Push(ResultSuccess);
rb.Push(0);
rb.Push(deviceID);
}
void Module::Interface::NeedsCleanup(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
const auto media_type = rp.Pop<u8>();
@ -1802,13 +1846,66 @@ void Module::serialize(Archive& ar, const unsigned int) {
}
SERIALIZE_IMPL(Module)
Module::Module(Core::System& system) : system(system) {
void Module::Interface::GetDeviceCert(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
[[maybe_unused]] u32 size = rp.Pop<u32>();
auto buffer = rp.PopMappedBuffer();
if (!am->ct_cert.IsValid()) {
LOG_ERROR(Service_AM, "Invalid or missing CTCert");
}
buffer.Write(&am->ct_cert, 0, std::min(sizeof(CTCert), buffer.GetSize()));
IPC::RequestBuilder rb = rp.MakeBuilder(2, 2);
rb.Push(ResultSuccess);
rb.Push(0);
rb.PushMappedBuffer(buffer);
}
std::string Module::GetCTCertPath() {
return FileUtil::GetUserPath(FileUtil::UserPath::SysDataDir) + "CTCert.bin";
}
CTCertLoadStatus Module::LoadCTCertFile(CTCert& output) {
if (output.IsValid()) {
return CTCertLoadStatus::Loaded;
}
std::string file_path = GetCTCertPath();
if (!FileUtil::Exists(file_path)) {
return CTCertLoadStatus::NotFound;
}
FileUtil::IOFile file(file_path, "rb");
if (!file.IsOpen()) {
return CTCertLoadStatus::IOError;
}
if (file.GetSize() != sizeof(CTCert)) {
return CTCertLoadStatus::Invalid;
}
if (file.ReadBytes(&output, sizeof(CTCert)) != sizeof(CTCert)) {
return CTCertLoadStatus::IOError;
}
if (!output.IsValid()) {
output = CTCert();
return CTCertLoadStatus::Invalid;
}
return CTCertLoadStatus::Loaded;
}
Module::Module(Core::System& _system) : system(_system) {
ScanForAllTitles();
LoadCTCertFile(ct_cert);
system_updater_mutex = system.Kernel().CreateMutex(false, "AM::SystemUpdaterMutex");
}
Module::~Module() = default;
std::shared_ptr<Module> GetModule(Core::System& system) {
auto am = system.ServiceManager().GetService<Service::AM::Module::Interface>("am:u");
if (!am)
return nullptr;
return am->GetModule();
}
void InstallInterfaces(Core::System& system) {
auto& service_manager = system.ServiceManager();
auto am = std::make_shared<Module>(system);

View File

@ -68,6 +68,31 @@ enum class InstallStatus : u32 {
ErrorEncrypted,
};
enum class CTCertLoadStatus {
Loaded,
NotFound,
Invalid,
IOError,
};
struct CTCert {
u32_be signature_type{};
std::array<u8, 0x1E> signature_r{};
std::array<u8, 0x1E> signature_s{};
INSERT_PADDING_BYTES(0x40){};
std::array<char, 0x40> issuer{};
u32_be key_type{};
std::array<char, 0x40> key_id{};
u32_be expiration_time{};
std::array<u8, 0x1E> public_key_x{};
std::array<u8, 0x1E> public_key_y{};
INSERT_PADDING_BYTES(0x3C){};
bool IsValid() const;
u32 GetDeviceID() const;
};
static_assert(sizeof(CTCert) == 0x180, "Invalid CTCert size.");
// Title ID valid length
constexpr std::size_t TITLE_ID_VALID_LENGTH = 16;
@ -216,6 +241,10 @@ public:
Interface(std::shared_ptr<Module> am, const char* name, u32 max_session);
~Interface();
std::shared_ptr<Module> GetModule() const {
return am;
}
protected:
/**
* AM::GetNumPrograms service function
@ -415,6 +444,16 @@ public:
*/
void GetTicketList(Kernel::HLERequestContext& ctx);
/**
* AM::GetDeviceID service function
* Inputs:
* Outputs:
* 1 : Result, 0 on success, otherwise error code
* 2 : Unknown
* 3 : DeviceID
*/
void GetDeviceID(Kernel::HLERequestContext& ctx);
/**
* AM::NeedsCleanup service function
* Inputs:
@ -702,10 +741,32 @@ public:
*/
void EndImportTicket(Kernel::HLERequestContext& ctx);
/**
* AM::GetDeviceCert service function
* Inputs:
* Outputs:
* 1 : Result, 0 on success, otherwise error code
* 2 : Unknown
* 3-4 : Device cert
*/
void GetDeviceCert(Kernel::HLERequestContext& ctx);
protected:
std::shared_ptr<Module> am;
};
/**
* Gets the CTCert.bin path in the host filesystem
* @returns std::string CTCert.bin path in the host filesystem
*/
static std::string GetCTCertPath();
/**
* Loads the CTCert.bin file from the filesystem.
* @returns CTCertLoadStatus indicating the file load status.
*/
static CTCertLoadStatus LoadCTCertFile(CTCert& output);
private:
/**
* Scans the for titles in a storage medium for listing.
@ -722,12 +783,15 @@ private:
bool cia_installing = false;
std::array<std::vector<u64_le>, 3> am_title_list;
std::shared_ptr<Kernel::Mutex> system_updater_mutex;
CTCert ct_cert{};
template <class Archive>
void serialize(Archive& ar, const unsigned int);
friend class boost::serialization::access;
};
std::shared_ptr<Module> GetModule(Core::System& system);
void InstallInterfaces(Core::System& system);
} // namespace Service::AM

View File

@ -19,7 +19,7 @@ AM_NET::AM_NET(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "a
{0x0007, &AM_NET::DeleteTicket, "DeleteTicket"},
{0x0008, &AM_NET::GetNumTickets, "GetNumTickets"},
{0x0009, &AM_NET::GetTicketList, "GetTicketList"},
{0x000A, nullptr, "GetDeviceID"},
{0x000A, &AM_NET::GetDeviceID, "GetDeviceID"},
{0x000B, nullptr, "GetNumImportTitleContexts"},
{0x000C, nullptr, "GetImportTitleContextList"},
{0x000D, nullptr, "GetImportTitleContexts"},
@ -103,7 +103,7 @@ AM_NET::AM_NET(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "a
{0x0815, nullptr, "GetCurrentImportContentContexts"},
{0x0816, nullptr, "Sign"},
{0x0817, nullptr, "Verify"},
{0x0818, nullptr, "GetDeviceCert"},
{0x0818, &AM_NET::GetDeviceCert, "GetDeviceCert"},
{0x0819, nullptr, "ImportCertificates"},
{0x081A, nullptr, "ImportCertificate"},
{0x081B, nullptr, "CommitImportTitlesAndUpdateFirmwareAuto"},

View File

@ -19,7 +19,7 @@ AM_SYS::AM_SYS(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "a
{0x0007, &AM_SYS::DeleteTicket, "DeleteTicket"},
{0x0008, &AM_SYS::GetNumTickets, "GetNumTickets"},
{0x0009, &AM_SYS::GetTicketList, "GetTicketList"},
{0x000A, nullptr, "GetDeviceID"},
{0x000A, &AM_SYS::GetDeviceID, "GetDeviceID"},
{0x000B, nullptr, "GetNumImportTitleContexts"},
{0x000C, nullptr, "GetImportTitleContextList"},
{0x000D, nullptr, "GetImportTitleContexts"},

View File

@ -19,7 +19,7 @@ AM_U::AM_U(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "am:u"
{0x0007, &AM_U::DeleteTicket, "DeleteTicket"},
{0x0008, &AM_U::GetNumTickets, "GetNumTickets"},
{0x0009, &AM_U::GetTicketList, "GetTicketList"},
{0x000A, nullptr, "GetDeviceID"},
{0x000A, &AM_U::GetDeviceID, "GetDeviceID"},
{0x000B, nullptr, "GetNumImportTitleContexts"},
{0x000C, nullptr, "GetImportTitleContextList"},
{0x000D, nullptr, "GetImportTitleContexts"},

View File

@ -574,7 +574,7 @@ Result AppletManager::PrepareToStartLibraryApplet(AppletId applet_id) {
if (Settings::values.lle_applets) {
auto cfg = Service::CFG::GetModule(system);
auto process = NS::LaunchTitle(FS::MediaType::NAND,
auto process = NS::LaunchTitle(system, FS::MediaType::NAND,
GetTitleIdForApplet(applet_id, cfg->GetRegionValue()));
if (process) {
return ResultSuccess;
@ -603,7 +603,7 @@ Result AppletManager::PreloadLibraryApplet(AppletId applet_id) {
if (Settings::values.lle_applets) {
auto cfg = Service::CFG::GetModule(system);
auto process = NS::LaunchTitle(FS::MediaType::NAND,
auto process = NS::LaunchTitle(system, FS::MediaType::NAND,
GetTitleIdForApplet(applet_id, cfg->GetRegionValue()));
if (process) {
return ResultSuccess;
@ -815,7 +815,7 @@ Result AppletManager::StartSystemApplet(AppletId applet_id, std::shared_ptr<Kern
applet_id == AppletId::HomeMenu ? AppletSlot::HomeMenu : AppletSlot::SystemApplet;
if (!GetAppletSlot(slot_id)->registered) {
auto cfg = Service::CFG::GetModule(system);
auto process = NS::LaunchTitle(FS::MediaType::NAND,
auto process = NS::LaunchTitle(system, FS::MediaType::NAND,
GetTitleIdForApplet(applet_id, cfg->GetRegionValue()));
if (!process) {
// TODO: Find the right error code.
@ -1346,8 +1346,8 @@ Result AppletManager::StartApplication(const std::vector<u8>& parameter,
active_slot = AppletSlot::Application;
// Launch the title directly.
auto process =
NS::LaunchTitle(app_start_parameters->next_media_type, app_start_parameters->next_title_id);
auto process = NS::LaunchTitle(system, app_start_parameters->next_media_type,
app_start_parameters->next_title_id);
if (!process) {
LOG_CRITICAL(Service_APT, "Failed to launch title during application start, exiting.");
system.RequestShutdown();
@ -1423,7 +1423,7 @@ void AppletManager::EnsureHomeMenuLoaded() {
auto cfg = Service::CFG::GetModule(system);
auto menu_title_id = GetTitleIdForApplet(AppletId::HomeMenu, cfg->GetRegionValue());
auto process = NS::LaunchTitle(FS::MediaType::NAND, menu_title_id);
auto process = NS::LaunchTitle(system, FS::MediaType::NAND, menu_title_id);
if (!process) {
LOG_WARNING(Service_APT,
"The Home Menu failed to launch, application jumping will not work.");

View File

@ -34,7 +34,6 @@
#include "core/hw/aes/ccm.h"
#include "core/hw/aes/key.h"
#include "core/loader/loader.h"
#include "core/telemetry_session.h"
SERVICE_CONSTRUCT_IMPL(Service::APT::Module)
@ -274,10 +273,6 @@ void Module::APTInterface::GetSharedFont(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
IPC::RequestBuilder rb = rp.MakeBuilder(2, 2);
// Log in telemetry if the game uses the shared font
apt->system.TelemetrySession().AddField(Common::Telemetry::FieldType::Session,
"RequiresSharedFont", true);
if (!apt->shared_font_loaded) {
// On real 3DS, font loading happens on booting. However, we load it on demand to coordinate
// with CFG region auto configuration, which happens later than APT initialization.

View File

@ -9,7 +9,8 @@
namespace Service::NS {
std::shared_ptr<Kernel::Process> LaunchTitle(FS::MediaType media_type, u64 title_id) {
std::shared_ptr<Kernel::Process> LaunchTitle(Core::System& system, FS::MediaType media_type,
u64 title_id) {
std::string path = AM::GetTitleContentPath(media_type, title_id);
auto loader = Loader::GetLoader(path);
@ -18,6 +19,17 @@ std::shared_ptr<Kernel::Process> LaunchTitle(FS::MediaType media_type, u64 title
return nullptr;
}
auto plg_ldr = Service::PLGLDR::GetService(system);
if (plg_ldr) {
const auto& plg_context = plg_ldr->GetPluginLoaderContext();
if (plg_context.is_enabled && plg_context.use_user_load_parameters &&
plg_context.user_load_parameters.low_title_Id == static_cast<u32>(title_id) &&
plg_context.user_load_parameters.plugin_memory_strategy ==
PLGLDR::PLG_LDR::PluginMemoryStrategy::PLG_STRATEGY_MODE3) {
loader->SetKernelMemoryModeOverride(Kernel::MemoryMode::Dev2);
}
}
std::shared_ptr<Kernel::Process> process;
Loader::ResultStatus result = loader->Load(process);

View File

@ -16,7 +16,8 @@ class System;
namespace Service::NS {
/// Loads and launches the title identified by title_id in the specified media type.
std::shared_ptr<Kernel::Process> LaunchTitle(FS::MediaType media_type, u64 title_id);
std::shared_ptr<Kernel::Process> LaunchTitle(Core::System& system, FS::MediaType media_type,
u64 title_id);
/// Reboots the system to the specified title.
void RebootToTitle(Core::System& system, FS::MediaType media_type, u64 title_id);

View File

@ -7,6 +7,7 @@
#include "common/archives.h"
#include "common/common_funcs.h"
#include "common/logging/log.h"
#include "common/scope_exit.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
@ -522,7 +523,16 @@ void Y2R_U::StartConversion(Kernel::HLERequestContext& ctx) {
HW::Y2R::PerformConversion(system.Memory(), conversion);
completion_event->Signal();
if (is_busy_conversion) {
system.CoreTiming().RemoveEvent(completion_signal_event);
}
// This value has been estimated as the minimum amount of cycles to resolve a race condition
// in the intro cutscene of the FIFA series of games.
// TODO: Measure the cycle count more accurately based on hardware.
static constexpr s64 MinY2RDelay = 50000;
system.CoreTiming().ScheduleEvent(MinY2RDelay, completion_signal_event);
is_busy_conversion = true;
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(ResultSuccess);
@ -533,6 +543,10 @@ void Y2R_U::StartConversion(Kernel::HLERequestContext& ctx) {
void Y2R_U::StopConversion(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
if (is_busy_conversion) {
system.CoreTiming().RemoveEvent(completion_signal_event);
}
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(ResultSuccess);
@ -544,7 +558,7 @@ void Y2R_U::IsBusyConversion(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
rb.Push(ResultSuccess);
rb.Push<u8>(0); // StartConversion always finishes immediately
rb.Push(is_busy_conversion);
LOG_DEBUG(Service_Y2R, "called");
}
@ -558,34 +572,38 @@ void Y2R_U::SetPackageParameter(Kernel::HLERequestContext& ctx) {
conversion.rotation = params.rotation;
conversion.block_alignment = params.block_alignment;
Result result = conversion.SetInputLineWidth(params.input_line_width);
if (result.IsError())
goto cleanup;
result = conversion.SetInputLines(params.input_lines);
if (result.IsError())
goto cleanup;
result = conversion.SetStandardCoefficient(params.standard_coefficient);
if (result.IsError())
goto cleanup;
conversion.padding = params.padding;
conversion.alpha = params.alpha;
cleanup:
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(result);
LOG_DEBUG(Service_Y2R,
"called input_format={} output_format={} rotation={} block_alignment={} "
"input_line_width={} input_lines={} standard_coefficient={} reserved={} alpha={:X}",
params.input_format, params.output_format, params.rotation, params.block_alignment,
params.input_line_width, params.input_lines, params.standard_coefficient,
params.padding, params.alpha);
auto result = conversion.SetInputLineWidth(params.input_line_width);
SCOPE_EXIT({
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(result);
});
if (result.IsError()) {
return;
}
result = conversion.SetInputLines(params.input_lines);
if (result.IsError()) {
return;
}
result = conversion.SetStandardCoefficient(params.standard_coefficient);
if (result.IsError()) {
return;
}
conversion.padding = params.padding;
conversion.alpha = params.alpha;
}
void Y2R_U::PingProcess(Kernel::HLERequestContext& ctx) {
@ -697,6 +715,11 @@ Y2R_U::Y2R_U(Core::System& system) : ServiceFramework("y2r:u", 1), system(system
RegisterHandlers(functions);
completion_event = system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "Y2R:Completed");
completion_signal_event =
system.CoreTiming().RegisterEvent("Y2R Completion Signal Event", [this](uintptr_t, s64) {
completion_event->Signal();
is_busy_conversion = false;
});
}
Y2R_U::~Y2R_U() = default;

View File

@ -349,11 +349,13 @@ private:
Core::System& system;
std::shared_ptr<Kernel::Event> completion_event;
Core::TimingEventType* completion_signal_event;
ConversionConfiguration conversion{};
DitheringWeightParams dithering_weight_params{};
bool temporal_dithering_enabled = false;
bool transfer_end_interrupt_enabled = false;
bool spacial_dithering_enabled = false;
bool is_busy_conversion = false;
template <class Archive>
void serialize(Archive& ar, const unsigned int);

View File

@ -217,12 +217,39 @@ void Module::Interface::GetRegion(Kernel::HLERequestContext& ctx) {
void Module::Interface::SecureInfoGetByte101(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
LOG_DEBUG(Service_CFG, "(STUBBED) called");
u8 ret = 0;
if (cfg->secure_info_a_loaded) {
ret = cfg->secure_info_a.unknown;
}
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
rb.Push(ResultSuccess);
// According to 3dbrew this is normally 0.
rb.Push<u8>(0);
rb.Push<u8>(ret);
}
void Module::Interface::SecureInfoGetSerialNo(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
[[maybe_unused]] u32 out_size = rp.Pop<u32>();
auto out_buffer = rp.PopMappedBuffer();
if (out_buffer.GetSize() < sizeof(SecureInfoA::serial_number)) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(Result(ErrorDescription::InvalidSize, ErrorModule::Config,
ErrorSummary::WrongArgument, ErrorLevel::Permanent));
}
// Never happens on real hardware, but may happen if user didn't supply a dump.
// Always make sure to have available both secure data kinds or error otherwise.
if (!cfg->secure_info_a_loaded || !cfg->local_friend_code_seed_b_loaded) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(Result(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::InvalidState,
ErrorLevel::Permanent));
}
out_buffer.Write(&cfg->secure_info_a.serial_number, 0, sizeof(SecureInfoA::serial_number));
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(ResultSuccess);
rb.PushMappedBuffer(out_buffer);
}
void Module::Interface::SetUUIDClockSequence(Kernel::HLERequestContext& ctx) {
@ -365,6 +392,43 @@ void Module::Interface::UpdateConfigNANDSavegame(Kernel::HLERequestContext& ctx)
rb.Push(cfg->UpdateConfigNANDSavegame());
}
void Module::Interface::GetLocalFriendCodeSeedData(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
[[maybe_unused]] u32 out_size = rp.Pop<u32>();
auto out_buffer = rp.PopMappedBuffer();
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
if (out_buffer.GetSize() < sizeof(LocalFriendCodeSeedB)) {
rb.Push(Result(ErrorDescription::InvalidSize, ErrorModule::Config,
ErrorSummary::WrongArgument, ErrorLevel::Permanent));
}
// Never happens on real hardware, but may happen if user didn't supply a dump.
// Always make sure to have available both secure data kinds or error otherwise.
if (!cfg->secure_info_a_loaded || !cfg->local_friend_code_seed_b_loaded) {
rb.Push(Result(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::InvalidState,
ErrorLevel::Permanent));
}
out_buffer.Write(&cfg->local_friend_code_seed_b, 0, sizeof(LocalFriendCodeSeedB));
rb.Push(ResultSuccess);
}
void Module::Interface::GetLocalFriendCodeSeed(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
// Never happens on real hardware, but may happen if user didn't supply a dump.
// Always make sure to have available both secure data kinds or error otherwise.
if (!cfg->secure_info_a_loaded || !cfg->local_friend_code_seed_b_loaded) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(Result(ErrorDescription::NotFound, ErrorModule::Config, ErrorSummary::InvalidState,
ErrorLevel::Permanent));
}
IPC::RequestBuilder rb = rp.MakeBuilder(3, 0);
rb.Push(ResultSuccess);
rb.Push<u64>(cfg->local_friend_code_seed_b.friend_code_seed);
}
void Module::Interface::FormatConfig(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
@ -506,6 +570,14 @@ Result Module::UpdateConfigNANDSavegame() {
return ResultSuccess;
}
std::string Module::GetLocalFriendCodeSeedBPath() {
return FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + "rw/sys/LocalFriendCodeSeed_B";
}
std::string Module::GetSecureInfoAPath() {
return FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + "rw/sys/SecureInfo_A";
}
Result Module::FormatConfig() {
Result res = DeleteConfigNANDSaveFile();
// The delete command fails if the file doesn't exist, so we have to check that too
@ -579,6 +651,55 @@ Result Module::LoadConfigNANDSaveFile() {
return FormatConfig();
}
void Module::InvalidateSecureData() {
secure_info_a_loaded = local_friend_code_seed_b_loaded = false;
}
SecureDataLoadStatus Module::LoadSecureInfoAFile() {
if (secure_info_a_loaded) {
return SecureDataLoadStatus::Loaded;
}
std::string file_path = GetSecureInfoAPath();
if (!FileUtil::Exists(file_path)) {
return SecureDataLoadStatus::NotFound;
}
FileUtil::IOFile file(file_path, "rb");
if (!file.IsOpen()) {
return SecureDataLoadStatus::IOError;
}
if (file.GetSize() != sizeof(SecureInfoA)) {
return SecureDataLoadStatus::Invalid;
}
if (file.ReadBytes(&secure_info_a, sizeof(SecureInfoA)) != sizeof(SecureInfoA)) {
return SecureDataLoadStatus::IOError;
}
secure_info_a_loaded = true;
return SecureDataLoadStatus::Loaded;
}
SecureDataLoadStatus Module::LoadLocalFriendCodeSeedBFile() {
if (local_friend_code_seed_b_loaded) {
return SecureDataLoadStatus::Loaded;
}
std::string file_path = GetLocalFriendCodeSeedBPath();
if (!FileUtil::Exists(file_path)) {
return SecureDataLoadStatus::NotFound;
}
FileUtil::IOFile file(file_path, "rb");
if (!file.IsOpen()) {
return SecureDataLoadStatus::IOError;
}
if (file.GetSize() != sizeof(LocalFriendCodeSeedB)) {
return SecureDataLoadStatus::Invalid;
}
if (file.ReadBytes(&local_friend_code_seed_b, sizeof(LocalFriendCodeSeedB)) !=
sizeof(LocalFriendCodeSeedB)) {
return SecureDataLoadStatus::IOError;
}
local_friend_code_seed_b_loaded = true;
return SecureDataLoadStatus::Loaded;
}
void Module::LoadMCUConfig() {
FileUtil::IOFile mcu_data_file(
fmt::format("{}/mcu.dat", FileUtil::GetUserPath(FileUtil::UserPath::SysDataDir)), "rb");
@ -616,6 +737,8 @@ Module::Module(Core::System& system_) : system(system_) {
SetEULAVersion(default_version);
UpdateConfigNANDSavegame();
}
LoadSecureInfoAFile();
LoadLocalFriendCodeSeedBFile();
}
Module::~Module() = default;

View File

@ -176,6 +176,28 @@ enum class AccessFlag : u16 {
};
DECLARE_ENUM_FLAG_OPERATORS(AccessFlag);
struct SecureInfoA {
std::array<u8, 0x100> signature;
u8 region;
u8 unknown;
std::array<u8, 0xF> serial_number;
};
static_assert(sizeof(SecureInfoA) == 0x111);
struct LocalFriendCodeSeedB {
std::array<u8, 0x100> signature;
u64 unknown;
u64 friend_code_seed;
};
static_assert(sizeof(LocalFriendCodeSeedB) == 0x110);
enum class SecureDataLoadStatus {
Loaded,
NotFound,
Invalid,
IOError,
};
class Module final {
public:
Module(Core::System& system_);
@ -230,6 +252,18 @@ public:
*/
void SecureInfoGetByte101(Kernel::HLERequestContext& ctx);
/**
* CFG::SecureInfoGetSerialNo service function
* Inputs:
* 1 : Buffer Size
* 2-3: Output mapped buffer
* Outputs:
* 0 : Result Header code
* 1 : Result of function, 0 on success, otherwise error code
* 2-3 : Output mapped buffer
*/
void SecureInfoGetSerialNo(Kernel::HLERequestContext& ctx);
/**
* CFG::SetUUIDClockSequence service function
* Inputs:
@ -345,6 +379,27 @@ public:
*/
void UpdateConfigNANDSavegame(Kernel::HLERequestContext& ctx);
/**
* CFG::GetLocalFriendCodeSeedData service function
* Inputs:
* 1 : Buffer Size
* 2-3: Output mapped buffer
* Outputs:
* 0 : Result Header code
* 1 : Result of function, 0 on success, otherwise error code
*/
void GetLocalFriendCodeSeedData(Kernel::HLERequestContext& ctx);
/**
* CFG::GetLocalFriendCodeSeed service function
* Inputs:
* Outputs:
* 0 : Result Header code
* 1 : Result of function, 0 on success, otherwise error code
* 2-3 : Friend code seed
*/
void GetLocalFriendCodeSeed(Kernel::HLERequestContext& ctx);
/**
* CFG::FormatConfig service function
* Inputs:
@ -575,6 +630,34 @@ public:
*/
Result UpdateConfigNANDSavegame();
/**
* Invalidates the loaded secure data so that it is loaded again.
*/
void InvalidateSecureData();
/**
* Loads the LocalFriendCodeSeed_B file from NAND.
* @returns LocalFriendCodeSeedBLoadStatus indicating the file load status.
*/
SecureDataLoadStatus LoadSecureInfoAFile();
/**
* Loads the LocalFriendCodeSeed_B file from NAND.
* @returns LocalFriendCodeSeedBLoadStatus indicating the file load status.
*/
SecureDataLoadStatus LoadLocalFriendCodeSeedBFile();
/**
* Gets the SecureInfo_A path in the host filesystem
* @returns std::string SecureInfo_A path in the host filesystem
*/
std::string GetSecureInfoAPath();
/**
* Gets the LocalFriendCodeSeed_B path in the host filesystem
* @returns std::string LocalFriendCodeSeed_B path in the host filesystem
*/
std::string GetLocalFriendCodeSeedBPath();
/**
* Saves MCU specific data
*/
@ -590,6 +673,10 @@ private:
std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer;
std::unique_ptr<FileSys::ArchiveBackend> cfg_system_save_data_archive;
u32 preferred_region_code = 0;
bool secure_info_a_loaded = false;
SecureInfoA secure_info_a;
bool local_friend_code_seed_b_loaded = false;
LocalFriendCodeSeedB local_friend_code_seed_b;
bool preferred_region_chosen = false;
MCUData mcu_data{};

View File

@ -28,11 +28,11 @@ CFG_I::CFG_I(std::shared_ptr<Module> cfg) : Module::Interface(std::move(cfg), "c
{0x0401, &CFG_I::GetSystemConfig, "GetSystemConfig"},
{0x0402, &CFG_I::SetSystemConfig, "SetSystemConfig"},
{0x0403, &CFG_I::UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
{0x0404, nullptr, "GetLocalFriendCodeSeedData"},
{0x0405, nullptr, "GetLocalFriendCodeSeed"},
{0x0404, &CFG_I::GetLocalFriendCodeSeedData, "GetLocalFriendCodeSeedData"},
{0x0405, &CFG_I::GetLocalFriendCodeSeed, "GetLocalFriendCodeSeed"},
{0x0406, &CFG_I::GetRegion, "GetRegion"},
{0x0407, &CFG_I::SecureInfoGetByte101, "SecureInfoGetByte101"},
{0x0408, nullptr, "SecureInfoGetSerialNo"},
{0x0408, &CFG_I::SecureInfoGetSerialNo, "SecureInfoGetSerialNo"},
{0x0409, nullptr, "UpdateConfigBlk00040003"},
// cfg:i
{0x0801, &CFG_I::GetSystemConfig, "GetSystemConfig"},

View File

@ -28,11 +28,11 @@ CFG_S::CFG_S(std::shared_ptr<Module> cfg) : Module::Interface(std::move(cfg), "c
{0x0401, &CFG_S::GetSystemConfig, "GetSystemConfig"},
{0x0402, &CFG_S::SetSystemConfig, "SetSystemConfig"},
{0x0403, &CFG_S::UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
{0x0404, nullptr, "GetLocalFriendCodeSeedData"},
{0x0405, nullptr, "GetLocalFriendCodeSeed"},
{0x0404, &CFG_S::GetLocalFriendCodeSeedData, "GetLocalFriendCodeSeedData"},
{0x0405, &CFG_S::GetLocalFriendCodeSeed, "GetLocalFriendCodeSeed"},
{0x0406, &CFG_S::GetRegion, "GetRegion"},
{0x0407, &CFG_S::SecureInfoGetByte101, "SecureInfoGetByte101"},
{0x0408, nullptr, "SecureInfoGetSerialNo"},
{0x0408, &CFG_S::SecureInfoGetSerialNo, "SecureInfoGetSerialNo"},
{0x0409, nullptr, "UpdateConfigBlk00040003"},
{0x040D, &CFG_S::SetUUIDClockSequence, "SetUUIDClockSequence"},
{0x040E, &CFG_S::GetUUIDClockSequence, "GetUUIDClockSequence"},

View File

@ -62,7 +62,7 @@ void File::Read(Kernel::HLERequestContext& ctx) {
const FileSessionSlot* file = GetSessionData(ctx.Session());
if (file->subfile && length > file->size) {
LOG_WARNING(Service_FS, "Trying to read beyond the subfile size, truncating");
LOG_DEBUG(Service_FS, "Trying to read beyond the subfile size, truncating");
length = static_cast<u32>(file->size);
}
@ -70,7 +70,7 @@ void File::Read(Kernel::HLERequestContext& ctx) {
offset += file->offset;
if (offset + length > backend->GetSize()) {
LOG_ERROR(Service_FS,
LOG_DEBUG(Service_FS,
"Reading from out of bounds offset=0x{:x} length=0x{:08X} file_size=0x{:x}",
offset, length, backend->GetSize());
}

View File

@ -121,7 +121,7 @@ void FS_USER::OpenFileDirectly(Kernel::HLERequestContext& ctx) {
rb.PushMoveObjects(file->Connect());
} else {
rb.PushMoveObjects<Kernel::Object>(nullptr);
LOG_ERROR(Service_FS, "failed to get a handle for file {} mode={} attributes={}",
LOG_DEBUG(Service_FS, "failed to get a handle for file {} mode={} attributes={}",
file_path.DebugStr(), mode.hex, attributes);
}
@ -301,7 +301,7 @@ void FS_USER::OpenDirectory(Kernel::HLERequestContext& ctx) {
directory->ClientConnected(server);
rb.PushMoveObjects(client);
} else {
LOG_ERROR(Service_FS, "failed to get a handle for directory type={} size={} data={}",
LOG_DEBUG(Service_FS, "failed to get a handle for directory type={} size={} data={}",
dirname_type, dirname_size, dir_path.DebugStr());
rb.PushMoveObjects<Kernel::Object>(nullptr);
}

View File

@ -575,10 +575,6 @@ void NWM_UDS::Shutdown(Kernel::HLERequestContext& ctx) {
recv_buffer_memory.reset();
SharedPage::Handler& shared_page = system.Kernel().GetSharedPageHandler();
shared_page.SetWifiLinkLevel(SharedPage::WifiLinkLevel::Off);
shared_page.SetWifiState(SharedPage::WifiState::Enabled);
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
rb.Push(ResultSuccess);
LOG_DEBUG(Service_NWM, "called");
@ -671,10 +667,6 @@ ResultVal<std::shared_ptr<Kernel::Event>> NWM_UDS::Initialize(
channel_data.clear();
}
SharedPage::Handler& shared_page = system.Kernel().GetSharedPageHandler();
shared_page.SetWifiLinkLevel(SharedPage::WifiLinkLevel::Best);
shared_page.SetWifiState(SharedPage::WifiState::Local1);
return connection_status_event;
}

View File

@ -204,7 +204,10 @@ void PLG_LDR::SetLoadSettings(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp(ctx);
plgldr_context.use_user_load_parameters = true;
plgldr_context.user_load_parameters.no_flash = rp.Pop<u32>() == 1;
u32_le flags = rp.Pop<u32>();
plgldr_context.user_load_parameters.no_flash = (flags & 1) == 1;
plgldr_context.user_load_parameters.plugin_memory_strategy =
static_cast<PluginMemoryStrategy>((flags >> 8) & 0xF);
plgldr_context.user_load_parameters.low_title_Id = rp.Pop<u32>();
auto path = rp.PopMappedBuffer();

View File

@ -33,10 +33,16 @@ namespace Service::PLGLDR {
class PLG_LDR final : public ServiceFramework<PLG_LDR> {
public:
enum class PluginMemoryStrategy : u8 {
PLG_STRATEGY_NONE = 2,
PLG_STRATEGY_SWAP = 0,
PLG_STRATEGY_MODE3 = 1,
};
struct PluginLoaderContext {
struct PluginLoadParameters {
u8 no_flash = 0;
u8 no_IR_Patch = 0;
PluginMemoryStrategy plugin_memory_strategy = PluginMemoryStrategy::PLG_STRATEGY_SWAP;
u32_le low_title_Id = 0;
char path[256] = {0};
u32_le config[32] = {0};
@ -44,7 +50,7 @@ public:
template <class Archive>
void serialize(Archive& ar, const unsigned int) {
ar& no_flash;
ar& no_IR_Patch;
ar& plugin_memory_strategy;
ar& low_title_Id;
ar& path;
ar& config;

View File

@ -2251,7 +2251,7 @@ std::optional<SOC_U::InterfaceInfo> SOC_U::GetDefaultInterfaceInfo() {
socklen_t s_info_len = sizeof(struct sockaddr_in);
sockaddr_in s_info;
if ((sock_fd = ::socket(AF_INET, SOCK_STREAM, 0)) == -1) {
if (static_cast<int>(sock_fd = ::socket(AF_INET, SOCK_STREAM, 0)) == -1) {
return std::nullopt;
}
@ -2269,7 +2269,7 @@ std::optional<SOC_U::InterfaceInfo> SOC_U::GetDefaultInterfaceInfo() {
#ifdef _WIN32
sock_fd = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
if (sock_fd == SOCKET_ERROR) {
if (static_cast<int>(sock_fd) == SOCKET_ERROR) {
return std::nullopt;
}

View File

@ -117,6 +117,14 @@ public:
return std::make_pair(0x2, ResultStatus::Success);
}
/**
* Forces the application memory mode to the specified value,
* overriding the memory mode specified in the metadata.
*/
void SetKernelMemoryModeOverride(Kernel::MemoryMode mem_override) {
memory_mode_override = mem_override;
}
/**
* Loads the memory mode that this application needs.
* This function defaults to Dev1 (96MB allocated to the application) if it can't read the
@ -124,6 +132,9 @@ public:
* @returns A pair with the optional memory mode, and the status.
*/
virtual std::pair<std::optional<Kernel::MemoryMode>, ResultStatus> LoadKernelMemoryMode() {
if (memory_mode_override.has_value()) {
return std::make_pair(*memory_mode_override, ResultStatus::Success);
}
// 96MB allocated to the application.
return std::make_pair(Kernel::MemoryMode::Dev1, ResultStatus::Success);
}
@ -257,6 +268,7 @@ protected:
Core::System& system;
FileUtil::IOFile file;
bool is_loaded = false;
std::optional<Kernel::MemoryMode> memory_mode_override = std::nullopt;
};
/**

View File

@ -26,7 +26,6 @@
#include "core/loader/smdh.h"
#include "core/memory.h"
#include "core/system_titles.h"
#include "core/telemetry_session.h"
#include "network/network.h"
namespace Loader {
@ -69,6 +68,9 @@ std::pair<std::optional<Kernel::MemoryMode>, ResultStatus> AppLoader_NCCH::LoadK
return std::make_pair(std::nullopt, res);
}
}
if (memory_mode_override.has_value()) {
return std::make_pair(memory_mode_override, ResultStatus::Success);
}
// Provide the memory mode from the exheader.
auto& ncch_caps = overlay_ncch->exheader_header.arm11_system_local_caps;
@ -159,7 +161,7 @@ ResultStatus AppLoader_NCCH::LoadExec(std::shared_ptr<Kernel::Process>& process)
// APPLICATION. See:
// https://github.com/LumaTeam/Luma3DS/blob/e2778a45/sysmodules/pm/source/launch.c#L237
auto& ncch_caps = overlay_ncch->exheader_header.arm11_system_local_caps;
const auto o3ds_mode = static_cast<Kernel::MemoryMode>(ncch_caps.system_mode.Value());
const auto o3ds_mode = *LoadKernelMemoryMode().first;
const auto n3ds_mode = static_cast<Kernel::New3dsMemoryMode>(ncch_caps.n3ds_mode);
const bool is_new_3ds = Settings::values.is_new_3ds.GetValue();
if (is_new_3ds && n3ds_mode == Kernel::New3dsMemoryMode::Legacy &&
@ -274,9 +276,6 @@ ResultStatus AppLoader_NCCH::Load(std::shared_ptr<Kernel::Process>& process) {
overlay_ncch = &update_ncch;
}
system.TelemetrySession().AddField(Common::Telemetry::FieldType::Session, "ProgramId",
program_id);
if (auto room_member = Network::GetRoomMember().lock()) {
Network::GameInfo game_info;
ReadTitle(game_info.name);

View File

@ -1,176 +0,0 @@
// Copyright 2017 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <cryptopp/osrng.h>
#include "common/assert.h"
#include "common/common_types.h"
#include "common/file_util.h"
#include "common/logging/log.h"
#include "common/scm_rev.h"
#include "common/settings.h"
#include "core/core.h"
#include "core/loader/loader.h"
#include "core/telemetry_session.h"
#include "network/network_settings.h"
#ifdef ENABLE_WEB_SERVICE
#include "web_service/telemetry_json.h"
#include "web_service/verify_login.h"
#endif
namespace Core {
namespace Telemetry = Common::Telemetry;
static u64 GenerateTelemetryId() {
u64 telemetry_id{};
CryptoPP::AutoSeededRandomPool rng;
rng.GenerateBlock(reinterpret_cast<CryptoPP::byte*>(&telemetry_id), sizeof(u64));
return telemetry_id;
}
u64 GetTelemetryId() {
u64 telemetry_id{};
const std::string filename{FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) +
"telemetry_id"};
if (FileUtil::Exists(filename)) {
FileUtil::IOFile file(filename, "rb");
if (!file.IsOpen()) {
LOG_ERROR(Core, "failed to open telemetry_id: {}", filename);
return {};
}
file.ReadBytes(&telemetry_id, sizeof(u64));
} else {
FileUtil::IOFile file(filename, "wb");
if (!file.IsOpen()) {
LOG_ERROR(Core, "failed to open telemetry_id: {}", filename);
return {};
}
telemetry_id = GenerateTelemetryId();
file.WriteBytes(&telemetry_id, sizeof(u64));
}
return telemetry_id;
}
u64 RegenerateTelemetryId() {
const u64 new_telemetry_id{GenerateTelemetryId()};
const std::string filename{FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) +
"telemetry_id"};
FileUtil::IOFile file(filename, "wb");
if (!file.IsOpen()) {
LOG_ERROR(Core, "failed to open telemetry_id: {}", filename);
return {};
}
file.WriteBytes(&new_telemetry_id, sizeof(u64));
return new_telemetry_id;
}
bool VerifyLogin(const std::string& username, const std::string& token) {
#ifdef ENABLE_WEB_SERVICE
return WebService::VerifyLogin(NetSettings::values.web_api_url, username, token);
#else
return false;
#endif
}
TelemetrySession::TelemetrySession() = default;
TelemetrySession::~TelemetrySession() {
// Log one-time session end information
const s64 shutdown_time{std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count()};
AddField(Telemetry::FieldType::Session, "Shutdown_Time", shutdown_time);
#ifdef ENABLE_WEB_SERVICE
auto backend = std::make_unique<WebService::TelemetryJson>(NetSettings::values.web_api_url,
NetSettings::values.citra_username,
NetSettings::values.citra_token);
#else
auto backend = std::make_unique<Telemetry::NullVisitor>();
#endif
// Complete the session, submitting to the web service backend if necessary
field_collection.Accept(*backend);
if (NetSettings::values.enable_telemetry) {
backend->Complete();
}
}
void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) {
// Log one-time top-level information
AddField(Telemetry::FieldType::None, "TelemetryId", GetTelemetryId());
// Log one-time session start information
const s64 init_time{std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count()};
AddField(Telemetry::FieldType::Session, "Init_Time", init_time);
std::string program_name;
const Loader::ResultStatus res{app_loader.ReadTitle(program_name)};
if (res == Loader::ResultStatus::Success) {
AddField(Telemetry::FieldType::Session, "ProgramName", program_name);
}
// Log application information
Telemetry::AppendBuildInfo(field_collection);
// Log user system information
Telemetry::AppendCPUInfo(field_collection);
Telemetry::AppendOSInfo(field_collection);
// Log user configuration information
AddField(Telemetry::FieldType::UserConfig, "Audio_SinkId",
static_cast<int>(Settings::values.output_type.GetValue()));
AddField(Telemetry::FieldType::UserConfig, "Audio_EnableAudioStretching",
Settings::values.enable_audio_stretching.GetValue());
AddField(Telemetry::FieldType::UserConfig, "Core_UseCpuJit",
Settings::values.use_cpu_jit.GetValue());
AddField(Telemetry::FieldType::UserConfig, "Renderer_ResolutionFactor",
Settings::values.resolution_factor.GetValue());
AddField(Telemetry::FieldType::UserConfig, "Renderer_FrameLimit",
Settings::values.frame_limit.GetValue());
AddField(Telemetry::FieldType::UserConfig, "Renderer_Backend",
static_cast<int>(Settings::values.graphics_api.GetValue()));
AddField(Telemetry::FieldType::UserConfig, "Renderer_UseHwShader",
Settings::values.use_hw_shader.GetValue());
AddField(Telemetry::FieldType::UserConfig, "Renderer_ShadersAccurateMul",
Settings::values.shaders_accurate_mul.GetValue());
AddField(Telemetry::FieldType::UserConfig, "Renderer_UseShaderJit",
Settings::values.use_shader_jit.GetValue());
AddField(Telemetry::FieldType::UserConfig, "Renderer_UseVsync",
Settings::values.use_vsync_new.GetValue());
AddField(Telemetry::FieldType::UserConfig, "Renderer_FilterMode",
Settings::values.filter_mode.GetValue());
AddField(Telemetry::FieldType::UserConfig, "Renderer_Render3d",
static_cast<int>(Settings::values.render_3d.GetValue()));
AddField(Telemetry::FieldType::UserConfig, "Renderer_Factor3d",
Settings::values.factor_3d.GetValue());
AddField(Telemetry::FieldType::UserConfig, "Renderer_MonoRenderOption",
static_cast<int>(Settings::values.mono_render_option.GetValue()));
AddField(Telemetry::FieldType::UserConfig, "System_IsNew3ds",
Settings::values.is_new_3ds.GetValue());
AddField(Telemetry::FieldType::UserConfig, "System_LLEApplets",
Settings::values.lle_applets.GetValue());
AddField(Telemetry::FieldType::UserConfig, "System_RegionValue",
Settings::values.region_value.GetValue());
}
bool TelemetrySession::SubmitTestcase() {
#ifdef ENABLE_WEB_SERVICE
auto backend = std::make_unique<WebService::TelemetryJson>(NetSettings::values.web_api_url,
NetSettings::values.citra_username,
NetSettings::values.citra_token);
field_collection.Accept(*backend);
return backend->SubmitTestcase();
#else
return false;
#endif
}
} // namespace Core

Some files were not shown because too many files have changed in this diff Show More