Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c754d3b821 | |||
| 269f6ead31 | |||
| be972d7fdc | |||
| 972860ac8f | |||
| 3d3ed4b7d1 | |||
| be21ccce25 | |||
| db83070bf2 | |||
| e903d70d9e | |||
| 802531c457 | |||
| bd071e3464 | |||
| a845100bf0 |
@@ -0,0 +1,2 @@
|
|||||||
|
liberapay: crueter
|
||||||
|
custom: 'https://www.paypal.biz/edenemulator'
|
||||||
@@ -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}
|
||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 5.6 KiB |
@@ -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 |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 11 KiB |
@@ -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 |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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).
|
||||||
|
|||||||
@@ -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)**
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 17 KiB |
@@ -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
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
@@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -143,20 +146,16 @@ public:
|
|||||||
return m_str;
|
return m_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr size_t GetLength() const {
|
size_t GetLength() const {
|
||||||
if (std::is_constant_evaluated()) {
|
|
||||||
return Strlen(this->GetString());
|
|
||||||
} else {
|
|
||||||
return std::strlen(this->GetString());
|
return std::strlen(this->GetString());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
constexpr bool IsEmpty() const {
|
constexpr bool IsEmpty() const {
|
||||||
return *m_str == '\x00';
|
return *m_str == '\x00';
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr bool IsMatchHead(const char* p, size_t len) const {
|
bool IsMatchHead(const char* p, size_t len) const {
|
||||||
return Strncmp(this->GetString(), p, len) == 0;
|
return std::strncmp(this->GetString(), p, len) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Initialize(const Path& rhs) {
|
Result Initialize(const Path& rhs) {
|
||||||
@@ -169,7 +168,7 @@ public:
|
|||||||
R_TRY(this->Preallocate(len + 1));
|
R_TRY(this->Preallocate(len + 1));
|
||||||
|
|
||||||
// Copy the path
|
// Copy the path
|
||||||
const size_t copied = Strlcpy<char>(m_write_buffer.Get(), rhs.GetString(), len + 1);
|
const size_t copied = strlcpy(m_write_buffer.Get(), rhs.GetString(), len + 1);
|
||||||
R_UNLESS(copied == len, ResultUnexpectedInPathA);
|
R_UNLESS(copied == len, ResultUnexpectedInPathA);
|
||||||
|
|
||||||
// Set normalized
|
// Set normalized
|
||||||
@@ -331,14 +330,14 @@ public:
|
|||||||
// Get our write buffer
|
// Get our write buffer
|
||||||
auto* dst = m_write_buffer.Get();
|
auto* dst = m_write_buffer.Get();
|
||||||
if (old_write_buffer.Get() != nullptr && cur_len > 0) {
|
if (old_write_buffer.Get() != nullptr && cur_len > 0) {
|
||||||
Strlcpy<char>(dst, old_write_buffer.Get(), cur_len + 1);
|
strlcpy(dst, old_write_buffer.Get(), cur_len + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add separator
|
// Add separator
|
||||||
dst[cur_len] = '/';
|
dst[cur_len] = '/';
|
||||||
|
|
||||||
// Copy the child path
|
// Copy the child path
|
||||||
const size_t copied = Strlcpy<char>(dst + cur_len + 1, c, child_len + 1);
|
const size_t copied = strlcpy(dst + cur_len + 1, c, child_len + 1);
|
||||||
R_UNLESS(copied == child_len, ResultUnexpectedInPathA);
|
R_UNLESS(copied == child_len, ResultUnexpectedInPathA);
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
@@ -375,7 +374,7 @@ public:
|
|||||||
if (m_write_buffer.Get() == nullptr) {
|
if (m_write_buffer.Get() == nullptr) {
|
||||||
if (const auto len = std::strlen(m_str); len > 0) {
|
if (const auto len = std::strlen(m_str); len > 0) {
|
||||||
R_TRY(this->Preallocate(len));
|
R_TRY(this->Preallocate(len));
|
||||||
Strlcpy<char>(m_write_buffer.Get(), m_str, len + 1);
|
strlcpy(m_write_buffer.Get(), m_str, len + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,7 +496,7 @@ private:
|
|||||||
R_TRY(this->Preallocate(size + 1));
|
R_TRY(this->Preallocate(size + 1));
|
||||||
|
|
||||||
// Copy the path
|
// Copy the path
|
||||||
const size_t copied = Strlcpy<char>(m_write_buffer.Get(), path, size + 1);
|
const size_t copied = strlcpy(m_write_buffer.Get(), path, size + 1);
|
||||||
R_UNLESS(copied >= size, ResultUnexpectedInPathA);
|
R_UNLESS(copied >= size, ResultUnexpectedInPathA);
|
||||||
} else {
|
} else {
|
||||||
// We can just clear the buffer
|
// We can just clear the buffer
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2025 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
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
@@ -1217,7 +1217,7 @@ public:
|
|||||||
replaced_src = static_cast<char*>(Allocate(replaced_src_len));
|
replaced_src = static_cast<char*>(Allocate(replaced_src_len));
|
||||||
}
|
}
|
||||||
|
|
||||||
Strlcpy<char>(replaced_src, src, replaced_src_len);
|
strlcpy(replaced_src, src, replaced_src_len);
|
||||||
|
|
||||||
Replace(replaced_src, replaced_src_len, AlternateDirectorySeparator,
|
Replace(replaced_src, replaced_src_len, AlternateDirectorySeparator,
|
||||||
DirectorySeparator);
|
DirectorySeparator);
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -7,85 +10,6 @@
|
|||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr int Strlen(const T* str) {
|
|
||||||
ASSERT(str != nullptr);
|
|
||||||
|
|
||||||
int length = 0;
|
|
||||||
while (*str++) {
|
|
||||||
++length;
|
|
||||||
}
|
|
||||||
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr int Strnlen(const T* str, std::size_t count) {
|
|
||||||
return Strnlen(str, static_cast<int>(count));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr int Strnlen(const T* str, int count) {
|
|
||||||
ASSERT(str != nullptr);
|
|
||||||
ASSERT(count >= 0);
|
|
||||||
|
|
||||||
int length = 0;
|
|
||||||
while (count-- && *str++) {
|
|
||||||
++length;
|
|
||||||
}
|
|
||||||
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr int Strncmp(const T* lhs, const T* rhs, std::size_t count) {
|
|
||||||
return Strncmp(lhs, rhs, static_cast<int>(count));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr int Strncmp(const T* lhs, const T* rhs, int count) {
|
|
||||||
ASSERT(lhs != nullptr);
|
|
||||||
ASSERT(rhs != nullptr);
|
|
||||||
ASSERT(count >= 0);
|
|
||||||
|
|
||||||
if (count == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
T l, r;
|
|
||||||
do {
|
|
||||||
l = *(lhs++);
|
|
||||||
r = *(rhs++);
|
|
||||||
} while (l && (l == r) && (--count));
|
|
||||||
|
|
||||||
return l - r;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static constexpr int Strlcpy(T* dst, const T* src, std::size_t count) {
|
|
||||||
return Strlcpy<T>(dst, src, static_cast<int>(count));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
static constexpr int Strlcpy(T* dst, const T* src, int count) {
|
|
||||||
ASSERT(dst != nullptr);
|
|
||||||
ASSERT(src != nullptr);
|
|
||||||
|
|
||||||
const T* cur = src;
|
|
||||||
if (count > 0) {
|
|
||||||
while ((--count) && *cur) {
|
|
||||||
*(dst++) = *(cur++);
|
|
||||||
}
|
|
||||||
*dst = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (*cur) {
|
|
||||||
cur++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return static_cast<int>(cur - src);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum CharacterEncodingResult {
|
enum CharacterEncodingResult {
|
||||||
CharacterEncodingResult_Success = 0,
|
CharacterEncodingResult_Success = 0,
|
||||||
CharacterEncodingResult_InsufficientLength = 1,
|
CharacterEncodingResult_InsufficientLength = 1,
|
||||||
|
|||||||
@@ -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")
|
|
||||||
@@ -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()
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ struct detail {
|
|||||||
shifts[arg_index] = bit_position;
|
shifts[arg_index] = bit_position;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if !defined(DYNARMIC_IGNORE_ASSERTS) && !defined(__ANDROID__)
|
#if !defined(__ANDROID__)
|
||||||
// Avoids a MSVC ICE, and avoids Android NDK issue.
|
// Avoids a MSVC ICE, and avoids Android NDK issue.
|
||||||
DEBUG_ASSERT(std::all_of(masks.begin(), masks.end(), [](auto m) { return m != 0; }));
|
DEBUG_ASSERT(std::all_of(masks.begin(), masks.end(), [](auto m) { return m != 0; }));
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -2632,3 +2632,66 @@ TEST_CASE("A64: Rounding", "[a64]") {
|
|||||||
CHECK(jit.GetVector(5) == Vector{0x4000000040000000, 0x4000000040000000});
|
CHECK(jit.GetVector(5) == Vector{0x4000000040000000, 0x4000000040000000});
|
||||||
CHECK(jit.GetVector(6) == Vector{0x4000000040000000, 0x4000000040000000});
|
CHECK(jit.GetVector(6) == Vector{0x4000000040000000, 0x4000000040000000});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("A64: SM4", "[a64]") {
|
||||||
|
A64TestEnv env;
|
||||||
|
A64::UserConfig jit_user_config{};
|
||||||
|
jit_user_config.callbacks = &env;
|
||||||
|
A64::Jit jit{jit_user_config};
|
||||||
|
|
||||||
|
oaknut::VectorCodeGenerator code{env.code_mem, nullptr};
|
||||||
|
|
||||||
|
code.SM4EKEY(V4.S4(), V0.S4(), V1.S4());
|
||||||
|
code.SM4E(V5.S4(), V0.S4(), V1.S4());
|
||||||
|
|
||||||
|
jit.SetPC(0);
|
||||||
|
jit.SetVector(0, {0xefcdab8967452301, 0x1032547698badcfe});
|
||||||
|
jit.SetVector(1, {0xefcdab8967452301, 0x1032547698badcfe});
|
||||||
|
env.ticks_left = env.code_mem.size();
|
||||||
|
CheckedRun([&]() { jit.Run(); });
|
||||||
|
|
||||||
|
CHECK(jit.GetVector(4) == Vector{0x486a0c2e00224466, 0x5c7e183a62402604});
|
||||||
|
CHECK(jit.GetVector(5) == Vector{0xc2e086a43c1e785a, 0xd7f593b104264062});
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("A64: SM3", "[a64]") {
|
||||||
|
A64TestEnv env;
|
||||||
|
A64::UserConfig jit_user_config{};
|
||||||
|
jit_user_config.callbacks = &env;
|
||||||
|
SECTION("SM3SS1") {
|
||||||
|
A64::Jit jit{jit_user_config};
|
||||||
|
oaknut::VectorCodeGenerator code{env.code_mem, nullptr};
|
||||||
|
code.SM3SS1(V0.S4(), V0.S4(), V1.S4(), V2.S4());
|
||||||
|
jit.SetPC(0);
|
||||||
|
jit.SetVector(0, {0xec4aff517369c667, 0x46e3fbf2abbacd29});
|
||||||
|
jit.SetVector(1, {0x8de7e81bf854c27c, 0x9ac99f33632e5a76});
|
||||||
|
jit.SetVector(2, {0x5aa35831b70d3266, 0xd45ee95817055d25});
|
||||||
|
env.ticks_left = env.code_mem.size();
|
||||||
|
CheckedRun([&]() { jit.Run(); });
|
||||||
|
CHECK(jit.GetVector(0) == Vector{0x0000000000000000, 0x73d67cd700000000});
|
||||||
|
}
|
||||||
|
SECTION("SM3PARTW1") {
|
||||||
|
A64::Jit jit{jit_user_config};
|
||||||
|
oaknut::VectorCodeGenerator code{env.code_mem, nullptr};
|
||||||
|
code.SM3PARTW1(V0.S4(), V0.S4(), V1.S4(), V2.S4());
|
||||||
|
jit.SetPC(0);
|
||||||
|
jit.SetVector(0, {0xec4aff517369c667, 0x46e3fbf2abbacd29});
|
||||||
|
jit.SetVector(1, {0x8de7e81bf854c27c, 0x9ac99f33632e5a76});
|
||||||
|
jit.SetVector(2, {0x5aa35831b70d3266, 0xd45ee95817055d25});
|
||||||
|
env.ticks_left = env.code_mem.size();
|
||||||
|
CheckedRun([&]() { jit.Run(); });
|
||||||
|
CHECK(jit.GetVector(0) == Vector{0x653c64995693280c, 0xabcc7db97adebf12});
|
||||||
|
}
|
||||||
|
SECTION("SM3PARTW2") {
|
||||||
|
A64::Jit jit{jit_user_config};
|
||||||
|
oaknut::VectorCodeGenerator code{env.code_mem, nullptr};
|
||||||
|
code.SM3PARTW2(V0.S4(), V0.S4(), V1.S4(), V2.S4());
|
||||||
|
jit.SetPC(0);
|
||||||
|
jit.SetVector(0, {0xec4aff517369c667, 0x46e3fbf2abbacd29});
|
||||||
|
jit.SetVector(1, {0x8de7e81bf854c27c, 0x9ac99f33632e5a76});
|
||||||
|
jit.SetVector(2, {0x5aa35831b70d3266, 0xd45ee95817055d25});
|
||||||
|
env.ticks_left = env.code_mem.size();
|
||||||
|
CheckedRun([&]() { jit.Run(); });
|
||||||
|
CHECK(jit.GetVector(0) == Vector{0x30010fe70da43740, 0x6702425b4a3a05d4});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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_executable(dynarmic_tests
|
add_executable(dynarmic_tests
|
||||||
fp/FPToFixed.cpp
|
fp/FPToFixed.cpp
|
||||||
fp/FPValue.cpp
|
fp/FPValue.cpp
|
||||||
@@ -44,13 +42,13 @@ if (DYNARMIC_TESTS_USE_UNICORN)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if ("riscv" IN_LIST ARCHITECTURE)
|
if (ARCHITECTURE_riscv64)
|
||||||
target_link_libraries(dynarmic_tests PRIVATE biscuit::biscuit)
|
target_link_libraries(dynarmic_tests PRIVATE biscuit::biscuit)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if ("x86_64" IN_LIST ARCHITECTURE)
|
if (ARCHITECTURE_x86_64)
|
||||||
target_link_libraries(dynarmic_tests PRIVATE xbyak::xbyak)
|
target_link_libraries(dynarmic_tests PRIVATE xbyak::xbyak)
|
||||||
target_architecture_specific_sources(dynarmic_tests "x86_64"
|
target_sources(dynarmic_tests PRIVATE
|
||||||
x64_cpu_info.cpp
|
x64_cpu_info.cpp
|
||||||
native/preserve_xmm.cpp
|
native/preserve_xmm.cpp
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ struct HostTranslateInfo {
|
|||||||
bool support_conditional_barrier{}; ///< True when the device supports barriers in conditional
|
bool support_conditional_barrier{}; ///< True when the device supports barriers in conditional
|
||||||
///< control flow
|
///< control flow
|
||||||
bool single_lane_geometry_subgroups{};
|
bool single_lane_geometry_subgroups{};
|
||||||
|
bool support_attribute_texture_handle{}; ///< True when the host binds texture handles that
|
||||||
|
///< arrive as vertex attributes
|
||||||
|
|
||||||
void ApplyDescriptorLimitPolicy() noexcept {
|
void ApplyDescriptorLimitPolicy() noexcept {
|
||||||
if (min_ssbo_alignment == 0) {
|
if (min_ssbo_alignment == 0) {
|
||||||
|
|||||||
@@ -322,6 +322,10 @@ static inline u32 ReadCbufCached(Environment& env, u32 index, u32 offset) {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool IsAttributeHandle(const ConstBufferAddr& cbuf) {
|
||||||
|
return cbuf.index == ATTRIBUTE_HANDLE_CBUF_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
static inline u32 GetTextureHandleCached(Environment& env, const ConstBufferAddr& cbuf) {
|
static inline u32 GetTextureHandleCached(Environment& env, const ConstBufferAddr& cbuf) {
|
||||||
// Must all be uniquely different variables
|
// Must all be uniquely different variables
|
||||||
// If has secondary, then it will be cbuf.secondary_{index|offset}, else its 0.
|
// If has secondary, then it will be cbuf.secondary_{index|offset}, else its 0.
|
||||||
@@ -341,14 +345,23 @@ static inline u32 GetTextureHandleCached(Environment& env, const ConstBufferAddr
|
|||||||
|
|
||||||
// Cached variants of existing helpers
|
// Cached variants of existing helpers
|
||||||
static inline TextureType ReadTextureTypeCached(Environment& env, const ConstBufferAddr& cbuf) {
|
static inline TextureType ReadTextureTypeCached(Environment& env, const ConstBufferAddr& cbuf) {
|
||||||
|
if (IsAttributeHandle(cbuf)) {
|
||||||
|
return TextureType::Color2D;
|
||||||
|
}
|
||||||
return env.ReadTextureType(GetTextureHandleCached(env, cbuf));
|
return env.ReadTextureType(GetTextureHandleCached(env, cbuf));
|
||||||
}
|
}
|
||||||
static inline TexturePixelFormat ReadTexturePixelFormatCached(Environment& env,
|
static inline TexturePixelFormat ReadTexturePixelFormatCached(Environment& env,
|
||||||
const ConstBufferAddr& cbuf) {
|
const ConstBufferAddr& cbuf) {
|
||||||
|
if (IsAttributeHandle(cbuf)) {
|
||||||
|
return TexturePixelFormat::A8B8G8R8_UNORM;
|
||||||
|
}
|
||||||
return env.ReadTexturePixelFormat(GetTextureHandleCached(env, cbuf));
|
return env.ReadTexturePixelFormat(GetTextureHandleCached(env, cbuf));
|
||||||
}
|
}
|
||||||
static inline bool IsTexturePixelFormatIntegerCached(Environment& env,
|
static inline bool IsTexturePixelFormatIntegerCached(Environment& env,
|
||||||
const ConstBufferAddr& cbuf) {
|
const ConstBufferAddr& cbuf) {
|
||||||
|
if (IsAttributeHandle(cbuf)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return env.IsTexturePixelFormatInteger(GetTextureHandleCached(env, cbuf));
|
return env.IsTexturePixelFormatInteger(GetTextureHandleCached(env, cbuf));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,15 +533,43 @@ std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst, Environme
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsAttributeSourcedHandle(const IR::Value& handle) {
|
||||||
|
if (handle.IsImmediate()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const IR::Inst* inst{handle.InstRecursive()};
|
||||||
|
if (inst->GetOpcode() == IR::Opcode::BitCastU32F32 && !inst->Arg(0).IsImmediate()) {
|
||||||
|
inst = inst->Arg(0).InstRecursive();
|
||||||
|
}
|
||||||
|
return inst->GetOpcode() == IR::Opcode::GetAttribute ||
|
||||||
|
inst->GetOpcode() == IR::Opcode::GetAttributeU32;
|
||||||
|
}
|
||||||
|
|
||||||
TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst, const HostTranslateInfo& host_info) {
|
TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst, const HostTranslateInfo& host_info) {
|
||||||
ConstBufferAddr addr;
|
ConstBufferAddr addr;
|
||||||
if (IsBindless(inst)) {
|
if (IsBindless(inst)) {
|
||||||
const std::optional<ConstBufferAddr> track_addr{TrackCached(inst.Arg(0), env, host_info, block)};
|
const std::optional<ConstBufferAddr> track_addr{TrackCached(inst.Arg(0), env, host_info, block)};
|
||||||
|
|
||||||
if (!track_addr) {
|
if (track_addr) {
|
||||||
throw NotImplementedException("Failed to track bindless texture constant buffer");
|
|
||||||
} else {
|
|
||||||
addr = *track_addr;
|
addr = *track_addr;
|
||||||
|
} else if (host_info.support_attribute_texture_handle &&
|
||||||
|
IsAttributeSourcedHandle(inst.Arg(0))) {
|
||||||
|
// The handle travels with the vertices (sprite batches pick the texture per quad), so
|
||||||
|
// there is no constant buffer to read it from. The host binds the handle of each run
|
||||||
|
// of vertices that share one.
|
||||||
|
addr = ConstBufferAddr{
|
||||||
|
.index = ATTRIBUTE_HANDLE_CBUF_INDEX,
|
||||||
|
.offset = 0,
|
||||||
|
.shift_left = 0,
|
||||||
|
.secondary_index = 0,
|
||||||
|
.secondary_offset = 0,
|
||||||
|
.secondary_shift_left = 0,
|
||||||
|
.dynamic_offset = {},
|
||||||
|
.count = 1,
|
||||||
|
.has_secondary = false,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
throw NotImplementedException("Failed to track bindless texture constant buffer");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
addr = ConstBufferAddr{
|
addr = ConstBufferAddr{
|
||||||
|
|||||||
@@ -38,6 +38,10 @@ enum class TextureType : u32 {
|
|||||||
};
|
};
|
||||||
constexpr u32 NUM_TEXTURE_TYPES = 9;
|
constexpr u32 NUM_TEXTURE_TYPES = 9;
|
||||||
|
|
||||||
|
/// Constant buffer index marking a texture handle that the shader receives as a vertex attribute
|
||||||
|
/// instead of reading it from a constant buffer. The host supplies the handle of each draw run.
|
||||||
|
constexpr u32 ATTRIBUTE_HANDLE_CBUF_INDEX = 0xFFFF;
|
||||||
|
|
||||||
enum class TexturePixelFormat {
|
enum class TexturePixelFormat {
|
||||||
A8B8G8R8_UNORM,
|
A8B8G8R8_UNORM,
|
||||||
A8B8G8R8_SNORM,
|
A8B8G8R8_SNORM,
|
||||||
|
|||||||
@@ -276,6 +276,9 @@ GraphicsPipeline::GraphicsPipeline(
|
|||||||
num_textures += Shader::NumDescriptors(info->texture_descriptors);
|
num_textures += Shader::NumDescriptors(info->texture_descriptors);
|
||||||
num_image_elements += Shader::NumDescriptors(info->texture_descriptors);
|
num_image_elements += Shader::NumDescriptors(info->texture_descriptors);
|
||||||
num_image_elements += Shader::NumDescriptors(info->image_descriptors);
|
num_image_elements += Shader::NumDescriptors(info->image_descriptors);
|
||||||
|
for (const auto& desc : info->texture_descriptors) {
|
||||||
|
uses_attribute_handle |= desc.cbuf_index == Shader::ATTRIBUTE_HANDLE_CBUF_INDEX;
|
||||||
|
}
|
||||||
num_descriptor_entries += NumDescriptorEntries(*info);
|
num_descriptor_entries += NumDescriptorEntries(*info);
|
||||||
}
|
}
|
||||||
fragment_has_color0_output = stage_infos[NUM_STAGES - 1].stores_frag_color[0];
|
fragment_has_color0_output = stage_infos[NUM_STAGES - 1].stores_frag_color[0];
|
||||||
@@ -375,6 +378,9 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
|
|||||||
}
|
}
|
||||||
const auto& cbufs{maxwell3d->state.shader_stages[stage].const_buffers};
|
const auto& cbufs{maxwell3d->state.shader_stages[stage].const_buffers};
|
||||||
const auto read_handle{[&](const auto& desc, u32 index) {
|
const auto read_handle{[&](const auto& desc, u32 index) {
|
||||||
|
if (desc.cbuf_index == Shader::ATTRIBUTE_HANDLE_CBUF_INDEX) {
|
||||||
|
return TexturePair(attribute_handle, via_header_index);
|
||||||
|
}
|
||||||
ASSERT(cbufs[desc.cbuf_index].enabled);
|
ASSERT(cbufs[desc.cbuf_index].enabled);
|
||||||
const u32 index_offset{index << desc.size_shift};
|
const u32 index_offset{index << desc.size_shift};
|
||||||
const u32 offset{desc.cbuf_offset + index_offset};
|
const u32 offset{desc.cbuf_offset + index_offset};
|
||||||
|
|||||||
@@ -110,6 +110,16 @@ public:
|
|||||||
return configure_func(this, is_indexed);
|
return configure_func(this, is_indexed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// True when a shader samples a texture whose handle arrives as a vertex attribute.
|
||||||
|
[[nodiscard]] bool UsesAttributeHandle() const noexcept {
|
||||||
|
return uses_attribute_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handle bound to those textures by the next Configure.
|
||||||
|
void SetAttributeHandle(u32 handle) noexcept {
|
||||||
|
attribute_handle = handle;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] GraphicsPipeline* Next(const GraphicsPipelineCacheKey& current_key) noexcept {
|
[[nodiscard]] GraphicsPipeline* Next(const GraphicsPipelineCacheKey& current_key) noexcept {
|
||||||
if (key == current_key) {
|
if (key == current_key) {
|
||||||
return this;
|
return this;
|
||||||
@@ -168,6 +178,8 @@ private:
|
|||||||
u32 num_descriptor_entries{};
|
u32 num_descriptor_entries{};
|
||||||
size_t num_image_elements{};
|
size_t num_image_elements{};
|
||||||
u32 num_textures{};
|
u32 num_textures{};
|
||||||
|
u32 attribute_handle{};
|
||||||
|
bool uses_attribute_handle{};
|
||||||
bool fragment_has_color0_output{};
|
bool fragment_has_color0_output{};
|
||||||
|
|
||||||
vk::DescriptorSetLayout descriptor_set_layout;
|
vk::DescriptorSetLayout descriptor_set_layout;
|
||||||
|
|||||||
@@ -493,6 +493,7 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
|
|||||||
.support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(),
|
.support_geometry_shader_passthrough = device.IsNvGeometryShaderPassthroughSupported(),
|
||||||
.support_conditional_barrier = device.SupportsConditionalBarriers(),
|
.support_conditional_barrier = device.SupportsConditionalBarriers(),
|
||||||
.single_lane_geometry_subgroups = !profile.SupportsSubgroupStage(Shader::Stage::Geometry),
|
.single_lane_geometry_subgroups = !profile.SupportsSubgroupStage(Shader::Stage::Geometry),
|
||||||
|
.support_attribute_texture_handle = true,
|
||||||
};
|
};
|
||||||
host_info.ApplyDescriptorLimitPolicy();
|
host_info.ApplyDescriptorLimitPolicy();
|
||||||
|
|
||||||
|
|||||||
@@ -253,6 +253,15 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
|
|||||||
std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
|
std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
|
||||||
// update engine as channel may be different.
|
// update engine as channel may be different.
|
||||||
pipeline->SetEngine(maxwell3d, gpu_memory);
|
pipeline->SetEngine(maxwell3d, gpu_memory);
|
||||||
|
attribute_handle_pipeline = nullptr;
|
||||||
|
attribute_handle_runs.clear();
|
||||||
|
if (split_attribute_handles && pipeline->UsesAttributeHandle()) {
|
||||||
|
CollectAttributeHandleRuns(is_indexed);
|
||||||
|
if (!attribute_handle_runs.empty()) {
|
||||||
|
attribute_handle_pipeline = pipeline;
|
||||||
|
pipeline->SetAttributeHandle(attribute_handle_runs.front().handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!pipeline->Configure(is_indexed))
|
if (!pipeline->Configure(is_indexed))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -264,22 +273,110 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
|
|||||||
draw_func();
|
draw_func();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterizerVulkan::CollectAttributeHandleRuns(bool is_indexed) {
|
||||||
|
using VertexAttribute = Maxwell::VertexAttribute;
|
||||||
|
const auto& regs = maxwell3d->regs;
|
||||||
|
const auto& draw_state = maxwell3d->draw_manager.draw_state;
|
||||||
|
const u32 total = is_indexed ? draw_state.index_buffer.count : draw_state.vertex_buffer.count;
|
||||||
|
if (total == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// The handle is an integer attribute; sprite batches repeat it on every vertex of a quad.
|
||||||
|
const VertexAttribute* source{};
|
||||||
|
for (const auto& attr : regs.vertex_attrib_format) {
|
||||||
|
if (attr.constant || attr.size == VertexAttribute::Size::Invalid) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (attr.type == VertexAttribute::Type::UInt || attr.type == VertexAttribute::Type::SInt) {
|
||||||
|
source = &attr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto& stream = regs.vertex_streams[source ? source->buffer.Value() : 0];
|
||||||
|
if (!source || !stream.IsEnabled()) {
|
||||||
|
attribute_handle_runs.push_back({0, total, 0});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Only plain triangle lists are split; anything else keeps the handle of its first vertex.
|
||||||
|
const u32 primitive_size =
|
||||||
|
draw_state.topology == Maxwell::PrimitiveTopology::Triangles ? 3 : total;
|
||||||
|
const GPUVAddr base_address = stream.Address() + source->offset;
|
||||||
|
const auto read_handle = [&](u32 position) {
|
||||||
|
u32 vertex;
|
||||||
|
if (is_indexed) {
|
||||||
|
const auto& index_buffer = draw_state.index_buffer;
|
||||||
|
const GPUVAddr address =
|
||||||
|
index_buffer.IndexStart() + size_t{position} * index_buffer.FormatSizeInBytes();
|
||||||
|
u32 index{};
|
||||||
|
gpu_memory->ReadBlockUnsafe(address, &index, index_buffer.FormatSizeInBytes());
|
||||||
|
vertex = static_cast<u32>(draw_state.base_index + index);
|
||||||
|
} else {
|
||||||
|
vertex = draw_state.vertex_buffer.first + position;
|
||||||
|
}
|
||||||
|
return gpu_memory->Read<u32>(base_address + static_cast<GPUVAddr>(vertex) * stream.stride);
|
||||||
|
};
|
||||||
|
for (u32 position = 0; position + primitive_size <= total; position += primitive_size) {
|
||||||
|
const u32 handle = read_handle(position);
|
||||||
|
if (!attribute_handle_runs.empty() && attribute_handle_runs.back().handle == handle) {
|
||||||
|
attribute_handle_runs.back().count += primitive_size;
|
||||||
|
} else {
|
||||||
|
attribute_handle_runs.push_back({position, primitive_size, handle});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (attribute_handle_runs.empty()) {
|
||||||
|
attribute_handle_runs.push_back({0, total, read_handle(0)});
|
||||||
|
} else {
|
||||||
|
const u32 covered = attribute_handle_runs.back().first + attribute_handle_runs.back().count;
|
||||||
|
if (covered < total) {
|
||||||
|
attribute_handle_runs.back().count += total - covered;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) {
|
void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) {
|
||||||
|
split_attribute_handles = true;
|
||||||
|
SCOPE_EXIT {
|
||||||
|
split_attribute_handles = false;
|
||||||
|
};
|
||||||
PrepareDraw(is_indexed, [this, is_indexed, instance_count] {
|
PrepareDraw(is_indexed, [this, is_indexed, instance_count] {
|
||||||
const auto& draw_state = maxwell3d->draw_manager.draw_state;
|
const auto& draw_state = maxwell3d->draw_manager.draw_state;
|
||||||
const u32 num_instances{instance_count};
|
const u32 num_instances{instance_count};
|
||||||
const DrawParams draw_params{MakeDrawParams(draw_state, num_instances, is_indexed)};
|
const DrawParams draw_params{MakeDrawParams(draw_state, num_instances, is_indexed)};
|
||||||
|
|
||||||
scheduler.Record([draw_params](vk::CommandBuffer cmdbuf) {
|
const auto record_draw = [this](const DrawParams& params) {
|
||||||
if (draw_params.is_indexed) {
|
scheduler.Record([params](vk::CommandBuffer cmdbuf) {
|
||||||
cmdbuf.DrawIndexed(draw_params.num_vertices, draw_params.num_instances,
|
if (params.is_indexed) {
|
||||||
draw_params.first_index, draw_params.base_vertex,
|
cmdbuf.DrawIndexed(params.num_vertices, params.num_instances,
|
||||||
draw_params.base_instance);
|
params.first_index, params.base_vertex,
|
||||||
|
params.base_instance);
|
||||||
} else {
|
} else {
|
||||||
cmdbuf.Draw(draw_params.num_vertices, draw_params.num_instances,
|
cmdbuf.Draw(params.num_vertices, params.num_instances, params.base_vertex,
|
||||||
draw_params.base_vertex, draw_params.base_instance);
|
params.base_instance);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
if (attribute_handle_pipeline && attribute_handle_runs.size() > 1) {
|
||||||
|
// The first run is already configured, each further one binds its own texture.
|
||||||
|
for (size_t i = 0; i < attribute_handle_runs.size(); ++i) {
|
||||||
|
const AttributeHandleRun& run = attribute_handle_runs[i];
|
||||||
|
if (i != 0) {
|
||||||
|
attribute_handle_pipeline->SetAttributeHandle(run.handle);
|
||||||
|
if (!attribute_handle_pipeline->Configure(is_indexed)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DrawParams run_params = draw_params;
|
||||||
|
run_params.num_vertices = run.count;
|
||||||
|
if (is_indexed) {
|
||||||
|
run_params.first_index += run.first;
|
||||||
|
} else {
|
||||||
|
run_params.base_vertex += run.first;
|
||||||
|
}
|
||||||
|
record_draw(run_params);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
record_draw(draw_params);
|
||||||
|
}
|
||||||
|
|
||||||
// Log draw call
|
// Log draw call
|
||||||
if (GPU::Logging::IsActive() &&
|
if (GPU::Logging::IsActive() &&
|
||||||
|
|||||||
@@ -157,6 +157,20 @@ private:
|
|||||||
template <typename Func>
|
template <typename Func>
|
||||||
void PrepareDraw(bool is_indexed, Func&&);
|
void PrepareDraw(bool is_indexed, Func&&);
|
||||||
|
|
||||||
|
/// A stretch of a draw whose vertices all carry the same texture handle.
|
||||||
|
struct AttributeHandleRun {
|
||||||
|
u32 first;
|
||||||
|
u32 count;
|
||||||
|
u32 handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Splits the current draw wherever the texture handle carried in the vertex data changes.
|
||||||
|
void CollectAttributeHandleRuns(bool is_indexed);
|
||||||
|
|
||||||
|
std::vector<AttributeHandleRun> attribute_handle_runs;
|
||||||
|
GraphicsPipeline* attribute_handle_pipeline{};
|
||||||
|
bool split_attribute_handles{};
|
||||||
|
|
||||||
void FlushWork();
|
void FlushWork();
|
||||||
|
|
||||||
void UpdateDynamicStates();
|
void UpdateDynamicStates();
|
||||||
|
|||||||
@@ -8,3 +8,8 @@ NPROC=$(nproc 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n
|
|||||||
|
|
||||||
# shellcheck disable=SC2038
|
# shellcheck disable=SC2038
|
||||||
find . -type f -iname '*.png' | xargs -P "$NPROC" -I {} optipng -o7 {}
|
find . -type f -iname '*.png' | xargs -P "$NPROC" -I {} optipng -o7 {}
|
||||||
|
|
||||||
|
which svgo || exit
|
||||||
|
|
||||||
|
# shellcheck disable=SC2038
|
||||||
|
find . -type f -iname '*.svg' | xargs -P "$NPROC" -I {} svgo {}
|
||||||
|
|||||||