Compare commits

...

16 Commits

Author SHA1 Message Date
Eden CI 060026dc2d [dist, android] Update translations from Transifex for Nov 02 (#4626)
Automatic translation update for Nov 02

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4626
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-11-02 18:59:46 +01:00
Bix 92f54a034a [android, docs] Update recommended drivers, Fix Android build Guide and Fix X link. (#4617)
Nitter has been taken down, Link has been reverted to X.
Updated driver recommended to T30 for Adreno 711- 899 and T29 for 700 - 710.
Fixed Build guide for android via terminal, Due to new android SDK suffox.

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [X] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.
- [X] I have read and followed the [website policy](https://git.eden-emu.dev/eden-emu/site-policy).
- [X] I affirm that the content of this pull request body was written and submitted entirely by me, in my own words, and not by an AI agent or LLM.
- [ ] I affirm that I did not read any of this, and understand that my pull request will be closed if I check this box.
- [X] I affirm that, by submitting this pull request, I am responsible for all of the changes contained within these commits.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4617
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-11-02 04:32:10 +01:00
crueter 7a6d055094 [desktop] queue FirstFrameDisplayed to fix loading screen race (#4536)
Signed-off-by: crueter <crueter@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md).
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Authored-by: Bitekiyo <334587657+Bitekiyo@users.noreply.github.com>

Co-authored-by: Bitekiyo <334587657+Bitekiyo@users.noreply.github.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4536
2026-11-01 21:53:04 +01:00
lizzie c6fa5c1f77 [common] use handrolled string utility conversions instead of wstring codecvt (#3773)
thanks to @chrelliott978 for the initial impl, basically clang will yell at you if you dare use wstring_codecvt<> and some other shit, and to be fair one day it will be removed because it's deprecated (but it's c++, we know it will NEVER be deprecated)

either way this makes clang shut up

untested at all

Signed-off-by: lizzie <lizzie@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3773
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-11-01 21:52:29 +01:00
lizzie 2c40328a23 [macos, net] add sysctl(RT_xx)-fetched network interfaces (#3656)
should fix macOS network interfaces

Signed-off-by: lizzie <lizzie@eden-emu.dev>
Co-Authored-by: @chrelliott978
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3656
Reviewed-by: Ghost <>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-11-01 21:51:51 +01:00
lizzie 41b6807f12 [fs] use mmap() to read files using VM/pagefaults for higher throughput (#3151)
main idea is basically to manually manage the file backed storage ourselves

basically the libc will use pooled workes who will read off sync data and may or may not use mmap, this detail can vary between libcs, so id rather have one unified concept of "paged file" as opposed to relying on the libc doing what it should

the main benefit is that one doesnt need to call fwrite/fread or whatever, they can just do normal paged file ops and such

this pr has seen changes from mapped flags as well, as some OSes; particularly android, do not enjoy being told to make hugepages that are 1GB in size, especially for lower end devices.

Signed-off-by: lizzie <lizzie@eden-emu.dev>
Co-authored-by: Caio Oliveira <caiooliveirafarias0@gmail.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3151
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-11-01 21:51:15 +01:00
lizzie 2bec66c092 [dynarmic] Remove redundant configure struct (#4485)
Trivial change. Makes translate use the top level user config instead of "grabbing" stuff into a dedicated struct.
This isn't a parent ref because TranslateVisitor is a light scoped struct.

Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4485
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-11-01 21:48:38 +01:00
lizzie be972d7fdc [dynarmic] Remove redundant constant pool ops (#4516)
Simplifies logic for adding constants to pool. Since std::pair<T,U>
is hash-able by boost::hash, and `std::array` (u128) has better cgen than `std::pair`.
I felt inclined to use std::pair for the map and u128 for the span (as later on I plan to
use vector_size(16) to make it unto a proper 128-bit primitive).

Another note is that I noticed a lot of collisions (especially on heavy games).
I used boost::hash as this seemed to reduce the number of them drastically.

Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4516
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-11-01 21:46:19 +01:00
crueter 972860ac8f [dist] reoptimize assets, and add svg optimization (#4537)
Co-authored-by: GreenStar <145512144+thegreatGreenstar@users.noreply.github.com>
Signed-off-by: crueter <crueter@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md).
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4537
2026-11-01 21:45:45 +01:00
PavelBARABANOV 3d3ed4b7d1 [shader_recompiler, renderer_vulkan] draw sprites whose texture handle comes from a vertex attribute (#4566)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md).
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------
credit: Ghael-V

Draw sprites whose texture handle comes from a vertex attribute. A bindless handle read from an interpolated vertex attribute could not be tracked to a constant buffer, so pipeline creation threw and every draw using the shader was dropped (FIFA player indicators, shadows and some text).

The handle now gets a sentinel descriptor, and the Vulkan rasterizer splits a triangle-list draw into runs of vertices that share a handle and binds each run's texture before drawing it.

https://github.com/Ghael-V/Lemon-Project/commit/4fec247e9eb29a6e81a51d8252323c5cda6b2cb9
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4566
Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
2026-11-01 21:44:40 +01:00
project516 be21ccce25 [docs] fix link to AI and LLM Usage in docs/README.md (#4618)
docs/policies/AI.md was removed in a2aa4d97e1.

I linked it to the policies section in CONTRIBUTING.md, since AI and LLM usage is important to have. We can just remove it though.

Signed-off-by: project516 <project516@project516.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.
- [x] I have read and followed the [website policy](https://git.eden-emu.dev/eden-emu/site-policy).
- [x] I affirm that the content of this pull request body was written and submitted entirely by me, in my own words, and not by an AI agent or LLM.
- [ ] I affirm that I did not read any of this, and understand that my pull request will be closed if I check this box.
- [x] I affirm that, by submitting this pull request, I am responsible for all of the changes contained within these commits.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4618
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-11-01 18:27:36 +01:00
crueter db83070bf2 [meta] Add FUNDING.yml (#4613)
Forgejo 17.0.0 adds support for FUNDING.yml, this also shows up on
GitHub.

Signed-off-by: crueter <crueter@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.
- [x] I have read and followed the [website policy](https://git.eden-emu.dev/eden-emu/site-policy).
- [x] I affirm that the content of this pull request body was written and submitted entirely by me, in my own words, and not by an AI agent or LLM.
- [ ] I affirm that I did not read any of this, and understand that my pull request will be closed if I check this box.
- [x] I affirm that, by submitting this pull request, I am responsible for all of the changes contained within these commits.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4613
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-11-01 05:16:02 +01:00
crueter e903d70d9e [docs] Add site policy, disallow AI-written PRs/issues and spam (#4612)
The spam got a little out of hand.

Site policy also disallows things such as asking for donations without
giving back to us, piracy, large file uploads, illegal stuff, and more.

Signed-off-by: crueter <crueter@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.
- [x] I have read and followed the [website policy](https://git.eden-emu.dev/eden-emu/site-policy).
- [x] I affirm that the content of this pull request body was written and submitted entirely by me, in my own words, and not by an AI agent or LLM.
- [ ] I affirm that I did not read any of this, and understand that my pull request will be closed if I check this box.
- [x] I affirm that, by submitting this pull request, I am responsible for all of the changes contained within these commits.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4612
Reviewed-by: lizzie <lizzie@eden-emu.dev>
Reviewed-by: John <john@eden-emu.dev>
2026-11-01 03:19:27 +01:00
lizzie 802531c457 [ports/*] Fix cross-compilation issues (#4493)
OpenSSL needs a patch to properly cross compile under rv64; fix infinite recursion with A32 thunks.
Updated cross build guide as well.

Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4493
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-11-01 03:12:55 +01:00
lizzie bd071e3464 [dynarmic] Add A64:SM4/SM3 tests (#4513)
Trivial change for upcoming work.

Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4513
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-11-01 03:12:03 +01:00
lizzie a845100bf0 [cmake] Cleanup dynarmic's CMake (#4365)
Removes a handful of unused/untested features (like disabling CPU detection)
and brings the CMake of dynarmic more in line with the rest of the build system.

Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4365
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-11-01 03:11:26 +01:00
117 changed files with 18527 additions and 20253 deletions
+2
View File
@@ -0,0 +1,2 @@
liberapay: crueter
custom: 'https://www.paypal.biz/edenemulator'
+4
View File
@@ -1,4 +1,8 @@
- [ ] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions). - [ ] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [ ] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability. - [ ] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.
- [ ] I have read and followed the [website policy](https://git.eden-emu.dev/eden-emu/site-policy).
- [ ] I affirm that the content of this pull request body was written and submitted entirely by me, in my own words, and not by an AI agent or LLM.
- [ ] I affirm that I did not read any of this, and understand that my pull request will be closed if I check this box.
- [ ] I affirm that, by submitting this pull request, I am responsible for all of the changes contained within these commits.
------------------- -------------------
@@ -0,0 +1,40 @@
diff --git a/cmake/ConfigureOpenSSL.cmake b/cmake/ConfigureOpenSSL.cmake
index 3012e05..2ae23ff 100644
--- a/cmake/ConfigureOpenSSL.cmake
+++ b/cmake/ConfigureOpenSSL.cmake
@@ -108,7 +108,8 @@ function(configure_openssl)
)
if(NOT "${CONFIGURE_OPTIONS_OLD}" STREQUAL "")
- if(CONFIGURE_OPTIONS STREQUAL CONFIGURE_OPTIONS_OLD)
+ # TODO(lizzie): Emscripten has issues with rebuilding due to the wrapper it uses
+ if(CMAKE_SYSTEM_NAME MATCHES "Emscripten" OR CONFIGURE_OPTIONS STREQUAL CONFIGURE_OPTIONS_OLD)
message(STATUS "Found previous configure results. Don't perform configuration")
return()
endif()
@@ -134,10 +135,24 @@ function(configure_openssl)
set(VERBOSE_OPTION OUTPUT_QUIET)
endif()
+ if (CMAKE_SYSTEM_NAME MATCHES "Emscripten")
+ set(EMSCRIPTEN_CMAKE_WRAPPER "emcmake")
+ find_program(EMCC emcc REQUIRED)
+ set(EMSCRIPTEN_LINKER ${EMCC})
+ list(APPEND CONFIGURE_COMMAND wasm64)
+ else()
+ set(EMSCRIPTEN_CMAKE_WRAPPER "")
+ set(EMSCRIPTEN_LINKER ${CMAKE_LINKER})
+ endif ()
+
execute_process(
- COMMAND ${CMAKE_COMMAND} -E env
+ COMMAND ${EMSCRIPTEN_CMAKE_WRAPPER} ${CMAKE_COMMAND} -E env
"CFLAGS=${CMAKE_C_FLAGS}"
"CXXFLAGS=${CMAKE_CXX_FLAGS}"
+ "LDFLAGS=${CMAKE_CXX_LINK_FLAGS}"
+ "CC=${CMAKE_C_COMPILER}"
+ "CXX=${CMAKE_CXX_COMPILER}"
+ "LD=${EMSCRIPTEN_LINKER}"
${CONFIGURE_COMMAND}
WORKING_DIRECTORY ${CONFIGURE_BUILD_DIR}
${VERBOSE_OPTION}
+5 -2
View File
@@ -1,7 +1,10 @@
# AGENTS # AGENTS
Read and follow the AI policy found in `docs/policies/AI.md`, and the coding policies found in `docs/policies/Coding.md`. Read and follow the [contribution guidelines](./CONTRIBUTING.md) and our [site policy](https://git.eden-emu.dev/eden-emu/site-policy/src/branch/master)..
Do not, under any circumstances, ever submit PRs or push commits on behalf of the user. Do not, under any circumstances, ever:
- Submit PRs, push commits, or request any API calls on behalf of the user.
- Write commit messages, PR descriptions, or issues on behalf of the user.
Keep comments to a reasonable level. Do not overexplain or add/remove comments from unrelated parts of the codebase. Keep comments to a reasonable level. Do not overexplain or add/remove comments from unrelated parts of the codebase.
+26 -2
View File
@@ -16,8 +16,11 @@ Eden is free, open-source, copyleft software, licensed under the terms of the [G
### Policies ### Policies
- AI usage is allowed, but we reserve the right to close and rework your PR if you don't fully understand the changes you're making. - AI usage is allowed, but we reserve the right to close and rework your PR if you don't fully understand the changes you're making. Additionally:
- As a common courtesy, please disclose your AI usage under the PR description, as `Assisted-by: <AI model> (<how it helped>)`. - As a common courtesy, please disclose your AI usage under the PR description, as `Assisted-by: <AI model> (<how it helped>)`.
- All PR descriptions, issue bodies, and comments **must** be written by you, in your own words.
- AI-written comments/descriptions/bodies are not only difficult for us to read, they also indicate to us that you did not put in the effort to actually understand your changes. These will be closed, deleted, or hidden without warning.
- Spamming of low-effort AI-generated pull requests or issues is considered a [Human Effort Denial of Service](https://tiangolo.com/open-source/contributing/#human-effort-denial-of-service), and will result in the immediate suspension of your Forgejo account, or you getting blocked from the organization on other platforms.
- Usage of any form of profanity or otherwise unsavory language is discouraged but not strictly disallowed. - Usage of any form of profanity or otherwise unsavory language is discouraged but not strictly disallowed.
- New code must follow the same style as the surrounding codebase. Exceptions may be granted in certain cases. - New code must follow the same style as the surrounding codebase. Exceptions may be granted in certain cases.
- Maintainers reserve the right to change your patches and pull requests at will. We will try to avoid this. - Maintainers reserve the right to change your patches and pull requests at will. We will try to avoid this.
@@ -26,6 +29,25 @@ Eden is free, open-source, copyleft software, licensed under the terms of the [G
- While we do *not* adhere to the terms of a formal code of conduct, you are expected to treat other developers, contributors, and community members respectfully. - While we do *not* adhere to the terms of a formal code of conduct, you are expected to treat other developers, contributors, and community members respectfully.
- You **must** have basic knowledge of [Git](https://git-scm.com/learn). Knowing how to manage your branches and follow proper fork policies is a necessity. - You **must** have basic knowledge of [Git](https://git-scm.com/learn). Knowing how to manage your branches and follow proper fork policies is a necessity.
### Pull Requests
Pull requests are only to be merged by core developers when properly tested and discussions conclude on Discord or other communication channels. Labels are recommended but not required. However, all PRs MUST be namespaced and optionally typed:
```txt
[cmake] refactor: CPM over submodules
[desktop] feat: implement firmware install from ZIP
[hle] stub fw20 functions
[core] test: raise maximum CPU cores to 6
[cmake, core] Unbreak FreeBSD Building Process
```
- The level of namespacing is generally left to the committer's choice.
- However, we never recommend going more than two levels *except* in `hle`, in which case you may go as many as four levels depending on the specificity of your changes.
- Ocassionally, up to two additional namespaces may be provided for more clarity.
- Changes that affect the entire project (sans CMake changes) should be namespaced as `meta`.
- Maintainers are permitted to change namespaces at will.
- Commits within PRs are not required to be namespaced, but it is highly recommended.
### Where do I start? ### Where do I start?
Anywhere you like! If you are facing an issue and want to fix it, go ahead. For new features, you are heavily encouraged to open a feature request on GitHub, Codeberg, or Forgejo first, discussing the motivations, potential implementation, and user flow of your desired feature. Our UI/UX designers will work with you to refine your feature before you actually choose to implement it. Anywhere you like! If you are facing an issue and want to fix it, go ahead. For new features, you are heavily encouraged to open a feature request on GitHub, Codeberg, or Forgejo first, discussing the motivations, potential implementation, and user flow of your desired feature. Our UI/UX designers will work with you to refine your feature before you actually choose to implement it.
@@ -39,6 +61,8 @@ There are five primary ways to contribute.
- Submit pull requests directly to our source tree - Submit pull requests directly to our source tree
- You must first [create an account](https://git.eden-emu.dev/user/sign_up). - You must first [create an account](https://git.eden-emu.dev/user/sign_up).
- You may use an internal account, or you may use a GitHub/Codeberg account linked to our instance. - You may use an internal account, or you may use a GitHub/Codeberg account linked to our instance.
- Please make sure to read our [site policy](https://git.eden-emu.dev/eden-emu/site-policy/src/branch/master).
- Both your account and your associated fork must be public, *not* limited/private, otherwise our CI workflow will not work on your pull requests.
- Submit pull requests to our [GitHub mirror](https://github.com/eden-emulator/Issue-Reports) - Submit pull requests to our [GitHub mirror](https://github.com/eden-emulator/Issue-Reports)
- Note that this is subject to being removed by DMCA, so don't rely on this. - Note that this is subject to being removed by DMCA, so don't rely on this.
- Submit pull requests to our [Codeberg mirror](https://codeberg.org/eden-emu/eden) - Submit pull requests to our [Codeberg mirror](https://codeberg.org/eden-emu/eden)
@@ -48,7 +72,7 @@ There are five primary ways to contribute.
- Alongside the contents of your email, please attach the patch/diff file itself for easy access and use. - Alongside the contents of your email, please attach the patch/diff file itself for easy access and use.
- Email our developers at [`developers@eden-emu.dev`](mailto:developers@eden-emu.dev) with any of your relevant findings or code changes. - Email our developers at [`developers@eden-emu.dev`](mailto:developers@eden-emu.dev) with any of your relevant findings or code changes.
To test your changes, ensure to read the [build documentation](./docs/Build.md) for your specific platform(s) to ensure everything compiles and works properly. You should also make sure that your branch is up-to-date with the upstream `master` branch before opening a pull request. To test your changes, ensure to read the [build documentation](./docs/Build.md) for your specific platform(s) to ensure everything compiles and works properly. You should also make sure that your branch is up-to-date with the upstream `master` branch before opening a pull request. **You** are responsible for ensuring that your contribution does what it says and doesn't break everything else horribly.
## Non-code Contributions ## Non-code Contributions
+2 -1
View File
@@ -202,7 +202,8 @@
"0001-cpmutil-compat.patch", "0001-cpmutil-compat.patch",
"0002-use-ccache.patch", "0002-use-ccache.patch",
"0003-use-cmake-compiler-flags.patch", "0003-use-cmake-compiler-flags.patch",
"0004-use-shell-wrapper.patch" "0004-use-shell-wrapper.patch",
"0005-cross-compile.patch"
], ],
"repo": "jimmy-park/openssl-cmake", "repo": "jimmy-park/openssl-cmake",
"version": "3.6.2" "version": "3.6.2"
+1 -230
View File
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

+1 -289
View File
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

+1 -144
View File
@@ -1,144 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512" fill="none" viewBox="0 0 512 512"><defs><linearGradient id="c"><stop offset="0" style="stop-color:#f71baa;stop-opacity:.56623769"/><stop offset="1" style="stop-color:#fa87d4;stop-opacity:.25"/></linearGradient><linearGradient id="b"><stop offset="0" style="stop-color:#fe00b1;stop-opacity:1"/><stop offset="1" style="stop-color:#fe00b1;stop-opacity:0"/></linearGradient><linearGradient id="a"><stop offset="0" style="stop-color:#ff0950;stop-opacity:.5"/><stop offset=".496" style="stop-color:#bf42f6;stop-opacity:.75"/><stop offset="1" style="stop-color:#5da5ed;stop-opacity:1"/></linearGradient><linearGradient xlink:href="#a" id="d" x1="270.4" x2="270.4" y1="40" y2="494.4" gradientTransform="translate(-33.928 -34.199)scale(1.07505)" gradientUnits="userSpaceOnUse" spreadMethod="reflect"/><linearGradient xlink:href="#b" id="f" x1="125.402" x2="431.024" y1="271.834" y2="271.834" gradientTransform="translate(-33.928 -34.199)scale(1.07505)" gradientUnits="userSpaceOnUse"/><linearGradient xlink:href="#c" id="e" x1="270.4" x2="270.4" y1="33.584" y2="500.816" gradientTransform="translate(-33.928 -34.199)scale(1.07505)" gradientUnits="userSpaceOnUse"/></defs><circle cx="256.764" cy="253.054" r="244.25" style="fill:url(#d);fill-opacity:1;stroke:url(#e);stroke-width:13.7948;stroke-opacity:.566238;paint-order:stroke fill markers"/><path d="M55.701 114.372a244 244 0 0 0-10.836 17.2h423.797a244 244 0 0 0-10.837-17.2z" style="fill:#fff;fill-opacity:.5;stroke:none;stroke-width:17.2007;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"/><path d="m219.665 499.138-10.338-55.949" style="fill:#ff2bd5;fill-opacity:1;stroke-width:14.3776;stroke-opacity:.415999;paint-order:stroke fill markers"/><path d="M58.272 395.39a244 244 0 0 0 13.54 17.2h369.902a244 244 0 0 0 13.541-17.2zM24.605 328.953a244 244 0 0 0 6.347 17.2h451.623a244 244 0 0 0 6.347-17.2zM12.586 259.075a244 244 0 0 0 1.033 17.2h486.289a244 244 0 0 0 1.033-17.2z" style="fill:#fff;fill-opacity:.5;stroke:none;stroke-width:17.2007;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"/><path d="M306.217 12.242s-11.75 42.031-17.703 63.363c-12.713 9.965-21.075 19.29-21.075 19.29s-22.956-32.534-44.85-46.065c-21.892-13.531-51.398-11.788-51.398-11.788s-12.257 0-27.092 5.806c-14.836 5.805-20.857 9.675-20.857 9.675s15.053-.43 37.199 7.095 31.82 12.042 31.82 12.042l30.423-6.881-8.277 11.611s14.514 9.353 22.362 17.739c7.848 8.385 11.502 13.114 11.502 13.114s-13.652-5.697-55.579-1.826-83.209 59.127-83.209 59.127 40.42-16.771 64.287-22.362c23.866-5.59 46.657-8.386 46.657-8.386s-18.06 7.74-37.41 40.207c-19.351 32.467-13.762 84.07-13.762 84.07s30.747-61.923 60.203-82.778 35.476-21.501 35.476-21.501-23.65 50.742-32.896 132.23c-9.245 81.489 29.671 217.804 29.671 217.804l46.872-7.311s-44.721-44.291-48.591-158.676 16.34-182.758 16.34-182.758 16.771 1.29 41.712 34.401 39.56 60.203 39.56 60.203 9.463-53.753-11.178-78.264-52.463-35.26-52.463-35.26 13.438-6.988 41.282-4.945c27.844 2.042 85.6 28.444 85.6 28.444S405.336 132.903 369 114.355s-79.77.307-79.77.307 4.055-16.119 28.533-34.21C342.24 62.358 373.56 44.42 373.56 44.42s-25.845 1.217-54.124 12.62c-7.036 2.837-13.79 6.605-19.966 10.666l17.067-53.528z" style="fill:url(#f);fill-opacity:1;stroke:#fff;stroke-width:17.2007;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"/></svg>
<svg
width="512"
height="512"
fill="none"
viewBox="0 0 512 512"
version="1.1"
id="svg7"
sodipodi:docname="base.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs7">
<linearGradient
id="linearGradient24"
inkscape:collect="always">
<stop
style="stop-color:#f71baa;stop-opacity:0.56623769;"
offset="0"
id="stop24" />
<stop
style="stop-color:#fa87d4;stop-opacity:0.25;"
offset="1"
id="stop25" />
</linearGradient>
<rect
x="22.627417"
y="402.76802"
width="521.34025"
height="248.94868"
id="rect24" />
<linearGradient
id="linearGradient1"
inkscape:collect="always">
<stop
style="stop-color:#fe00b1;stop-opacity:1;"
offset="0"
id="stop1" />
<stop
style="stop-color:#fe00b1;stop-opacity:0;"
offset="1"
id="stop2" />
</linearGradient>
<linearGradient
id="linearGradient11"
inkscape:collect="always">
<stop
style="stop-color:#ff0950;stop-opacity:0.5;"
offset="0"
id="stop11" />
<stop
style="stop-color:#bf42f6;stop-opacity:0.75;"
offset="0.49556771"
id="stop20" />
<stop
style="stop-color:#5da5ed;stop-opacity:1;"
offset="1"
id="stop12" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient11"
id="linearGradient12"
x1="270.39996"
y1="39.999989"
x2="270.39996"
y2="494.39996"
gradientUnits="userSpaceOnUse"
spreadMethod="reflect"
gradientTransform="matrix(1.075046,0,0,1.075046,-33.928383,-34.198735)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1"
id="linearGradient2"
x1="125.40197"
y1="271.834"
x2="431.02424"
y2="271.834"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.075046,0,0,1.075046,-33.928383,-34.198735)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient24"
id="linearGradient25"
x1="270.39996"
y1="33.58408"
x2="270.39996"
y2="500.81589"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.075046,0,0,1.075046,-33.928383,-34.198735)" />
</defs>
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="0.88388348"
inkscape:cx="141.98704"
inkscape:cy="265.87215"
inkscape:window-width="1600"
inkscape:window-height="849"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg7" />
<circle
style="fill:url(#linearGradient12);fill-opacity:1;stroke:url(#linearGradient25);stroke-width:13.7948;stroke-opacity:0.566238;paint-order:stroke fill markers"
id="path8"
cx="256.76401"
cy="253.05354"
r="244.25046" />
<path
id="rect1-3"
style="fill:#ffffff;fill-opacity:0.5;stroke:none;stroke-width:17.2007;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
d="M 55.701477,114.37179 A 244.25044,244.25044 0 0 0 44.86493,131.57252 h 423.79699 a 244.25044,244.25044 0 0 0 -10.83655,-17.20073 z" />
<path
style="fill:#ff2bd5;fill-opacity:1;stroke-width:14.3776;stroke-opacity:0.415999;paint-order:stroke fill markers"
d="M 219.6651,499.13816 209.32675,443.18948"
id="path9" />
<path
id="rect1-2"
style="fill:#ffffff;fill-opacity:0.5;stroke:none;stroke-width:17.2007;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
d="m 58.271509,395.38922 a 244.25044,244.25044 0 0 0 13.54096,17.20073 H 441.71437 a 244.25044,244.25044 0 0 0 13.54097,-17.20073 z" />
<path
id="rect1-2-5"
style="fill:#ffffff;fill-opacity:0.5;stroke:none;stroke-width:17.2007;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
d="m 24.604933,328.95264 a 244.25044,244.25044 0 0 0 6.347389,17.20074 H 482.57453 a 244.25044,244.25044 0 0 0 6.34738,-17.20074 z" />
<path
id="rect1"
style="fill:#ffffff;fill-opacity:0.5;stroke:none;stroke-width:17.2007;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
d="m 12.586253,259.07464 a 244.25044,244.25044 0 0 0 1.033053,17.20075 H 499.90754 a 244.25044,244.25044 0 0 0 1.03305,-17.20075 z" />
<path
id="path15"
style="fill:url(#linearGradient2);fill-opacity:1;stroke:#ffffff;stroke-width:17.2007;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
d="m 306.21658,12.242412 c 0,0 -11.75029,42.031067 -17.70256,63.362621 -12.7133,9.964494 -21.07468,19.289937 -21.07468,19.289937 0,0 -22.95662,-32.534232 -44.84956,-46.065299 C 200.69681,35.298604 171.19123,37.04196 171.19123,37.04196 c 0,0 -12.25678,4.2e-4 -27.09242,5.805668 -14.83563,5.805249 -20.85631,9.675414 -20.85631,9.675414 0,0 15.05232,-0.430438 37.19828,7.094883 22.14594,7.525322 31.82093,12.041775 31.82093,12.041775 l 30.42255,-6.880714 -8.27702,11.611336 c 0,0 14.51396,9.3529 22.36179,17.738259 7.84785,8.385359 11.50216,13.114729 11.50216,13.114729 0,0 -13.65224,-5.69691 -55.57904,-1.82674 -41.92679,3.87016 -83.20898,59.12752 -83.20898,59.12752 0,0 40.42048,-16.77155 64.28649,-22.36179 23.86602,-5.59024 46.65742,-8.3862 46.65742,-8.3862 0,0 -18.05952,7.74075 -37.41035,40.20714 -19.35082,32.46639 -13.76142,84.06986 -13.76142,84.06986 0,0 30.74631,-61.92266 60.20258,-82.77854 29.45625,-20.8559 35.47652,-21.50092 35.47652,-21.50092 0,0 -23.6506,50.74216 -32.896,132.23065 -9.24539,81.48849 29.67085,217.8039 29.67085,217.8039 l 46.87159,-7.31116 c 0,0 -44.72107,-44.29147 -48.59124,-158.67636 -3.87017,-114.3849 16.33986,-182.75782 16.33986,-182.75782 0,0 16.77156,1.29005 41.71263,34.40147 24.94106,33.11142 39.56043,60.20258 39.56043,60.20258 0,0 9.46208,-53.75314 -11.1788,-78.26419 -20.64088,-24.51105 -52.46309,-35.26025 -52.46309,-35.26025 0,0 13.4385,-6.98738 41.28219,-4.94479 27.84369,2.04258 85.60053,28.44463 85.60053,28.44462 0,0 -15.50743,-26.7591 -51.84367,-45.30731 -36.33623,-18.548198 -79.76967,0.30655 -79.76967,0.30655 0,0 4.05525,-16.118294 28.53281,-34.210394 24.47756,-18.092095 55.79742,-36.030833 55.79742,-36.030833 0,0 -25.84554,1.216607 -54.12395,12.619193 -7.03608,2.837127 -13.78978,6.605056 -19.96604,10.666471 l 17.06635,-53.527632 z" />
</svg>

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 10 KiB

+1 -230
View File
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 10 KiB

+1 -672
View File
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 11 KiB

+1 -80
View File
@@ -1,80 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512" fill="none" viewBox="0 0 512 512"><defs><linearGradient id="a"><stop offset="0" style="stop-color:#f977d9;stop-opacity:1"/><stop offset=".541" style="stop-color:#a655d5;stop-opacity:1"/><stop offset=".571" style="stop-color:#984fd5;stop-opacity:1"/><stop offset=".597" style="stop-color:#8c4ad4;stop-opacity:1"/><stop offset="1" style="stop-color:#3928d2;stop-opacity:1"/></linearGradient><linearGradient xlink:href="#a" id="b" x1="264.175" x2="264.175" y1="28.386" y2="488.651" gradientTransform="matrix(.97816 0 0 .9788 4.57 5.88)" gradientUnits="userSpaceOnUse"/></defs><path d="M262.975 33.688A218.443 225.23 0 0 0 138.838 73.59l2.3-1.324 20.083-7.07 19.799-3.678 23.334 2.687L228.96 76.65 265.8 115 283 99.4l21.6-13.6 26.4-9.4 29.6-6.8 19.355-.391a218.443 225.23 0 0 0-116.98-35.521M380.076 69.29l-29.877 8.51-21 11.398L307.4 108l-18.6 21.8-1.4 5.2 15-5.4 16.6-1.8 29.8 4 21.4 9.6 22.8 20 6.6 10.2-24.8-10.8-36.4-10-29.2-.8-20.4 4.4 4.4.8 26 13.6 18.8 18.4 12.8 36.8-1.6 36-23.2-37.2-23.2-28.8-25.2-21.6-8.4 15.2-12.4 94L258 364l20.4 88.8 18.795 28.57a218.443 225.23 0 0 0 184.223-222.452A218.443 225.23 0 0 0 380.076 69.291M133.074 77.84a218.443 225.23 0 0 0-88.54 181.078A218.443 225.23 0 0 0 257.04 484.066l-9.695-25.437-9.475-40.445-4.809-37.76-2.687-25.457-.424-33.658 2.404-29.98 5.092-36.347 17.112-63.074 7.07-19.375-6.08 1.557-14.567 6.787-11.382 9.322-19 18-13.2 21.201-11 23.2-13 16.4-2-15.8 2.2-23.8 9.4-27 16.4-24.4 21.641-24.559-12.02 2.264-31.962 7.07-28.99 8.627L119.925 183l.707-2.83 9.191-14.283 21.356-18.385 21.779-12.02 17.111-5.941 18.951-1.555 18.667.707 20.082-.283-1.272-3.252-19.799-19.234-7.072-8.485 1.84-7.353-14.71 3.959-10.888 1.414-16.406-6.787-23.334-7.213z" style="fill:url(#b);fill-opacity:1;stroke:none;stroke-width:13.3314;stroke-opacity:1;paint-order:stroke fill markers"/><path d="M259.367 490.166 298.4 483.2l-20-30.4L258 364l-1.2-82.4 12.4-94 8.4-15.2 25.2 21.6 23.2 28.8 23.2 37.2 1.6-36-12.8-36.8-18.8-18.4-26-13.6-4.4-.8 20.4-4.4 29.2.8 36.4 10 24.8 10.8-6.6-10.2-22.8-20-21.4-9.6-29.8-4-16.6 1.8-15 5.4 1.4-5.2 18.6-21.8 21.8-18.8 21-11.4 30.2-8.6-19.8.4-29.6 6.8-26.4 9.4L283 99.4 265.8 115 228.96 76.65l-24.607-12.445-23.335-2.687-19.799 3.677-20.082 7.071-9.333 5.374 24.324 3.818 23.335 7.213 16.404 6.788 10.89-1.414 14.708-3.96-1.839 7.354 7.071 8.485 19.8 19.234 1.272 3.252-20.082.283-18.667-.707-18.95 1.556-17.113 5.94-21.779 12.02-21.354 18.385-9.193 14.284-.707 2.828 28.143-11.597 28.991-8.626 31.962-7.071 12.02-2.263L199.4 178 183 202.4l-9.4 27-2.2 23.8 2 15.8 13-16.4 11-23.2 13.2-21.2 19-18 11.382-9.322 14.566-6.789 6.081-1.555-7.07 19.375-17.113 63.073-5.09 36.346-2.405 29.981.424 33.658 2.687 25.456 4.809 37.76 9.475 40.446z" style="fill:#1b1b1b;fill-opacity:.12492698;stroke:none;stroke-width:13.374;stroke-opacity:.415999;paint-order:stroke fill markers"/></svg>
<svg
width="512"
height="512"
fill="none"
viewBox="0 0 512 512"
version="1.1"
id="svg7"
sodipodi:docname="base_small.svg"
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs7">
<linearGradient
id="linearGradient10"
inkscape:collect="always">
<stop
style="stop-color:#f977d9;stop-opacity:1;"
offset="0"
id="stop10" />
<stop
style="stop-color:#a655d5;stop-opacity:1;"
offset="0.54051435"
id="stop13" />
<stop
style="stop-color:#984fd5;stop-opacity:1;"
offset="0.5714342"
id="stop12" />
<stop
style="stop-color:#8c4ad4;stop-opacity:1;"
offset="0.59666741"
id="stop14" />
<stop
style="stop-color:#3928d2;stop-opacity:1;"
offset="1"
id="stop11" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient10"
id="linearGradient11"
x1="264.17508"
y1="28.385544"
x2="264.17508"
y2="488.65109"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.97815818,0,0,0.97880258,4.570042,5.8799159)" />
</defs>
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="0.88388348"
inkscape:cx="153.30075"
inkscape:cy="243.24473"
inkscape:window-width="1600"
inkscape:window-height="849"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="svg7"
showguides="false" />
<path
id="path9"
style="fill:url(#linearGradient11);fill-opacity:1;stroke:none;stroke-width:13.3314;stroke-opacity:1;paint-order:stroke fill markers"
d="M 262.97461 33.6875 A 218.44267 225.23091 0 0 0 138.83789 73.589844 L 141.13867 72.265625 L 161.2207 65.195312 L 181.01953 61.517578 L 204.35352 64.205078 L 228.96094 76.650391 L 265.80078 115 L 283 99.400391 L 304.59961 85.800781 L 331 76.400391 L 360.59961 69.599609 L 379.95508 69.208984 A 218.44267 225.23091 0 0 0 262.97461 33.6875 z M 380.07617 69.291016 L 350.19922 77.800781 L 329.19922 89.199219 L 307.40039 108 L 288.80078 129.80078 L 287.40039 135 L 302.40039 129.59961 L 319 127.80078 L 348.80078 131.80078 L 370.19922 141.40039 L 393 161.40039 L 399.59961 171.59961 L 374.80078 160.80078 L 338.40039 150.80078 L 309.19922 150 L 288.80078 154.40039 L 293.19922 155.19922 L 319.19922 168.80078 L 338 187.19922 L 350.80078 224 L 349.19922 260 L 326 222.80078 L 302.80078 194 L 277.59961 172.40039 L 269.19922 187.59961 L 256.80078 281.59961 L 258 364 L 278.40039 452.80078 L 297.19531 481.36914 A 218.44267 225.23091 0 0 0 481.41797 258.91797 A 218.44267 225.23091 0 0 0 380.07617 69.291016 z M 133.07422 77.839844 A 218.44267 225.23091 0 0 0 44.533203 258.91797 A 218.44267 225.23091 0 0 0 257.04102 484.06641 L 247.3457 458.62891 L 237.87109 418.18359 L 233.0625 380.42383 L 230.375 354.9668 L 229.95117 321.30859 L 232.35547 291.32812 L 237.44727 254.98242 L 254.55859 191.9082 L 261.62891 172.5332 L 255.54883 174.08984 L 240.98242 180.87695 L 229.59961 190.19922 L 210.59961 208.19922 L 197.40039 229.40039 L 186.40039 252.59961 L 173.40039 269 L 171.40039 253.19922 L 173.59961 229.40039 L 183 202.40039 L 199.40039 178 L 221.04102 153.44141 L 209.02148 155.70508 L 177.05859 162.77539 L 148.06836 171.40234 L 119.92578 183 L 120.63281 180.16992 L 129.82422 165.88672 L 151.17969 147.50195 L 172.95898 135.48242 L 190.07031 129.54102 L 209.02148 127.98633 L 227.6875 128.69336 L 247.76953 128.41016 L 246.49805 125.1582 L 226.69922 105.92383 L 219.62695 97.439453 L 221.4668 90.085938 L 206.75781 94.044922 L 195.86914 95.458984 L 179.46289 88.671875 L 156.12891 81.458984 L 133.07422 77.839844 z " />
<path
style="fill:#1b1b1b;fill-opacity:0.12492698;stroke:none;stroke-width:13.374;stroke-opacity:0.415999;paint-order:stroke fill markers"
d="m 259.36665,490.16617 39.03323,-6.96642 -20,-30.4 -20.4,-88.8 -1.2,-82.4 12.4,-94 8.4,-15.2 25.2,21.6 23.2,28.8 23.2,37.2 1.6,-36 -12.8,-36.8 -18.8,-18.4 -26,-13.6 -4.4,-0.8 20.4,-4.4 29.2,0.8 36.4,10 24.8,10.8 -6.6,-10.2 -22.8,-20 -21.4,-9.6 -29.8,-4 -16.6,1.8 -15,5.4 1.4,-5.2 18.6,-21.8 21.8,-18.800003 21,-11.4 30.2,-8.6 -19.8,0.4 -29.6,6.8 -26.4,9.4 -21.6,13.6 -17.2,15.600003 -36.83882,-38.349628 -24.60732,-12.445079 -23.33452,-2.687006 -19.79899,3.676955 -20.08184,7.071068 -9.33381,5.374012 24.32448,3.818376 23.33452,7.212489 16.40488,6.788226 10.88944,-1.414214 14.70782,-3.959798 -1.83847,7.353911 7.07106,8.485288 19.79899,19.2333 1.2728,3.25269 -20.08184,0.28284 -18.66762,-0.7071 -18.95046,1.55563 -17.11198,5.9397 -21.77889,12.02081 -21.35462,18.38478 -9.19239,14.28356 -0.70711,2.82843 28.14285,-11.59656 28.99138,-8.6267 31.96122,-7.07107 12.02082,-2.26274 -21.64158,24.55783 -16.4,24.4 -9.4,27 -2.2,23.8 2,15.8 13,-16.4 11,-23.2 13.2,-21.2 19,-18 11.38199,-9.32209 14.5664,-6.78822 6.08112,-1.55564 -7.07107,19.37473 -17.11198,63.07393 -5.09117,36.34528 -2.40416,29.98133 0.42426,33.65828 2.68701,25.45585 4.80832,37.7595 9.47523,40.44651 z"
id="path8-4" />
</svg>

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 32 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

+667 -653
View File
File diff suppressed because it is too large Load Diff
+630 -620
View File
File diff suppressed because it is too large Load Diff
+634 -624
View File
File diff suppressed because it is too large Load Diff
+634 -624
View File
File diff suppressed because it is too large Load Diff
+631 -621
View File
File diff suppressed because it is too large Load Diff
+634 -624
View File
File diff suppressed because it is too large Load Diff
+631 -621
View File
File diff suppressed because it is too large Load Diff
+635 -625
View File
File diff suppressed because it is too large Load Diff
+630 -620
View File
File diff suppressed because it is too large Load Diff
+629 -619
View File
File diff suppressed because it is too large Load Diff
+629 -619
View File
File diff suppressed because it is too large Load Diff
+631 -621
View File
File diff suppressed because it is too large Load Diff
+639 -628
View File
File diff suppressed because it is too large Load Diff
+688 -673
View File
File diff suppressed because it is too large Load Diff
+634 -624
View File
File diff suppressed because it is too large Load Diff
+634 -624
View File
File diff suppressed because it is too large Load Diff
+631 -621
View File
File diff suppressed because it is too large Load Diff
+630 -620
View File
File diff suppressed because it is too large Load Diff
+629 -619
View File
File diff suppressed because it is too large Load Diff
+631 -621
View File
File diff suppressed because it is too large Load Diff
+632 -622
View File
File diff suppressed because it is too large Load Diff
+630 -620
View File
File diff suppressed because it is too large Load Diff
+631 -621
View File
File diff suppressed because it is too large Load Diff
+634 -624
View File
File diff suppressed because it is too large Load Diff
+634 -624
View File
File diff suppressed because it is too large Load Diff
+717 -702
View File
File diff suppressed because it is too large Load Diff
+630 -620
View File
File diff suppressed because it is too large Load Diff
+25 -4
View File
@@ -6,10 +6,31 @@ General guide for cross compiling.
A painless guide for cross compilation (or to test NCE) from a x86_64 system without polluting your main. A painless guide for cross compilation (or to test NCE) from a x86_64 system without polluting your main.
- Install QEMU: `sudo pkg install qemu` ```sh
- Download Debian 13: `wget https://cdimage.debian.org/debian-cd/current/arm64/iso-cd/debian-13.0.0-arm64-netinst.iso` #!/bin/sh
- Create a system disk: `qemu-img create -f qcow2 debian-13-arm64-ci.qcow2 30G` ISO_FILE="debian-13.0.0-arm64-netinst.iso"
- Run the VM: `qemu-system-aarch64 -M virt -m 2G -cpu max -bios /usr/local/share/qemu/edk2-aarch64-code.fd -drive if=none,file=debian-13.0.0-arm64-netinst.iso,format=raw,id=cdrom -device scsi-cd,drive=cdrom -drive if=none,file=debian-13-arm64-ci.qcow2,id=hd0,format=qcow2 -device virtio-blk-device,drive=hd0 -device virtio-gpu-pci -device usb-ehci -device usb-kbd -device intel-hda -device hda-output -nic user,model=virtio-net-pci` DISK_FILE="debian-13-arm64-ci.qcow2"
which -- qemu-system-aarch64 || sudo pkg install qemu
[ -f "$ISO_FILE" ] || wget https://cdimage.debian.org/debian-cd/current/arm64/iso-cd/$ISO_FILE
[ -f "$DISK_FILE" ] || qemu-img create -f qcow2 "$DISK_FILE" 30G
QEMU_FLAGS=(
-M virt
-m 2G
-cpu max
-bios /usr/local/share/qemu/edk2-aarch64-code.fd
-drive if=none,file=$ISO_FILE,format=raw,id=cdrom
-drive if=none,file=$DISK_FILE,id=hd0,format=qcow2
-device scsi-cd,drive=cdrom
-device virtio-blk-device,drive=hd0
-device virtio-gpu-pci
-device usb-ehci
-device usb-kbd
-device intel-hda
-device hda-output
-nic user,model=virtio-net-pci
)
qemu-system-aarch64 "${QEMU_FLAGS[@]}"
```
## Gentoo ## Gentoo
-19
View File
@@ -24,25 +24,6 @@ If the work is licensed/vendored from other people or projects, you may omit the
For more information on the license header script, run `.ci/license-header.sh -h`. For more information on the license header script, run `.ci/license-header.sh -h`.
## Pull Requests
Pull requests are only to be merged by core developers when properly tested and discussions conclude on Discord or other communication channels. Labels are recommended but not required. However, all PRs MUST be namespaced and optionally typed:
```txt
[cmake] refactor: CPM over submodules
[desktop] feat: implement firmware install from ZIP
[hle] stub fw20 functions
[core] test: raise maximum CPU cores to 6
[cmake, core] Unbreak FreeBSD Building Process
```
- The level of namespacing is generally left to the committer's choice.
- However, we never recommend going more than two levels *except* in `hle`, in which case you may go as many as four levels depending on the specificity of your changes.
- Ocassionally, up to two additional namespaces may be provided for more clarity.
- Changes that affect the entire project (sans CMake changes) should be namespaced as `meta`.
- Maintainers are permitted to change namespaces at will.
- Commits within PRs are not required to be namespaced, but it is highly recommended.
## Adding new settings ## Adding new settings
When adding new settings, use `tr("Setting:")` if the setting is meant to be a field, otherwise use `tr("Setting")` if the setting is meant to be a Yes/No or checkmark type of setting, see [this short style guide](https://learn.microsoft.com/en-us/style-guide/punctuation/colons#in-ui). When adding new settings, use `tr("Setting:")` if the setting is meant to be a field, otherwise use `tr("Setting")` if the setting is meant to be a Yes/No or checkmark type of setting, see [this short style guide](https://learn.microsoft.com/en-us/style-guide/punctuation/colons#in-ui).
+1 -1
View File
@@ -28,7 +28,7 @@ This contains documentation created by developers, build instructions, guideline
Policies and information on development. Policies and information on development.
- **[AI and LLM Usage](./policies/AI.md)** - **[AI and LLM Usage](./CONTRIBUTING.md#policies)**
- **[Coding guidelines](./policies/Coding.md)** - **[Coding guidelines](./policies/Coding.md)**
- **[Contributing](../CONTRIBUTING.md)** - **[Contributing](../CONTRIBUTING.md)**
+3 -4
View File
@@ -33,10 +33,9 @@ Eden by default will be cloned into:
## Building with Terminal ## Building with Terminal
1. Download the SDK and NDK from Android Studio. 1. Download the SDK and NDK from Android Studio.
2. Navigate to SDK and NDK paths. 2. Navigate to SDK path.
3. Then set ANDROID_SDK_ROOT and ANDROID_NDK_ROOT in terminal via 3. Then set ANDROID_HOME in terminal via
`export ANDROID_SDK_ROOT=path/to/sdk` `export ANDROID_HOME=path/to/sdk`
`export ANDROID_NDK_ROOT=path/to/ndk`.
4. Navigate to `eden/src/android`. 4. Navigate to `eden/src/android`.
5. Then Build with `./gradlew assembleRelWithDebInfo`. 5. Then Build with `./gradlew assembleRelWithDebInfo`.
6. To build the optimised build use `./gradlew assembleGenshinSpoofRelWithDebInfo`. 6. To build the optimised build use `./gradlew assembleGenshinSpoofRelWithDebInfo`.
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 128 KiB

After

Width:  |  Height:  |  Size: 120 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 17 KiB

+5 -5
View File
@@ -101,6 +101,11 @@ endfunction()
# ia64 exists # ia64 exists
# the rest exist, but are probably less popular than ia64 # the rest exist, but are probably less popular than ia64
detect_architecture_symbols(
ARCH wasm
SYMBOLS
"__EMSCRIPTEN__")
detect_architecture_symbols( detect_architecture_symbols(
ARCH arm64 ARCH arm64
SYMBOLS SYMBOLS
@@ -203,11 +208,6 @@ detect_architecture_symbols(
"__loongarch__" "__loongarch__"
"__loongarch64") "__loongarch64")
detect_architecture_symbols(
ARCH wasm
SYMBOLS
"__EMSCRIPTEN__")
# "generic" target # "generic" target
# If you have reached this point, you're on some as-of-yet unsupported architecture. # If you have reached this point, you're on some as-of-yet unsupported architecture.
# See the docs up above for known unsupported architectures # See the docs up above for known unsupported architectures
@@ -79,9 +79,8 @@ class DriverFetcherFragment : Fragment() {
IntRange(100, 599) to "Unsupported", IntRange(100, 599) to "Unsupported",
IntRange(600, 639) to "Mr. Purple EOL-24.3.4", IntRange(600, 639) to "Mr. Purple EOL-24.3.4",
IntRange(640, 699) to "Mr. Purple T19", IntRange(640, 699) to "Mr. Purple T19",
IntRange(700, 710) to "KIMCHI 25.2.0_r5", IntRange(700, 710) to "Mr. Purple T29",
IntRange(711, 799) to "Mr. Purple T23", IntRange(711, 899) to "Mr. Purple T30",
IntRange(800, 899) to "GameHub Adreno 8xx",
IntRange(900, Int.MAX_VALUE) to "Unsupported" IntRange(900, Int.MAX_VALUE) to "Unsupported"
) )
Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

@@ -351,7 +351,7 @@
<string name="frame_generation_unsupported">غير مدعوم (لا يتوفر نموذج ذاكرة Vulkan أو float16)</string> <string name="frame_generation_unsupported">غير مدعوم (لا يتوفر نموذج ذاكرة Vulkan أو float16)</string>
<string name="lossless_scaling">Lossless Scaling</string> <string name="lossless_scaling">Lossless Scaling</string>
<string name="lossless_scaling_description">قم بتوفير نسختك الخاصة من ملف Lossless.dll لتفعيل توليد الإطارات</string> <string name="lossless_scaling_description">قم بتوفير نسختك الخاصة من ملف Lossless.dll لتفعيل توليد الإطارات</string>
<string name="lossless_scaling_installed">مثبت</string> <string name="lossless_scaling_installed">تم التثبيت</string>
<string name="lossless_scaling_not_installed">غير مثبت</string> <string name="lossless_scaling_not_installed">غير مثبت</string>
<string name="lossless_scaling_replace">استبدل</string> <string name="lossless_scaling_replace">استبدل</string>
<string name="lossless_scaling_remove">إزالة</string> <string name="lossless_scaling_remove">إزالة</string>
@@ -501,9 +501,9 @@
<string name="frame_limit_enable_description">يحدد سرعة المحاكاة بنسبة مئوية محددة من السرعة العادية.</string> <string name="frame_limit_enable_description">يحدد سرعة المحاكاة بنسبة مئوية محددة من السرعة العادية.</string>
<string name="frame_limit_slider">نسبة الحد الأقصى للسرعة</string> <string name="frame_limit_slider">نسبة الحد الأقصى للسرعة</string>
<string name="frame_limit_slider_description">يحدد النسبة المئوية للحد من سرعة المحاكاة. %100 هي السرعة الطبيعية. القيم الأعلى أو الأقل ستزيد أو تقلل من الحد الأقصى للسرعة.</string> <string name="frame_limit_slider_description">يحدد النسبة المئوية للحد من سرعة المحاكاة. %100 هي السرعة الطبيعية. القيم الأعلى أو الأقل ستزيد أو تقلل من الحد الأقصى للسرعة.</string>
<string name="turbo_speed_limit">سرعة تيربو</string> <string name="turbo_speed_limit">السرعة الفائقة</string>
<string name="turbo_speed_limit_description">عند تفعيل وضع التيربو، سيتم تشغيل المحاكاة بهذه السرعة.</string> <string name="turbo_speed_limit_description">عند تفعيل وضع التيربو، سيتم تشغيل المحاكاة بهذه السرعة.</string>
<string name="slow_speed_limit">سرعة بطيئة</string> <string name="slow_speed_limit">السرعة البطيئة</string>
<string name="slow_speed_limit_description">عند تفعيل الوضع البطيء، سيتم تشغيل المحاكاة بهذه السرعة.</string> <string name="slow_speed_limit_description">عند تفعيل الوضع البطيء، سيتم تشغيل المحاكاة بهذه السرعة.</string>
<string name="cpu_backend">خلفية وحدة المعالجة المركزية</string> <string name="cpu_backend">خلفية وحدة المعالجة المركزية</string>
<string name="cpu_accuracy">دقة وحدة المعالجة المركزية</string> <string name="cpu_accuracy">دقة وحدة المعالجة المركزية</string>
@@ -514,7 +514,7 @@
<!-- System settings strings --> <!-- System settings strings -->
<string name="device_name">اسم الجهاز</string> <string name="device_name">اسم الجهاز</string>
<string name="use_docked_mode">وضع الإرساء</string> <string name="use_docked_mode">وضع المنصة</string>
<string name="use_docked_mode_description">يزيد الدقة ويقلل الأداء. يتم استخدام الوضع المحمول عند تعطيله، مما يقلل الدقة ويزيد الأداء.</string> <string name="use_docked_mode_description">يزيد الدقة ويقلل الأداء. يتم استخدام الوضع المحمول عند تعطيله، مما يقلل الدقة ويزيد الأداء.</string>
<string name="emulated_region">المنطقة التي تمت محاكاتها</string> <string name="emulated_region">المنطقة التي تمت محاكاتها</string>
<string name="emulated_language">لغة المحاكاة</string> <string name="emulated_language">لغة المحاكاة</string>
@@ -543,7 +543,7 @@
<string name="network">الشبكة</string> <string name="network">الشبكة</string>
<!-- Graphics settings strings --> <!-- Graphics settings strings -->
<string name="renderer_resolution">الدقة (الإرساء/محمول)</string> <string name="renderer_resolution">الدقة (المنصة/محمول)</string>
<string name="renderer_vsync">VSync وضع</string> <string name="renderer_vsync">VSync وضع</string>
<string name="renderer_scaling_filter">مرشح ملائم للنافذة</string> <string name="renderer_scaling_filter">مرشح ملائم للنافذة</string>
<string name="fsr_sharpness">حدة FSR/SGSR</string> <string name="fsr_sharpness">حدة FSR/SGSR</string>
@@ -588,7 +588,7 @@
<string name="skip_cpu_inner_invalidation">تخطي إبطال صلاحية وحدة المعالجة المركزية الداخلية</string> <string name="skip_cpu_inner_invalidation">تخطي إبطال صلاحية وحدة المعالجة المركزية الداخلية</string>
<string name="skip_cpu_inner_invalidation_description">يتخطى بعض عمليات إبطال ذاكرة التخزين المؤقتة من جانب وحدة المعالجة المركزية أثناء تحديثات الذاكرة، مما يقلل من استخدام وحدة المعالجة المركزية ويحسن أداءها. قد يتسبب ذلك في حدوث أعطال أو تعطل في بعض الألعاب.</string> <string name="skip_cpu_inner_invalidation_description">يتخطى بعض عمليات إبطال ذاكرة التخزين المؤقتة من جانب وحدة المعالجة المركزية أثناء تحديثات الذاكرة، مما يقلل من استخدام وحدة المعالجة المركزية ويحسن أداءها. قد يتسبب ذلك في حدوث أعطال أو تعطل في بعض الألعاب.</string>
<string name="fix_bloom_effects">إصلاح تأثيرات التوهج</string> <string name="fix_bloom_effects">إصلاح تأثيرات التوهج</string>
<string name="fix_bloom_effects_description">يقلل من ضبابية التوهج في LA/EOW (Adreno A6XX - A7XX/ Turnip)، ويزيل التوهج في Burnout. تحذير: قد يسبب تشوهات رسومية في ألعاب أخرى.</string> <string name="fix_bloom_effects_description">يزيل تأثير التوهج في لعبة Burnout.</string>
<string name="emulate_bgr565">محاكاة BGR565</string> <string name="emulate_bgr565">محاكاة BGR565</string>
<string name="emulate_bgr565_description">يُصلح مشاكل انعكاس الألوان في الألعاب أو ظهور تشوهات غريبة أو ظلال غريبة.</string> <string name="emulate_bgr565_description">يُصلح مشاكل انعكاس الألوان في الألعاب أو ظهور تشوهات غريبة أو ظلال غريبة.</string>
<string name="rescale_hack">تفعيل ميزة إعادة التحجيم القديمة</string> <string name="rescale_hack">تفعيل ميزة إعادة التحجيم القديمة</string>
@@ -694,7 +694,7 @@
<string name="control_stick">عصا التحكم</string> <string name="control_stick">عصا التحكم</string>
<string name="right_stick">العصا اليمنى</string> <string name="right_stick">العصا اليمنى</string>
<string name="c_stick">عصا-C</string> <string name="c_stick">عصا-C</string>
<string name="pressed">مضغوط</string> <string name="pressed">ضغط العصا</string>
<string name="range">النطاق</string> <string name="range">النطاق</string>
<string name="deadzone">المنطقة الميتة</string> <string name="deadzone">المنطقة الميتة</string>
<string name="modifier">معدل</string> <string name="modifier">معدل</string>
@@ -821,10 +821,16 @@
<!-- Preferences Screen --> <!-- Preferences Screen -->
<string name="preferences_settings">الإعدادات</string> <string name="preferences_settings">الإعدادات</string>
<string name="preferences_system">النظام</string> <string name="preferences_system">النظام</string>
<string name="preferences_system_description">وضع الإرساء، المنطقة، اللغة</string> <string name="preferences_system_description">وضع المنصة، المنطقة، اللغة</string>
<string name="preferences_graphics">الرسومات</string> <string name="preferences_graphics">الرسومات</string>
<string name="preferences_graphics_description">مستوى دقة المحاكاة، الدقة، ذاكرة التخزين المؤقتة للتظليل</string> <string name="preferences_graphics_description">مستوى دقة المحاكاة، الدقة، ذاكرة التخزين المؤقتة للتظليل</string>
<string name="quick_settings">الإعدادات السريعة</string> <string name="quick_settings">الإعدادات السريعة</string>
<string name="cheats">رموز الغش</string>
<string name="enable_all_cheats">تفعيل جميع رموز الغش</string>
<string name="disable_all_cheats">تعطيل جميع رموز الغش</string>
<string name="unnamed_cheat">رمز الغش بدون اسم</string>
<string name="enable_cheats_by_default">تفعيل رموز الغش بشكل افتراضي</string>
<string name="enable_cheats_by_default_description">تفعيل رموز الغش الاعتيادية عند بدء اللعبة</string>
<string name="enable_quick_settings">تفعيل الإعدادات السريعة</string> <string name="enable_quick_settings">تفعيل الإعدادات السريعة</string>
<string name="enable_quick_settings_description">السماح بالوصول إلى قائمة الإعدادات السريعة عن طريق التمرير و زر القائمة</string> <string name="enable_quick_settings_description">السماح بالوصول إلى قائمة الإعدادات السريعة عن طريق التمرير و زر القائمة</string>
<string name="preferences_audio">الصوت</string> <string name="preferences_audio">الصوت</string>
@@ -869,12 +875,12 @@
<string name="copy_details">نسخ التفاصيل</string> <string name="copy_details">نسخ التفاصيل</string>
<string name="add_ons">الإضافات</string> <string name="add_ons">الإضافات</string>
<string name="add_ons_description">تفعيل/تعطيل التعديلات، التحديثات، المحتوى القابل للتنزيل</string> <string name="add_ons_description">تفعيل/تعطيل التعديلات، التحديثات، المحتوى القابل للتنزيل</string>
<string name="playtime">زمن اللعب:</string> <string name="playtime">وقت اللعب:</string>
<string name="reset_playtime">مسح زمن اللعب</string> <string name="reset_playtime">مسح وقت اللعب</string>
<string name="reset_playtime_description">إعادة تعيين زمن اللعب للعبة الحالية إلى 0 ثانية</string> <string name="reset_playtime_description">إعادة تعيين وقت لعب اللعبة الحالية إلى 0 ثانية</string>
<string name="reset_playtime_warning_description">سيؤدي هذا إلى مسح بيانات زمن اللعب الحالية للعبة. هل أنت متأكد؟</string> <string name="reset_playtime_warning_description">سيؤدي هذا إلى مسح بيانات وقت اللعب للعبة الحالية. هل أنت متأكد؟</string>
<string name="playtime_reset_successfully">تمت إعادة تعيين زمن اللعب</string> <string name="playtime_reset_successfully">تمت إعادة تعيين وقت اللعب</string>
<string name="edit_playtime">تعديل زمن اللعب</string> <string name="edit_playtime">تعديل وقت اللعب</string>
<string name="hours">ساعات</string> <string name="hours">ساعات</string>
<string name="minutes">دقائق</string> <string name="minutes">دقائق</string>
<string name="hours_abbr">س</string> <string name="hours_abbr">س</string>
@@ -883,7 +889,7 @@
<string name="hours_must_be_between_0_and_9999">يجب أن تكون الساعات بين 0 و 9999</string> <string name="hours_must_be_between_0_and_9999">يجب أن تكون الساعات بين 0 و 9999</string>
<string name="minutes_must_be_between_0_and_59">يجب أن تكون الدقائق بين 0 و 59</string> <string name="minutes_must_be_between_0_and_59">يجب أن تكون الدقائق بين 0 و 59</string>
<string name="seconds_must_be_between_0_and_59">يجب أن تكون الثواني بين 0 و 59</string> <string name="seconds_must_be_between_0_and_59">يجب أن تكون الثواني بين 0 و 59</string>
<string name="playtime_updated_successfully">تم تحديث زمن اللعب بنجاح</string> <string name="playtime_updated_successfully">تم تحديث وقت اللعب بنجاح</string>
<string name="clear_shader_cache">مسح ذاكرة التخزين المؤقتة للتظليل</string> <string name="clear_shader_cache">مسح ذاكرة التخزين المؤقتة للتظليل</string>
<string name="clear_shader_cache_description">يزيل جميع التظليلات التي تم إنشاؤها أثناء لعب هذه اللعبة</string> <string name="clear_shader_cache_description">يزيل جميع التظليلات التي تم إنشاؤها أثناء لعب هذه اللعبة</string>
<string name="clear_shader_cache_warning_description">ستواجه المزيد من التقطع مع إعادة إنشاء ذاكرة التخزين المؤقتة للتظلل</string> <string name="clear_shader_cache_warning_description">ستواجه المزيد من التقطع مع إعادة إنشاء ذاكرة التخزين المؤقتة للتظلل</string>
@@ -531,7 +531,6 @@
<string name="skip_cpu_inner_invalidation">Omitir invalidación interna de la CPU</string> <string name="skip_cpu_inner_invalidation">Omitir invalidación interna de la CPU</string>
<string name="skip_cpu_inner_invalidation_description">Omite ciertas invalidaciones de caché de la CPU durante las actualizaciones de memoria, lo que reduce el uso de la CPU y mejora su rendimiento. Esto puede causar fallos o bloqueos en algunos juegos.</string> <string name="skip_cpu_inner_invalidation_description">Omite ciertas invalidaciones de caché de la CPU durante las actualizaciones de memoria, lo que reduce el uso de la CPU y mejora su rendimiento. Esto puede causar fallos o bloqueos en algunos juegos.</string>
<string name="fix_bloom_effects">Arreglar los efectos de resplandor</string> <string name="fix_bloom_effects">Arreglar los efectos de resplandor</string>
<string name="fix_bloom_effects_description">Reduce el efecto de resplandor en LA/EOW (Adreno A6XX - A7XX/ Turnip), elimina el resplandor en Burnout. Advertencia: puede causar artefactos gráficos en otros juegos.</string>
<string name="emulate_bgr565">Emular BGR565</string> <string name="emulate_bgr565">Emular BGR565</string>
<string name="emulate_bgr565_description">Soluciona problemas con colores invertidos en juegos, artefactos o sombras extrañas.</string> <string name="emulate_bgr565_description">Soluciona problemas con colores invertidos en juegos, artefactos o sombras extrañas.</string>
<string name="rescale_hack">Activar la pasada de reescalado heredada</string> <string name="rescale_hack">Activar la pasada de reescalado heredada</string>
@@ -577,7 +577,6 @@
<string name="skip_cpu_inner_invalidation">Пропустить внутреннюю инвалидацию ЦП</string> <string name="skip_cpu_inner_invalidation">Пропустить внутреннюю инвалидацию ЦП</string>
<string name="skip_cpu_inner_invalidation_description">Пропускает некоторые инвалидации кэша на стороне ЦП при обновлениях памяти, уменьшая нагрузку на процессор и повышая производительность. Может вызывать сбои в некоторых играх.</string> <string name="skip_cpu_inner_invalidation_description">Пропускает некоторые инвалидации кэша на стороне ЦП при обновлениях памяти, уменьшая нагрузку на процессор и повышая производительность. Может вызывать сбои в некоторых играх.</string>
<string name="fix_bloom_effects">Исправить эффекты размытия</string> <string name="fix_bloom_effects">Исправить эффекты размытия</string>
<string name="fix_bloom_effects_description">Частично убирает размытие в LA/EOW (Adreno A6XX - A7XX/ Turnip), полностью отключает его в Burnout. Внимание: может вызывать графические артефакты в других играх.</string>
<string name="emulate_bgr565">Эмулировать BGR565</string> <string name="emulate_bgr565">Эмулировать BGR565</string>
<string name="emulate_bgr565_description">Исправляет проблемы с инвертированными цветами в играх, а также со странными артефактами или некорректными тенями.</string> <string name="emulate_bgr565_description">Исправляет проблемы с инвертированными цветами в играх, а также со странными артефактами или некорректными тенями.</string>
<string name="rescale_hack">Включить старый метод изменения разрешения</string> <string name="rescale_hack">Включить старый метод изменения разрешения</string>
@@ -493,7 +493,6 @@
<string name="skip_cpu_inner_invalidation">Пропустити внутрішнє інвалідування CPU</string> <string name="skip_cpu_inner_invalidation">Пропустити внутрішнє інвалідування CPU</string>
<string name="skip_cpu_inner_invalidation_description">Пропускає деякі інвалідації кешу на стороні CPU під час оновлення пам\'яті, зменшуючи навантаження на процесор і покращуючи продуктивність. Може спричинити збої в деяких іграх.</string> <string name="skip_cpu_inner_invalidation_description">Пропускає деякі інвалідації кешу на стороні CPU під час оновлення пам\'яті, зменшуючи навантаження на процесор і покращуючи продуктивність. Може спричинити збої в деяких іграх.</string>
<string name="fix_bloom_effects">Виправити ефекти світіння</string> <string name="fix_bloom_effects">Виправити ефекти світіння</string>
<string name="fix_bloom_effects_description">Зменшує розмиття світіння в LA/EOW (Adreno A6XX–A7XX / Turnip), прибирає світіння в Burnout. Увага: може спричинити графічні артефакти в інших іграх.</string>
<string name="emulate_bgr565">Емулювати BGR565</string> <string name="emulate_bgr565">Емулювати BGR565</string>
<string name="emulate_bgr565_description">Виправляє проблеми з інвертованими кольорами в іграх або дивними артефактами чи тінями.</string> <string name="emulate_bgr565_description">Виправляє проблеми з інвертованими кольорами в іграх або дивними артефактами чи тінями.</string>
<string name="rescale_hack">Увімкнути застаріле масштабування</string> <string name="rescale_hack">Увімкнути застаріле масштабування</string>
@@ -578,7 +578,7 @@
<string name="skip_cpu_inner_invalidation">跳过CPU内部无效化</string> <string name="skip_cpu_inner_invalidation">跳过CPU内部无效化</string>
<string name="skip_cpu_inner_invalidation_description">在更新内存时跳过某些 CPU 端的缓存失效操作,从而降低 CPU 占用率并提升性能。可能会在某些游戏中引发故障点或崩溃。</string> <string name="skip_cpu_inner_invalidation_description">在更新内存时跳过某些 CPU 端的缓存失效操作,从而降低 CPU 占用率并提升性能。可能会在某些游戏中引发故障点或崩溃。</string>
<string name="fix_bloom_effects">修复 Bloom 效果</string> <string name="fix_bloom_effects">修复 Bloom 效果</string>
<string name="fix_bloom_effects_description">减少《智慧的再现》和《众神的三角力量2》(Adreno A6XX - A7XX/ Turnip)中的 bloom 模糊,并移除《Burnout》中的 bloom 效果。警告:可能会导致在其他游戏中出现图形异常。</string> <string name="fix_bloom_effects_description">去除《火爆狂飙》中的泛光特效。</string>
<string name="emulate_bgr565">模拟 BGR565</string> <string name="emulate_bgr565">模拟 BGR565</string>
<string name="emulate_bgr565_description">修复游戏中的颜色反转或是异常的画面瑕疵或阴影问题</string> <string name="emulate_bgr565_description">修复游戏中的颜色反转或是异常的画面瑕疵或阴影问题</string>
<string name="rescale_hack">启用旧版缩放处理</string> <string name="rescale_hack">启用旧版缩放处理</string>
@@ -815,6 +815,12 @@
<string name="preferences_graphics">图形</string> <string name="preferences_graphics">图形</string>
<string name="preferences_graphics_description">精度等级、分辨率及着色器缓存</string> <string name="preferences_graphics_description">精度等级、分辨率及着色器缓存</string>
<string name="quick_settings">快速设置</string> <string name="quick_settings">快速设置</string>
<string name="cheats">作弊</string>
<string name="enable_all_cheats">开启所有作弊</string>
<string name="disable_all_cheats">关闭所有作弊</string>
<string name="unnamed_cheat">未命名的作弊</string>
<string name="enable_cheats_by_default">默认开启作弊</string>
<string name="enable_cheats_by_default_description">在游戏启动时启用常规作弊</string>
<string name="enable_quick_settings">启用快速设置</string> <string name="enable_quick_settings">启用快速设置</string>
<string name="enable_quick_settings_description">允许通过滑动和菜单按钮访问快速设置菜单</string> <string name="enable_quick_settings_description">允许通过滑动和菜单按钮访问快速设置菜单</string>
<string name="preferences_audio">声音</string> <string name="preferences_audio">声音</string>
@@ -36,7 +36,7 @@
<string name="input_overlay_options">虛擬按鍵設定</string> <string name="input_overlay_options">虛擬按鍵設定</string>
<string name="input_overlay_options_description">調整虛擬按鍵的位置與顯示設定</string> <string name="input_overlay_options_description">調整虛擬按鍵的位置與顯示設定</string>
<string name="edit_overlay_layout">編輯虛擬按鍵</string> <string name="edit_overlay_layout">調整虛擬按鍵</string>
<string name="edit_overlay_layout_description">調整虛擬按鍵的位置和大小</string> <string name="edit_overlay_layout_description">調整虛擬按鍵的位置和大小</string>
@@ -253,8 +253,8 @@
<string name="install_firmware_warning">跳過安裝韌體?</string> <string name="install_firmware_warning">跳過安裝韌體?</string>
<string name="emulator_data">設定模擬器資料</string> <string name="emulator_data">設定模擬器資料</string>
<string name="emulator_data_description">模擬器需要金鑰才能正常執行,同時建議安裝韌體以啟動 QLaunch 小程式</string> <string name="emulator_data_description">模擬器需要金鑰才能正常執行,同時建議安裝韌體以啟動 QLaunch 小程式</string>
<string name="permissions">授予權限</string> <string name="permissions">授予通知權限</string>
<string name="permissions_description">授予權限以使用模擬器的特定功能</string> <string name="permissions_description">授予 Eden 傳送通知的權限以使用模擬器的特定功能</string>
<string name="install_firmware_warning_description">許多遊戲需要韌體才能正常運作</string> <string name="install_firmware_warning_description">許多遊戲需要韌體才能正常運作</string>
<string name="install_firmware_warning_help">https://yuzu-mirror.github.io/help/quickstart/#guide-introduction</string> <string name="install_firmware_warning_help">https://yuzu-mirror.github.io/help/quickstart/#guide-introduction</string>
<string name="notifications">通知</string> <string name="notifications">通知</string>
@@ -268,8 +268,8 @@
<string name="device_manufacturer">製造商</string> <string name="device_manufacturer">製造商</string>
<string name="device_model">型號</string> <string name="device_model">型號</string>
<string name="product">型號代碼</string> <string name="product">型號代碼</string>
<string name="android_version">安卓版本</string> <string name="android_version">Android 版本</string>
<string name="android_security_patch">安卓安全性修補程式等級</string> <string name="android_security_patch">Android 安全性修補程式等級</string>
<string name="build_id">版本號碼</string> <string name="build_id">版本號碼</string>
<string name="general_information">基本資訊</string> <string name="general_information">基本資訊</string>
<string name="hardware">硬體</string> <string name="hardware">硬體</string>
@@ -287,7 +287,7 @@
<string name="warning_skip">跳過</string> <string name="warning_skip">跳過</string>
<string name="warning_cancel">取消</string> <string name="warning_cancel">取消</string>
<string name="install_amiibo_keys">安裝 Amiibo 金鑰</string> <string name="install_amiibo_keys">安裝 Amiibo 金鑰</string>
<string name="install_amiibo_keys_description">需要先安裝才能在遊戲中使用 Amiibo</string> <string name="install_amiibo_keys_description">安裝 Amiibo 以在日後遊玩時使用</string>
<string name="gpu_driver_fetcher">GPU 驅動程式下載器</string> <string name="gpu_driver_fetcher">GPU 驅動程式下載器</string>
<string name="gpu_driver_manager">GPU 驅動程式管理員</string> <string name="gpu_driver_manager">GPU 驅動程式管理員</string>
<string name="install_gpu_driver_description">安裝替代驅動程式以取得潛在的更佳效能或準確度</string> <string name="install_gpu_driver_description">安裝替代驅動程式以取得潛在的更佳效能或準確度</string>
@@ -417,17 +417,17 @@
<string name="custom_driver_not_supported">您的裝置不支援自訂驅動程式</string> <string name="custom_driver_not_supported">您的裝置不支援自訂驅動程式</string>
<string name="custom_driver_not_supported_description">此裝置不支援注入自訂驅動程式\n請以後再來查看是否已新增支援!</string> <string name="custom_driver_not_supported_description">此裝置不支援注入自訂驅動程式\n請以後再來查看是否已新增支援!</string>
<string name="manage_yuzu_data">管理 Eden 資料</string> <string name="manage_yuzu_data">管理 Eden 資料</string>
<string name="manage_yuzu_data_description">安裝韌體、金鑰,導入/導出使用者資料及安裝其它項目!</string> <string name="manage_yuzu_data_description">安裝韌體、金鑰,匯入/匯出使用者資料及安裝其它項目!</string>
<string name="game_folders">遊戲資料夾</string> <string name="game_folders">遊戲資料夾</string>
<string name="deep_scan">深度掃描</string> <string name="deep_scan">深度掃描</string>
<string name="add_game_folder">新增遊戲資料夾</string> <string name="add_game_folder">新增遊戲資料夾</string>
<string name="folder_already_added">這個資料夾已經新增過了!</string> <string name="folder_already_added">這個資料夾已經新增過了!</string>
<string name="game_folder_properties">遊戲資料夾設定</string> <string name="game_folder_properties">遊戲資料夾設定</string>
<plurals name="saves_import_failed"> <plurals name="saves_import_failed">
<item quantity="other">%d 個存檔導入失敗</item> <item quantity="other">%d 個存檔匯入失敗</item>
</plurals> </plurals>
<plurals name="saves_import_success"> <plurals name="saves_import_success">
<item quantity="other">成功導入 %d 個存檔</item> <item quantity="other">成功匯入 %d 個存檔</item>
</plurals> </plurals>
<string name="no_save_data_found">找不到儲存資料</string> <string name="no_save_data_found">找不到儲存資料</string>
<string name="verify_installed_content">驗證已安裝內容的完整性</string> <string name="verify_installed_content">驗證已安裝內容的完整性</string>
@@ -451,7 +451,7 @@
<!-- Applet launcher strings --> <!-- Applet launcher strings -->
<string name="qlaunch_applet">Qlaunch</string> <string name="qlaunch_applet">Qlaunch</string>
<string name="qlaunch_description">從 Switch 系統主畫面啟動應用程式(目前僅支援英文)</string> <string name="qlaunch_description">從 Switch 系統主畫面啟動應用程式(目前模擬區域尚不支援臺灣、澳洲、中國、南韓啟動 Qlaunch)</string>
<string name="applets">小程式啟動器</string> <string name="applets">小程式啟動器</string>
<string name="applets_description">使用已安裝的韌體啟動系統小程式</string> <string name="applets_description">使用已安裝的韌體啟動系統小程式</string>
<string name="applets_error_firmware">未安裝韌體</string> <string name="applets_error_firmware">未安裝韌體</string>
@@ -578,7 +578,7 @@
<string name="skip_cpu_inner_invalidation">跳過 CPU 內部失效處理</string> <string name="skip_cpu_inner_invalidation">跳過 CPU 內部失效處理</string>
<string name="skip_cpu_inner_invalidation_description">在記憶體更新期間跳過某些 CPU 端快取的失效處理,減少 CPU 使用率並提高其性能。可能會導致某些遊戲出現故障或當機</string> <string name="skip_cpu_inner_invalidation_description">在記憶體更新期間跳過某些 CPU 端快取的失效處理,減少 CPU 使用率並提高其性能。可能會導致某些遊戲出現故障或當機</string>
<string name="fix_bloom_effects">修正光暈特效</string> <string name="fix_bloom_effects">修正光暈特效</string>
<string name="fix_bloom_effects_description">在 \"薩爾達傳說:織夢島\" 和 \"薩爾達傳說:智慧的再現\" 中減少光暈模糊的問題並移除 \"橫衝直撞:狂飆樂園重製版\" 中的光暈效果(適用於 Adreno A6XX - A7XX/ Turnip)。警告:可能會在其它遊戲中導致圖形異常</string> <string name="fix_bloom_effects_description">移除《橫衝直撞:狂飆樂園重製版》中的光暈效果</string>
<string name="emulate_bgr565">模擬 BGR565</string> <string name="emulate_bgr565">模擬 BGR565</string>
<string name="emulate_bgr565_description">修正遊戲中出現的色彩反轉、圖形異常或陰影異常</string> <string name="emulate_bgr565_description">修正遊戲中出現的色彩反轉、圖形異常或陰影異常</string>
<string name="rescale_hack">啟用舊版重新縮放處理</string> <string name="rescale_hack">啟用舊版重新縮放處理</string>
@@ -601,7 +601,7 @@
<string name="extensions">擴充功能</string> <string name="extensions">擴充功能</string>
<string name="dyna_state">擴展動態狀態</string> <string name="dyna_state">擴展動態狀態</string>
<string name="dyna_state_description">控制擴展動態狀態中可使用的功能數量,較高的數值可根據驅動程式支援的動態狀態減少管線編譯的次數</string> <string name="dyna_state_description">控制 Vulkan 擴展動態狀態中可使用的功能數量,較高的數值可根據驅動程式支援的動態狀態減少管線編譯的次數</string>
<string name="disabled">停用</string> <string name="disabled">停用</string>
<string name="vertex_input_dynamic_state">頂點輸入動態狀態</string> <string name="vertex_input_dynamic_state">頂點輸入動態狀態</string>
<string name="vertex_input_dynamic_state_description">啟用此功能可提供更彈性的頂點輸入處理方式,並可能減少頂點/緩衝區的管線編譯時間</string> <string name="vertex_input_dynamic_state_description">啟用此功能可提供更彈性的頂點輸入處理方式,並可能減少頂點/緩衝區的管線編譯時間</string>
@@ -806,7 +806,7 @@
<string name="recommended_driver">推薦驅動程式:</string> <string name="recommended_driver">推薦驅動程式:</string>
<string name="gpu_model">GPU 型號</string> <string name="gpu_model">GPU 型號</string>
<string name="unsupported_gpu">不支援的 GPU</string> <string name="unsupported_gpu">不支援的 GPU</string>
<string name="unsupported_gpu_warning">您的 GPU 不支援驅動程式注入,不建議嘗試設定自訂驅動程式</string> <string name="unsupported_gpu_warning">您的 GPU 不支援驅動程式注入,不建議嘗試安裝自訂驅動程式</string>
<!-- Preferences Screen --> <!-- Preferences Screen -->
<string name="preferences_settings">設定</string> <string name="preferences_settings">設定</string>
@@ -815,6 +815,12 @@
<string name="preferences_graphics">圖形</string> <string name="preferences_graphics">圖形</string>
<string name="preferences_graphics_description">準確度層級、解析度及著色器快取</string> <string name="preferences_graphics_description">準確度層級、解析度及著色器快取</string>
<string name="quick_settings">快捷設定</string> <string name="quick_settings">快捷設定</string>
<string name="cheats">金手指</string>
<string name="enable_all_cheats">啟用所有金手指</string>
<string name="disable_all_cheats">停用所有金手指</string>
<string name="unnamed_cheat">未命名的金手指</string>
<string name="enable_cheats_by_default">預設啟用金手指</string>
<string name="enable_cheats_by_default_description">在遊戲啟動時啟用一般金手指</string>
<string name="enable_quick_settings">啟用快捷設定</string> <string name="enable_quick_settings">啟用快捷設定</string>
<string name="enable_quick_settings_description">允許透過滑動和選單按鈕存取快捷設定選單</string> <string name="enable_quick_settings_description">允許透過滑動和選單按鈕存取快捷設定選單</string>
<string name="preferences_audio">音訊</string> <string name="preferences_audio">音訊</string>
@@ -831,9 +837,9 @@
<string name="custom_save_directory">遊戲儲存資料路徑</string> <string name="custom_save_directory">遊戲儲存資料路徑</string>
<string name="custom_save_directory_description">設定遊戲儲存資料的自訂路徑</string> <string name="custom_save_directory_description">設定遊戲儲存資料的自訂路徑</string>
<string name="reset_to_nand">重設為預設值</string> <string name="reset_to_nand">重設為預設值</string>
<string name="migrate_save_data">遷移儲存資料</string> <string name="migrate_save_data">移動儲存資料</string>
<string name="migrate_save_data_question">您要將現有的儲存資料移至新位置嗎?</string> <string name="migrate_save_data_question">您要將現有的儲存資料移至新位置嗎?</string>
<string name="save_migration_complete">成功遷移儲存資料</string> <string name="save_migration_complete">儲存資料遷移成功</string>
<string name="save_migration_failed">儲存資料遷移失敗</string> <string name="save_migration_failed">儲存資料遷移失敗</string>
<string name="save_directory_set">存檔目錄設定完成</string> <string name="save_directory_set">存檔目錄設定完成</string>
<string name="destination_has_saves">所選取的位置已有儲存資料,是否要取代該檔案?</string> <string name="destination_has_saves">所選取的位置已有儲存資料,是否要取代該檔案?</string>
@@ -889,10 +895,10 @@
<string name="save_data_deleted_successfully">儲存資料已成功刪除</string> <string name="save_data_deleted_successfully">儲存資料已成功刪除</string>
<string name="select_content_type">內容類型</string> <string name="select_content_type">內容類型</string>
<string name="updates_and_dlc">更新及 DLC</string> <string name="updates_and_dlc">更新及 DLC</string>
<string name="mods_and_cheats">模組及金手指</string> <string name="mods_and_cheats">Mod 和金手指</string>
<string name="addon_notice">重要的˙附加元件通知</string> <string name="addon_notice">注意!</string>
<!-- \"cheats/" "romfs/" and \"exefs/ should not be translated --> <!-- \"cheats/" "romfs/" and \"exefs/ should not be translated -->
<string name="addon_notice_description">若要安裝模組及金手指,您必須選擇一個包含 cheats/、romfs/ 或 exefs/ 的目錄。我們無法驗證這些內容是否與您的遊戲相容,所以請謹慎安裝!</string> <string name="addon_notice_description">若要安裝 Mod 和金手指,您必須選擇一個包含 cheats/、romfs/ 或 exefs/ 的目錄。我們無法驗證這些內容是否與您的遊戲相容,所以請謹慎安裝!</string>
<string name="invalid_directory">無效的目錄</string> <string name="invalid_directory">無效的目錄</string>
<!-- \"cheats/" "romfs/" and \"exefs/ should not be translated --> <!-- \"cheats/" "romfs/" and \"exefs/ should not be translated -->
<string name="invalid_directory_description">請確保您選取的目錄包含 cheats/、romfs/ 或 exefs/ 資料夾,然後再試一次</string> <string name="invalid_directory_description">請確保您選取的目錄包含 cheats/、romfs/ 或 exefs/ 資料夾,然後再試一次</string>
@@ -979,7 +985,7 @@
<string name="emulation_pause">暫停模擬</string> <string name="emulation_pause">暫停模擬</string>
<string name="emulation_unpause">繼續模擬</string> <string name="emulation_unpause">繼續模擬</string>
<string name="emulation_input_overlay">疊加層/虛擬按鍵設定</string> <string name="emulation_input_overlay">疊加層/虛擬按鍵設定</string>
<string name="load_amiibo">導入 Amiibo</string> <string name="load_amiibo">匯入 Amiibo</string>
<string name="touchscreen">觸控螢幕</string> <string name="touchscreen">觸控螢幕</string>
<string name="lock_drawer">鎖定側邊選單</string> <string name="lock_drawer">鎖定側邊選單</string>
<string name="unlock_drawer">解鎖側邊選單</string> <string name="unlock_drawer">解鎖側邊選單</string>
@@ -1126,6 +1132,16 @@
<string name="freedreno_clear_all">全部清除</string> <string name="freedreno_clear_all">全部清除</string>
<string name="freedreno_saved">Freedreno 設定已儲存</string> <string name="freedreno_saved">Freedreno 設定已儲存</string>
<string name="freedreno_cleared_all">已清除所有 Freedreno 變數</string> <string name="freedreno_cleared_all">已清除所有 Freedreno 變數</string>
<string name="freedreno_variable_added">變數 %1$s 已新增</string>
<string name="freedreno_preset_applied">設定檔 \"%1$s\" 已套用</string>
<string name="freedreno_error_empty_name">變數名稱不可空白</string>
<string name="freedreno_error_setting_variable">變數設定失敗</string>
<string name="freedreno_info_title">關於 Freedreno 設定</string>
<string name="freedreno_info_description">透過調整 Freedreno/Turnip GPU 驅動程式的設定來偵錯、分析和最佳化效能,會自動儲存變更。詳情請參閱 https://docs.mesa3d.org/drivers/freedreno.html</string>
<string name="freedreno_per_game_title">Freedreno 設定</string>
<string name="freedreno_per_game_description">調整此遊戲的 GPU 驅動程式設定</string>
<string name="freedreno_per_game_saved">Freedreno 設定已儲存</string>
<!-- Gamepad Buttons --> <!-- Gamepad Buttons -->
<string name="gamepad_d_pad">方向鍵</string> <string name="gamepad_d_pad">方向鍵</string>
<string name="gamepad_left_stick">左搖桿</string> <string name="gamepad_left_stick">左搖桿</string>
@@ -1134,14 +1150,17 @@
<string name="gamepad_screenshot">螢幕截圖</string> <string name="gamepad_screenshot">螢幕截圖</string>
<!-- Disk shader cache --> <!-- Disk shader cache -->
<string name="building_shaders">正在建置著色器</string> <string name="building_shaders">正在編譯著色器</string>
<!-- App options --> <!-- App options -->
<string name="change_app_theme">變更應用程式主題</string> <string name="change_app_theme">變更應用程式主題</string>
<string name="theme_default">預設</string> <string name="theme_default">預設</string>
<string name="theme_material_you">質感設計3</string> <string name="theme_material_you">Material You</string>
<string name="app_settings">Eden介面設定</string> <string name="app_settings">Eden 介面設定</string>
<string name="theme_and_color">主題和顏色</string> <string name="theme_and_color">主題和顏色</string>
<string name="fullscreen_mode">全螢幕模式</string>
<string name="fullscreen_mode_description">在使用 Eden 時隱藏 Android 系統的導覽列,在直向時從螢幕底部往上滑以暫時顯示它們;橫向時則從螢幕側邊往內滑動</string>
<!-- Theme Modes --> <!-- Theme Modes -->
<string name="change_theme_mode">變更主題模式</string> <string name="change_theme_mode">變更主題模式</string>
<string name="theme_mode_follow_system">跟隨系統</string> <string name="theme_mode_follow_system">跟隨系統</string>
@@ -1150,18 +1169,26 @@
<!-- Black backgrounds theme --> <!-- Black backgrounds theme -->
<string name="use_black_backgrounds">黑色背景</string> <string name="use_black_backgrounds">黑色背景</string>
<string name="use_black_backgrounds_description">使用深色主題時,套用黑色背景。</string> <string name="use_black_backgrounds_description">使用深色主題時套用黑色背景</string>
<!-- Buttons -->
<string name="enable_folder_button">遊戲資料夾</string>
<string name="enable_folder_button_description">在 Eden 首頁顯示新增遊戲資料夾的按鈕</string>
<string name="enable_qlaunch_button">QLaunch</string>
<string name="enable_qlaunch_button_description">在 Eden 首頁顯示 QLaunch 按鈕</string>
<!-- App Language --> <!-- App Language -->
<string name="app_language">語言</string> <string name="app_language">語言</string>
<string name="app_language_description">選擇Eden顯示的語言</string> <string name="app_language_description">選擇 Eden 顯示的語言</string>
<string name="app_language_system">跟隨系統</string> <string name="app_language_system">跟隨系統</string>
<!-- Static Themes --> <!-- Static Themes -->
<string name="static_theme_color">主題色彩</string> <string name="static_theme_color">主題色彩</string>
<string name="eden_theme">Eden</string>
<string name="violet">紫色</string> <string name="violet">紫色</string>
<string name="blue">藍色</string> <string name="blue">藍色</string>
<string name="cyan">青色</string> <string name="cyan">青色</string>
<string name="red">紅色</string> <string name="red">紅色</string>
<string name="green">綠色</string>
<string name="yellow">黃色</string> <string name="yellow">黃色</string>
<string name="orange">橘色</string> <string name="orange">橘色</string>
<string name="pink">粉紅色</string> <string name="pink">粉紅色</string>
@@ -1183,13 +1210,27 @@
<string name="applets_menu_description">更改小程式前端和設定</string> <string name="applets_menu_description">更改小程式前端和設定</string>
<string name="applet_hle">自訂前端</string> <string name="applet_hle">自訂前端</string>
<string name="applet_lle">Switch小程式</string> <string name="applet_lle">Switch 小程式</string>
<string name="swkbd_applet">軟體鍵盤</string> <string name="swkbd_applet">軟體鍵盤</string>
<string name="airplane_mode">飛航模式</string> <string name="airplane_mode">飛航模式</string>
<string name="airplane_mode_description">將飛航模式傳遞給Switch作業系統</string> <string name="airplane_mode_description">將飛航模式傳遞給 Switch 作業系統</string>
<string name="enable_overlay">啟用小程式虛擬按鍵</string>
<string name="enable_overlay_description">啟用 Horizon OS 內建的小程式虛擬按鍵,長按 Home 鍵 1 秒以顯示虛擬按鍵</string>
<!-- Profile Management -->
<string name="profile_manager">使用者管理</string>
<string name="profile_manager_description">更改使用者名稱、圖片及新增或刪除使用者</string>
<string name="profile_add_user">新增使用者</string>
<string name="profile_new_user">新增使用者</string>
<string name="profile_edit_user">編輯使用者資料</string>
<string name="profile_edit">編輯</string>
<string name="profile_delete">刪除</string>
<string name="profile_username">使用者名稱</string>
<string name="profile_uuid">使用者 ID (通用唯一辨識碼)</string>
<string name="profile_uuid_description">這是此使用者設定檔的唯一識別碼,建立後就無法進行更改</string>
<!-- Licenses screen strings --> <!-- Licenses screen strings -->
<string name="licenses">授權</string> <string name="licenses">授權</string>
<string name="license_fidelityfx_fsr_description">來自 AMD 的升級圖像品質</string> <string name="license_fidelityfx_fsr_description">來自 AMD 的升級圖像品質</string>
@@ -498,7 +498,7 @@
<string name="user_data_import_failed_description">Make sure the user data folders are at the root of the zip folder and contain a config file at config/config.ini and try again.</string> <string name="user_data_import_failed_description">Make sure the user data folders are at the root of the zip folder and contain a config file at config/config.ini and try again.</string>
<string name="discord_link" translatable="false">https://discord.gg/HstXbPch7X</string> <string name="discord_link" translatable="false">https://discord.gg/HstXbPch7X</string>
<string name="stoat_link" translatable="false">https://stt.gg/qKgFEAbH</string> <string name="stoat_link" translatable="false">https://stt.gg/qKgFEAbH</string>
<string name="x_link" translatable="false">https://nitter.poast.org/edenemuofficial</string> <string name="x_link" translatable="false">https://x.com/edenemuofficial</string>
<string name="website_link" translatable="false">https://eden-emu.dev</string> <string name="website_link" translatable="false">https://eden-emu.dev</string>
<string name="github_link" translatable="false">https://git.eden-emu.dev/eden-emu</string> <string name="github_link" translatable="false">https://git.eden-emu.dev/eden-emu</string>
+221 -99
View File
@@ -7,18 +7,25 @@
#include <vector> #include <vector>
#include "common/assert.h" #include "common/assert.h"
#include "common/bit_util.h"
#include "common/fs/file.h" #include "common/fs/file.h"
#include "common/fs/fs.h" #include "common/fs/fs.h"
#include "common/fs/fs_types.h"
#ifdef __ANDROID__ #ifdef __ANDROID__
#include "common/fs/fs_android.h" #include "common/fs/fs_android.h"
#endif #endif
#include "common/logging.h" #include "common/logging.h"
#include "common/literals.h"
#ifdef _WIN32 #ifdef _WIN32
#include <io.h> #include <io.h>
#include <share.h> #include <share.h>
#include <windows.h>
#else #else
#include <unistd.h> #include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#endif #endif
#ifdef _MSC_VER #ifdef _MSC_VER
@@ -36,13 +43,13 @@ namespace {
#ifdef _WIN32 #ifdef _WIN32
/** /**
* Converts the file access mode and file type enums to a file access mode wide string. * Converts the file access mode and file type enums to a file access mode wide string.
* *
* @param mode File access mode * @param mode File access mode
* @param type File type * @param type File type
* *
* @returns A pointer to a wide string representing the file access mode. * @returns A pointer to a wide string representing the file access mode.
*/ */
[[nodiscard]] constexpr const wchar_t* AccessModeToWStr(FileAccessMode mode, FileType type) { [[nodiscard]] constexpr const wchar_t* AccessModeToWStr(FileAccessMode mode, FileType type) {
switch (type) { switch (type) {
case FileType::BinaryFile: case FileType::BinaryFile:
@@ -79,12 +86,12 @@ namespace {
} }
/** /**
* Converts the file-share access flag enum to a Windows defined file-share access flag. * Converts the file-share access flag enum to a Windows defined file-share access flag.
* *
* @param flag File-share access flag * @param flag File-share access flag
* *
* @returns Windows defined file-share access flag. * @returns Windows defined file-share access flag.
*/ */
[[nodiscard]] constexpr int ToWindowsFileShareFlag(FileShareFlag flag) { [[nodiscard]] constexpr int ToWindowsFileShareFlag(FileShareFlag flag) {
switch (flag) { switch (flag) {
case FileShareFlag::ShareNone: case FileShareFlag::ShareNone:
@@ -102,13 +109,13 @@ namespace {
#else #else
/** /**
* Converts the file access mode and file type enums to a file access mode string. * Converts the file access mode and file type enums to a file access mode string.
* *
* @param mode File access mode * @param mode File access mode
* @param type File type * @param type File type
* *
* @returns A pointer to a string representing the file access mode. * @returns A pointer to a string representing the file access mode.
*/ */
[[nodiscard]] constexpr const char* AccessModeToStr(FileAccessMode mode, FileType type) { [[nodiscard]] constexpr const char* AccessModeToStr(FileAccessMode mode, FileType type) {
switch (type) { switch (type) {
case FileType::BinaryFile: case FileType::BinaryFile:
@@ -147,12 +154,12 @@ namespace {
#endif #endif
/** /**
* Converts the seek origin enum to a seek origin integer. * Converts the seek origin enum to a seek origin integer.
* *
* @param origin Seek origin * @param origin Seek origin
* *
* @returns Seek origin integer. * @returns Seek origin integer.
*/ */
[[nodiscard]] constexpr int ToSeekOrigin(SeekOrigin origin) { [[nodiscard]] constexpr int ToSeekOrigin(SeekOrigin origin) {
switch (origin) { switch (origin) {
case SeekOrigin::SetOrigin: case SeekOrigin::SetOrigin:
@@ -244,42 +251,162 @@ FileType IOFile::GetType() const {
return file_type; return file_type;
} }
#if defined(__unix__)
static int PlatformMapReadOnly(IOFile& io, const char* path) {
io.mmap_fd = open(path, O_RDONLY);
if (io.mmap_fd > 0) {
struct stat st;
fstat(io.mmap_fd, &st);
io.mmap_size = st.st_size;
int map_flags = MAP_PRIVATE;
#ifdef MAP_PREFAULT_READ
// Prefaults reads so the final resulting pagetable from this big stupid mmap()
// isn't comically lazily loaded, we just coalesce everything in-place for our
// lovely mmap flags; if we didn't prefault the reads the page table will be
// constructed in-place (i.e on a read-by-read basis) causing lovely soft-faults
// which would nuke any performance gains.
//
// This of course incurs a cost in the initial mmap(2) call, but that is fine.
map_flags |= MAP_PREFAULT_READ;
#endif
#ifdef MAP_NOSYNC
// This causes physical media to not be synched to our file/memory
// This means that if the read-only file is written to, we won't see changes
// or we may see changes which are just funnily scattered, in any case
// this presumes the files won't be changed during execution
//
// Do not ever use this on write files (if we ever support that); this will create
// a fun amount of fragmentation on the disk.
map_flags |= MAP_NOSYNC;
#endif
#if defined(NDEBUG) && defined(MAP_NOCORE)
map_flags |= MAP_NOCORE;
#endif
#ifdef MAP_HUGE_2MB
map_flags |= MAP_HUGE_2MB; //2mb pages
#elif defined(MAP_ALIGNED)
// File must be big enough that it's worth to super align. We can't just super-align every
// file otherwise we will run out of alignments for actually important files :)
// System doesn't guarantee a super alignment, but if it's available it will delete
// about 3 layers(?) of the TLB tree for each read/write.
// Again the cost of faults may make this negligible gains, but hey, we gotta work
// what we gotta work with.
map_flags |= MAP_ALIGNED(21); //2^21 = 2mb use 2MB pages
#endif
io.mmap_base = (u8*)mmap(nullptr, io.mmap_size, PROT_READ, map_flags, io.mmap_fd, 0);
if (io.mmap_base == MAP_FAILED) {
close(io.mmap_fd);
io.mmap_fd = -1;
} else {
using namespace Common::Literals;
// For small files it is acceptable to use a full readahead
// See https://github.com/torvalds/linux/blob/e80d033851b3bc94c3d254ac66660ddd0a49d72c/include/linux/pagemap.h#L1392
if (u64(st.st_size) >= 256_MiB) {
posix_madvise(io.mmap_base, io.mmap_size, POSIX_MADV_RANDOM);
} else {
posix_madvise(io.mmap_base, io.mmap_size, POSIX_MADV_SEQUENTIAL);
}
}
}
return io.mmap_fd;
}
static void PlatformUnmap(IOFile& io) {
if (io.mmap_fd != -1) {
munmap(io.mmap_base, io.mmap_size);
close(io.mmap_fd);
io.mmap_fd = -1;
}
}
#elif defined(__APPLE__)
// NO IMPLEMENTATION YET
#else
static int PlatformMapReadOnly(IOFile& io, const wchar_t* path) {
io.file_handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, nullptr);
if (HANDLE(io.file_handle) != INVALID_HANDLE_VALUE) {
io.mapping_handle = CreateFileMappingW(HANDLE(io.file_handle), nullptr, PAGE_READONLY, 0, 0, nullptr);
if (io.mapping_handle) {
io.mmap_base = (u8*)MapViewOfFile(HANDLE(io.mapping_handle), FILE_MAP_READ, 0, 0, 0);
if (io.mmap_base) {
_LARGE_INTEGER pvalue;
GetFileSizeEx(io.file_handle, &pvalue);
io.mmap_size = uint32_t(pvalue.QuadPart);
} else {
CloseHandle(io.mapping_handle);
CloseHandle(io.file_handle);
return -1;
}
} else {
CloseHandle(io.file_handle);
return -1;
}
}
return 0;
}
static void PlatformUnmap(IOFile& io) {
if(io.mapping_handle) {
if(io.mmap_base)
UnmapViewOfFile(HANDLE(io.mmap_base));
CloseHandle(HANDLE(io.mapping_handle));
}
if(io.file_handle != INVALID_HANDLE_VALUE)
CloseHandle(HANDLE(io.file_handle));
}
#endif
void IOFile::Open(const fs::path& path, FileAccessMode mode, FileType type, FileShareFlag flag) { void IOFile::Open(const fs::path& path, FileAccessMode mode, FileType type, FileShareFlag flag) {
Close(); Close();
file_path = path; file_path = path;
file_access_mode = mode; file_access_mode = mode;
file_type = type; file_type = type;
errno = 0; errno = 0;
#ifdef _WIN32 #ifdef _WIN32
// TODO: this probably can use better logic but oh well I'm not a windowser
file_handle = nullptr;
if (type == FileType::BinaryFile && mode == FileAccessMode::Read) {
if (PlatformMapReadOnly(*this, path.c_str()) == -1) {
LOG_ERROR(Common_Filesystem, "Error mmap'ing file"); //: {}", path.c_str());
}
}
if (file_handle == nullptr) {
if (flag != FileShareFlag::ShareNone) { if (flag != FileShareFlag::ShareNone) {
file = _wfsopen(path.c_str(), AccessModeToWStr(mode, type), ToWindowsFileShareFlag(flag)); file = _wfsopen(path.c_str(), AccessModeToWStr(mode, type), ToWindowsFileShareFlag(flag));
} else { } else {
_wfopen_s(&file, path.c_str(), AccessModeToWStr(mode, type)); _wfopen_s(&file, path.c_str(), AccessModeToWStr(mode, type));
} }
}
#elif __ANDROID__ #elif __ANDROID__
if (Android::IsContentUri(path)) { if (Android::IsContentUri(path)) {
ASSERT_MSG(mode == FileAccessMode::Read, "Content URI file access is for read-only!"); ASSERT_MSG(mode == FileAccessMode::Read, "Content URI file access is for read-only!");
const auto fd = Android::OpenContentUri(path, Android::OpenMode::Read); if (PlatformMapReadOnly(*this, path.c_str()) == -1) {
LOG_ERROR(Common_Filesystem, "Error mmap'ing file: {}", path.c_str());
int const fd = Android::OpenContentUri(path, Android::OpenMode::Read);
if (fd != -1) { if (fd != -1) {
file = fdopen(fd, "r"); file = fdopen(fd, "r");
const auto error_num = errno; if (errno != 0 && file == nullptr)
if (error_num != 0 && file == nullptr) { LOG_ERROR(Common_Filesystem, "Error opening file: {}, error: {}", path.c_str(), strerror(errno));
LOG_ERROR(Common_Filesystem, "Error opening file: {}, error: {}", path.c_str(),
strerror(error_num));
}
} else { } else {
LOG_ERROR(Common_Filesystem, "Error opening file: {}", path.c_str()); LOG_ERROR(Common_Filesystem, "Error opening file: {}", path.c_str());
} }
}
} else { } else {
file = std::fopen(path.c_str(), AccessModeToStr(mode, type)); file = std::fopen(path.c_str(), AccessModeToStr(mode, type));
} }
#elif defined(__HAIKU__) || defined(__managarm__) || defined(__OPENORBIS__) || defined(__APPLE__)
file = std::fopen(path.c_str(), AccessModeToStr(mode, type));
#elif defined(__unix__)
if (type == FileType::BinaryFile && mode == FileAccessMode::Read) {
if (PlatformMapReadOnly(*this, path.c_str()) == -1) {
LOG_ERROR(Common_Filesystem, "Error mmap'ing file: {}", path.c_str());
}
}
if (mmap_fd == -1) {
file = std::fopen(path.c_str(), AccessModeToStr(mode, type)); // mmap(2) failed or simply we can't use it
}
#else #else
// Some other fancy OS (ahem fucking Darwin/Mac OSX)
file = std::fopen(path.c_str(), AccessModeToStr(mode, type)); file = std::fopen(path.c_str(), AccessModeToStr(mode, type));
#endif #endif
if (!IsOpen()) { if (!IsOpen()) {
const auto ec = std::error_code{errno, std::generic_category()}; const auto ec = std::error_code{errno, std::generic_category()};
LOG_ERROR(Common_Filesystem, "Failed to open the file at path={}, ec_message={}", LOG_ERROR(Common_Filesystem, "Failed to open the file at path={}, ec_message={}",
@@ -288,25 +415,25 @@ void IOFile::Open(const fs::path& path, FileAccessMode mode, FileType type, File
} }
void IOFile::Close() { void IOFile::Close() {
if (!IsOpen()) { #if defined(__APPLE__)
return; // NO IMPLEMENTATION YET
} #else
PlatformUnmap(*this);
#endif
if (file) {
errno = 0; errno = 0;
const auto close_result = std::fclose(file) == 0; const auto close_result = std::fclose(file) == 0;
if (!close_result) { if (!close_result) {
const auto ec = std::error_code{errno, std::generic_category()}; const auto ec = std::error_code{errno, std::generic_category()};
LOG_ERROR(Common_Filesystem, "Failed to close the file at path={}, ec_message={}", LOG_ERROR(Common_Filesystem, "Failed to close the file at path={}, ec_message={}",
PathToUTF8String(file_path), ec.message()); PathToUTF8String(file_path), ec.message());
} }
file = nullptr; file = nullptr;
}
} }
bool IOFile::IsOpen() const { bool IOFile::IsOpen() const {
return file != nullptr; return file != nullptr || IsMappedFile();
} }
std::string IOFile::ReadString(size_t length) const { std::string IOFile::ReadString(size_t length) const {
@@ -323,80 +450,65 @@ size_t IOFile::WriteString(std::span<const char> string) const {
} }
bool IOFile::Flush() const { bool IOFile::Flush() const {
if (!IsOpen()) { ASSERT(!IsMappedFile());
return false; if (file) {
}
errno = 0; errno = 0;
auto const flush_result = std::fflush(file) == 0;
#ifdef _WIN32
const auto flush_result = std::fflush(file) == 0;
#else
const auto flush_result = std::fflush(file) == 0;
#endif
if (!flush_result) { if (!flush_result) {
const auto ec = std::error_code{errno, std::generic_category()}; const auto ec = std::error_code{errno, std::generic_category()};
LOG_ERROR(Common_Filesystem, "Failed to flush the file at path={}, ec_message={}", LOG_ERROR(Common_Filesystem, "Failed to flush the file at path={}, ec_message={}",
PathToUTF8String(file_path), ec.message()); PathToUTF8String(file_path), ec.message());
} }
return flush_result; return flush_result;
}
return false;
} }
bool IOFile::Commit() const { bool IOFile::Commit() const {
if (!IsOpen()) { ASSERT(!IsMappedFile());
return false; if (file) {
}
errno = 0; errno = 0;
#ifdef _WIN32 #ifdef _WIN32
const auto commit_result = std::fflush(file) == 0 && _commit(fileno(file)) == 0; const auto commit_result = std::fflush(file) == 0 && _commit(fileno(file)) == 0;
#else #else
const auto commit_result = std::fflush(file) == 0 && fsync(fileno(file)) == 0; const auto commit_result = std::fflush(file) == 0 && fsync(fileno(file)) == 0;
#endif #endif
if (!commit_result) { if (!commit_result) {
const auto ec = std::error_code{errno, std::generic_category()}; const auto ec = std::error_code{errno, std::generic_category()};
LOG_ERROR(Common_Filesystem, "Failed to commit the file at path={}, ec_message={}", LOG_ERROR(Common_Filesystem, "Failed to commit the file at path={}, ec_message={}",
PathToUTF8String(file_path), ec.message()); PathToUTF8String(file_path), ec.message());
} }
return commit_result; return commit_result;
}
return false;
} }
bool IOFile::SetSize(u64 size) const { bool IOFile::SetSize(u64 size) const {
if (!IsOpen()) { ASSERT(!IsMappedFile());
return false; if (file) {
}
errno = 0; errno = 0;
#ifdef _WIN32 #ifdef _WIN32
const auto set_size_result = _chsize_s(fileno(file), static_cast<s64>(size)) == 0; const auto set_size_result = _chsize_s(fileno(file), s64(size)) == 0;
#else #else
const auto set_size_result = ftruncate(fileno(file), static_cast<s64>(size)) == 0; const auto set_size_result = ftruncate(fileno(file), s64(size)) == 0;
#endif #endif
if (!set_size_result) { if (!set_size_result) {
const auto ec = std::error_code{errno, std::generic_category()}; const auto ec = std::error_code{errno, std::generic_category()};
LOG_ERROR(Common_Filesystem, "Failed to resize the file at path={}, size={}, ec_message={}", LOG_ERROR(Common_Filesystem, "Failed to resize the file at path={}, size={}, ec_message={}",
PathToUTF8String(file_path), size, ec.message()); PathToUTF8String(file_path), size, ec.message());
} }
return set_size_result; return set_size_result;
}
return false;
} }
u64 IOFile::GetSize() const { u64 IOFile::GetSize() const {
if (!IsOpen()) { if (IsMappedFile())
return 0; return mmap_size;
} if (file) {
// Flush any unwritten buffered data into the file prior to retrieving the file mmap_size.
// Flush any unwritten buffered data into the file prior to retrieving the file size.
std::fflush(file); std::fflush(file);
#if __ANDROID__
#ifdef __ANDROID__
u64 file_size = 0; u64 file_size = 0;
if (Android::IsContentUri(file_path)) { if (Android::IsContentUri(file_path)) {
file_size = Android::GetSize(file_path); file_size = Android::GetSize(file_path);
@@ -406,54 +518,64 @@ u64 IOFile::GetSize() const {
file_size = fs::file_size(file_path, ec); file_size = fs::file_size(file_path, ec);
if (ec) { if (ec) {
LOG_ERROR(Common_Filesystem, LOG_ERROR(Common_Filesystem, "Failed to retrieve the file mmap_size of path={}, ec_message={}",
"Failed to retrieve the file size of path={}, ec_message={}",
PathToUTF8String(file_path), ec.message()); PathToUTF8String(file_path), ec.message());
return 0; return 0;
} }
} }
#else #else
std::error_code ec; std::error_code ec;
auto const file_size = fs::file_size(file_path, ec);
const auto file_size = fs::file_size(file_path, ec);
if (ec) { if (ec) {
LOG_ERROR(Common_Filesystem, "Failed to retrieve the file size of path={}, ec_message={}", LOG_ERROR(Common_Filesystem, "Failed to retrieve the file mmap_size of path={}, ec_message={}",
PathToUTF8String(file_path), ec.message()); PathToUTF8String(file_path), ec.message());
return 0; return 0;
} }
#endif #endif
return file_size; return file_size;
}
return 0;
} }
bool IOFile::Seek(s64 offset, SeekOrigin origin) const { bool IOFile::Seek(s64 offset, SeekOrigin origin) const {
if (!IsOpen()) { if (IsMappedFile()) {
return false; // fuck you to whoever made this method const
switch (origin) {
case SeekOrigin::SetOrigin:
mmap_offset = s64(offset);
break;
case SeekOrigin::CurrentPosition:
mmap_offset += s64(offset);
break;
case SeekOrigin::End:
mmap_offset = s64(mmap_size) + s64(offset);
break;
} }
return true;
}
if (file) {
errno = 0; errno = 0;
const auto seek_result = fseeko(file, offset, ToSeekOrigin(origin)) == 0; const auto seek_result = fseeko(file, offset, ToSeekOrigin(origin)) == 0;
if (!seek_result) { if (!seek_result) {
const auto ec = std::error_code{errno, std::generic_category()}; const auto ec = std::error_code{errno, std::generic_category()};
LOG_ERROR(Common_Filesystem, LOG_ERROR(Common_Filesystem, "Failed to seek the file at path={}, offset={}, origin={}, ec_message={}",
"Failed to seek the file at path={}, offset={}, origin={}, ec_message={}",
PathToUTF8String(file_path), offset, origin, ec.message()); PathToUTF8String(file_path), offset, origin, ec.message());
} }
return seek_result; return seek_result;
}
return false;
} }
s64 IOFile::Tell() const { s64 IOFile::Tell() const {
if (!IsOpen()) { if (IsMappedFile()) {
return 0; errno = 0;
} return s64(mmap_offset);
}
if (file) {
errno = 0; errno = 0;
return ftello(file); return ftello(file);
}
return 0;
} }
} // namespace Common::FS } // namespace Common::FS
+78 -70
View File
@@ -7,6 +7,7 @@
#pragma once #pragma once
#include <cstdio> #include <cstdio>
#include <cstring>
#include <filesystem> #include <filesystem>
#include <span> #include <span>
#include <type_traits> #include <type_traits>
@@ -24,12 +25,12 @@ enum class SeekOrigin {
}; };
/** /**
* Opens a file stream at path with the specified open mode. * Opens a file stream at path with the specified open mode.
* *
* @param file_stream Reference to file stream * @param file_stream Reference to file stream
* @param path Filesystem path * @param path Filesystem path
* @param open_mode File stream open mode * @param open_mode File stream open mode
*/ */
template <typename FileStream> template <typename FileStream>
void OpenFileStream(FileStream& file_stream, const std::filesystem::path& path, void OpenFileStream(FileStream& file_stream, const std::filesystem::path& path,
std::ios_base::openmode open_mode) { std::ios_base::openmode open_mode) {
@@ -48,14 +49,14 @@ void OpenFileStream(FileStream& file_stream, const Path& path, std::ios_base::op
#endif #endif
/** /**
* Reads an entire file at path and returns a string of the contents read from the file. * Reads an entire file at path and returns a string of the contents read from the file.
* If the filesystem object at path is not a regular file, this function returns an empty string. * If the filesystem object at path is not a regular file, this function returns an empty string.
* *
* @param path Filesystem path * @param path Filesystem path
* @param type File type * @param type File type
* *
* @returns A string of the contents read from the file. * @returns A string of the contents read from the file.
*/ */
[[nodiscard]] std::string ReadStringFromFile(const std::filesystem::path& path, FileType type); [[nodiscard]] std::string ReadStringFromFile(const std::filesystem::path& path, FileType type);
#ifdef _WIN32 #ifdef _WIN32
@@ -70,16 +71,16 @@ template <typename Path>
#endif #endif
/** /**
* Writes a string to a file at path and returns the number of characters successfully written. * Writes a string to a file at path and returns the number of characters successfully written.
* If a file already exists at path, its contents will be erased. * If a file already exists at path, its contents will be erased.
* If a file does not exist at path, it creates and opens a new empty file for writing. * If a file does not exist at path, it creates and opens a new empty file for writing.
* If the filesystem object at path exists and is not a regular file, this function returns 0. * If the filesystem object at path exists and is not a regular file, this function returns 0.
* *
* @param path Filesystem path * @param path Filesystem path
* @param type File type * @param type File type
* *
* @returns Number of characters successfully written. * @returns Number of characters successfully written.
*/ */
[[nodiscard]] size_t WriteStringToFile(const std::filesystem::path& path, FileType type, [[nodiscard]] size_t WriteStringToFile(const std::filesystem::path& path, FileType type,
std::string_view string); std::string_view string);
@@ -95,15 +96,15 @@ template <typename Path>
#endif #endif
/** /**
* Appends a string to a file at path and returns the number of characters successfully written. * Appends a string to a file at path and returns the number of characters successfully written.
* If a file does not exist at path, it creates and opens a new empty file for appending. * If a file does not exist at path, it creates and opens a new empty file for appending.
* If the filesystem object at path exists and is not a regular file, this function returns 0. * If the filesystem object at path exists and is not a regular file, this function returns 0.
* *
* @param path Filesystem path * @param path Filesystem path
* @param type File type * @param type File type
* *
* @returns Number of characters successfully written. * @returns Number of characters successfully written.
*/ */
[[nodiscard]] size_t AppendStringToFile(const std::filesystem::path& path, FileType type, [[nodiscard]] size_t AppendStringToFile(const std::filesystem::path& path, FileType type,
std::string_view string); std::string_view string);
@@ -186,19 +187,6 @@ public:
FileType type = FileType::BinaryFile, FileType type = FileType::BinaryFile,
FileShareFlag flag = FileShareFlag::ShareReadOnly); FileShareFlag flag = FileShareFlag::ShareReadOnly);
// #ifdef _WIN32
// template <typename Path>
// void Open(const Path& path, FileAccessMode mode, FileType type = FileType::BinaryFile,
// FileShareFlag flag = FileShareFlag::ShareReadOnly) {
// using ValueType = typename Path::value_type;
// if constexpr (IsChar<ValueType>) {
// Open(ToU8String(path), mode, type, flag);
// } else {
// Open(std::filesystem::path{path}, mode, type, flag);
// }
// }
// #endif
/// Closes the file if it is opened. /// Closes the file if it is opened.
void Close(); void Close();
@@ -228,8 +216,7 @@ public:
[[nodiscard]] size_t Read(T& data) const { [[nodiscard]] size_t Read(T& data) const {
if constexpr (IsContiguousContainer<T>) { if constexpr (IsContiguousContainer<T>) {
using ContiguousType = typename T::value_type; using ContiguousType = typename T::value_type;
static_assert(std::is_trivially_copyable_v<ContiguousType>, static_assert(std::is_trivially_copyable_v<ContiguousType>, "Data type must be trivially copyable.");
"Data type must be trivially copyable.");
return ReadSpan<ContiguousType>(data); return ReadSpan<ContiguousType>(data);
} else { } else {
return ReadObject(data) ? 1 : 0; return ReadObject(data) ? 1 : 0;
@@ -254,8 +241,7 @@ public:
[[nodiscard]] size_t Write(const T& data) const { [[nodiscard]] size_t Write(const T& data) const {
if constexpr (IsContiguousContainer<T>) { if constexpr (IsContiguousContainer<T>) {
using ContiguousType = typename T::value_type; using ContiguousType = typename T::value_type;
static_assert(std::is_trivially_copyable_v<ContiguousType>, static_assert(std::is_trivially_copyable_v<ContiguousType>, "Data type must be trivially copyable.");
"Data type must be trivially copyable.");
return WriteSpan<ContiguousType>(data); return WriteSpan<ContiguousType>(data);
} else { } else {
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable."); static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
@@ -282,10 +268,11 @@ public:
template <typename T> template <typename T>
requires std::is_trivially_copyable_v<T> requires std::is_trivially_copyable_v<T>
[[nodiscard]] size_t ReadSpan(std::span<T> data) const { [[nodiscard]] size_t ReadSpan(std::span<T> data) const {
if (!IsOpen()) { if (IsMappedFile()) {
return 0; std::memcpy(data.data(), mmap_base + mmap_offset, sizeof(T) * data.size());
return data.size();
} }
return std::fread(data.data(), sizeof(T), data.size(), file); return IsOpen() ? std::fread(data.data(), sizeof(T), data.size(), file) : 0;
} }
/** /**
@@ -306,12 +293,11 @@ public:
template <typename T> template <typename T>
[[nodiscard]] size_t WriteSpan(std::span<const T> data) const { [[nodiscard]] size_t WriteSpan(std::span<const T> data) const {
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable."); static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
if (IsMappedFile()) {
if (!IsOpen()) { std::memcpy(mmap_base + mmap_offset, data.data(), sizeof(T) * data.size());
return 0; return data.size();
} }
return IsOpen() ? std::fwrite(data.data(), sizeof(T), data.size(), file) : 0;
return std::fwrite(data.data(), sizeof(T), data.size(), file);
} }
/** /**
@@ -334,12 +320,15 @@ public:
[[nodiscard]] bool ReadObject(T& object) const { [[nodiscard]] bool ReadObject(T& object) const {
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable."); static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
static_assert(!std::is_pointer_v<T>, "T must not be a pointer to an object."); static_assert(!std::is_pointer_v<T>, "T must not be a pointer to an object.");
if (IsMappedFile()) {
if (!IsOpen()) { std::memcpy(&object, mmap_base + mmap_offset, sizeof(T));
return false; #ifdef _WIN32
return bool(sizeof(T));
#else
return sizeof(T);
#endif
} }
return IsOpen() ? std::fread(&object, sizeof(T), 1, file) == 1 : false;
return std::fread(&object, sizeof(T), 1, file) == 1;
} }
/** /**
@@ -361,12 +350,15 @@ public:
[[nodiscard]] bool WriteObject(const T& object) const { [[nodiscard]] bool WriteObject(const T& object) const {
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable."); static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
static_assert(!std::is_pointer_v<T>, "T must not be a pointer to an object."); static_assert(!std::is_pointer_v<T>, "T must not be a pointer to an object.");
if (IsMappedFile()) {
if (!IsOpen()) { std::memcpy(mmap_base + mmap_offset, &object, sizeof(T));
return false; #ifdef _WIN32
return sizeof(T) != 0;
#else
return sizeof(T);
#endif
} }
return IsOpen() ? std::fwrite(&object, sizeof(T), 1, file) == 1 : false;
return std::fwrite(&object, sizeof(T), 1, file) == 1;
} }
/** /**
@@ -449,12 +441,28 @@ public:
*/ */
[[nodiscard]] s64 Tell() const; [[nodiscard]] s64 Tell() const;
private: #ifdef _WIN32
inline bool IsMappedFile() const noexcept { return mapping_handle != nullptr; }
#else // POSIX
inline bool IsMappedFile() const noexcept { return mmap_fd != -1; }
#endif
std::filesystem::path file_path; std::filesystem::path file_path;
FileAccessMode file_access_mode{}; FileAccessMode file_access_mode{};
FileType file_type{}; FileType file_type{};
std::FILE* file = nullptr; std::FILE* file = nullptr;
// Any decent system should have mmap() for files
// Systems with artifical mmap() limitations should simply change the logic within file.cpp
// and reduce the threshold for which the mmap() is set to
#ifdef _WIN32
void *mapping_handle = nullptr;
void *file_handle = nullptr;
#else // POSIX
int mmap_fd = -1;
#endif
u8* mmap_base = nullptr;
size_t mmap_size = 0;
mutable s64 mmap_offset = 0; // fuck you
}; };
} // namespace Common::FS } // namespace Common::FS
+108 -6
View File
@@ -116,20 +116,122 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
} }
std::string UTF16ToUTF8(std::u16string_view input) { std::string UTF16ToUTF8(std::u16string_view input) {
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; std::string result;
return convert.to_bytes(input.data(), input.data() + input.size()); result.reserve(input.size() * 4);
for (size_t i = 0; i < input.size(); ++i) {
uint32_t code = input[i];
// Handle surrogate pairs
if (code >= 0xD800 && code <= 0xDBFF) {
if (i + 1 < input.size()) {
uint32_t low = input[i + 1];
if (low >= 0xDC00 && low <= 0xDFFF) {
code = ((code - 0xD800) << 10) + (low - 0xDC00) + 0x10000;
++i;
}
}
}
if (code <= 0x7F) {
result.push_back(char(code));
} else if (code <= 0x7FF) {
result.push_back(char(0xC0 | (code >> 6)));
result.push_back(char(0x80 | (code & 0x3F)));
} else if (code <= 0xFFFF) {
result.push_back(char(0xE0 | (code >> 12)));
result.push_back(char(0x80 | ((code >> 6) & 0x3F)));
result.push_back(char(0x80 | (code & 0x3F)));
} else {
result.push_back(char(0xF0 | (code >> 18)));
result.push_back(char(0x80 | ((code >> 12) & 0x3F)));
result.push_back(char(0x80 | ((code >> 6) & 0x3F)));
result.push_back(char(0x80 | (code & 0x3F)));
}
}
return result;
} }
std::u16string UTF8ToUTF16(std::string_view input) { std::u16string UTF8ToUTF16(std::string_view input) {
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert; std::u16string result;
return convert.from_bytes(input.data(), input.data() + input.size()); result.reserve(input.size() * 2);
for (size_t i = 0; i < input.size(); ) {
uint32_t code = 0;
unsigned char c = input[i];
size_t len = 0;
if ((c & 0x80) == 0) {
code = c;
len = 1;
} else if ((c & 0xE0) == 0xC0) {
code = c & 0x1F;
len = 2;
} else if ((c & 0xF0) == 0xE0) {
code = c & 0x0F;
len = 3;
} else if ((c & 0xF8) == 0xF0) {
code = c & 0x07;
len = 4;
} else {
++i;
continue;
}
if (i + len - 1 >= input.size())
break;
for (size_t j = 1; j <= len - 1; ++j) {
if ((input[i + j] & 0xC0) != 0x80) {
code = 0xFFFD;
break;
}
code = (code << 6) | (input[i + j] & 0x3F);
}
if (code <= 0xFFFF) {
result.push_back(char16_t(code));
} else {
code -= 0x10000;
result.push_back(char16_t(0xD800 + (code >> 10)));
result.push_back(char16_t(0xDC00 + (code & 0x3FF)));
}
i += len;
}
return result;
} }
std::u32string UTF8ToUTF32(std::string_view input) { std::u32string UTF8ToUTF32(std::string_view input) {
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert; std::u32string result;
return convert.from_bytes(input.data(), input.data() + input.size()); result.reserve(input.size());
for (size_t i = 0; i < input.size(); ) {
uint32_t code = 0;
unsigned char c = input[i];
size_t len = 0;
if ((c & 0x80) == 0) {
code = c;
len = 1;
} else if ((c & 0xE0) == 0xC0) {
code = c & 0x1F;
len = 2;
} else if ((c & 0xF0) == 0xE0) {
code = c & 0x0F;
len = 3;
} else if ((c & 0xF8) == 0xF0) {
code = c & 0x07;
len = 4;
} else {
++i;
continue;
}
if (i + len - 1 >= input.size())
break;
for (size_t j = 1; j <= len - 1; ++j) {
if ((input[i + j] & 0xC0) != 0x80) {
code = 0xFFFD;
break;
}
code = (code << 6) | (input[i + j] & 0x3F);
}
result.push_back(code);
i += len;
}
return result;
} }
#ifdef _WIN32 #ifdef _WIN32
static std::wstring CPToUTF16(u32 code_page, std::string_view input) { static std::wstring CPToUTF16(u32 code_page, std::string_view input) {
const auto size = const auto size =
@@ -13,7 +13,7 @@
#include <winsock2.h> #include <winsock2.h>
#include <windows.h> #include <windows.h>
#include <iphlpapi.h> #include <iphlpapi.h>
#elif defined(__linux__) || defined(__ANDROID__) #elif defined(__linux__) || defined(__ANDROID__) || defined(__APPLE__)
#include <cerrno> #include <cerrno>
#include <ifaddrs.h> #include <ifaddrs.h>
#include <net/if.h> #include <net/if.h>
@@ -33,6 +33,13 @@
#include <netinet/if_ether.h> #include <netinet/if_ether.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
// Darwin doesn't define this for some very odd reason
// See https://stackoverflow.com/questions/5390164/getting-routing-table-on-macosx-programmatically
#ifndef SA_SIZE
#define SA_SIZE(sa) \
((!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? sizeof(long) \
: 1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) )
#endif
#endif #endif
#include "common/common_types.h" #include "common/common_types.h"
@@ -104,7 +111,7 @@ std::vector<Network::NetworkInterface> GetAvailableNetworkInterfaces() {
#else #else
std::vector<Network::NetworkInterface> GetAvailableNetworkInterfaces() { std::vector<Network::NetworkInterface> GetAvailableNetworkInterfaces() {
#if defined(__ANDROID__) || defined(__linux__) #if defined(__ANDROID__) || defined(__linux__) || defined(__APPLE__) || defined(__managarm__)
struct ifaddrs* ifaddr = nullptr; struct ifaddrs* ifaddr = nullptr;
if (getifaddrs(&ifaddr) != 0) { if (getifaddrs(&ifaddr) != 0) {
LOG_ERROR(Network, "getifaddrs: {}", std::strerror(errno)); LOG_ERROR(Network, "getifaddrs: {}", std::strerror(errno));
@@ -119,8 +126,9 @@ std::vector<Network::NetworkInterface> GetAvailableNetworkInterfaces() {
u32 flags; u32 flags;
}; };
std::vector<RoutingEntry> routes{}; std::vector<RoutingEntry> routes{};
#ifdef __ANDROID__ #if defined(__ANDROID__) || defined(__APPLE__)
// Even through Linux based, we can't reliably obtain routing information from there :( // Even through Linux based, we can't reliably obtain routing information from there :(
// macOS not Linux based and would murder us if we attempt to access /proc
#else #else
if (std::ifstream file("/proc/net/route"); file.is_open()) { if (std::ifstream file("/proc/net/route"); file.is_open()) {
file.ignore((std::numeric_limits<std::streamsize>::max)(), '\n'); //ignore header file.ignore((std::numeric_limits<std::streamsize>::max)(), '\n'); //ignore header
@@ -138,7 +146,10 @@ std::vector<Network::NetworkInterface> GetAvailableNetworkInterfaces() {
std::vector<Network::NetworkInterface> ifaces; std::vector<Network::NetworkInterface> ifaces;
for (auto ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) { for (auto ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == nullptr || ifa->ifa_netmask == nullptr /* Have a netmask and address */ if (ifa->ifa_addr == nullptr || ifa->ifa_netmask == nullptr /* Have a netmask and address */
// Apple hates human beings so lets pretend all families are fine
#if !defined(__APPLE__) && !defined(__managarm__)
|| ifa->ifa_addr->sa_family != AF_INET /* Must be of kind AF_INET */ || ifa->ifa_addr->sa_family != AF_INET /* Must be of kind AF_INET */
#endif
|| (ifa->ifa_flags & IFF_UP) == 0 || (ifa->ifa_flags & IFF_LOOPBACK) != 0) /* Not loopback */ || (ifa->ifa_flags & IFF_UP) == 0 || (ifa->ifa_flags & IFF_LOOPBACK) != 0) /* Not loopback */
continue; continue;
// Just use 0 as the gateway address if not found OR routes are empty :) // Just use 0 as the gateway address if not found OR routes are empty :)
@@ -158,7 +169,7 @@ std::vector<Network::NetworkInterface> GetAvailableNetworkInterfaces() {
} }
freeifaddrs(ifaddr); freeifaddrs(ifaddr);
return ifaces; return ifaces;
#elif defined(__FreeBSD__) #elif defined(__FreeBSD__) || defined(__APPLE__)
std::vector<Network::NetworkInterface> ifaces; std::vector<Network::NetworkInterface> ifaces;
int fd = ::socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC); int fd = ::socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
if (fd < 0) { if (fd < 0) {
@@ -198,11 +209,15 @@ std::vector<Network::NetworkInterface> GetAvailableNetworkInterfaces() {
if (msglen == 0 || msglen < SA_SIZE(sa)) if (msglen == 0 || msglen < SA_SIZE(sa))
break; break;
if (i == RTA_NETMASK && sa->sa_family == AF_LINK) { if (i == RTA_NETMASK && sa->sa_family == AF_LINK) {
size_t namelen = 0;
struct sockaddr_dl const* sdl = reinterpret_cast<struct sockaddr_dl const*>(sa); struct sockaddr_dl const* sdl = reinterpret_cast<struct sockaddr_dl const*>(sa);
#if defined(__FreeBSD__) && __FreeBSD__ < 15
iface.name = std::string{::link_ntoa(sdl)};
#else
size_t namelen = 0;
::link_ntoa_r(sdl, nullptr, &namelen); ::link_ntoa_r(sdl, nullptr, &namelen);
iface.name = std::string(namelen, ' '); iface.name = std::string(namelen, ' ');
::link_ntoa_r(sdl, iface.name.data(), &namelen); ::link_ntoa_r(sdl, iface.name.data(), &namelen);
#endif
std::memcpy(&iface.ip_address, sa, sizeof(struct sockaddr_in)); std::memcpy(&iface.ip_address, sa, sizeof(struct sockaddr_in));
} }
msglen -= SA_SIZE(sa); msglen -= SA_SIZE(sa);
+13 -66
View File
@@ -11,34 +11,15 @@ set(dynarmic_VERSION ${dynarmic_VERSION_MAJOR}.${dynarmic_VERSION_MINOR}.${dynar
project(dynarmic LANGUAGES C CXX ASM VERSION ${dynarmic_VERSION}) project(dynarmic LANGUAGES C CXX ASM VERSION ${dynarmic_VERSION})
# Determine if we're built as a subproject (using add_subdirectory)
# or if this is the master project.
set(MASTER_PROJECT OFF)
if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(MASTER_PROJECT ON)
endif()
if (MASTER_PROJECT)
include(CTest)
endif()
# Dynarmic project options
option(DYNARMIC_ENABLE_CPU_FEATURE_DETECTION "Turning this off causes dynarmic to assume the host CPU doesn't support anything later than SSE3" ON)
if (OPENBSD OR DRAGONFLY OR NETBSD) if (OPENBSD OR DRAGONFLY OR NETBSD)
set(REQUIRE_WX ON) set(REQUIRE_WX ON)
else() else()
set(REQUIRE_WX OFF) set(REQUIRE_WX OFF)
endif() endif()
option(DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT "Enables support for systems that require W^X" ${REQUIRE_WX}) option(DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT "Enables support for systems that require W^X" ${REQUIRE_WX})
option(DYNARMIC_IGNORE_ASSERTS "Ignore asserts" ON)
option(DYNARMIC_TESTS_USE_UNICORN "Enable fuzzing tests against unicorn" OFF) option(DYNARMIC_TESTS_USE_UNICORN "Enable fuzzing tests against unicorn" OFF)
CMAKE_DEPENDENT_OPTION(DYNARMIC_USE_LLVM "Support disassembly of jitted x86_64 code using LLVM" OFF "NOT YUZU_DISABLE_LLVM" OFF) CMAKE_DEPENDENT_OPTION(DYNARMIC_USE_LLVM "Support disassembly of jitted x86_64 code using LLVM" OFF "NOT YUZU_DISABLE_LLVM" OFF)
option(DYNARMIC_INSTALL "Install dynarmic headers and CMake files" OFF)
option(DYNARMIC_USE_BUNDLED_EXTERNALS "Use all bundled externals (useful when e.g. cross-compiling)" OFF)
# Set hard requirements for C++ # Set hard requirements for C++
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
@@ -88,7 +69,7 @@ if (MSVC)
-Wno-missing-braces) -Wno-missing-braces)
endif() endif()
else() else()
set(DYNARMIC_CXX_FLAGS list(APPEND DYNARMIC_CXX_FLAGS
-Wall -Wall
-Wextra -Wextra
-Wcast-qual -Wcast-qual
@@ -103,37 +84,35 @@ else()
# to Address& after first checking isMEM(), and that code is inlined in a situation where # to Address& after first checking isMEM(), and that code is inlined in a situation where
# GCC knows that the variable is actually a Reg64. isMEM() will never return true for a # GCC knows that the variable is actually a Reg64. isMEM() will never return true for a
# Reg64, but GCC doesn't know that. # Reg64, but GCC doesn't know that.
list(APPEND DYNARMIC_CXX_FLAGS -Wno-array-bounds) list(APPEND DYNARMIC_CXX_FLAGS
list(APPEND DYNARMIC_CXX_FLAGS -Wstack-usage=4096) -Wno-array-bounds
-Wstack-usage=4096)
endif() endif()
if (CXX_CLANG) if (CXX_CLANG)
list(APPEND DYNARMIC_CXX_FLAGS
# Bracket depth determines maximum size of a fold expression in Clang since 9c9974c3ccb6. # Bracket depth determines maximum size of a fold expression in Clang since 9c9974c3ccb6.
# And this in turns limits the size of a std::array. # And this in turns limits the size of a std::array.
list(APPEND DYNARMIC_CXX_FLAGS -fbracket-depth=1024) -fbracket-depth=1024
# Clang mistakenly blames CMake for using unused arguments during compilation # Clang mistakenly blames CMake for using unused arguments during compilation
list(APPEND DYNARMIC_CXX_FLAGS -Wno-unused-command-line-argument) -Wno-unused-command-line-argument)
endif() endif()
endif() endif()
if (NOT Boost_FOUND) if (NOT Boost_FOUND)
find_package(Boost 1.57 REQUIRED) find_package(Boost 1.57 REQUIRED)
endif() endif()
find_package(fmt 8 CONFIG) find_package(fmt 8 CONFIG)
if ("arm64" IN_LIST ARCHITECTURE OR DYNARMIC_TESTS) if (ARCHITECTURE_arm64)
find_package(oaknut 2.0.1 CONFIG) find_package(oaknut 2.0.1 CONFIG)
endif() endif()
if (ARCHITECTURE_riscv64)
if ("riscv64" IN_LIST ARCHITECTURE)
find_package(biscuit 0.9.1 REQUIRED) find_package(biscuit 0.9.1 REQUIRED)
endif() endif()
if (ARCHITECTURE_loongarch64)
if ("loongarch64" IN_LIST ARCHITECTURE)
find_package(lagoon REQUIRED) find_package(lagoon REQUIRED)
endif() endif()
if (ARCHITECTURE_x86_64)
if ("x86_64" IN_LIST ARCHITECTURE)
find_package(xbyak 7 CONFIG) find_package(xbyak 7 CONFIG)
endif() endif()
@@ -142,44 +121,12 @@ if (DYNARMIC_USE_LLVM)
separate_arguments(LLVM_DEFINITIONS) separate_arguments(LLVM_DEFINITIONS)
endif() endif()
# Dynarmic project files
add_subdirectory(src/dynarmic)
if (DYNARMIC_TESTS) if (DYNARMIC_TESTS)
find_package(Catch2 3 CONFIG) find_package(Catch2 3 CONFIG)
if (DYNARMIC_TESTS_USE_UNICORN) if (DYNARMIC_TESTS_USE_UNICORN)
find_package(Unicorn REQUIRED) find_package(Unicorn REQUIRED)
endif() endif()
endif()
# Dynarmic project files
add_subdirectory(src/dynarmic)
if (DYNARMIC_TESTS)
add_subdirectory(tests) add_subdirectory(tests)
endif() endif()
#
# Install
#
if (DYNARMIC_INSTALL)
include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
install(TARGETS dynarmic EXPORT dynarmicTargets)
install(EXPORT dynarmicTargets
NAMESPACE dynarmic::
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/dynarmic"
)
configure_package_config_file(CMakeModules/dynarmicConfig.cmake.in
dynarmicConfig.cmake
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/dynarmic"
)
write_basic_package_version_file(dynarmicConfigVersion.cmake
COMPATIBILITY SameMajorVersion
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/dynarmicConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/dynarmicConfigVersion.cmake"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/dynarmic"
)
install(DIRECTORY src/dynarmic TYPE INCLUDE FILES_MATCHING PATTERN "*.h")
endif()
@@ -1,29 +0,0 @@
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
function(target_architecture_specific_sources project arch)
if (NOT MULTIARCH_BUILD)
target_sources("${project}" PRIVATE ${ARGN})
return()
endif()
foreach(input_file IN LISTS ARGN)
if(input_file MATCHES ".cpp$")
if(NOT IS_ABSOLUTE ${input_file})
set(input_file "${CMAKE_CURRENT_SOURCE_DIR}/${input_file}")
endif()
set(output_file "${CMAKE_CURRENT_BINARY_DIR}/arch_gen/${input_file}")
add_custom_command(
OUTPUT "${output_file}"
COMMAND ${CMAKE_COMMAND} "-Darch=${arch}"
"-Dinput_file=${input_file}"
"-Doutput_file=${output_file}"
-P "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/impl/TargetArchitectureSpecificSourcesWrapFile.cmake"
DEPENDS "${input_file}"
VERBATIM
)
target_sources(${project} PRIVATE "${output_file}")
endif()
endforeach()
endfunction()
@@ -1,31 +0,0 @@
@PACKAGE_INIT@
include(CMakeFindDependencyMacro)
set(ARCHITECTURE "@ARCHITECTURE@")
if (NOT @BUILD_SHARED_LIBS@)
find_dependency(Boost 1.57)
find_dependency(fmt 9)
find_dependency(mcl 0.1.12 EXACT)
if ("arm64" IN_LIST ARCHITECTURE)
find_dependency(oaknut 2.0.1)
endif()
if ("riscv" IN_LIST ARCHITECTURE)
find_dependency(biscuit 0.9.1)
endif()
if ("x86_64" IN_LIST ARCHITECTURE)
find_dependency(xbyak 7)
endif()
if (@DYNARMIC_USE_LLVM@)
find_dependency(LLVM)
endif()
endif()
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
check_required_components(@PROJECT_NAME@)
@@ -1,6 +0,0 @@
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
string(TOUPPER "${arch}" arch)
file(READ "${input_file}" f_contents)
file(WRITE "${output_file}" "#if defined(ARCHITECTURE_${arch})\n${f_contents}\n#endif\n")
+6 -14
View File
@@ -1,7 +1,5 @@
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project # SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
include(TargetArchitectureSpecificSources)
add_library(dynarmic STATIC add_library(dynarmic STATIC
mcl/bit.hpp mcl/bit.hpp
mcl/function_info.hpp mcl/function_info.hpp
@@ -135,7 +133,7 @@ add_library(dynarmic STATIC
interface/A64/config.h interface/A64/config.h
) )
if ("x86_64" IN_LIST ARCHITECTURE) if (ARCHITECTURE_x86_64)
# Newer versions of xbyak (>= 7.25.0) have stricter checks that currently # Newer versions of xbyak (>= 7.25.0) have stricter checks that currently
# fail in dynarmic # fail in dynarmic
target_compile_definitions(dynarmic PRIVATE XBYAK_STRICT_CHECK_MEM_REG_SIZE=0) target_compile_definitions(dynarmic PRIVATE XBYAK_STRICT_CHECK_MEM_REG_SIZE=0)
@@ -143,7 +141,7 @@ if ("x86_64" IN_LIST ARCHITECTURE)
target_compile_definitions(dynarmic PRIVATE XBYAK_OLD_DISP_CHECK=1) target_compile_definitions(dynarmic PRIVATE XBYAK_OLD_DISP_CHECK=1)
target_link_libraries(dynarmic PRIVATE xbyak::xbyak) target_link_libraries(dynarmic PRIVATE xbyak::xbyak)
target_architecture_specific_sources(dynarmic "x86_64" target_sources(dynarmic PRIVATE
backend/x64/abi.cpp backend/x64/abi.cpp
backend/x64/abi.h backend/x64/abi.h
backend/x64/block_of_code.cpp backend/x64/block_of_code.cpp
@@ -201,10 +199,10 @@ if ("x86_64" IN_LIST ARCHITECTURE)
) )
endif() endif()
if ("arm64" IN_LIST ARCHITECTURE) if (ARCHITECTURE_arm64)
target_link_libraries(dynarmic PRIVATE merry::oaknut) target_link_libraries(dynarmic PRIVATE merry::oaknut)
target_architecture_specific_sources(dynarmic "arm64" target_sources(dynarmic PRIVATE
backend/arm64/a32_jitstate.cpp backend/arm64/a32_jitstate.cpp
backend/arm64/a32_jitstate.h backend/arm64/a32_jitstate.h
backend/arm64/a64_jitstate.h backend/arm64/a64_jitstate.h
@@ -255,7 +253,7 @@ if ("arm64" IN_LIST ARCHITECTURE)
) )
endif() endif()
if ("riscv64" IN_LIST ARCHITECTURE) if (ARCHITECTURE_riscv64)
target_link_libraries(dynarmic PRIVATE biscuit::biscuit) target_link_libraries(dynarmic PRIVATE biscuit::biscuit)
target_sources(dynarmic PRIVATE target_sources(dynarmic PRIVATE
@@ -295,7 +293,7 @@ if ("riscv64" IN_LIST ARCHITECTURE)
message(WARNING "TODO: Incomplete frontend for this host architecture") message(WARNING "TODO: Incomplete frontend for this host architecture")
endif() endif()
if ("loongarch64" IN_LIST ARCHITECTURE) if (ARCHITECTURE_loongarch64)
target_link_libraries(dynarmic PRIVATE lagoon::lagoon) target_link_libraries(dynarmic PRIVATE lagoon::lagoon)
target_sources(dynarmic PRIVATE target_sources(dynarmic PRIVATE
@@ -400,15 +398,9 @@ if (DYNARMIC_USE_LLVM)
target_compile_definitions(dynarmic PRIVATE DYNARMIC_USE_LLVM=1 ${LLVM_DEFINITIONS}) target_compile_definitions(dynarmic PRIVATE DYNARMIC_USE_LLVM=1 ${LLVM_DEFINITIONS})
llvm_config(dynarmic USE_SHARED armdesc armdisassembler aarch64desc aarch64disassembler x86desc x86disassembler) llvm_config(dynarmic USE_SHARED armdesc armdisassembler aarch64desc aarch64disassembler x86desc x86disassembler)
endif() endif()
if (DYNARMIC_ENABLE_CPU_FEATURE_DETECTION)
target_compile_definitions(dynarmic PRIVATE DYNARMIC_ENABLE_CPU_FEATURE_DETECTION=1)
endif()
if (DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT) if (DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT)
target_compile_definitions(dynarmic PRIVATE DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT=1) target_compile_definitions(dynarmic PRIVATE DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT=1)
endif() endif()
if (DYNARMIC_IGNORE_ASSERTS)
target_compile_definitions(dynarmic PRIVATE MCL_IGNORE_ASSERTS=1)
endif()
if (CMAKE_SYSTEM_NAME STREQUAL "Windows") if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
target_compile_definitions(dynarmic PRIVATE FMT_USE_WINDOWS_H=0) target_compile_definitions(dynarmic PRIVATE FMT_USE_WINDOWS_H=0)
endif() endif()
@@ -201,7 +201,7 @@ A32AddressSpace::A32AddressSpace(const A32::UserConfig& conf)
void A32AddressSpace::GenerateIR(IR::Block& ir_block, IR::LocationDescriptor descriptor) const { void A32AddressSpace::GenerateIR(IR::Block& ir_block, IR::LocationDescriptor descriptor) const {
ir_block.Reset(descriptor); ir_block.Reset(descriptor);
A32::Translate(ir_block, A32::LocationDescriptor{descriptor}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions}); A32::Translate(ir_block, A32::LocationDescriptor{descriptor}, conf);
Optimization::Optimize(ir_block, conf, {}); Optimization::Optimize(ir_block, conf, {});
} }
@@ -366,8 +366,7 @@ A64AddressSpace::A64AddressSpace(const A64::UserConfig& conf)
void A64AddressSpace::GenerateIR(IR::Block& ir_block, IR::LocationDescriptor descriptor) const { void A64AddressSpace::GenerateIR(IR::Block& ir_block, IR::LocationDescriptor descriptor) const {
ir_block.Reset(descriptor); ir_block.Reset(descriptor);
const auto get_code = [this](u64 vaddr) { return conf.callbacks->MemoryReadCode(vaddr); }; A64::Translate(ir_block, A64::LocationDescriptor{descriptor}, conf);
A64::Translate(ir_block, A64::LocationDescriptor{descriptor}, get_code, {conf.define_unpredictable_behaviour, conf.wall_clock_cntpct});
Optimization::Optimize(ir_block, conf, {}); Optimization::Optimize(ir_block, conf, {});
} }
@@ -21,7 +21,7 @@ A32AddressSpace::A32AddressSpace(const A32::UserConfig& conf)
} }
void A32AddressSpace::GenerateIR(IR::Block& ir_block, IR::LocationDescriptor descriptor) const { void A32AddressSpace::GenerateIR(IR::Block& ir_block, IR::LocationDescriptor descriptor) const {
A32::Translate(ir_block, A32::LocationDescriptor{descriptor}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions}); A32::Translate(ir_block, A32::LocationDescriptor{descriptor}, conf);
Optimization::Optimize(ir_block, conf, {.sha256 = true}); Optimization::Optimize(ir_block, conf, {.sha256 = true});
} }
@@ -27,7 +27,7 @@ A32AddressSpace::A32AddressSpace(const A32::UserConfig& conf)
} }
void A32AddressSpace::GenerateIR(IR::Block& ir_block, IR::LocationDescriptor descriptor) const { void A32AddressSpace::GenerateIR(IR::Block& ir_block, IR::LocationDescriptor descriptor) const {
A32::Translate(ir_block, A32::LocationDescriptor{descriptor}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions}); A32::Translate(ir_block, A32::LocationDescriptor{descriptor}, conf);
Optimization::Optimize(ir_block, conf, {}); Optimization::Optimize(ir_block, conf, {});
} }
@@ -197,15 +197,15 @@ void EmitA32Terminal(biscuit::Assembler& as, EmitContext& ctx, IR::Term::CheckHa
void EmitA32LeafTerminal(biscuit::Assembler& as, EmitContext& ctx, IR::Term::LeafTerminal terminal, IR::LocationDescriptor initial_location, bool is_single_step) { void EmitA32LeafTerminal(biscuit::Assembler& as, EmitContext& ctx, IR::Term::LeafTerminal terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
if (auto const x = std::get_if<IR::Term::ReturnToDispatch>(&terminal)) if (auto const x = std::get_if<IR::Term::ReturnToDispatch>(&terminal))
return EmitA32LeafTerminal(as, ctx, *x, initial_location, is_single_step); return EmitA32Terminal(as, ctx, *x, initial_location, is_single_step);
if (auto const x = std::get_if<IR::Term::LinkBlock>(&terminal)) if (auto const x = std::get_if<IR::Term::LinkBlock>(&terminal))
return EmitA32LeafTerminal(as, ctx, *x, initial_location, is_single_step); return EmitA32Terminal(as, ctx, *x, initial_location, is_single_step);
if (auto const x = std::get_if<IR::Term::LinkBlockFast>(&terminal)) if (auto const x = std::get_if<IR::Term::LinkBlockFast>(&terminal))
return EmitA32LeafTerminal(as, ctx, *x, initial_location, is_single_step); return EmitA32Terminal(as, ctx, *x, initial_location, is_single_step);
if (auto const x = std::get_if<IR::Term::PopRSBHint>(&terminal)) if (auto const x = std::get_if<IR::Term::PopRSBHint>(&terminal))
return EmitA32LeafTerminal(as, ctx, *x, initial_location, is_single_step); return EmitA32Terminal(as, ctx, *x, initial_location, is_single_step);
if (auto const x = std::get_if<IR::Term::FastDispatchHint>(&terminal)) if (auto const x = std::get_if<IR::Term::FastDispatchHint>(&terminal))
return EmitA32LeafTerminal(as, ctx, *x, initial_location, is_single_step); return EmitA32Terminal(as, ctx, *x, initial_location, is_single_step);
UNREACHABLE(); UNREACHABLE();
} }
@@ -202,7 +202,7 @@ private:
// LocationDescriptor ctor() does important ops (like tflags) do not skip // LocationDescriptor ctor() does important ops (like tflags) do not skip
auto const arch_descriptor = A32::LocationDescriptor{descriptor}; auto const arch_descriptor = A32::LocationDescriptor{descriptor};
ir_block.Reset(arch_descriptor); ir_block.Reset(arch_descriptor);
A32::Translate(ir_block, arch_descriptor, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions}); A32::Translate(ir_block, arch_descriptor, conf);
Optimization::Optimize(ir_block, conf, polyfill_options); Optimization::Optimize(ir_block, conf, polyfill_options);
return emitter.Emit(ir_block); return emitter.Emit(ir_block);
} }
@@ -254,11 +254,10 @@ private:
block_of_code.EnsureMemoryCommitted(MINIMUM_REMAINING_CODESIZE); block_of_code.EnsureMemoryCommitted(MINIMUM_REMAINING_CODESIZE);
// JIT Compile // JIT Compile
const auto get_code = [this](u64 vaddr) { return conf.callbacks->MemoryReadCode(vaddr); };
// LocationDescriptor ctor() does important ops (like tflags) do not skip // LocationDescriptor ctor() does important ops (like tflags) do not skip
auto const arch_descriptor = A64::LocationDescriptor{descriptor}; auto const arch_descriptor = A64::LocationDescriptor{descriptor};
ir_block.Reset(arch_descriptor); ir_block.Reset(arch_descriptor);
A64::Translate(ir_block, arch_descriptor, get_code, {conf.define_unpredictable_behaviour, conf.wall_clock_cntpct}); A64::Translate(ir_block, arch_descriptor, conf);
Optimization::Optimize(ir_block, conf, polyfill_options); Optimization::Optimize(ir_block, conf, polyfill_options);
return emitter.Emit(ir_block).entrypoint; return emitter.Emit(ir_block).entrypoint;
} }
@@ -78,7 +78,6 @@ void ProtectMemory(const void* base, size_t size, bool is_executable) {
static const HostFeature features = []() { static const HostFeature features = []() {
HostFeature f{}; HostFeature f{};
#ifdef DYNARMIC_ENABLE_CPU_FEATURE_DETECTION
using Cpu = Xbyak::util::Cpu; using Cpu = Xbyak::util::Cpu;
Xbyak::util::Cpu cpu_info{}; Xbyak::util::Cpu cpu_info{};
if (cpu_info.has(Cpu::tSSSE3)) f |= HostFeature::SSSE3; if (cpu_info.has(Cpu::tSSSE3)) f |= HostFeature::SSSE3;
@@ -121,7 +120,6 @@ static const HostFeature features = []() {
} }
} }
return f; return f;
#endif
}(); }();
HostFeature GetHostFeatures() { HostFeature GetHostFeatures() {
return features; return features;
@@ -7,34 +7,27 @@
*/ */
#include <cstring> #include <cstring>
#include <cassert>
#include "common/assert.h"
#include "dynarmic/backend/x64/block_of_code.h" #include "dynarmic/backend/x64/block_of_code.h"
#include "dynarmic/backend/x64/constant_pool.h" #include "dynarmic/backend/x64/constant_pool.h"
namespace Dynarmic::Backend::X64 { namespace Dynarmic::Backend::X64 {
ConstantPool::ConstantPool(BlockOfCode& code, size_t size) ConstantPool::ConstantPool(BlockOfCode& code, size_t size) noexcept {
: insertion_point(0) auto const align_size = 64; //always align to cacheline
{ code.EnsureMemoryCommitted(2 * align_size + size);
code.EnsureMemoryCommitted(align_size + size);
code.int3();
code.align(align_size); code.align(align_size);
pool = std::span<ConstantT>(reinterpret_cast<ConstantT*>(code.AllocateFromCodeSpace(size)), size / align_size); pool = std::span<u128>(static_cast<u128*>(code.AllocateFromCodeSpace(size)), size / sizeof(u128));
} }
Xbyak::Address ConstantPool::GetConstant(BlockOfCode& code, const Xbyak::AddressFrame& frame, u64 lower, u64 upper) { Xbyak::Address ConstantPool::GetConstant(BlockOfCode& code, const Xbyak::AddressFrame& frame, u64 lo, u64 hi) noexcept {
const auto constant = ConstantT(lower, upper); // offset grows iff new constant is added
auto it = constant_info.find(constant); auto const key = std::make_pair(lo, hi);
if (it == constant_info.end()) { auto const val = u32(constant_info.size());
ASSERT(insertion_point < pool.size()); auto const [it, _] = constant_info.insert({key, val});
ConstantT& target_constant = pool[insertion_point]; // if it != constant_info.end(): assume(pool[it->second] == c);
target_constant = constant; pool[it->second] = u128{lo, hi};
it = constant_info.insert({constant, &target_constant}).first; return frame[code.rip + std::addressof(pool[it->second])];
++insertion_point;
}
return frame[code.rip + it->second];
} }
} // namespace Dynarmic::Backend::X64 } // namespace Dynarmic::Backend::X64
@@ -12,6 +12,7 @@
#include <cstddef> #include <cstddef>
#include <span> #include <span>
#include <utility> #include <utility>
#include <boost/functional/hash.hpp>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/container/unordered_map.h" #include "common/container/unordered_map.h"
@@ -21,31 +22,17 @@ namespace Dynarmic::Backend::X64 {
class BlockOfCode; class BlockOfCode;
/// ConstantPool allocates a block of memory from BlockOfCode. /// @brief ConstantPool allocates a block of memory from BlockOfCode.
/// It places constants into this block of memory, returning the address /// It places constants into this block of memory, returning the address
/// of the memory location where the constant is placed. If the constant /// of the memory location where the constant is placed. If the constant
/// already exists, its memory location is reused. /// already exists, its memory location is reused.
class ConstantPool final { class ConstantPool final {
public: public:
ConstantPool(BlockOfCode& code, size_t size); ConstantPool(BlockOfCode& code, size_t size) noexcept;
Xbyak::Address GetConstant(BlockOfCode& code, const Xbyak::AddressFrame& frame, u64 lower, u64 upper = 0) noexcept;
Xbyak::Address GetConstant(BlockOfCode& code, const Xbyak::AddressFrame& frame, u64 lower, u64 upper = 0); // key = identity hash, value = offset from pool.data()
::Common::unordered_map<std::pair<u64, u64>, u32, boost::hash<std::pair<u64, u64>>> constant_info;
private: std::span<u128> pool;
static constexpr size_t align_size = 16; // bytes
using ConstantT = std::pair<u64, u64>;
static_assert(sizeof(ConstantT) == align_size);
struct ConstantHash {
std::size_t operator()(const ConstantT& constant) const noexcept {
return constant.first ^ std::rotl<u64>(constant.second, 1);
}
};
::Common::unordered_map<ConstantT, void*, ConstantHash> constant_info;
std::span<ConstantT> pool;
std::size_t insertion_point;
}; };
} // namespace Dynarmic::Backend::X64 } // namespace Dynarmic::Backend::X64
@@ -275,6 +275,7 @@ const void* EmitReadMemoryMov(BlockOfCode& code, int value_idx, const Xbyak::Reg
code.xadd(qword[addr], Xbyak::Reg64(value_idx)); code.xadd(qword[addr], Xbyak::Reg64(value_idx));
break; break;
case 128: case 128:
ASSERT(Xbyak::Xmm(value_idx) != xmm0);
code.lock(); code.lock();
code.cmpxchg16b(xword[addr]); code.cmpxchg16b(xword[addr]);
if (code.HasHostFeature(HostFeature::SSE41)) { if (code.HasHostFeature(HostFeature::SSE41)) {
@@ -6226,9 +6226,7 @@ void EmitX64::EmitVectorZeroExtend64(EmitContext& ctx, IR::Inst* inst) {
void EmitX64::EmitVectorZeroUpper(EmitContext& ctx, IR::Inst* inst) { void EmitX64::EmitVectorZeroUpper(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto const a = ctx.reg_alloc.UseScratchXmm(code, args[0]); auto const a = ctx.reg_alloc.UseScratchXmm(code, args[0]);
code.movq(a, a); // TODO: !IsLastUse code.movq(a, a); // TODO: !IsLastUse
ctx.reg_alloc.DefineValue(code, inst, a); ctx.reg_alloc.DefineValue(code, inst, a);
} }
@@ -14,12 +14,6 @@
#include "dynarmic/backend/x64/hostloc.h" #include "dynarmic/backend/x64/hostloc.h"
#include "dynarmic/common/spin_lock.h" #include "dynarmic/common/spin_lock.h"
#ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT
static const auto default_cg_mode = Xbyak::DontSetProtectRWE;
#else
static const auto default_cg_mode = nullptr; //Allow RWE
#endif
namespace Dynarmic { namespace Dynarmic {
void EmitSpinLockLock(Xbyak::CodeGenerator& code, Xbyak::Reg64 ptr, Xbyak::Reg32 tmp, bool waitpkg) { void EmitSpinLockLock(Xbyak::CodeGenerator& code, Xbyak::Reg64 ptr, Xbyak::Reg32 tmp, bool waitpkg) {
@@ -78,7 +72,13 @@ namespace {
struct SpinLockImpl { struct SpinLockImpl {
void Initialize() noexcept; void Initialize() noexcept;
static void GlobalInitialize() noexcept; static void GlobalInitialize() noexcept;
Xbyak::CodeGenerator code = Xbyak::CodeGenerator(4096, default_cg_mode); Xbyak::CodeGenerator code = Xbyak::CodeGenerator(4096
#ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT
, Xbyak::DontSetProtectRWE
#else
, nullptr //Allow RWE
#endif
);
void (*lock)(volatile int*) = nullptr; void (*lock)(volatile int*) = nullptr;
void (*unlock)(volatile int*) = nullptr; void (*unlock)(volatile int*) = nullptr;
}; };
@@ -9,15 +9,16 @@
#include "dynarmic/frontend/A32/translate/a32_translate.h" #include "dynarmic/frontend/A32/translate/a32_translate.h"
#include "dynarmic/frontend/A32/a32_location_descriptor.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h"
#include "dynarmic/interface/A32/config.h"
#include "dynarmic/ir/basic_block.h" #include "dynarmic/ir/basic_block.h"
namespace Dynarmic::A32 { namespace Dynarmic::A32 {
void TranslateArm(IR::Block& block, LocationDescriptor descriptor, TranslateCallbacks* tcb, const TranslationOptions& options); void TranslateArm(IR::Block& block, LocationDescriptor descriptor, const A32::UserConfig& conf);
void TranslateThumb(IR::Block& block, LocationDescriptor descriptor, TranslateCallbacks* tcb, const TranslationOptions& options); void TranslateThumb(IR::Block& block, LocationDescriptor descriptor, const A32::UserConfig& conf);
void Translate(IR::Block& block, LocationDescriptor descriptor, TranslateCallbacks* tcb, const TranslationOptions& options) { void Translate(IR::Block& block, LocationDescriptor descriptor, const A32::UserConfig& conf) {
return (descriptor.TFlag() ? TranslateThumb : TranslateArm)(block, descriptor, tcb, options); return (descriptor.TFlag() ? TranslateThumb : TranslateArm)(block, descriptor, conf);
} }
bool TranslateSingleArmInstruction(IR::Block& block, LocationDescriptor descriptor, u32 instruction); bool TranslateSingleArmInstruction(IR::Block& block, LocationDescriptor descriptor, u32 instruction);
@@ -10,6 +10,7 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "dynarmic/interface/A32/arch_version.h" #include "dynarmic/interface/A32/arch_version.h"
#include "dynarmic/interface/A32/config.h"
namespace Dynarmic::IR { namespace Dynarmic::IR {
class Block; class Block;
@@ -20,28 +21,14 @@ namespace Dynarmic::A32 {
class LocationDescriptor; class LocationDescriptor;
struct TranslateCallbacks; struct TranslateCallbacks;
struct TranslationOptions {
ArchVersion arch_version;
/// This changes what IR we emit when we translate an unpredictable instruction.
/// If this is false, the ExceptionRaised IR instruction is emitted.
/// If this is true, we define some behaviour for some instructions.
bool define_unpredictable_behaviour = false;
/// This changes what IR we emit when we translate a hint instruction.
/// If this is false, we treat the instruction as a NOP.
/// If this is true, we emit an ExceptionRaised instruction.
bool hook_hint_instructions = true;
};
/** /**
* This function translates instructions in memory into our intermediate representation. * This function translates instructions in memory into our intermediate representation.
* @param descriptor The starting location of the basic block. Includes information like PC, Thumb state, &c. * @param descriptor The starting location of the basic block. Includes information like PC, Thumb state, &c.
* @param tcb The callbacks we should use to read emulated memory. * @param tcb The callbacks we should use to read emulated memory.
* @param options Configures how certain instructions are translated. * @param conf Configures how certain instructions are translated.
* @return A translated basic block in the intermediate representation. * @return A translated basic block in the intermediate representation.
*/ */
void Translate(IR::Block& block, LocationDescriptor descriptor, TranslateCallbacks* tcb, const TranslationOptions& options); void Translate(IR::Block& block, LocationDescriptor descriptor, const A32::UserConfig& conf);
/** /**
* This function translates a single provided instruction into our intermediate representation. * This function translates a single provided instruction into our intermediate representation.
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* This file is part of the dynarmic project. /* This file is part of the dynarmic project.
* Copyright (c) 2016 MerryMage * Copyright (c) 2016 MerryMage
* SPDX-License-Identifier: 0BSD * SPDX-License-Identifier: 0BSD
@@ -10,7 +13,7 @@ namespace Dynarmic::A32 {
// BKPT #<imm16> // BKPT #<imm16>
bool TranslatorVisitor::arm_BKPT(Cond cond, Imm<12> /*imm12*/, Imm<4> /*imm4*/) { bool TranslatorVisitor::arm_BKPT(Cond cond, Imm<12> /*imm12*/, Imm<4> /*imm4*/) {
if (cond != Cond::AL && !options.define_unpredictable_behaviour) { if (cond != Cond::AL && !conf.define_unpredictable_behaviour) {
return UnpredictableInstruction(); return UnpredictableInstruction();
} }
// UNPREDICTABLE: The instruction executes conditionally. // UNPREDICTABLE: The instruction executes conditionally.
@@ -9,6 +9,7 @@
#pragma once #pragma once
#include "common/assert.h" #include "common/assert.h"
#include "dynarmic/interface/A32/config.h"
#include "dynarmic/mcl/bit.hpp" #include "dynarmic/mcl/bit.hpp"
#include "dynarmic/frontend/A32/a32_ir_emitter.h" #include "dynarmic/frontend/A32/a32_ir_emitter.h"
@@ -25,12 +26,14 @@ enum class Exception;
struct TranslatorVisitor final { struct TranslatorVisitor final {
using instruction_return_type = bool; using instruction_return_type = bool;
explicit TranslatorVisitor(IR::Block& block, LocationDescriptor descriptor, const TranslationOptions& options) explicit TranslatorVisitor(IR::Block& block, LocationDescriptor descriptor, const A32::UserConfig& conf)
: ir(block, descriptor, options.arch_version), options(options) {} : ir(block, descriptor, conf.arch_version)
, conf(conf)
{}
A32::IREmitter ir; A32::IREmitter ir;
ConditionalState cond_state = ConditionalState::None; ConditionalState cond_state = ConditionalState::None;
TranslationOptions options; A32::UserConfig const& conf;
size_t current_instruction_size; size_t current_instruction_size;
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* This file is part of the dynarmic project. /* This file is part of the dynarmic project.
* Copyright (c) 2019 MerryMage * Copyright (c) 2019 MerryMage
* SPDX-License-Identifier: 0BSD * SPDX-License-Identifier: 0BSD
@@ -9,7 +12,7 @@
namespace Dynarmic::A32 { namespace Dynarmic::A32 {
bool TranslatorVisitor::arm_PLD_imm(bool /*add*/, bool R, Reg /*n*/, Imm<12> /*imm12*/) { bool TranslatorVisitor::arm_PLD_imm(bool /*add*/, bool R, Reg /*n*/, Imm<12> /*imm12*/) {
if (!options.hook_hint_instructions) { if (!conf.hook_hint_instructions) {
return true; return true;
} }
@@ -18,7 +21,7 @@ bool TranslatorVisitor::arm_PLD_imm(bool /*add*/, bool R, Reg /*n*/, Imm<12> /*i
} }
bool TranslatorVisitor::arm_PLD_reg(bool /*add*/, bool R, Reg /*n*/, Imm<5> /*imm5*/, ShiftType /*shift*/, Reg /*m*/) { bool TranslatorVisitor::arm_PLD_reg(bool /*add*/, bool R, Reg /*n*/, Imm<5> /*imm5*/, ShiftType /*shift*/, Reg /*m*/) {
if (!options.hook_hint_instructions) { if (!conf.hook_hint_instructions) {
return true; return true;
} }
@@ -27,7 +30,7 @@ bool TranslatorVisitor::arm_PLD_reg(bool /*add*/, bool R, Reg /*n*/, Imm<5> /*im
} }
bool TranslatorVisitor::arm_SEV() { bool TranslatorVisitor::arm_SEV() {
if (!options.hook_hint_instructions) { if (!conf.hook_hint_instructions) {
return true; return true;
} }
@@ -35,7 +38,7 @@ bool TranslatorVisitor::arm_SEV() {
} }
bool TranslatorVisitor::arm_SEVL() { bool TranslatorVisitor::arm_SEVL() {
if (!options.hook_hint_instructions) { if (!conf.hook_hint_instructions) {
return true; return true;
} }
@@ -43,7 +46,7 @@ bool TranslatorVisitor::arm_SEVL() {
} }
bool TranslatorVisitor::arm_WFE() { bool TranslatorVisitor::arm_WFE() {
if (!options.hook_hint_instructions) { if (!conf.hook_hint_instructions) {
return true; return true;
} }
@@ -51,7 +54,7 @@ bool TranslatorVisitor::arm_WFE() {
} }
bool TranslatorVisitor::arm_WFI() { bool TranslatorVisitor::arm_WFI() {
if (!options.hook_hint_instructions) { if (!conf.hook_hint_instructions) {
return true; return true;
} }
@@ -59,7 +62,7 @@ bool TranslatorVisitor::arm_WFI() {
} }
bool TranslatorVisitor::arm_YIELD() { bool TranslatorVisitor::arm_YIELD() {
if (!options.hook_hint_instructions) { if (!conf.hook_hint_instructions) {
return true; return true;
} }
@@ -642,7 +642,7 @@ bool TranslatorVisitor::thumb16_SUB_sp(Imm<7> imm7) {
// SEV<c> // SEV<c>
bool TranslatorVisitor::thumb16_SEV() { bool TranslatorVisitor::thumb16_SEV() {
if (!options.hook_hint_instructions) { if (!conf.hook_hint_instructions) {
return true; return true;
} }
return RaiseException(Exception::SendEvent); return RaiseException(Exception::SendEvent);
@@ -650,7 +650,7 @@ bool TranslatorVisitor::thumb16_SEV() {
// SEVL<c> // SEVL<c>
bool TranslatorVisitor::thumb16_SEVL() { bool TranslatorVisitor::thumb16_SEVL() {
if (!options.hook_hint_instructions) { if (!conf.hook_hint_instructions) {
return true; return true;
} }
return RaiseException(Exception::SendEventLocal); return RaiseException(Exception::SendEventLocal);
@@ -658,7 +658,7 @@ bool TranslatorVisitor::thumb16_SEVL() {
// WFE<c> // WFE<c>
bool TranslatorVisitor::thumb16_WFE() { bool TranslatorVisitor::thumb16_WFE() {
if (!options.hook_hint_instructions) { if (!conf.hook_hint_instructions) {
return true; return true;
} }
return RaiseException(Exception::WaitForEvent); return RaiseException(Exception::WaitForEvent);
@@ -666,7 +666,7 @@ bool TranslatorVisitor::thumb16_WFE() {
// WFI<c> // WFI<c>
bool TranslatorVisitor::thumb16_WFI() { bool TranslatorVisitor::thumb16_WFI() {
if (!options.hook_hint_instructions) { if (!conf.hook_hint_instructions) {
return true; return true;
} }
return RaiseException(Exception::WaitForInterrupt); return RaiseException(Exception::WaitForInterrupt);
@@ -674,7 +674,7 @@ bool TranslatorVisitor::thumb16_WFI() {
// YIELD<c> // YIELD<c>
bool TranslatorVisitor::thumb16_YIELD() { bool TranslatorVisitor::thumb16_YIELD() {
if (!options.hook_hint_instructions) { if (!conf.hook_hint_instructions) {
return true; return true;
} }
return RaiseException(Exception::Yield); return RaiseException(Exception::Yield);
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* This file is part of the dynarmic project. /* This file is part of the dynarmic project.
* Copyright (c) 2021 MerryMage * Copyright (c) 2021 MerryMage
* SPDX-License-Identifier: 0BSD * SPDX-License-Identifier: 0BSD
@@ -8,7 +11,7 @@
namespace Dynarmic::A32 { namespace Dynarmic::A32 {
static bool PLDHandler(TranslatorVisitor& v, bool W) { static bool PLDHandler(TranslatorVisitor& v, bool W) {
if (!v.options.hook_hint_instructions) { if (!v.conf.hook_hint_instructions) {
return true; return true;
} }
@@ -18,7 +21,7 @@ static bool PLDHandler(TranslatorVisitor& v, bool W) {
} }
static bool PLIHandler(TranslatorVisitor& v) { static bool PLIHandler(TranslatorVisitor& v) {
if (!v.options.hook_hint_instructions) { if (!v.conf.hook_hint_instructions) {
return true; return true;
} }
@@ -22,10 +22,12 @@
namespace Dynarmic::A32 { namespace Dynarmic::A32 {
void TranslateArm(IR::Block& block, LocationDescriptor descriptor, TranslateCallbacks* tcb, const TranslationOptions& options) { void TranslateArm(IR::Block& block, LocationDescriptor descriptor, const A32::UserConfig& conf) {
const bool single_step = descriptor.SingleStepping(); const bool single_step = descriptor.SingleStepping();
TranslatorVisitor visitor{block, descriptor, options}; TranslatorVisitor visitor{block, descriptor, conf};
bool should_continue = true; bool should_continue = true;
auto tcb = conf.callbacks;
do { do {
const u32 arm_pc = visitor.ir.current_location.PC(); const u32 arm_pc = visitor.ir.current_location.PC();
u64 ticks_for_instruction = 1; u64 ticks_for_instruction = 1;
@@ -103,10 +103,12 @@ inline bool MaybeVFPOrASIMDInstruction(u32 thumb_instruction) noexcept {
} // namespace } // namespace
void TranslateThumb(IR::Block& block, LocationDescriptor descriptor, TranslateCallbacks* tcb, const TranslationOptions& options) { void TranslateThumb(IR::Block& block, LocationDescriptor descriptor, const A32::UserConfig& conf) {
const bool single_step = descriptor.SingleStepping(); const bool single_step = descriptor.SingleStepping();
TranslatorVisitor visitor{block, descriptor, options}; TranslatorVisitor visitor{block, descriptor, conf};
bool should_continue = true; bool should_continue = true;
auto tcb = conf.callbacks;
do { do {
const u32 arm_pc = visitor.ir.current_location.PC(); const u32 arm_pc = visitor.ir.current_location.PC();
u64 ticks_for_instruction = 1; u64 ticks_for_instruction = 1;
@@ -11,19 +11,20 @@
#include "dynarmic/frontend/A64/a64_location_descriptor.h" #include "dynarmic/frontend/A64/a64_location_descriptor.h"
#include "dynarmic/frontend/A64/decoder/a64.h" #include "dynarmic/frontend/A64/decoder/a64.h"
#include "dynarmic/frontend/A64/translate/impl/impl.h" #include "dynarmic/frontend/A64/translate/impl/impl.h"
#include "dynarmic/interface/A64/config.h"
#include "dynarmic/ir/basic_block.h" #include "dynarmic/ir/basic_block.h"
#include "dynarmic/ir/terminal.h" #include "dynarmic/ir/terminal.h"
namespace Dynarmic::A64 { namespace Dynarmic::A64 {
void Translate(IR::Block& block, LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code, TranslationOptions options) { void Translate(IR::Block& block, LocationDescriptor descriptor, A64::UserConfig const& conf) {
const bool single_step = descriptor.SingleStepping(); const bool single_step = descriptor.SingleStepping();
TranslatorVisitor visitor{block, descriptor, std::move(options)}; TranslatorVisitor visitor{block, descriptor, conf};
bool should_continue = true; bool should_continue = true;
do { do {
const u64 pc = visitor.ir.current_location->PC(); const u64 pc = visitor.ir.current_location->PC();
if (const auto instruction = memory_read_code(pc)) { if (const auto instruction = conf.callbacks->MemoryReadCode(pc)) {
if (auto decoder = Decode<TranslatorVisitor, bool>(visitor, *instruction)) { if (auto decoder = Decode<TranslatorVisitor, bool>(visitor, *instruction)) {
should_continue = *decoder; should_continue = *decoder;
} else { } else {
@@ -11,6 +11,7 @@
#include <optional> #include <optional>
#include "common/common_types.h" #include "common/common_types.h"
#include "dynarmic/interface/A64/config.h"
namespace Dynarmic { namespace Dynarmic {
@@ -22,32 +23,14 @@ namespace A64 {
class LocationDescriptor; class LocationDescriptor;
using MemoryReadCodeFuncType = std::function<std::optional<u32>(u64 vaddr)>;
struct TranslationOptions {
/// This changes what IR we emit when we translate an unpredictable instruction.
/// If this is false, the ExceptionRaised IR instruction is emitted.
/// If this is true, we define some behaviour for some instructions.
bool define_unpredictable_behaviour = false;
/// This tells the translator a wall clock will be used, thus allowing it
/// to avoid writting certain unnecessary code only needed for cycle timers.
bool wall_clock_cntpct = false;
/// This changes what IR we emit when we translate a hint instruction.
/// If this is false, we treat the instruction as a NOP.
/// If this is true, we emit an ExceptionRaised instruction.
bool hook_hint_instructions = true;
};
/** /**
* This function translates instructions in memory into our intermediate representation. * This function translates instructions in memory into our intermediate representation.
* @param descriptor The starting location of the basic block. Includes information like PC, FPCR state, &c. * @param descriptor The starting location of the basic block. Includes information like PC, FPCR state, &c.
* @param memory_read_code The function we should use to read emulated memory. * @param memory_read_code The function we should use to read emulated memory.
* @param options Configures how certain instructions are translated. * @param conf Configures how certain instructions are translated.
* @return A translated basic block in the intermediate representation. * @return A translated basic block in the intermediate representation.
*/ */
void Translate(IR::Block& block, LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code, TranslationOptions options); void Translate(IR::Block& block, LocationDescriptor descriptor, A64::UserConfig const& conf);
/** /**
* This function translates a single provided instruction into our intermediate representation. * This function translates a single provided instruction into our intermediate representation.
@@ -15,17 +15,20 @@
#include "dynarmic/frontend/A64/a64_types.h" #include "dynarmic/frontend/A64/a64_types.h"
#include "dynarmic/frontend/A64/translate/a64_translate.h" #include "dynarmic/frontend/A64/translate/a64_translate.h"
#include "dynarmic/frontend/imm.h" #include "dynarmic/frontend/imm.h"
#include "dynarmic/interface/A64/config.h"
namespace Dynarmic::A64 { namespace Dynarmic::A64 {
struct TranslatorVisitor final { struct TranslatorVisitor final {
using instruction_return_type = bool; using instruction_return_type = bool;
explicit TranslatorVisitor(IR::Block& block, LocationDescriptor descriptor, TranslationOptions options) explicit TranslatorVisitor(IR::Block& block, LocationDescriptor descriptor, A64::UserConfig const& conf)
: ir(block, descriptor), options(std::move(options)) {} : ir(block, descriptor)
, conf(conf)
{}
A64::IREmitter ir; A64::IREmitter ir;
TranslationOptions options; A64::UserConfig const& conf;
bool UnpredictableInstruction(); bool UnpredictableInstruction();
bool DecodeError(); bool DecodeError();
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* This file is part of the dynarmic project. /* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage * Copyright (c) 2018 MerryMage
* SPDX-License-Identifier: 0BSD * SPDX-License-Identifier: 0BSD
@@ -25,7 +28,7 @@ static bool ExclusiveSharedDecodeAndOperation(TranslatorVisitor& v, bool pair, s
if (memop == IR::MemOp::LOAD && pair && Rt == *Rt2) { if (memop == IR::MemOp::LOAD && pair && Rt == *Rt2) {
return v.UnpredictableInstruction(); return v.UnpredictableInstruction();
} else if (memop == IR::MemOp::STORE && (*Rs == Rt || (pair && *Rs == *Rt2))) { } else if (memop == IR::MemOp::STORE && (*Rs == Rt || (pair && *Rs == *Rt2))) {
if (!v.options.define_unpredictable_behaviour) { if (!v.conf.define_unpredictable_behaviour) {
return v.UnpredictableInstruction(); return v.UnpredictableInstruction();
} }
// UNPREDICTABLE: The Constraint_NONE case is executed. // UNPREDICTABLE: The Constraint_NONE case is executed.
@@ -42,35 +42,35 @@ bool TranslatorVisitor::NOP() {
} }
bool TranslatorVisitor::YIELD() { bool TranslatorVisitor::YIELD() {
if (!options.hook_hint_instructions) { if (!conf.hook_hint_instructions) {
return true; return true;
} }
return RaiseException(Exception::Yield); return RaiseException(Exception::Yield);
} }
bool TranslatorVisitor::WFE() { bool TranslatorVisitor::WFE() {
if (!options.hook_hint_instructions) { if (!conf.hook_hint_instructions) {
return true; return true;
} }
return RaiseException(Exception::WaitForEvent); return RaiseException(Exception::WaitForEvent);
} }
bool TranslatorVisitor::WFI() { bool TranslatorVisitor::WFI() {
if (!options.hook_hint_instructions) { if (!conf.hook_hint_instructions) {
return true; return true;
} }
return RaiseException(Exception::WaitForInterrupt); return RaiseException(Exception::WaitForInterrupt);
} }
bool TranslatorVisitor::SEV() { bool TranslatorVisitor::SEV() {
if (!options.hook_hint_instructions) { if (!conf.hook_hint_instructions) {
return true; return true;
} }
return RaiseException(Exception::SendEvent); return RaiseException(Exception::SendEvent);
} }
bool TranslatorVisitor::SEVL() { bool TranslatorVisitor::SEVL() {
if (!options.hook_hint_instructions) { if (!conf.hook_hint_instructions) {
return true; return true;
} }
return RaiseException(Exception::SendEventLocal); return RaiseException(Exception::SendEventLocal);
@@ -129,7 +129,7 @@ bool TranslatorVisitor::MRS(Imm<1> o0, Imm<3> op1, Imm<4> CRn, Imm<4> CRm, Imm<3
return true; return true;
case SystemRegisterEncoding::CNTPCT_EL0: case SystemRegisterEncoding::CNTPCT_EL0:
// HACK: Ensure that this is the first instruction in the block it's emitted in, so the cycle count is most up-to-date. // HACK: Ensure that this is the first instruction in the block it's emitted in, so the cycle count is most up-to-date.
if (!ir.block.instructions.empty() && !options.wall_clock_cntpct) { if (!ir.block.instructions.empty() && !conf.wall_clock_cntpct) {
ir.block.CycleCount()--; ir.block.CycleCount()--;
ir.SetTerm(IR::Term::LinkBlock{*ir.current_location}); ir.SetTerm(IR::Term::LinkBlock{*ir.current_location});
return false; return false;

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