Compare commits

..

39 Commits

Author SHA1 Message Date
lizzie a19d270b3f fix emul atomic 2026-05-14 01:53:53 +02:00
lizzie 9723e348d4 [hid_core] remove contentious mutex from EmulatedController and just rely on atomic semantics for fields
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-05-14 01:53:53 +02:00
lizzie db7ed8f95a license 2026-05-14 01:53:53 +02:00
lizzie 5a7f17d118 fx 2026-05-14 01:53:53 +02:00
lizzie 50d6f30d60 [dynarmic, macroHLE] Use faster ankerl for xbyak maps
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-05-14 01:53:53 +02:00
lizzie bfcbf27794 fix windows shit 2026-05-14 01:53:53 +02:00
lizzie 6c0c1535d5 fuck android 2026-05-14 01:53:53 +02:00
lizzie 66b8d0b5c1 fixup nce 2026-05-14 01:53:53 +02:00
lizzie 8bc6868fcf rem indir func 2026-05-14 01:53:53 +02:00
lizzie 6d183b8e57 fix cmake 2026-05-14 01:53:53 +02:00
lizzie 7bac557025 [common] remove ptr indirection on WallClock
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-05-14 01:53:53 +02:00
lizzie e615845774 e 2026-05-14 01:53:53 +02:00
lizzie 6154679802 fuck fix 2026-05-14 01:53:53 +02:00
lizzie 0677e26387 f 2026-05-14 01:53:53 +02:00
lizzie b51165beae suboptimal cgen for windows 2026-05-14 01:53:53 +02:00
lizzie 3ff2d39faf oops 2026-05-14 01:53:53 +02:00
lizzie 6f974dca83 fix license 2026-05-14 01:53:53 +02:00
lizzie c9daf37714 [dynarmic] use constant resolution instead of clobbering a register when doing spinlocks
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-05-14 01:53:53 +02:00
lizzie 6db95b529f use 2mb pages 2026-05-14 01:53:53 +02:00
lizzie 8581d95b82 oopsie 2026-05-14 01:53:53 +02:00
lizzie 170669fbd2 fix linux readahead 2026-05-14 01:53:53 +02:00
lizzie 4e09c6a23f alignment with log2 2026-05-14 01:53:53 +02:00
lizzie 1a74f10c9d license 2026-05-14 01:53:53 +02:00
Caio Oliveira a47b1459ab f you msvc 2026-05-14 01:53:53 +02:00
Caio Oliveira 74772d651c [chore] It can possible kill someone
Signed-off-by: Caio Oliveira <caiooliveirafarias0@gmail.com>
2026-05-14 01:53:53 +02:00
lizzie 8a8e75a99a [chore] Fix windows building 2026-05-14 01:53:53 +02:00
lizzie f4d54772f1 Add for windows and Android 2026-05-14 01:53:53 +02:00
lizzie 32fa2475d3 fuck macos 2026-05-14 01:53:53 +02:00
lizzie 29ca9aded2 super align + nosync opts 2026-05-14 01:53:53 +02:00
lizzie 66c0a295da add cstring 4 std::memcpy 2026-05-14 01:53:53 +02:00
lizzie 720e6fedb5 fucking license 2026-05-14 01:53:53 +02:00
lizzie 8fff64adc3 [fs] use mmap() to read files off the mmap system for higher throughput
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-05-14 01:53:53 +02:00
lizzie 57ddcf73b1 fx 2026-05-14 01:53:53 +02:00
lizzie 9d1bb08333 fx 2026-05-14 01:53:53 +02:00
lizzie eb1c28d494 ershuf 2026-05-14 01:53:53 +02:00
lizzie 5da1621921 better generation of time system archives 2026-05-14 01:53:53 +02:00
lizzie f15846eb40 Revert "[externals] nuke nx_tzdb"
This reverts commit a0b68e383df1d39022479f11b1864484ce354db9.
2026-05-14 01:53:53 +02:00
lizzie 6c243241e4 [externals] nuke nx_tzdb
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-05-14 01:53:53 +02:00
lizzie d1ceeeca22 [cmake] use -mtls-dialect=gnu2 (#3948)
see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120933

we use TLS very sparingly (which is a good thing), some of our dependencies, in turn, may not
we should be aware of that fact

allegedly, there are minor glibc issues and such, but most distros should be fine
additionally, this is only enabled for FreeBSD and Linux, if it works on FreeBSD, naturally every Linux distro should support it as well

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

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3948
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: Maufeat <sahyno1996@gmail.com>
2026-05-14 00:17:13 +02:00
161 changed files with 19329 additions and 20823 deletions
+5 -6
View File
@@ -7,7 +7,7 @@
EXCLUDE_FILES="CPM.cmake CPMUtil.cmake GetSCMRev.cmake renderdoc_app.h tools/cpm tools/shellcheck.sh tools/update-cpm.sh tools/windows/vcvarsall.sh externals/stb externals/glad externals/getopt externals/gamemode externals/FidelityFX-FSR externals/demangle externals/bc_decoder externals/cmake-modules"
# license header constants, please change when needed :))))
YEAR=$(date "+%Y")
YEAR=2026
HOLDER="Eden Emulator Project"
LICENSE="GPL-3.0-or-later"
@@ -112,10 +112,10 @@ for file in $FILES; do
[ "$excluded" = "true" ] && continue
case "$file" in
*.cmake|*.sh|*.ps1|*.py|*.rb|*.perl|*.pl|*.nix|*CMakeLists.txt)
*.cmake|*.sh|*CMakeLists.txt)
begin="#"
;;
*.kt|*.kts|*.cpp|*.h|*.qml|*.c|*.hpp|*.hxx|*.cxx|*.h.in|*.inc)
*.kt*|*.cpp|*.h|*.qml)
begin="//"
;;
*)
@@ -185,12 +185,11 @@ if [ "$UPDATE" = "true" ]; then
for file in $SRC_FILES $OTHER_FILES; do
case $(basename -- "$file") in
# Windows Powershell wont use shebangs
*.cmake|*.ps1|*CMakeLists.txt)
*.cmake|*CMakeLists.txt)
begin="#"
shell="false"
;;
*.sh|*.py|*.rb|*.perl|*.pl|*.nix)
*.sh)
begin="#"
shell=true
;;
Executable
+22
View File
@@ -0,0 +1,22 @@
#!/bin/bash -ex
# git-archive-all
export PATH="$PATH:/home/$USER/.local/bin"
GITDATE="`git show -s --date=short --format='%ad' | sed 's/-//g'`"
GITREV="`git show -s --format='%h'`"
REV_NAME="eden-unified-source-${GITDATE}-${GITREV}"
COMPAT_LIST='dist/compatibility_list/compatibility_list.json'
mkdir artifacts
touch "${COMPAT_LIST}"
git describe --abbrev=0 --always HEAD > GIT-COMMIT
git describe --tags HEAD > GIT-TAG || echo 'unknown' > GIT-TAG
git-archive-all --include "${COMPAT_LIST}" --include GIT-COMMIT --include GIT-TAG --force-submodules artifacts/"${REV_NAME}.tar"
cd artifacts/
xz -T0 -9 "${REV_NAME}.tar"
sha256sum "${REV_NAME}.tar.xz" > "${REV_NAME}.tar.xz.sha256sum"
cd ..
+133 -74
View File
@@ -6,8 +6,8 @@
viewBox="0 0 512 512"
version="1.1"
id="svg7"
sodipodi:docname="base.svg.2026_01_12_14_43_47.0.svg"
inkscape:version="1.4.2 (ebf0e94, 2025-05-08)"
sodipodi:docname="1stanni.svg"
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
inkscape:export-filename="base.svg.2026_01_12_14_43_47.0.svg"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
@@ -19,36 +19,34 @@
<defs
id="defs7">
<linearGradient
id="linearGradient1"
id="linearGradient34"
inkscape:collect="always">
<stop
style="stop-color:#ff2e88;stop-opacity:0.5;"
style="stop-color:#ffd700;stop-opacity:1;"
offset="0"
id="stop3" />
id="stop34" />
<stop
style="stop-color:#bf42f6;stop-opacity:0.5;"
offset="0.44631511"
id="stop4" />
<stop
style="stop-color:#5da5ed;stop-opacity:0.5;"
offset="0.90088946"
id="stop2" />
style="stop-color:#ffd700;stop-opacity:0.48031053;"
offset="1"
id="stop35" />
</linearGradient>
<rect
x="20.999999"
y="287.30493"
width="487.07235"
height="134.69506"
id="rect22" />
<linearGradient
id="linearGradient138"
id="linearGradient21"
inkscape:collect="always">
<stop
style="stop-color:#ff2e88;stop-opacity:1;"
style="stop-color:#3a0057;stop-opacity:1;"
offset="0"
id="stop152" />
id="stop21" />
<stop
style="stop-color:#bf42f6;stop-opacity:1;"
offset="0.44971901"
id="stop137" />
<stop
style="stop-color:#5da5ed;stop-opacity:1;"
offset="0.89793283"
id="stop138" />
style="stop-color:#830091;stop-opacity:1;"
offset="1"
id="stop22" />
</linearGradient>
<linearGradient
id="swatch37"
@@ -116,33 +114,6 @@
width="521.34025"
height="248.94868"
id="rect24" />
<linearGradient
id="linearGradient11"
inkscape:collect="always">
<stop
style="stop-color:#ff2e88;stop-opacity:1;"
offset="0"
id="stop11" />
<stop
style="stop-color:#bf42f6;stop-opacity:1;"
offset="0.44971901"
id="stop154" />
<stop
style="stop-color:#5da5ed;stop-opacity:1;"
offset="0.89793283"
id="stop12" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient138"
id="linearGradient6"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.118028,0,0,1.116699,-46.314723,-42.388667)"
x1="270.39996"
y1="40.000019"
x2="270.39996"
y2="494.39996"
spreadMethod="pad" />
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath18">
@@ -165,16 +136,6 @@
inkscape:label="Circle"
r="191.89999" />
</clipPath>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient11"
id="linearGradient27"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-6.9401139e-5,-2.8678628)"
x1="256.00012"
y1="102.94693"
x2="256.00012"
y2="409.05307" />
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath128">
@@ -187,14 +148,106 @@
</clipPath>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient1"
id="linearGradient2"
xlink:href="#linearGradient21"
id="linearGradient22"
x1="256"
y1="64"
y1="0"
x2="256"
y2="448"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3229974,0,0,1.3214002,-82.687336,-82.290326)" />
y2="512"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient34"
id="linearGradient35"
x1="256"
y1="-0.048701428"
x2="256"
y2="512.04932"
gradientUnits="userSpaceOnUse" />
<filter
inkscape:label="Glowing Bubble"
inkscape:menu="Ridges"
inkscape:menu-tooltip="Bubble effect with refraction and glow"
x="-0.19420711"
y="-0.11239541"
width="1.3884142"
height="1.2247908"
style="color-interpolation-filters:sRGB;"
id="filter61">
<feGaussianBlur
stdDeviation="1"
result="result1"
id="feGaussianBlur56" />
<feGaussianBlur
stdDeviation="10"
result="result6"
in="result1"
id="feGaussianBlur57" />
<feComposite
operator="atop"
in="result6"
in2="result1"
result="result8"
id="feComposite57" />
<feComposite
operator="xor"
result="fbSourceGraphic"
in="result6"
in2="result8"
id="feComposite58" />
<feColorMatrix
result="fbSourceGraphicAlpha"
in="fbSourceGraphic"
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 2 0 "
id="feColorMatrix58" />
<feGaussianBlur
result="result0"
in="fbSourceGraphicAlpha"
stdDeviation="1"
id="feGaussianBlur58" />
<feSpecularLighting
specularExponent="35"
specularConstant="1.5"
surfaceScale="-2"
lighting-color="rgb(255,255,255)"
result="result1"
in="result0"
id="feSpecularLighting58">
<feDistantLight
azimuth="230"
elevation="60"
id="feDistantLight58" />
</feSpecularLighting>
<feComposite
operator="in"
result="result2"
in="result1"
in2="fbSourceGraphicAlpha"
id="feComposite59" />
<feComposite
k3="1.2"
k2="1.1"
operator="arithmetic"
result="result4"
in="fbSourceGraphic"
in2="result2"
id="feComposite60" />
<feGaussianBlur
result="result80"
in="result4"
stdDeviation="0.5"
id="feGaussianBlur60" />
<feComposite
operator="atop"
in="result9"
in2="result80"
result="result91"
id="feComposite61" />
<feBlend
mode="multiply"
in2="result91"
id="feBlend61" />
</filter>
</defs>
<sodipodi:namedview
id="namedview7"
@@ -205,23 +258,29 @@
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="1.4142136"
inkscape:cx="261.62951"
inkscape:cy="230.87036"
inkscape:window-width="1920"
inkscape:window-height="1008"
inkscape:window-x="1080"
inkscape:window-y="351"
inkscape:zoom="1"
inkscape:cx="213.49999"
inkscape:cy="248.99999"
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(#linearGradient22);fill-opacity:1;stroke:none;stroke-width:8"
id="path21"
cx="256"
cy="256"
r="256" />
<path
id="path8-7"
style="display:inline;mix-blend-mode:multiply;fill:url(#linearGradient6);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient2);stroke-width:3.9666;stroke-dasharray:none;stroke-opacity:0.566238;paint-order:stroke fill markers"
style="display:inline;mix-blend-mode:normal;fill:url(#linearGradient35);fill-opacity:1;fill-rule:nonzero;stroke:#320081;stroke-width:4.067;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
inkscape:label="Circle"
d="M 256,2.2792898 A 254.0155,253.71401 0 0 0 150.68475,25.115202 c 19.54414,1.070775 38.74692,5.250294 51.56848,11.647658 14.14361,7.056691 28.63804,19.185961 39.4212,29.347551 h 40.60981 c 1.03847,-0.68139 2.10297,-1.36938 3.1938,-2.05957 5.45602,-15.78533 14.79164,-43.183497 19.49612,-57.0097682 A 254.0155,253.71401 0 0 0 256,2.2792898 Z m 61.57106,7.567234 -18.26098,46.1544672 c 7.79702,-4.13918 16.35655,-7.87447 25.20671,-10.87081 23.1229,-7.828433 43.96931,-10.170904 54.94058,-10.868226 A 254.0155,253.71401 0 0 0 317.57106,9.8465238 Z m 65.39277,26.4001532 c -9.68256,4.806644 -33.05532,16.642034 -55.68217,29.863734 H 424.4677 A 254.0155,253.71401 0 0 0 382.96383,36.246677 Z M 113.90698,45.690231 A 254.0155,253.71401 0 0 0 87.532302,66.110411 H 194.2739 c -1.47402,-0.80231 -2.35141,-1.25949 -2.35141,-1.25949 l 10.4496,-11.83348 -38.40568,7.01234 c 0,1e-5 -12.21537,-4.60266 -40.17313,-12.27223 -3.45336,-0.94731 -6.75329,-1.61824 -9.8863,-2.06732 z m -36.803618,30.18635 a 254.0155,253.71401 0 0 0 -34.88372,43.090929 h 59.976738 c 18.11461,-12.04145 40.14252,-22.882149 62.31266,-24.534159 52.93006,-3.9444 70.16538,1.86342 70.16538,1.86342 0,0 -4.612,-4.8206 -14.51938,-13.36656 -2.72366,-2.34942 -6.0844,-4.77373 -9.52455,-7.05363 z m 174.472868,0 c 4.57322,4.7186 7.29716,7.83565 7.29716,7.83565 0,0 3.53501,-3.18484 9.62532,-7.83565 z m 60.27649,0 c -21.56573,15.45339 -25.4703,27.979669 -25.4703,27.979669 0,0 54.83326,-19.215729 100.70543,-0.31228 11.63986,4.79661 21.58481,10.13159 29.94832,15.42354 h 52.74419 A 254.0155,253.71401 0 0 0 434.89664,75.876581 Z M 36.250648,128.73367 A 254.0155,253.71401 0 0 0 16.372095,171.82459 H 147.45478 c 1.45695,-2.5815 3.06539,-5.08648 4.83979,-7.48982 14.23694,-19.28301 27.92088,-30.0088 36.86047,-35.6011 h -30.25323 c -5.87346,0.93472 -12.04945,1.99094 -18.28166,3.16937 -30.12936,5.69727 -81.157618,22.78945 -81.157618,22.78945 0,0 11.47125,-12.39249 29.11369,-25.95882 z m 265.630492,0 c 33.48676,11.2434 52.42799,26.78443 62.7752,43.09092 h 130.97157 a 254.0155,253.71401 0 0 0 -19.87856,-43.09092 h -44.81136 c 14.85233,11.5863 21.59948,20.9854 21.59948,20.9854 0,0 -33.5226,-12.37087 -66.0646,-20.9854 z m -45.96641,16.27007 c -1.00419,0.0106 -10.12705,0.72026 -44.98966,20.64729 -3.12132,1.78406 -6.25434,3.86182 -9.37468,6.17356 h 41.81911 c 7.17181,-17.34774 12.64083,-26.82085 12.64083,-26.82085 0,0 -0.0287,-7.1e-4 -0.0957,0 z m 14.18088,0.0465 c 0,0 -3.31228,9.32762 -7.30492,26.77438 h 51.78554 C 287.6577,146.14158 270.09561,145.0502 270.09561,145.0502 Z M 13.152456,181.59075 A 254.0155,253.71401 0 0 0 3.927651,224.68167 H 134.1447 c 0.56161,-12.72411 2.67825,-28.50188 8.61499,-43.09092 z m 176.661504,0 c -14.27121,13.10564 -27.60733,29.58761 -37.56073,43.09092 h 73.3721 c 4.47018,-16.79061 9.35068,-31.26371 13.86562,-43.09092 z m 70.85787,0 c -2.41384,11.76417 -4.9032,26.20707 -6.94831,43.09092 H 360.4832 c -8.32133,-10.88917 -20.66988,-26.17008 -36.35141,-43.09092 z m 109.17313,0 c 6.63611,15.24089 6.92441,30.5373 5.57882,43.09092 h 132.64857 a 254.0155,253.71401 0 0 0 -9.22481,-43.09092 z M 2.90181,234.44783 A 254.0155,253.71401 0 0 0 1.984498,255.9933 254.0155,253.71401 0 0 0 2.90181,277.53876 h 211.89923 c 2.25762,-15.52555 5.14325,-29.93448 8.3385,-43.09093 h -77.8863 c -6.46396,9.27617 -10.33076,15.56549 -10.33076,15.56549 0,0 -0.82623,-6.14945 -0.9354,-15.56549 z m 249.72093,0 c -1.3692,13.09684 -2.4456,27.49209 -3.02068,43.09093 h 259.49613 a 254.0155,253.71401 0 0 0 0.91731,-21.54546 254.0155,253.71401 0 0 0 -0.91731,-21.54547 H 374.02584 c -0.445,2.5469 -0.90878,4.89768 -1.32817,7.01751 0,0 -1.69726,-2.53821 -4.94056,-7.01751 z M 3.927651,287.30493 a 254.0155,253.71401 0 0 0 9.224805,43.09091 H 214.04393 c -1.29238,-15.40742 -1.57503,-30.04388 -0.41861,-43.09091 z m 245.385009,0 c -0.30355,13.54349 -0.22032,27.92598 0.36951,43.09091 h 249.16537 a 254.0155,253.71401 0 0 0 9.22481,-43.09091 z M 16.369511,340.16201 a 254.0155,253.71401 0 0 0 19.878554,43.09091 H 221.4677 c -2.69781,-14.4523 -4.96108,-29.01285 -6.4832,-43.09091 z m 233.842379,0 c 1.15864,15.47765 3.81286,29.83979 7.51679,43.09091 h 218.02325 a 254.0155,253.71401 0 0 0 19.87856,-43.09091 z M 42.217052,393.01909 a 254.0155,253.71401 0 0 0 34.88372,43.09093 H 233.09561 c -3.40902,-13.67281 -6.76794,-28.2531 -9.73902,-43.09093 z m 218.490958,0 c 5.34985,16.15926 12.22007,30.51982 19.68733,43.09093 h 154.50389 a 254.0155,253.71401 0 0 0 34.88371,-43.09093 z M 87.529722,445.87618 a 254.0155,253.71401 0 0 0 166.229968,63.8208 c -3.67805,-12.0825 -10.85464,-35.49828 -18.18088,-63.8208 z m 199.010328,0 c 17.5887,26.43772 36.99259,43.60598 47.33592,51.61309 a 254.0155,253.71401 0 0 0 90.59431,-51.61309 z" />
<path
id="path27"
style="display:inline;mix-blend-mode:multiply;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient27);stroke-width:3;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
style="display:inline;mix-blend-mode:multiply;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
d="m 318.98012,441.7375 c -9.87518,-6.73978 -64.39137,-49.0272 -67.68975,-127.81978 -3.69298,-88.21893 15.36468,-141.91029 15.36468,-141.91029 0,0 16.00378,0.99513 39.80316,26.53195 23.79939,25.53753 37.74965,46.43102 37.74965,46.43102 3.91262,-19.79992 12.84563,-66.32402 -60.72865,-87.55523 0,0 12.82326,-5.38883 39.3925,-3.81382 26.56907,1.57572 81.6822,21.93799 81.6822,21.93799 0,0 -14.79766,-20.63773 -49.47063,-34.94295 -34.67291,-14.30533 -76.1182,0.23644 -76.1182,0.23644 0,0 3.86959,-12.43127 27.22669,-26.38478 23.35718,-13.9537 49.27409,-26.501533 49.27409,-26.501533 0,0 -21.97854,-0.26548 -47.67725,8.44535 -6.68948,2.267506 -13.15863,5.094213 -19.05208,8.226563 l 16.05803,-40.634103 -4.4617,-1.89059 -5.1305,-0.95965 c 0,0 -11.24072,33.12428 -16.92051,49.576513 -12.13137,7.68489 -20.11005,14.87735 -20.11005,14.87735 0,0 -21.90573,-25.09227 -42.79668,-35.527803 -26.03412,-13.00525 -86.88249,-13.90359 -94.0044,10.401173 0,0 13.56804,-7.884703 34.70032,-2.080917 21.13214,5.803997 30.3644,9.287307 30.3644,9.287307 l 29.02989,-5.30681 -7.89811,8.95527 c 0,0 13.8496,7.21324 21.33822,13.68063 7.48859,6.46722 10.9757,10.11472 10.9757,10.11472 0,0 -13.02739,-4.39388 -53.03507,-1.40893 -40.00771,2.98473 -79.40016,45.60209 -79.40016,45.60209 0,0 38.57037,-12.93531 61.34393,-17.24677 22.77354,-4.31126 44.52166,-6.46757 44.52166,-6.46757 0,0 -17.23298,5.97003 -35.69792,31.00932 -18.46522,25.03987 -13.13146,64.83866 -13.13146,64.83866 0,0 29.33874,-47.7577 57.44675,-63.84249 28.10798,-16.08527 34.0799,-15.6238 34.0799,-15.6238 0,0 -22.56785,39.13486 -31.39017,101.98268 -8.03005,57.2039 26.77689,163.75449 31.1572,178.89699"
sodipodi:nodetypes="cscsccscscscsccccccscscccscscscscscsc"
inkscape:label="MainOutline"

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 14 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 KiB

After

Width:  |  Height:  |  Size: 256 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 335 KiB

After

Width:  |  Height:  |  Size: 556 KiB

+612 -637
View File
File diff suppressed because it is too large Load Diff
+612 -636
View File
File diff suppressed because it is too large Load Diff
+612 -636
View File
File diff suppressed because it is too large Load Diff
+612 -636
View File
File diff suppressed because it is too large Load Diff
+612 -636
View File
File diff suppressed because it is too large Load Diff
+612 -636
View File
File diff suppressed because it is too large Load Diff
+618 -643
View File
File diff suppressed because it is too large Load Diff
+611 -635
View File
File diff suppressed because it is too large Load Diff
+611 -635
View File
File diff suppressed because it is too large Load Diff
+612 -636
View File
File diff suppressed because it is too large Load Diff
+612 -636
View File
File diff suppressed because it is too large Load Diff
+611 -635
View File
File diff suppressed because it is too large Load Diff
+612 -636
View File
File diff suppressed because it is too large Load Diff
+1465 -1591
View File
File diff suppressed because it is too large Load Diff
+612 -636
View File
File diff suppressed because it is too large Load Diff
+612 -636
View File
File diff suppressed because it is too large Load Diff
+613 -635
View File
File diff suppressed because it is too large Load Diff
+673 -700
View File
File diff suppressed because it is too large Load Diff
+612 -636
View File
File diff suppressed because it is too large Load Diff
+613 -637
View File
File diff suppressed because it is too large Load Diff
+613 -635
View File
File diff suppressed because it is too large Load Diff
+613 -637
View File
File diff suppressed because it is too large Load Diff
+612 -637
View File
File diff suppressed because it is too large Load Diff
+612 -636
View File
File diff suppressed because it is too large Load Diff
+612 -636
View File
File diff suppressed because it is too large Load Diff
+613 -635
View File
File diff suppressed because it is too large Load Diff
+613 -637
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 27 KiB

+1 -1
View File
@@ -46,7 +46,7 @@ Qt Widgets appears to be broken. For now, add `-DENABLE_QT=OFF` to your configur
This is needed for some dependencies that call cc directly (tz):
```sh
echo '#!/bin/sh -e' >cc
echo '#!/bin/sh' >cc
echo 'gcc $@' >>cc
chmod +x cc
export PATH="$PATH:$PWD"
+1 -1
View File
@@ -59,7 +59,7 @@ EmuDeck will automatically create an *Emulators - Emulators* parser for ***Steam
4. Paste the following code into the contents of the file, save and close the file.
```bash
#!/bin/sh -e
#!/bin/bash
emuName="eden" #parameterize me
. "$HOME/.config/EmuDeck/backend/functions/all.sh"
-1
View File
@@ -13,7 +13,6 @@ The main origin repository is always at https://git.eden-emu.dev/eden-emu/eden.
- https://github.com/eden-emulator/mirror
- https://git.crueter.xyz/mirror/eden
- https://codeberg.org/eden-emu/eden
- https://collective.taymaerz.de/eden/eden
Other mirrors obviously exist on the internet, but we can't guarantee their reliability and/or availability.
+1
View File
@@ -30,6 +30,7 @@
"tag": "v%VERSION%",
"hash": "5efa8140aadffe105dcf39935b732476e95755f6c7473ada3d0b64df2bc02c557633ae3948a25b45e1cf67e89a3ff6329fb30362e4ac033b9a1d1e453aa2eded",
"git_version": "0.37.0",
"version": "0.18.7",
"find_args": "MODULE GLOBAL",
"patches": [
"0001-mingw.patch",
+21 -6
View File
@@ -1,3 +1,6 @@
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2023 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
@@ -16,15 +19,24 @@ if (NOT FILE_LIST)
endif()
set(DIRECTORY_NAME ${HEADER_NAME})
set(FILE_DATA "")
string(APPEND FILE_DATA "[[nodiscard]] static inline std::vector<FileSys::VirtualFile> CollectFiles_${DIRECTORY_NAME}() {\n")
string(APPEND FILE_DATA [[
std::vector<FileSys::VirtualFile> vfs_files;
auto const fn = [&](std::string_view name, std::span<const u8> data) {
vfs_files.push_back(std::make_shared<FileSys::VectorVfsFile>(
std::vector<u8>(data.begin(), data.end()),
std::string{name}
));
};
]])
foreach(ZONE_FILE ${FILE_LIST})
if (ZONE_FILE STREQUAL "\n")
continue()
endif()
string(APPEND FILE_DATA "{\"${ZONE_FILE}\",\n{")
string(APPEND FILE_DATA " {\n")
string(APPEND FILE_DATA " constexpr uint8_t tzdb_data[] = {\n")
file(READ ${ZONE_PATH}/${ZONE_FILE} ZONE_DATA HEX)
string(LENGTH "${ZONE_DATA}" ZONE_DATA_LEN)
foreach(I RANGE 0 ${ZONE_DATA_LEN} 2)
@@ -42,9 +54,12 @@ foreach(ZONE_FILE ${FILE_LIST})
string(APPEND FILE_DATA " ")
endif()
endforeach()
string(APPEND FILE_DATA "}},\n")
string(APPEND FILE_DATA " };\n")
string(APPEND FILE_DATA " fn(\"${ZONE_FILE}\", tzdb_data);\n")
string(APPEND FILE_DATA " }\n")
endforeach()
string(APPEND FILE_DATA " return vfs_files;\n")
string(APPEND FILE_DATA "}\n")
file(READ ${NX_TZDB_SOURCE_DIR}/tzdb_template.h.in NX_TZDB_TEMPLATE_H_IN)
file(CONFIGURE OUTPUT ${NX_TZDB_INCLUDE_DIR}/nx_tzdb/${HEADER_NAME}.h CONTENT "${NX_TZDB_TEMPLATE_H_IN}")
+3 -6
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -12,10 +9,10 @@
namespace NxTzdb {
// @DIRECTORY_NAME@
// clang-format off
const static std::map<const char*, const std::vector<uint8_t>> @DIRECTORY_NAME@ =
{
@FILE_DATA@};
@FILE_DATA@
// clang-format on
} // namespace NxTzdb
+6 -7
View File
@@ -1,7 +1,5 @@
#!/bin/sh -e
#!/bin/sh
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2015 Citra Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
@@ -12,19 +10,20 @@ paths_to_check="src/ CMakeLists.txt"
# If there are whitespace errors, print the offending file names and fail.
if ! git diff --cached --check -- $paths_to_check ; then
cat<<EOF
cat<<END
Error: This commit would contain trailing spaces or tabs, which is against this repo's policy.
Please correct those issues before committing. (Use 'git diff --check' for more details)
If you know what you are doing, you can try 'git commit --no-verify' to bypass the check
EOF
END
exit 1
fi
# Check for tabs, since tab-in-indent catches only those at the beginning of a line
if git diff --cached -- $paths_to_check | egrep '^\+.* '; then
cat<<EOF
cat<<END
Error: This commit would contain a tab, which is against this repo's policy.
If you know what you are doing, you can try 'git commit --no-verify' to bypass the check.
EOF
END
exit 1
fi
Executable → Regular
-4
View File
@@ -1,7 +1,3 @@
#!/usr/bin/nix-shell
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
let
nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/tarball/nixos-24.05";
pkgs = import nixpkgs { config = {}; overlays = []; };
+4 -22
View File
@@ -21,41 +21,20 @@ if (YUZU_STATIC_BUILD)
add_compile_definitions(QT_STATICPLUGIN)
endif()
# Build identifiers
if (NIGHTLY_BUILD)
add_compile_definitions(NIGHTLY_BUILD)
endif()
# Legacy (android only)
if (YUZU_LEGACY)
message(WARNING "Making legacy build. Performance may suffer.")
add_compile_definitions(YUZU_LEGACY)
endif()
# Genshin Spoof (android only)
if (GENSHIN_SPOOF)
message(WARNING "Making Genshin spoof build")
add_compile_definitions(GENSHIN_SPOOF)
endif()
# Build ID (mingw only right now)
# Pretty much just refers to the CI "target" for this build
if (NOT BUILD_ID)
if (ARCHITECTURE_x86_64)
set(BUILD_ID amd64)
elseif(ARCHITECTURE_arm64)
if (WIN32)
set(BUILD_ID arm64)
else()
set(BUILD_ID aarch64)
endif()
else()
set(BUILD_ID "${ARCHITECTURE}")
endif()
endif()
add_compile_definitions(BUILD_ID="${BUILD_ID}")
# Set compilation flags
if (MSVC AND NOT CXX_CLANG)
set(CMAKE_CONFIGURATION_TYPES Debug Release CACHE STRING "" FORCE)
@@ -180,7 +159,10 @@ else()
endif()
if (ARCHITECTURE_x86_64)
add_compile_options(-mcx16)
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:-mcx16>)
if (PLATFORM_LINUX OR PLATFORM_FREEBSD)
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX>:-mtls-dialect=gnu2>)
endif()
endif()
if (APPLE AND CXX_CLANG)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 61 KiB

@@ -462,8 +462,8 @@
<string name="renderer_resolution">الدقة (الإرساء/محمول)</string>
<string name="renderer_vsync">VSync وضع</string>
<string name="renderer_scaling_filter">مرشح ملائم للنافذة</string>
<string name="fsr_sharpness">حدة FSR/SGSR</string>
<string name="fsr_sharpness_description">يحدد مدى وضوح الصورة عند استخدام مرشحات FSR أو SGSR</string>
<string name="fsr_sharpness">حدة FSR</string>
<string name="fsr_sharpness_description">يحدد مدى وضوح الصورة عند استخدام التباين الديناميكي لـ FSR</string>
<string name="renderer_anti_aliasing">طريقة مضاد التعرج</string>
@@ -329,6 +329,8 @@
<string name="renderer_resolution">ڕوونی (دۆخی دەستی/دۆخی دۆک)</string>
<string name="renderer_vsync">دۆخی VSync</string>
<string name="renderer_scaling_filter">فلتەری گونجاندنی پەنجەرە</string>
<string name="fsr_sharpness">تیژی FSR</string>
<string name="fsr_sharpness_description">دیاریکردنی تیژی وێنە لە کاتی بەکارهێنانی FSR</string>
<string name="renderer_anti_aliasing">شێوازی دژە-خاوڕۆیی</string>
@@ -439,6 +439,8 @@
<string name="renderer_resolution">Rozlišení (Handheld/V doku)</string>
<string name="renderer_vsync">Režim VSync</string>
<string name="renderer_scaling_filter">Škálovací filtr</string>
<string name="fsr_sharpness">Ostrost FSR</string>
<string name="fsr_sharpness_description">Určuje jak ostře bude obraz vypadat při použití dynamického kontrastu FSR.</string>
<string name="renderer_anti_aliasing">Metoda anti-aliasingu</string>
@@ -439,6 +439,8 @@ Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die
<string name="renderer_resolution">Auflösung (Handheld/Gedockt)</string>
<string name="renderer_vsync">VSync-Modus</string>
<string name="renderer_scaling_filter">Skalierungsfilter</string>
<string name="fsr_sharpness">FSR-Schärfe</string>
<string name="fsr_sharpness_description">Bestimmt die Schärfe bei FSR-Nutzung.</string>
<string name="renderer_anti_aliasing">Kantenglättung</string>
@@ -376,7 +376,7 @@
<string name="qlaunch_applet">Qlaunch</string>
<string name="qlaunch_description">Iniciar aplicaciones desde la pantalla de inicio del sistema</string>
<string name="applets">Lanzador de Applet</string>
<string name="applets_description">Ejecutar applets del sistema usando el firmware instalado</string>
<string name="applets_description">Ejecutar applets de sistema usando el firmware instalado</string>
<string name="applets_error_firmware">El firmware no está instalado</string>
<string name="applets_error_applet">Applet no disponible</string>
<string name="applets_error_description"><![CDATA[Por favor, asegúrese de que su archivo <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> y el <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-system-firmware\">firmware</a> están instalados e inténtelo de nuevo.]]></string>
@@ -456,8 +456,8 @@
<string name="renderer_resolution">Resolución (Portátil/Sobremesa)</string>
<string name="renderer_vsync">Modo de sincronización vertical</string>
<string name="renderer_scaling_filter">Filtro de adaptación de ventana</string>
<string name="fsr_sharpness">Nitidez FSR/SGSR</string>
<string name="fsr_sharpness_description">Determina el grado de nitidez de la imagen al usar filtros FSR o SGSR</string>
<string name="fsr_sharpness">Nitidez FSR</string>
<string name="fsr_sharpness_description">Ajusta la intensidad del filtro de enfoque al usar el contraste dinámico de FSR.</string>
<string name="renderer_anti_aliasing">Método de suavizado de bordes</string>
@@ -489,8 +489,6 @@
<string name="enable_buffer_history">Activar el historial del búfer</string>
<string name="enable_buffer_history_description">Permite el acceso al estado del búfer anterior. Esta opción puede mejorar la calidad de renderizado y la consistencia en el rendimiento de algunos juegos.</string>
<string name="use_optimized_vertex_buffers">Búferes de vértices optimizados</string>
<string name="use_optimized_vertex_buffers_description">Permite la optimización del enlace del búfer de vértices para un mejor rendimiento. Requiere controladores Mesa 26.0+ Turnip/ controladores QCOM. Fallará con controladores Turnip más antiguos (versión 25.3 o inferior).</string>
<string name="hacks">Hacks</string>
<string name="fast_gpu_time">Tiempo rápido de la GPU</string>
@@ -502,7 +500,6 @@
<string name="emulate_bgr565">Emular BGR565</string>
<string name="emulate_bgr565_description">Soluciona problemas con colores invertidos en juegos, artefactos o sombras extrañas.</string>
<string name="rescale_hack">Activar la pasada de reescalado heredada</string>
<string name="rescale_hack_description">Permite el manejo de versiones anteriores para el paso de configuración de reescalado para juegos mediante el uso de una ruta de reescalado rápida.</string>
<string name="renderer_asynchronous_shaders">Usar sombreadores asíncronos</string>
<string name="renderer_asynchronous_shaders_description">Compila los sombreadores de forma asíncrona. Esto puede reducir los tirones, pero también puede introducir errores gráficos.</string>
<string name="gpu_unswizzle_settings">Ajustes de desentrelazado de la GPU</string>
@@ -521,10 +518,8 @@
<string name="extensions">Extensiones</string>
<string name="dyna_state">Estado dinámico extendido</string>
<string name="dyna_state_description">Controla la cantidad de características que se pueden usar en ExtendedDynamicState (EDS). Un valor más alto permitirá reducir la cantidad de compilaciones de canalización basadas en el estado dinámico compatible con el controlador.</string>
<string name="disabled">Desactivado</string>
<string name="vertex_input_dynamic_state">Estado dinámico de entrada de vértices</string>
<string name="vertex_input_dynamic_state_description">La activación de esta función permite un manejo más flexible de la entrada de vértices, lo que podría reducir el tiempo de compilación de la canalización en vértices/búfer.</string>
<string name="sample_shading_fraction">Muestreo de sombreado</string>
<string name="sample_shading_fraction_description">Permite que el sombreador de fragmentos se ejecute por muestra en un fragmento multimuestreado, en lugar de una sola vez por fragmento. Mejora la calidad de los gráficos a coste de algo de rendimiento.</string>
@@ -1072,7 +1067,7 @@
<!-- Black backgrounds theme -->
<string name="use_black_backgrounds">Fondos oscuros</string>
<string name="use_black_backgrounds_description">Cuando se usa el modo oscuro, aplicar fondos de pantalla negros.</string>
<string name="use_black_backgrounds_description">Cuando utilice el modo oscuro, aplique fondos negros.</string>
<!-- Buttons -->
<string name="enable_folder_button">Carpeta</string>
@@ -454,12 +454,11 @@
<string name="renderer_resolution">Résolution (Mode Portable/Mode TV)</string>
<string name="renderer_vsync">Mode VSync</string>
<string name="renderer_scaling_filter">Filtre de fenêtre adaptatif</string>
<string name="fsr_sharpness">Netteté FSR</string>
<string name="fsr_sharpness_description">Détermine à quel point l\'image sera affinée lors de l\'utilisation du contraste dynamique FSR.</string>
<string name="renderer_anti_aliasing">Méthode d\'anticrénelage</string>
<string name="advanced">Avancé</string>
<string name="renderer_accuracy">Mode GPU</string>
<string name="dma_accuracy">Précision DMA</string>
<string name="dma_accuracy_description">Contrôle la précision du DMA. Une précision sûre peut résoudre les problèmes dans certains jeux, mais peut aussi affecter les performances dans certains cas. Si vous n\'êtes pas sûr, laissez ce paramètre sur Par défaut.</string>
<string name="anisotropic_filtering">Filtrage anisotropique</string>
@@ -475,29 +474,15 @@
<string name="use_disk_shader_cache_description">Réduire les saccades en stockant et en chargeant localement les shaders générés</string>
<string name="renderer_force_max_clock">Forcer les fréquences maximales (Adreno uniquement)</string>
<string name="renderer_force_max_clock_description">Forcer le GPU à fonctionner à ses fréquences maximales possibles (les contraintes thermiques seront toujours appliquées).</string>
<string name="renderer_asynchronous_gpu_emulation">Émulation GPU asynchrone </string>
<string name="renderer_asynchronous_gpu_emulation_description">Ce contournement peut améliorer les performances en faisant tourner l\'émulation GPU de manière asynchrone au détriment de la fidélité graphique et de la stabilité (plantages plus fréquents) dus à des erreurs de cadence.</string>
<string name="renderer_reactive_flushing">Utiliser le vidage réactif</string>
<string name="renderer_reactive_flushing_description">Améliore la précision du rendu dans certains jeux au détriment des performances.</string>
<string name="enable_buffer_history">Activer l\'historique du tampon</string>
<string name="hacks">Contournements</string>
<string name="fast_gpu_time">Temps GPU rapide</string>
<string name="skip_cpu_inner_invalidation">Ignorer l\'invalidation interne du CPU</string>
<string name="skip_cpu_inner_invalidation_description">Ignore certaines invalidations de cache côté CPU lors des mises à jour mémoire, réduisant l\'utilisation du CPU et améliorant ses performances. Peut causer des bugs ou plantages sur certains jeux.</string>
<string name="emulate_bgr565">Emuler BGR565</string>
<string name="renderer_asynchronous_shaders">Utiliser les shaders asynchrones</string>
<string name="renderer_asynchronous_shaders_description">Compile les shaders de manière asynchrone. Cela peut réduire les saccades mais peut aussi provoquer des problèmes graphiques.</string>
<string name="gpu_unswizzle_disabled">Désactivé</string>
<string name="gpu_unswizzle_default_button">Par défaut</string>
<string name="extensions">Extensions</string>
<string name="dyna_state">État dynamique étendu</string>
<string name="disabled">Désactivé</string>
<string name="vertex_input_dynamic_state">État dynamique d\'entrée de sommet</string>
<string name="sample_shading_fraction">Échantillonnage de shading</string>
<string name="display">Affichage</string>
<string name="renderer_screen_layout">Orientation</string>
@@ -523,21 +508,6 @@
<string name="flush_by_line">Vider les journaux de débogage ligne par ligne</string>
<string name="flush_by_line_description">Vide les journaux de débogage à chaque ligne écrite, facilitant le débogage en cas de plantage ou de gel.</string>
<!-- GPU Logging strings -->
<string name="gpu_logging_header">Journalisation GPU</string>
<string name="gpu_logging_enabled">Activer la journalisation GPU</string>
<string name="gpu_log_level">Niveau de journalisation</string>
<string name="gpu_log_vulkan_calls">Journaliser les appels API Vulkan</string>
<string name="gpu_log_shader_dumps">Extraire les shaders</string>
<string name="gpu_log_shader_dumps_description">Sauvegarder le shader SPIR-V complié dans les fichiers</string>
<string name="gpu_log_memory_tracking">Monitorer la mémoire GPU</string>
<string name="gpu_log_memory_tracking_description">Monitorer les allocations et désallocations de la mémoire GPU</string>
<string name="gpu_log_driver_debug">Informations de débogage du pilote</string>
<string name="gpu_log_ring_buffer_size_description">Nombre d\'appels Vulkans récents à monitorer (par défaut : 512)</string>
<string name="gpu_log_ring_buffer_size_hint">64 à 4096 entrées</string>
<string name="general">Général</string>
<!-- Audio settings strings -->
<string name="audio_output_engine">Moteur de sortie</string>
<string name="audio_volume">Volume</string>
@@ -620,7 +590,6 @@
<!-- Miscellaneous -->
<string name="slider_default">Par défaut</string>
<string name="default_string">Par défaut</string>
<string name="loading">Chargement...</string>
<string name="shutting_down">Extinction en cours...</string>
<string name="reset_setting_confirmation">Voulez-vous réinitialiser ce paramètre à sa valeur par défaut ?</string>
@@ -659,7 +628,6 @@
<string name="select_gpu_driver_default">Par défaut</string>
<string name="select_gpu_driver_error">Pilote non valide sélectionné</string>
<string name="driver_already_installed">Pilote déjà installé</string>
<string name="installed_label">%1$s (Installé)</string>
<string name="system_gpu_driver">Pilote du GPU du système</string>
<string name="installing_driver">Installation du pilote...</string>
@@ -679,7 +647,6 @@
<string name="installing">Installation en cours…</string>
<string name="latest">Dernière</string>
<string name="recommended_driver">Pilote recommandé :</string>
<string name="gpu_model">Modèle GPU</string>
<string name="unsupported_gpu">GPU non pris en charge</string>
<string name="unsupported_gpu_warning">Votre GPU ne prend pas en charge l\'injection de pilotes. Il n\'est pas recommandé de définir des pilotes personnalisés.</string>
@@ -689,9 +656,6 @@
<string name="preferences_system_description">Mode TV, région, langue</string>
<string name="preferences_graphics">Vidéo</string>
<string name="preferences_graphics_description">Niveau de précision, résolution, cache de shaders</string>
<string name="quick_settings">Paramètres rapides</string>
<string name="enable_quick_settings">Activer les paramètres rapides</string>
<string name="enable_quick_settings_description">Autoriser l\'accès aux paramètres rapides par le balayage de l\'écran et le bouton du menu</string>
<string name="preferences_audio">Audio</string>
<string name="preferences_audio_description">Moteur de sortie, volume</string>
<string name="preferences_controls">Contrôles</string>
@@ -699,25 +663,6 @@
<string name="preferences_player">Joueur %d</string>
<string name="preferences_debug">Débogage</string>
<string name="preferences_debug_description">Débogage CPU/GPU, API graphique, fastmem</string>
<string name="preferences_custom_paths">Chemins personnalisés</string>
<string name="preferences_custom_paths_description">Sauvegarder le répertoire des données</string>
<!-- Custom Paths settings -->
<string name="custom_save_directory">Sauvegarder le répertoire des données</string>
<string name="custom_save_directory_description">Définir un chemin personnalisé pour les sauvegardes</string>
<string name="reset_to_nand">Réinitialiser par défaut</string>
<string name="migrate_save_data">Migrer les données de sauvegarde</string>
<string name="save_migration_complete">Données de sauvegarde supprimées avec succès</string>
<string name="save_migration_failed">Échec de la migration des données de sauvegarde</string>
<string name="destination_has_saves">La destination contient déjà des données. Voulez-vous les écraser \?</string>
<string name="grant_permission">Accorder la permission</string>
<string name="custom_nand_directory">Dossier NAND</string>
<string name="custom_nand_directory_description">Définir un chemin personnalisé pour le stockage NAND</string>
<string name="custom_sdmc_directory">Répertoire de carte SD</string>
<string name="custom_sdmc_directory_description">Définir un chemin personnalisé pour le stockage de la carte SD virtuelle</string>
<string name="path_set">Chemin défini avec succès</string>
<string name="skip_migration">Sauter</string>
<!-- Game properties -->
<string name="info">Info</string>
<string name="info_description">ID du programme, développeur, version</string>
@@ -731,7 +676,6 @@
<string name="copy_details">Copier les détails</string>
<string name="add_ons">Extensions</string>
<string name="add_ons_description">Activer les mods, mises à jour et DLC</string>
<string name="playtime">Temps de jeu :</string>
<string name="reset_playtime">Réinitialiser le Temps de Jeu</string>
<string name="reset_playtime_description">Réinitialiser le temps de jeu du jeu actuel à 0 seconde</string>
<string name="reset_playtime_warning_description">Cela effacera les données de temps de jeu du jeu actuel. Êtes-vous sûr\?</string>
@@ -739,9 +683,6 @@
<string name="edit_playtime">Modifier le Temps de Jeu</string>
<string name="hours">Heures</string>
<string name="minutes">Minutes</string>
<string name="hours_abbr">h</string>
<string name="minutes_abbr">m</string>
<string name="seconds_abbr">s</string>
<string name="hours_must_be_between_0_and_9999">Les heures doivent être comprises entre 0 et 9999</string>
<string name="minutes_must_be_between_0_and_59">Les minutes doivent être comprises entre 0 et 59</string>
<string name="seconds_must_be_between_0_and_59">Les secondes doivent être comprises entre 0 et 59</string>
@@ -773,7 +714,6 @@
<string name="confirm_uninstall">Confirmer la désinstallation</string>
<string name="confirm_uninstall_description">Êtes-vous sûr de vouloir désinstaller cette extension ?</string>
<string name="verify_integrity">Vérifier l\'intégrité</string>
<string name="verifying">Vérification...</string>
<string name="verify_success">La vérification de l\'intégrité a réussi !</string>
<string name="verify_failure">La vérification de l\'intégrité a échoué !</string>
<string name="verify_failure_description">Le contenu d\'un fichier peut être corrompu</string>
@@ -845,7 +785,6 @@
<string name="emulation_control_opacity">Opacité</string>
<string name="emulation_touch_overlay_reset">Réinitialiser l\'overlay</string>
<string name="emulation_touch_overlay_edit">Modifier l\'overlay</string>
<string name="emulation_snap_to_grid">Aimanter à la grille</string>
<string name="emulation_pause">Mettre en pause l\'émulation</string>
<string name="emulation_unpause">Reprendre l\'émulation</string>
<string name="emulation_input_overlay">Options de l\'overlay</string>
@@ -899,32 +838,6 @@
<string name="clock_boost">Boost (1700MHz)</string>
<string name="clock_fast">Rapide (2000MHz)</string>
<!-- GPU overclock factors -->
<string name="off">Désactivé</string>
<string name="fast_gpu_medium">Moyen (256)</string>
<string name="fast_gpu_high">Élevé (512)</string>
<!-- GPU swizzle texture size -->
<string name="gpu_texturesizeswizzle_verysmall">Très petit (16 Mo)</string>
<string name="gpu_texturesizeswizzle_small">Petit (32 Mo)</string>
<string name="gpu_texturesizeswizzle_normal">Normal (128 Mo)</string>
<string name="gpu_texturesizeswizzle_large">Large (256 Mo)</string>
<string name="gpu_texturesizeswizzle_verylarge">Très large (512 Mo)</string>
<!-- GPU swizzle streams -->
<string name="gpu_swizzle_verylow">Très faible (4 Mo)</string>
<string name="gpu_swizzle_low">Faible (8 Mo)</string>
<string name="gpu_swizzle_normal">Normal (16 Mo)</string>
<string name="gpu_swizzle_medium">Moyen (32 Mo)</string>
<string name="gpu_swizzle_high">Élevé (64 Mo)</string>
<!-- GPU swizzle chunks -->
<string name="gpu_swizzlechunk_verylow">Très faible (32)</string>
<string name="gpu_swizzlechunk_low">Faible (64)</string>
<string name="gpu_swizzlechunk_normal">Normal (128)</string>
<string name="gpu_swizzlechunk_medium">Moyen (256)</string>
<string name="gpu_swizzlechunk_high">Élevé (512)</string>
<!-- Temperature Units -->
<string name="temperature_celsius">Celsius</string>
<string name="temperature_fahrenheit">Fahrenheit</string>
@@ -940,11 +853,6 @@
<string name="renderer_none">Aucune</string>
<!-- Renderer Accuracy -->
<string name="renderer_accuracy_low">Rapide</string>
<string name="renderer_accuracy_medium">Moyen</string>
<string name="renderer_accuracy_high">Précis</string>
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Défaut</string>
<string name="dma_accuracy_unsafe">Dangereux</string>
@@ -978,26 +886,6 @@
<string name="cpu_accuracy_paranoid">Paranoïaque</string>
<string name="cpu_accuracy_debugging">Débogage</string>
<!-- Freedreno Settings -->
<string name="freedreno_settings_title">Paramètres de Freedreno</string>
<string name="gpu_driver_settings">Paramètres du pilote GPU</string>
<string name="freedreno_presets">Préréglages rapides</string>
<string name="freedreno_current_settings">Paramètres actuels</string>
<string name="freedreno_debug">Paramètres avancés</string>
<string name="freedreno_var_value">Valeur de la variable</string>
<string name="freedreno_add_variable">Ajouter la variable</string>
<string name="freedreno_clear_all">Effacer tout</string>
<string name="freedreno_saved">Configuration Freedreno sauvegardée</string>
<string name="freedreno_cleared_all">Toutes les variables Freedreno effacées</string>
<string name="freedreno_variable_added">Variable %1$s ajouté</string>
<string name="freedreno_preset_applied">Préréglage \'%1$s\' appliqué</string>
<string name="freedreno_error_empty_name">Le nom de la variable ne peut pas être vide</string>
<string name="freedreno_error_setting_variable">Échec de l\'assignation de la variable</string>
<string name="freedreno_info_title">À propos de la configuration Freedreno</string>
<string name="freedreno_per_game_title">Paramètres de Freedreno</string>
<string name="freedreno_per_game_description">Configurer les paramètres du pilote GPU pour ce jeu</string>
<string name="freedreno_per_game_saved">Configuration Freedreno sauvegardée</string>
<!-- Gamepad Buttons -->
<string name="gamepad_d_pad">Pavé directionnel</string>
<string name="gamepad_left_stick">Stick gauche</string>
@@ -1014,37 +902,26 @@
<string name="theme_material_you">Material You</string>
<string name="app_settings">Paramètres de lApp</string>
<string name="theme_and_color">Thème et Couleur</string>
<string name="fullscreen_mode">Mode plein écran</string>
<!-- Theme Modes -->
<string name="change_theme_mode">Changer le mode de thème</string>
<string name="theme_mode_follow_system">Automatique</string>
<string name="theme_mode_light">Lumineux</string>
<string name="theme_mode_dark">Sombre</string>
<string name="multiplier_none">Aucun</string>
<!-- Black backgrounds theme -->
<string name="use_black_backgrounds">Arrière-plan noir</string>
<string name="use_black_backgrounds_description">Lorsque vous utilisez le thème sombre, appliquer un arrière-plan noir.</string>
<!-- Buttons -->
<string name="enable_folder_button">Dossier</string>
<string name="enable_folder_button_description">Afficher le bouton pour ajouter les dossiers de jeu</string>
<string name="enable_qlaunch_button">QLaunch</string>
<string name="enable_qlaunch_button_description">Afficher le bouton pour lancer QLaunch</string>
<!-- App Language -->
<string name="app_language">Language de l\'application</string>
<string name="app_language_description">Changer la langue de l\'interface</string>
<string name="app_language_system">Suivre le système</string>
<!-- Static Themes -->
<string name="static_theme_color">Couleur du thème</string>
<string name="eden_theme">Eden</string>
<string name="violet">Violet (Par défaut)</string>
<string name="blue">Bleu</string>
<string name="cyan">Cyan</string>
<string name="red">Rouge</string>
<string name="green">Vert</string>
<string name="yellow">Jaune</string>
<string name="orange">Orange</string>
<string name="pink">Rose</string>
@@ -1063,8 +940,6 @@
<!-- Applet Modes -->
<string name="applets_menu">Applets</string>
<string name="applets_menu_description">Modifier les frontends et paramètres des applets</string>
<string name="applet_hle">Frontend personnalisé</string>
<string name="applet_lle">Applet réel</string>
@@ -1073,39 +948,7 @@
<string name="airplane_mode">Mode avion</string>
<string name="airplane_mode_description">Passe le mode avion au système d\'exploitation Switch</string>
<string name="enable_overlay">Activer l\'applet d\'overlay</string>
<!-- Profile Management -->
<string name="profile_manager">Gestionnaire de profil</string>
<string name="profile_manager_description">Gérer les profils utilisateurs</string>
<string name="profile_add_user">Ajouter un utilisateur</string>
<string name="profile_new_user">Nouvel utilisateur</string>
<string name="profile_edit_user">Modifier l\'utilisateur</string>
<string name="profile_edit">Éditer</string>
<string name="profile_delete">Supprimer</string>
<string name="profile_username">Nom d\'utilisateur</string>
<string name="profile_uuid">ID de l\'utilisateur (UUID)</string>
<string name="profile_uuid_description">Il s\'agit de l\'identifiant unique de ce profil utilisateur. Il ne peut pas être changé après sa création.</string>
<string name="profile_generate">Générer</string>
<string name="profile_avatar">Avatar de l\'utilisateur</string>
<string name="profile_select_image">Sélectionner l\'image</string>
<string name="profile_firmware_avatars">Avatars du firmware</string>
<string name="profile_firmware_avatars_unavailable">Avatars du firmware non disponibles. Veuillez installer le firmware pour utiliser cette fonctionnalité.</string>
<string name="profile_revert_image">Restaurer à la valeur par défaut</string>
<string name="profile_current_user">Utilisateur actuel</string>
<string name="profile_max_users_title">Nombre d\'Utilisateurs Maximum Atteint</string>
<string name="profile_max_users_message">Vous ne pouvez pas créer plus du 8 profils utilisateurs. Veuillez supprimer un des profils existants pour en créer un nouveau.</string>
<string name="profile_delete_confirm_title">Supprimer le profil \?</string>
<string name="profile_create_failed">Échec de la création du profil utilisateur</string>
<string name="profile_update_failed">Échec de la mise à jour du profil utilisateur</string>
<string name="profile_image_load_error">Échec du chargement de l\'image : %1$s</string>
<string name="profile_image_save_error">Échec de la sauvegarde de l\'image : %1$s</string>
<string name="error">Erreur</string>
<!-- Licenses screen strings -->
<string name="licenses">Licences</string>
<string name="license_fidelityfx_fsr_description">Mise à l\'échelle de haute qualité par AMD.</string>
<string name="external_content">Contenu externe</string>
<string name="add_folders">Ajouter un dossier</string>
<string name="percent">%1$d%%</string>
</resources>
</resources>
@@ -359,6 +359,8 @@
<string name="renderer_resolution">רזולוציה (מעוגן/נייד)</string>
<string name="renderer_vsync">מצב VSync</string>
<string name="renderer_scaling_filter">פילטר מתאם חלון</string>
<string name="fsr_sharpness">חדות FSR</string>
<string name="fsr_sharpness_description">קובע את מידת החדות בעת שימוש ב-FSR.</string>
<string name="renderer_anti_aliasing">שיטת Anti-aliasing</string>
@@ -348,6 +348,8 @@
<string name="renderer_resolution">Felbontás (Kézi/Dockolt)</string>
<string name="renderer_vsync">VSync mód</string>
<string name="renderer_scaling_filter">Ablakhoz alkalmazkodó szűrő</string>
<string name="fsr_sharpness">FSR élesség</string>
<string name="fsr_sharpness_description">Meghatározza, milyen éles lesz a kép az FSR dinamikus kontraszt használata közben.</string>
<string name="renderer_anti_aliasing">Élsimítási módszer</string>
@@ -380,6 +380,8 @@
<string name="renderer_resolution">Resolusi (Handheld/Docked)</string>
<string name="renderer_vsync">Mode Sinkronisasi Vertikal</string>
<string name="renderer_scaling_filter">Filter penyesuaian jendela</string>
<string name="fsr_sharpness">Ketajaman FSR</string>
<string name="fsr_sharpness_description">Menentukan seberapa tajam gambar akan terlihat saat menggunakan kontras dinamis FSR</string>
<string name="renderer_anti_aliasing">Metode anti-aliasing</string>
@@ -387,6 +387,8 @@
<string name="renderer_resolution">Risoluzione (Portatile/Docked)</string>
<string name="renderer_vsync">Modalità VSync</string>
<string name="renderer_scaling_filter">Filtro adattivo della finestra </string>
<string name="fsr_sharpness">Nitidezza FSR</string>
<string name="fsr_sharpness_description">Determina quanto sarà nitida l\'immagine utilizzando il contrasto dinamico di FSR</string>
<string name="renderer_anti_aliasing">Metodo di anti-aliasing</string>
@@ -6,8 +6,8 @@
<string name="notification_permission_not_granted">알림 권한이 부여되지 않았습니다!</string>
<!-- Stats Overlay settings -->
<string name="process_ram">프로세스 RAM: %1$d MB</string>
<string name="shaders_prefix">구축 중</string>
<string name="shaders_suffix">개 셰이더</string>
<string name="shaders_prefix">셰이더</string>
<string name="shaders_suffix">빌드 중</string>
<string name="charging">(충전 중)</string>
<string name="system_info_label">시스템:</string>
@@ -329,6 +329,8 @@
<string name="renderer_resolution">Oppløsning (håndholdt/dokket)</string>
<string name="renderer_vsync">VSync-modus</string>
<string name="renderer_scaling_filter">Filter for vindustilpasning</string>
<string name="fsr_sharpness">FSR-skarphet</string>
<string name="fsr_sharpness_description">Bestemmer bildekvalitet med FSR</string>
<string name="renderer_anti_aliasing">Anti-aliasing-metode</string>
@@ -439,6 +439,8 @@
<string name="renderer_resolution">Rozdzielczość (Handheld/Zadokowany)</string>
<string name="renderer_vsync">Synchronizacja pionowa VSync</string>
<string name="renderer_scaling_filter">Filtr adaptacji rozdzielczości</string>
<string name="fsr_sharpness">Ostrość FSR</string>
<string name="fsr_sharpness_description">Kontroluje ostrość obrazu w FSR.</string>
<string name="renderer_anti_aliasing">Metoda wygładzania krawędzi</string>
@@ -430,6 +430,8 @@
<string name="renderer_resolution">Resolução (Portátil/Modo TV)</string>
<string name="renderer_vsync">Modo de VSync</string>
<string name="renderer_scaling_filter">Filtro de Adaptação da Janela</string>
<string name="fsr_sharpness">Nitidez do FSR</string>
<string name="fsr_sharpness_description">Determina a nitidez da imagem ao utilizar o contraste dinâmico do FSR</string>
<string name="renderer_anti_aliasing">Método de Anti-aliasing</string>
@@ -352,6 +352,8 @@
<string name="renderer_resolution">Resolução (Portátil/Ancorado)</string>
<string name="renderer_vsync">Modo VSync</string>
<string name="renderer_scaling_filter">Filtro de Adaptação da Janela</string>
<string name="fsr_sharpness">Nitidez do FSR</string>
<string name="fsr_sharpness_description">Determina a nitidez da imagem ao usar contraste dinâmico do FSR</string>
<string name="renderer_anti_aliasing">Método de Anti-Serrilhado</string>
@@ -458,8 +458,8 @@
<string name="renderer_resolution">Разрешение (портативное/в док-станции)</string>
<string name="renderer_vsync">Режим верт. синхронизации</string>
<string name="renderer_scaling_filter">Фильтр адаптации окна</string>
<string name="fsr_sharpness">Резкость FSR/SGSR</string>
<string name="fsr_sharpness_description">Определяет, насколько чётким будет изображение при использовании динамического контраста FSR или SGSR фильтров</string>
<string name="fsr_sharpness">Резкость FSR</string>
<string name="fsr_sharpness_description">Определяет, насколько чётким будет изображение при использовании динамического контраста FSR.</string>
<string name="renderer_anti_aliasing">Метод сглаживания</string>
@@ -351,6 +351,8 @@
<string name="renderer_resolution">Резолуција (ручно / прикључено)</string>
<string name="renderer_vsync">Всинц мод</string>
<string name="renderer_scaling_filter">Филтер прилагођавања прозора</string>
<string name="fsr_sharpness">ФСР оштрина</string>
<string name="fsr_sharpness_description">Одређује колико ће се слика наоштрен трајати док користи \"ФСР\" динамички контраст</string>
<string name="renderer_anti_aliasing">Метода против алиасирања</string>
@@ -3,7 +3,7 @@
<string name="app_disclaimer">Цей застосунок запускає ігри для ігрової консолі Nintendo Switch. Він не містить ігор чи ключів.<br /><br />Перш ніж почати, укажіть розташування файлу <![CDATA[<b> prod.keys </b>]]> у пам’яті вашого пристрою.<br /><br /><![CDATA[<a href=\"https://yuzu-mirror.github.io/help/quickstart\">Дізнатися більше</a>]]></string>
<string name="notice_notification_channel_name">Сповіщення та помилки</string>
<string name="notice_notification_channel_description">Показує сповіщення у разі виникнення проблем.</string>
<string name="notice_notification_channel_description">Виводить сповіщення у разі виникнення проблем.</string>
<string name="notification_permission_not_granted">Дозвіл на сповіщення не надано!</string>
<string name="app_notification_channel_description">Сповіщення емулятора Switch Eden</string>
<string name="app_notification_running">Eden працює</string>
@@ -458,8 +458,8 @@
<string name="renderer_resolution">Роздільна здатність (Портативний/Док)</string>
<string name="renderer_vsync">Режим верт. синхронізації</string>
<string name="renderer_scaling_filter">Фільтр масштабування вікна</string>
<string name="fsr_sharpness">Різкість FSR/SGSR</string>
<string name="fsr_sharpness_description">Визначає різкість зображення при використанні фільтрів FSR або SGSR.</string>
<string name="fsr_sharpness">Різкість FSR</string>
<string name="fsr_sharpness_description">Визначає різкість зображення при використанні FSR.</string>
<string name="renderer_anti_aliasing">Згладжування</string>
@@ -327,6 +327,8 @@
<string name="renderer_resolution">Độ phân giải (Handheld/Docked)</string>
<string name="renderer_vsync">Chế độ VSync</string>
<string name="renderer_scaling_filter">Bộ lọc điều chỉnh cửa sổ</string>
<string name="fsr_sharpness">Độ sắc nét FSR</string>
<string name="fsr_sharpness_description">Độ sắc nét khi dùng FSR</string>
<string name="renderer_anti_aliasing">Phương pháp khử răng cưa</string>
@@ -66,8 +66,6 @@
<string name="show_power_info_description">显示当前功耗和电池剩余容量</string>
<string name="show_shaders_building">显示着色器编译信息</string>
<string name="show_shaders_building_description">显示当前正在编译的着色器数量</string>
<string name="pipeline_worker_cores">管线工作线程</string>
<string name="pipeline_worker_cores_description">管理用于构建 Vulkan 管线的核心数量,数值越高则管线编译性能越好,但温度也会随之升高。</string>
<string name="overlay_position">叠加层位置</string>
<string name="overlay_position_description">选择叠加层在屏幕上显示的位置</string>
<string name="overlay_position_top_left">左上</string>
@@ -106,7 +104,7 @@
<!-- NVDEC Emulation -->
<string name="nvdec_emulation">NVDEC模拟</string>
<string name="nvdec_emulation_description">播放过场与开场动画期间的视频解码处理方式(NVDEC)。</string>
<string name="nvdec_emulation_description">选择视频解码处理方式</string>
<string name="nvdec_emulation_none">禁用</string>
<!-- Optimize SPIRV output -->
@@ -181,14 +179,14 @@
<string name="multiplayer_hide_full_rooms">隐藏满员房间</string>
<string name="multiplayer_hide_empty_rooms">隐藏空房间</string>
<string name="multiplayer_tap_refresh_to_check_again">点击刷新重试</string>
<string name="multiplayer_search_public_lobbies">搜索游戏大厅</string>
<string name="multiplayer_search_public_lobbies">搜索房间</string>
<string name="multiplayer_preferred_game_name">首选游戏</string>
<string name="multiplayer_lobby_type">游戏大厅类型</string>
<string name="multiplayer_lobby_type">大厅类型</string>
<string name="multiplayer_room_name_error">长度需为3-20个字符</string>
<string name="multiplayer_required">必填</string>
<string name="multiplayer_token_required">需要Web令牌,请前往高级设置 -> 系统 -> 网络</string>
<string name="multiplayer_ip_error">IP格式无效</string>
<string name="multiplayer_username_error">必须为420个字符,且仅包含字母数字、点号、连字符、下划线和空格</string>
<string name="multiplayer_username_error">必须为4-20个字符(仅字母数字、点号、连字符、下划线和空格</string>
<string name="multiplayer_nickname_invalid">用户名无效,请在系统→网络中检查设置</string>
<string name="multiplayer_token_error">必须为48个字符,且仅包含小写字母a-z</string>
<string name="multiplayer_port_error">端口需为1-65535</string>
@@ -437,23 +435,23 @@
<string name="custom_cpu_ticks_description">设置自定义的CPU时钟值。更高的值可能提高性能,但也可能导致游戏卡顿。建议范围为77-21000。</string>
<string name="cpu_ticks">时钟</string>
<string name="memory_layout">内存布局</string>
<string name="memory_layout_description">(实验性) 更改模拟内存布局。此设置不会提性能,但可能有助于游戏通过 mods 来利用高分辨率。请不要在内存不大于 8GB 的手机上使用。仅适用于 DynamicJIT)后端。</string>
<string name="memory_layout_description">(实验性) 更改模拟内存布局。此设置不会提性能,但可能有助于通过模组使用高分辨率的游戏。不要在 RAM 为 8GB 或更少的手机上使用。</string>
<string name="generate">生成</string>
<!-- Network settings strings -->
<string name="web_token">网络令牌</string>
<string name="web_token_description">用于创建公共游戏大厅的 web token。这是一个仅包含小写字母 a-z 的 48 位字符串</string>
<string name="web_token_description">用于创建公共房间的网络令牌。它是一个48个字符的字符串,仅包含小写字母a-z。</string>
<string name="web_username">网络用户名</string>
<string name="web_username_description">多人游戏大厅中显示的用户名。用户名必须为420个字符,且仅可包含字母数字、连字符、点号、下划线和空格。</string>
<string name="web_username_description">多人游戏房间中显示的用户名。必须为4-20个字符(仅字母数字、连字符、点号、下划线和空格</string>
<string name="network">网络</string>
<!-- Graphics settings strings -->
<string name="renderer_resolution">分辨率 (掌机模式/主机模式)</string>
<string name="renderer_vsync">垂直同步模式</string>
<string name="renderer_scaling_filter">窗口滤镜</string>
<string name="fsr_sharpness">FSR/SGSR 锐度</string>
<string name="fsr_sharpness_description">确定在使用 FSR 或 SGSR 过滤器时的图像锐</string>
<string name="fsr_sharpness">FSR 锐</string>
<string name="fsr_sharpness_description">指定使用 FSR 时图像的锐化程</string>
<string name="renderer_anti_aliasing">抗锯齿方式</string>
@@ -475,18 +473,14 @@
<string name="use_disk_shader_cache">磁盘着色器缓存</string>
<string name="use_disk_shader_cache_description">将生成的着色器缓存于磁盘中并进行读取,以减少卡顿。</string>
<string name="renderer_force_max_clock">强制最大时钟 (仅限 Adreno)</string>
<string name="renderer_force_max_clock_description">强制 GPU 以最大时钟运行 (温控依然生效)。</string>
<string name="renderer_force_max_clock_description">强制 GPU 以最大时钟运行 (仍被温控限制)。</string>
<string name="renderer_asynchronous_gpu_emulation">GPU 异步模拟</string>
<string name="renderer_asynchronous_gpu_emulation_description">此技巧可通过异步运行 GPU 模拟来提升性能,但在执行与时序相关的操作时,可能引入图形问题和增加崩溃概率。</string>
<string name="renderer_async_presentation">异步呈现</string>
<string name="renderer_async_presentation_description">此技巧通过将图形呈现移至独立的 CPU 线程来提升性能,但可能会引入图形显示问题。</string>
<string name="renderer_reactive_flushing">启用反应性刷新</string>
<string name="renderer_reactive_flushing_description">通过牺牲性能来提高某些游戏的渲染精度。</string>
<string name="enable_buffer_history">启用缓冲区历史</string>
<string name="enable_buffer_history_description">启用对先前缓冲区状态的访问。此选项可在某些游戏中提升渲染质量并保持性能的一致性。</string>
<string name="use_optimized_vertex_buffers">优化顶点缓冲区</string>
<string name="use_optimized_vertex_buffers_description">启用经过优化的顶点缓冲区绑定以提升性能。需要 Mesa 26.0 及以上版本的 Turnip 或 QCOM 驱动程序。若使用较旧版本的 Turnip 驱动 (25.3 及以下版本) 则会导致崩溃。</string>
<string name="hacks">Hacks</string>
<string name="fast_gpu_time">GPU 超频频率</string>
@@ -496,9 +490,7 @@
<string name="fix_bloom_effects">修复 Bloom 效果</string>
<string name="fix_bloom_effects_description">减少《塞尔达传说:智慧的再现》(Adreno A6XX - A7XX/ Turnip)中的 bloom 模糊,并移除《Burnout》中的 bloom 效果。警告:可能会导致在其他游戏中出现图形异常。</string>
<string name="emulate_bgr565">模拟 BGR565</string>
<string name="emulate_bgr565_description">修复游戏中的颜色反转或是异常画面瑕疵或阴影问题</string>
<string name="rescale_hack">启用旧版缩放处理</string>
<string name="rescale_hack_description">启用通过使用快速缩放路径,来为游戏提供缩放配置处理的传统处理方式</string>
<string name="emulate_bgr565_description">修复游戏中的颜色反转以及出现的异常画面瑕疵或奇怪阴影问题</string>
<string name="renderer_asynchronous_shaders">使用异步着色器</string>
<string name="renderer_asynchronous_shaders_description">异步编译着色器。这可能会减少卡顿,但也可能会导致图形错误。</string>
<string name="gpu_unswizzle_settings">GPU 还原设置</string>
@@ -508,19 +500,17 @@
<string name="gpu_unswizzle_texture_size">GPU 还原最大纹理尺寸</string>
<string name="gpu_unswizzle_texture_size_description">设置基于 GPU 的纹理还原的最大尺寸(单位:MiB)。\n虽然 GPU 在处理中型和大型纹理时速度更快,但对于非常小的纹理,CPU 的效率可能更高。\n调整此设置,以便在 GPU 加速和 CPU 开销之间找到最佳平衡点。</string>
<string name="gpu_unswizzle_stream_size">GPU 还原流大小</string>
<string name="gpu_unswizzle_stream_size_description">设置用于 unswizzling 大型纹理时的每帧数据限制。较高的数值可以加快纹理加载速度,但增加帧延迟。而较低的数值可以降低 GPU 开销,但可能会导致可见的纹理 闪现</string>
<string name="gpu_unswizzle_stream_size_description">设置每帧还原大型纹理的数据限制。较高的数值可以加快纹理加载速度,但代价是增加帧延迟(影响响应速度/平滑度);较低的数值可以减少 GPU 开销,但可能会导致明显的纹理突然出现(Pop-in)现象</string>
<string name="gpu_unswizzle_chunk_size">GPU 还原块大小</string>
<string name="gpu_unswizzle_chunk_size_description">定义了 3D 纹理每批次处理的深度切片数量。增加此数值可在高性能 GPU 上提升吞吐效率,但在性能较弱的硬件上可能会导致卡顿或驱动超时</string>
<string name="gpu_unswizzle_chunk_size_description">定义了 3D 纹理在单个批次(Batch)中处理的深度切片(Depth Slices数量。增加此数值可以提升强力 GPU 吞吐效率,但在性能较弱的硬件上可能会引起卡顿或驱动程序超时(Driver Timeouts</string>
<string name="gpu_unswizzle_default_button">默认</string>
<string name="extensions">扩展</string>
<string name="dyna_state">扩展动态状态</string>
<string name="dyna_state_description">控制扩展动态状态 (EDS) 可使用的功能数目。较高的数值将允许根据驱动程序支持的动态状态来减少管线编译的次数。</string>
<string name="disabled">已禁用</string>
<string name="vertex_input_dynamic_state">顶点输入动态状态</string>
<string name="vertex_input_dynamic_state_description">启用此功能可实现更灵活的顶点输入处理,可能减少顶点/缓冲区的管线编译时间。</string>
<string name="sample_shading_fraction">采样着色</string>
<string name="sample_shading_fraction_description">允许片段着色器在多采样片段中每个样本执行一次,而不是每个片段执行一次。以提高性能为代价改善图形质量。</string>
@@ -437,6 +437,8 @@
<string name="renderer_resolution">解析度 (手提/底座)</string>
<string name="renderer_vsync">垂直同步</string>
<string name="renderer_scaling_filter">視窗適應過濾器</string>
<string name="fsr_sharpness">FSR 銳化度</string>
<string name="fsr_sharpness_description">使用 FSR 時圖片的銳化程度</string>
<string name="renderer_anti_aliasing">抗鋸齒</string>
@@ -1 +1 @@
<?xml version='1.0' encoding='utf-8'?><resources><color name='ic_launcher_background'>#1F143C</color></resources>
<?xml version='1.0' encoding='utf-8'?><resources><color name='ic_launcher_background'>#ffd700</color></resources>
+4 -2
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
@@ -177,8 +177,10 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz
queued_buffers.store(0);
release_cv.notify_one();
}
static constexpr std::array<s16, 6> silence{};
for (size_t i = 0; i < num_frames; i++)
std::memset(&output_buffer[i * frame_size], 0, frame_size_bytes);
std::memcpy(&output_buffer[i * frame_size], silence.data(), frame_size_bytes);
return;
}
+1 -8
View File
@@ -184,19 +184,12 @@ if(ARCHITECTURE_x86_64)
x64/cpu_detect.h
x64/cpu_wait.cpp
x64/cpu_wait.h
x64/native_clock.cpp
x64/native_clock.h
x64/rdtsc.cpp
x64/rdtsc.h
x64/xbyak_abi.h
x64/xbyak_util.h)
x64/xbyak.h)
target_link_libraries(common PRIVATE xbyak::xbyak)
endif()
if(HAS_NCE)
target_sources(common PRIVATE arm64/native_clock.cpp arm64/native_clock.h)
endif()
if(MSVC)
target_compile_definitions(
common
-87
View File
@@ -1,87 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#ifdef ANDROID
#include <sys/system_properties.h>
#endif
#include "common/arm64/native_clock.h"
namespace Common::Arm64 {
namespace {
NativeClock::FactorType GetFixedPointFactor(u64 num, u64 den) {
return (static_cast<NativeClock::FactorType>(num) << 64) / den;
}
u64 MultiplyHigh(u64 m, NativeClock::FactorType factor) {
return static_cast<u64>((m * factor) >> 64);
}
} // namespace
NativeClock::NativeClock() {
const u64 host_cntfrq = GetHostCNTFRQ();
ns_cntfrq_factor = GetFixedPointFactor(NsRatio::den, host_cntfrq);
us_cntfrq_factor = GetFixedPointFactor(UsRatio::den, host_cntfrq);
ms_cntfrq_factor = GetFixedPointFactor(MsRatio::den, host_cntfrq);
guest_cntfrq_factor = GetFixedPointFactor(CNTFRQ, host_cntfrq);
gputick_cntfrq_factor = GetFixedPointFactor(GPUTickFreq, host_cntfrq);
}
std::chrono::nanoseconds NativeClock::GetTimeNS() const {
return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_cntfrq_factor)};
}
std::chrono::microseconds NativeClock::GetTimeUS() const {
return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_cntfrq_factor)};
}
std::chrono::milliseconds NativeClock::GetTimeMS() const {
return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_cntfrq_factor)};
}
s64 NativeClock::GetCNTPCT() const {
return MultiplyHigh(GetUptime(), guest_cntfrq_factor);
}
s64 NativeClock::GetGPUTick() const {
return MultiplyHigh(GetUptime(), gputick_cntfrq_factor);
}
s64 NativeClock::GetUptime() const {
s64 cntvct_el0 = 0;
asm volatile("dsb ish\n\t"
"mrs %[cntvct_el0], cntvct_el0\n\t"
"dsb ish\n\t"
: [cntvct_el0] "=r"(cntvct_el0));
return cntvct_el0;
}
bool NativeClock::IsNative() const {
return true;
}
s64 NativeClock::GetHostCNTFRQ() {
u64 cntfrq_el0 = 0;
std::string_view board{""};
#ifdef ANDROID
char buffer[PROP_VALUE_MAX];
int len{__system_property_get("ro.product.board", buffer)};
board = std::string_view(buffer, static_cast<size_t>(len));
#endif
if (board == "s5e9925") { // Exynos 2200
cntfrq_el0 = 25600000;
} else if (board == "exynos2100") { // Exynos 2100
cntfrq_el0 = 26000000;
} else if (board == "exynos9810") { // Exynos 9810
cntfrq_el0 = 26000000;
} else if (board == "s5e8825") { // Exynos 1280
cntfrq_el0 = 26000000;
} else {
asm("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0));
}
return cntfrq_el0;
}
} // namespace Common::Arm64
-45
View File
@@ -1,45 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/wall_clock.h"
namespace Common::Arm64 {
class NativeClock final : public WallClock {
public:
explicit NativeClock();
std::chrono::nanoseconds GetTimeNS() const override;
std::chrono::microseconds GetTimeUS() const override;
std::chrono::milliseconds GetTimeMS() const override;
s64 GetCNTPCT() const override;
s64 GetGPUTick() const override;
s64 GetUptime() const override;
bool IsNative() const override;
static s64 GetHostCNTFRQ();
public:
using FactorType = unsigned __int128;
FactorType GetGuestCNTFRQFactor() const {
return guest_cntfrq_factor;
}
private:
FactorType ns_cntfrq_factor;
FactorType us_cntfrq_factor;
FactorType ms_cntfrq_factor;
FactorType guest_cntfrq_factor;
FactorType gputick_cntfrq_factor;
};
} // namespace Common::Arm64
-5
View File
@@ -1,12 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2005-2014 Daniel James
// SPDX-FileCopyrightText: 2016 Austin Appleby
// SPDX-License-Identifier: BSL-1.0
#pragma once
#include <array>
#include <climits>
#include <cstdint>
+281 -159
View File
@@ -7,18 +7,25 @@
#include <vector>
#include "common/assert.h"
#include "common/bit_util.h"
#include "common/fs/file.h"
#include "common/fs/fs.h"
#include "common/fs/fs_types.h"
#ifdef ANDROID
#include "common/fs/fs_android.h"
#endif
#include "common/logging.h"
#include "common/literals.h"
#ifdef _WIN32
#include <io.h>
#include <share.h>
#include <windows.h>
#else
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#endif
#ifdef _MSC_VER
@@ -36,13 +43,13 @@ namespace {
#ifdef _WIN32
/**
* Converts the file access mode and file type enums to a file access mode wide string.
*
* @param mode File access mode
* @param type File type
*
* @returns A pointer to a wide string representing the file access mode.
*/
* Converts the file access mode and file type enums to a file access mode wide string.
*
* @param mode File access mode
* @param type File type
*
* @returns A pointer to a wide string representing the file access mode.
*/
[[nodiscard]] constexpr const wchar_t* AccessModeToWStr(FileAccessMode mode, FileType type) {
switch (type) {
case FileType::BinaryFile:
@@ -79,12 +86,12 @@ namespace {
}
/**
* Converts the file-share access flag enum to a Windows defined file-share access flag.
*
* @param flag File-share access flag
*
* @returns Windows defined file-share access flag.
*/
* Converts the file-share access flag enum to a Windows defined file-share access flag.
*
* @param flag File-share access flag
*
* @returns Windows defined file-share access flag.
*/
[[nodiscard]] constexpr int ToWindowsFileShareFlag(FileShareFlag flag) {
switch (flag) {
case FileShareFlag::ShareNone:
@@ -102,13 +109,13 @@ namespace {
#else
/**
* Converts the file access mode and file type enums to a file access mode string.
*
* @param mode File access mode
* @param type File type
*
* @returns A pointer to a string representing the file access mode.
*/
* Converts the file access mode and file type enums to a file access mode string.
*
* @param mode File access mode
* @param type File type
*
* @returns A pointer to a string representing the file access mode.
*/
[[nodiscard]] constexpr const char* AccessModeToStr(FileAccessMode mode, FileType type) {
switch (type) {
case FileType::BinaryFile:
@@ -147,12 +154,12 @@ namespace {
#endif
/**
* Converts the seek origin enum to a seek origin integer.
*
* @param origin Seek origin
*
* @returns Seek origin integer.
*/
* Converts the seek origin enum to a seek origin integer.
*
* @param origin Seek origin
*
* @returns Seek origin integer.
*/
[[nodiscard]] constexpr int ToSeekOrigin(SeekOrigin origin) {
switch (origin) {
case SeekOrigin::SetOrigin:
@@ -178,7 +185,7 @@ std::string ReadStringFromFile(const std::filesystem::path& path, FileType type)
}
size_t WriteStringToFile(const std::filesystem::path& path, FileType type,
std::string_view string) {
std::string_view string) {
if (Exists(path) && !IsFile(path)) {
return 0;
}
@@ -189,7 +196,7 @@ size_t WriteStringToFile(const std::filesystem::path& path, FileType type,
}
size_t AppendStringToFile(const std::filesystem::path& path, FileType type,
std::string_view string) {
std::string_view string) {
if (Exists(path) && !IsFile(path)) {
return 0;
}
@@ -244,69 +251,189 @@ FileType IOFile::GetType() const {
return file_type;
}
#if defined(__unix__)
static int PlatformMapReadOnly(IOFile& io, const char* path) {
io.mmap_fd = open(path, O_RDONLY);
if (io.mmap_fd > 0) {
struct stat st;
fstat(io.mmap_fd, &st);
io.mmap_size = st.st_size;
int map_flags = MAP_PRIVATE;
#ifdef MAP_PREFAULT_READ
// Prefaults reads so the final resulting pagetable from this big stupid mmap()
// isn't comically lazily loaded, we just coalesce everything in-place for our
// lovely mmap flags; if we didn't prefault the reads the page table will be
// constructed in-place (i.e on a read-by-read basis) causing lovely soft-faults
// which would nuke any performance gains.
//
// This of course incurs a cost in the initial mmap(2) call, but that is fine.
map_flags |= MAP_PREFAULT_READ;
#endif
#ifdef MAP_NOSYNC
// This causes physical media to not be synched to our file/memory
// This means that if the read-only file is written to, we won't see changes
// or we may see changes which are just funnily scattered, in any case
// this presumes the files won't be changed during execution
//
// Do not ever use this on write files (if we ever support that); this will create
// a fun amount of fragmentation on the disk.
map_flags |= MAP_NOSYNC;
#endif
#if defined(NDEBUG) && defined(MAP_NOCORE)
map_flags |= MAP_NOCORE;
#endif
#ifdef MAP_HUGE_2MB
map_flags |= MAP_HUGE_2MB; //2mb pages
#elif defined(MAP_ALIGNED)
// File must be big enough that it's worth to super align. We can't just super-align every
// file otherwise we will run out of alignments for actually important files :)
// System doesn't guarantee a super alignment, but if it's available it will delete
// about 3 layers(?) of the TLB tree for each read/write.
// Again the cost of faults may make this negligible gains, but hey, we gotta work
// what we gotta work with.
map_flags |= MAP_ALIGNED(21); //2^21 = 2mb use 2MB pages
#endif
io.mmap_base = (u8*)mmap(nullptr, io.mmap_size, PROT_READ, map_flags, io.mmap_fd, 0);
if (io.mmap_base == MAP_FAILED) {
close(io.mmap_fd);
io.mmap_fd = -1;
} else {
using namespace Common::Literals;
// For small files it is acceptable to use a full readahead
// See https://github.com/torvalds/linux/blob/e80d033851b3bc94c3d254ac66660ddd0a49d72c/include/linux/pagemap.h#L1392
if (u64(st.st_size) >= 256_MiB) {
posix_madvise(io.mmap_base, io.mmap_size, POSIX_MADV_RANDOM);
} else {
posix_madvise(io.mmap_base, io.mmap_size, POSIX_MADV_SEQUENTIAL);
}
}
}
return io.mmap_fd;
}
static void PlatformUnmap(IOFile& io) {
if (io.mmap_fd != -1) {
munmap(io.mmap_base, io.mmap_size);
close(io.mmap_fd);
io.mmap_fd = -1;
}
}
#elif defined(__APPLE__)
// NO IMPLEMENTATION YET
#else
static int PlatformMapReadOnly(IOFile& io, const wchar_t* path) {
io.file_handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, nullptr);
if (HANDLE(io.file_handle) != INVALID_HANDLE_VALUE) {
io.mapping_handle = CreateFileMappingW(HANDLE(io.file_handle), nullptr, PAGE_READONLY, 0, 0, nullptr);
if (io.mapping_handle) {
io.mmap_base = (u8*)MapViewOfFile(HANDLE(io.mapping_handle), FILE_MAP_READ, 0, 0, 0);
if (io.mmap_base) {
_LARGE_INTEGER pvalue;
GetFileSizeEx(io.file_handle, &pvalue);
io.mmap_size = uint32_t(pvalue.QuadPart);
} else {
CloseHandle(io.mapping_handle);
CloseHandle(io.file_handle);
return -1;
}
} else {
CloseHandle(io.file_handle);
return -1;
}
}
return 0;
}
static void PlatformUnmap(IOFile& io) {
if(io.mapping_handle) {
if(io.mmap_base)
UnmapViewOfFile(HANDLE(io.mmap_base));
CloseHandle(HANDLE(io.mapping_handle));
}
if(io.file_handle != INVALID_HANDLE_VALUE)
CloseHandle(HANDLE(io.file_handle));
}
#endif
void IOFile::Open(const fs::path& path, FileAccessMode mode, FileType type, FileShareFlag flag) {
Close();
file_path = path;
file_access_mode = mode;
file_type = type;
errno = 0;
#ifdef _WIN32
if (flag != FileShareFlag::ShareNone) {
file = _wfsopen(path.c_str(), AccessModeToWStr(mode, type), ToWindowsFileShareFlag(flag));
} else {
_wfopen_s(&file, path.c_str(), AccessModeToWStr(mode, type));
// TODO: this probably can use better logic but oh well I'm not a windowser
file_handle = nullptr;
if (type == FileType::BinaryFile && mode == FileAccessMode::Read) {
if (PlatformMapReadOnly(*this, path.c_str()) == -1) {
LOG_ERROR(Common_Filesystem, "Error mmap'ing file"); //: {}", path.c_str());
}
}
if (file_handle == nullptr) {
if (flag != FileShareFlag::ShareNone) {
file = _wfsopen(path.c_str(), AccessModeToWStr(mode, type), ToWindowsFileShareFlag(flag));
} else {
_wfopen_s(&file, path.c_str(), AccessModeToWStr(mode, type));
}
}
#elif ANDROID
if (Android::IsContentUri(path)) {
ASSERT_MSG(mode == FileAccessMode::Read, "Content URI file access is for read-only!");
const auto fd = Android::OpenContentUri(path, Android::OpenMode::Read);
if (fd != -1) {
file = fdopen(fd, "r");
const auto error_num = errno;
if (error_num != 0 && file == nullptr) {
LOG_ERROR(Common_Filesystem, "Error opening file: {}, error: {}", path.c_str(),
strerror(error_num));
if (PlatformMapReadOnly(*this, path.c_str()) == -1) {
LOG_ERROR(Common_Filesystem, "Error mmap'ing file: {}", path.c_str());
int const fd = Android::OpenContentUri(path, Android::OpenMode::Read);
if (fd != -1) {
file = fdopen(fd, "r");
if (errno != 0 && file == nullptr)
LOG_ERROR(Common_Filesystem, "Error opening file: {}, error: {}", path.c_str(), strerror(errno));
} else {
LOG_ERROR(Common_Filesystem, "Error opening file: {}", path.c_str());
}
} else {
LOG_ERROR(Common_Filesystem, "Error opening file: {}", path.c_str());
}
} else {
file = std::fopen(path.c_str(), AccessModeToStr(mode, type));
}
#elif defined(__HAIKU__) || defined(__managarm__) || defined(__OPENORBIS__) || defined(__APPLE__)
file = std::fopen(path.c_str(), AccessModeToStr(mode, type));
#elif defined(__unix__)
if (type == FileType::BinaryFile && mode == FileAccessMode::Read) {
if (PlatformMapReadOnly(*this, path.c_str()) == -1) {
LOG_ERROR(Common_Filesystem, "Error mmap'ing file: {}", path.c_str());
}
}
if (mmap_fd == -1) {
file = std::fopen(path.c_str(), AccessModeToStr(mode, type)); // mmap(2) failed or simply we can't use it
}
#else
// Some other fancy OS (ahem fucking Darwin/Mac OSX)
file = std::fopen(path.c_str(), AccessModeToStr(mode, type));
#endif
if (!IsOpen()) {
const auto ec = std::error_code{errno, std::generic_category()};
LOG_ERROR(Common_Filesystem, "Failed to open the file at path={}, ec_message={}",
PathToUTF8String(file_path), ec.message());
PathToUTF8String(file_path), ec.message());
}
}
void IOFile::Close() {
if (!IsOpen()) {
return;
#if defined(__APPLE__)
// NO IMPLEMENTATION YET
#else
PlatformUnmap(*this);
#endif
if (file) {
errno = 0;
const auto close_result = std::fclose(file) == 0;
if (!close_result) {
const auto ec = std::error_code{errno, std::generic_category()};
LOG_ERROR(Common_Filesystem, "Failed to close the file at path={}, ec_message={}",
PathToUTF8String(file_path), ec.message());
}
file = nullptr;
}
errno = 0;
const auto close_result = std::fclose(file) == 0;
if (!close_result) {
const auto ec = std::error_code{errno, std::generic_category()};
LOG_ERROR(Common_Filesystem, "Failed to close the file at path={}, ec_message={}",
PathToUTF8String(file_path), ec.message());
}
file = nullptr;
}
bool IOFile::IsOpen() const {
return file != nullptr;
return file != nullptr || IsMappedFile();
}
std::string IOFile::ReadString(size_t length) const {
@@ -323,137 +450,132 @@ size_t IOFile::WriteString(std::span<const char> string) const {
}
bool IOFile::Flush() const {
if (!IsOpen()) {
return false;
ASSERT(!IsMappedFile());
if (file) {
errno = 0;
auto const flush_result = std::fflush(file) == 0;
if (!flush_result) {
const auto ec = std::error_code{errno, std::generic_category()};
LOG_ERROR(Common_Filesystem, "Failed to flush the file at path={}, ec_message={}",
PathToUTF8String(file_path), ec.message());
}
return flush_result;
}
errno = 0;
#ifdef _WIN32
const auto flush_result = std::fflush(file) == 0;
#else
const auto flush_result = std::fflush(file) == 0;
#endif
if (!flush_result) {
const auto ec = std::error_code{errno, std::generic_category()};
LOG_ERROR(Common_Filesystem, "Failed to flush the file at path={}, ec_message={}",
PathToUTF8String(file_path), ec.message());
}
return flush_result;
return false;
}
bool IOFile::Commit() const {
if (!IsOpen()) {
return false;
}
errno = 0;
ASSERT(!IsMappedFile());
if (file) {
errno = 0;
#ifdef _WIN32
const auto commit_result = std::fflush(file) == 0 && _commit(fileno(file)) == 0;
const auto commit_result = std::fflush(file) == 0 && _commit(fileno(file)) == 0;
#else
const auto commit_result = std::fflush(file) == 0 && fsync(fileno(file)) == 0;
const auto commit_result = std::fflush(file) == 0 && fsync(fileno(file)) == 0;
#endif
if (!commit_result) {
const auto ec = std::error_code{errno, std::generic_category()};
LOG_ERROR(Common_Filesystem, "Failed to commit the file at path={}, ec_message={}",
PathToUTF8String(file_path), ec.message());
if (!commit_result) {
const auto ec = std::error_code{errno, std::generic_category()};
LOG_ERROR(Common_Filesystem, "Failed to commit the file at path={}, ec_message={}",
PathToUTF8String(file_path), ec.message());
}
return commit_result;
}
return commit_result;
return false;
}
bool IOFile::SetSize(u64 size) const {
if (!IsOpen()) {
return false;
}
errno = 0;
ASSERT(!IsMappedFile());
if (file) {
errno = 0;
#ifdef _WIN32
const auto set_size_result = _chsize_s(fileno(file), static_cast<s64>(size)) == 0;
const auto set_size_result = _chsize_s(fileno(file), s64(size)) == 0;
#else
const auto set_size_result = ftruncate(fileno(file), static_cast<s64>(size)) == 0;
const auto set_size_result = ftruncate(fileno(file), s64(size)) == 0;
#endif
if (!set_size_result) {
const auto ec = std::error_code{errno, std::generic_category()};
LOG_ERROR(Common_Filesystem, "Failed to resize the file at path={}, size={}, ec_message={}",
PathToUTF8String(file_path), size, ec.message());
if (!set_size_result) {
const auto ec = std::error_code{errno, std::generic_category()};
LOG_ERROR(Common_Filesystem, "Failed to resize the file at path={}, size={}, ec_message={}",
PathToUTF8String(file_path), size, ec.message());
}
return set_size_result;
}
return set_size_result;
return false;
}
u64 IOFile::GetSize() const {
if (!IsOpen()) {
return 0;
}
// Flush any unwritten buffered data into the file prior to retrieving the file size.
std::fflush(file);
if (IsMappedFile())
return mmap_size;
if (file) {
// Flush any unwritten buffered data into the file prior to retrieving the file mmap_size.
std::fflush(file);
#if ANDROID
u64 file_size = 0;
if (Android::IsContentUri(file_path)) {
file_size = Android::GetSize(file_path);
} else {
u64 file_size = 0;
if (Android::IsContentUri(file_path)) {
file_size = Android::GetSize(file_path);
} else {
std::error_code ec;
file_size = fs::file_size(file_path, ec);
if (ec) {
LOG_ERROR(Common_Filesystem, "Failed to retrieve the file mmap_size of path={}, ec_message={}",
PathToUTF8String(file_path), ec.message());
return 0;
}
}
#else
std::error_code ec;
file_size = fs::file_size(file_path, ec);
auto const file_size = fs::file_size(file_path, ec);
if (ec) {
LOG_ERROR(Common_Filesystem,
"Failed to retrieve the file size of path={}, ec_message={}",
PathToUTF8String(file_path), ec.message());
LOG_ERROR(Common_Filesystem, "Failed to retrieve the file mmap_size of path={}, ec_message={}",
PathToUTF8String(file_path), ec.message());
return 0;
}
}
#else
std::error_code ec;
const auto file_size = fs::file_size(file_path, ec);
if (ec) {
LOG_ERROR(Common_Filesystem, "Failed to retrieve the file size of path={}, ec_message={}",
PathToUTF8String(file_path), ec.message());
return 0;
}
#endif
return file_size;
return file_size;
}
return 0;
}
bool IOFile::Seek(s64 offset, SeekOrigin origin) const {
if (!IsOpen()) {
return false;
if (IsMappedFile()) {
// fuck you to whoever made this method const
switch (origin) {
case SeekOrigin::SetOrigin:
mmap_offset = s64(offset);
break;
case SeekOrigin::CurrentPosition:
mmap_offset += s64(offset);
break;
case SeekOrigin::End:
mmap_offset = s64(mmap_size) + s64(offset);
break;
}
return true;
}
errno = 0;
const auto seek_result = fseeko(file, offset, ToSeekOrigin(origin)) == 0;
if (!seek_result) {
const auto ec = std::error_code{errno, std::generic_category()};
LOG_ERROR(Common_Filesystem,
"Failed to seek the file at path={}, offset={}, origin={}, ec_message={}",
PathToUTF8String(file_path), offset, origin, ec.message());
if (file) {
errno = 0;
const auto seek_result = fseeko(file, offset, ToSeekOrigin(origin)) == 0;
if (!seek_result) {
const auto ec = std::error_code{errno, std::generic_category()};
LOG_ERROR(Common_Filesystem, "Failed to seek the file at path={}, offset={}, origin={}, ec_message={}",
PathToUTF8String(file_path), offset, origin, ec.message());
}
return seek_result;
}
return seek_result;
return false;
}
s64 IOFile::Tell() const {
if (!IsOpen()) {
return 0;
if (IsMappedFile()) {
errno = 0;
return s64(mmap_offset);
}
errno = 0;
return ftello(file);
if (file) {
errno = 0;
return ftello(file);
}
return 0;
}
} // namespace Common::FS
+258 -249
View File
@@ -1,9 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <cstdio>
#include <cstring>
#include <filesystem>
#include <span>
#include <type_traits>
@@ -21,12 +25,12 @@ enum class SeekOrigin {
};
/**
* Opens a file stream at path with the specified open mode.
*
* @param file_stream Reference to file stream
* @param path Filesystem path
* @param open_mode File stream open mode
*/
* Opens a file stream at path with the specified open mode.
*
* @param file_stream Reference to file stream
* @param path Filesystem path
* @param open_mode File stream open mode
*/
template <typename FileStream>
void OpenFileStream(FileStream& file_stream, const std::filesystem::path& path,
std::ios_base::openmode open_mode) {
@@ -45,14 +49,14 @@ void OpenFileStream(FileStream& file_stream, const Path& path, std::ios_base::op
#endif
/**
* Reads an entire file at path and returns a string of the contents read from the file.
* If the filesystem object at path is not a regular file, this function returns an empty string.
*
* @param path Filesystem path
* @param type File type
*
* @returns A string of the contents read from the file.
*/
* Reads an entire file at path and returns a string of the contents read from the file.
* If the filesystem object at path is not a regular file, this function returns an empty string.
*
* @param path Filesystem path
* @param type File type
*
* @returns A string of the contents read from the file.
*/
[[nodiscard]] std::string ReadStringFromFile(const std::filesystem::path& path, FileType type);
#ifdef _WIN32
@@ -67,18 +71,18 @@ template <typename Path>
#endif
/**
* Writes a string to a file at path and returns the number of characters successfully written.
* If a file already exists at path, its contents will be erased.
* If a file does not exist at path, it creates and opens a new empty file for writing.
* If the filesystem object at path exists and is not a regular file, this function returns 0.
*
* @param path Filesystem path
* @param type File type
*
* @returns Number of characters successfully written.
*/
* Writes a string to a file at path and returns the number of characters successfully written.
* If a file already exists at path, its contents will be erased.
* If a file does not exist at path, it creates and opens a new empty file for writing.
* If the filesystem object at path exists and is not a regular file, this function returns 0.
*
* @param path Filesystem path
* @param type File type
*
* @returns Number of characters successfully written.
*/
[[nodiscard]] size_t WriteStringToFile(const std::filesystem::path& path, FileType type,
std::string_view string);
std::string_view string);
#ifdef _WIN32
template <typename Path>
@@ -92,15 +96,15 @@ template <typename Path>
#endif
/**
* Appends a string to a file at path and returns the number of characters successfully written.
* If a file does not exist at path, it creates and opens a new empty file for appending.
* If the filesystem object at path exists and is not a regular file, this function returns 0.
*
* @param path Filesystem path
* @param type File type
*
* @returns Number of characters successfully written.
*/
* Appends a string to a file at path and returns the number of characters successfully written.
* If a file does not exist at path, it creates and opens a new empty file for appending.
* If the filesystem object at path exists and is not a regular file, this function returns 0.
*
* @param path Filesystem path
* @param type File type
*
* @returns Number of characters successfully written.
*/
[[nodiscard]] size_t AppendStringToFile(const std::filesystem::path& path, FileType type,
std::string_view string);
@@ -128,14 +132,14 @@ public:
FileShareFlag flag = FileShareFlag::ShareReadOnly);
/**
* An IOFile is a lightweight wrapper on C Library file operations.
* Automatically closes an open file on the destruction of an IOFile object.
*
* @param path Filesystem path
* @param mode File access mode
* @param type File type, default is BinaryFile. Use TextFile to open the file as a text file
* @param flag (Windows only) File-share access flag, default is ShareReadOnly
*/
* An IOFile is a lightweight wrapper on C Library file operations.
* Automatically closes an open file on the destruction of an IOFile object.
*
* @param path Filesystem path
* @param mode File access mode
* @param type File type, default is BinaryFile. Use TextFile to open the file as a text file
* @param flag (Windows only) File-share access flag, default is ShareReadOnly
*/
explicit IOFile(const std::filesystem::path& path, FileAccessMode mode,
FileType type = FileType::BinaryFile,
FileShareFlag flag = FileShareFlag::ShareReadOnly);
@@ -149,84 +153,70 @@ public:
IOFile& operator=(IOFile&& other) noexcept;
/**
* Gets the path of the file.
*
* @returns The path of the file.
*/
* Gets the path of the file.
*
* @returns The path of the file.
*/
[[nodiscard]] std::filesystem::path GetPath() const;
/**
* Gets the access mode of the file.
*
* @returns The access mode of the file.
*/
* Gets the access mode of the file.
*
* @returns The access mode of the file.
*/
[[nodiscard]] FileAccessMode GetAccessMode() const;
/**
* Gets the type of the file.
*
* @returns The type of the file.
*/
* Gets the type of the file.
*
* @returns The type of the file.
*/
[[nodiscard]] FileType GetType() const;
/**
* Opens a file at path with the specified file access mode.
* This function behaves differently depending on the FileAccessMode.
* These behaviors are documented in each enum value of FileAccessMode.
*
* @param path Filesystem path
* @param mode File access mode
* @param type File type, default is BinaryFile. Use TextFile to open the file as a text file
* @param flag (Windows only) File-share access flag, default is ShareReadOnly
*/
* Opens a file at path with the specified file access mode.
* This function behaves differently depending on the FileAccessMode.
* These behaviors are documented in each enum value of FileAccessMode.
*
* @param path Filesystem path
* @param mode File access mode
* @param type File type, default is BinaryFile. Use TextFile to open the file as a text file
* @param flag (Windows only) File-share access flag, default is ShareReadOnly
*/
void Open(const std::filesystem::path& path, FileAccessMode mode,
FileType type = FileType::BinaryFile,
FileShareFlag flag = FileShareFlag::ShareReadOnly);
// #ifdef _WIN32
// template <typename Path>
// void Open(const Path& path, FileAccessMode mode, FileType type = FileType::BinaryFile,
// FileShareFlag flag = FileShareFlag::ShareReadOnly) {
// using ValueType = typename Path::value_type;
// if constexpr (IsChar<ValueType>) {
// Open(ToU8String(path), mode, type, flag);
// } else {
// Open(std::filesystem::path{path}, mode, type, flag);
// }
// }
// #endif
FileType type = FileType::BinaryFile,
FileShareFlag flag = FileShareFlag::ShareReadOnly);
/// Closes the file if it is opened.
void Close();
/**
* Checks whether the file is open.
* Use this to check whether the calls to Open() or Close() succeeded.
*
* @returns True if the file is open, false otherwise.
*/
* Checks whether the file is open.
* Use this to check whether the calls to Open() or Close() succeeded.
*
* @returns True if the file is open, false otherwise.
*/
[[nodiscard]] bool IsOpen() const;
/**
* Helper function which deduces the value type of a contiguous STL container used in ReadSpan.
* If T is not a contiguous container as defined by the concept IsContiguousContainer, this
* calls ReadObject and T must be a trivially copyable object.
*
* See ReadSpan for more details if T is a contiguous container.
* See ReadObject for more details if T is a trivially copyable object.
*
* @tparam T Contiguous container or trivially copyable object
*
* @param data Container of T::value_type data or reference to object
*
* @returns Count of T::value_type data or objects successfully read.
*/
* Helper function which deduces the value type of a contiguous STL container used in ReadSpan.
* If T is not a contiguous container as defined by the concept IsContiguousContainer, this
* calls ReadObject and T must be a trivially copyable object.
*
* See ReadSpan for more details if T is a contiguous container.
* See ReadObject for more details if T is a trivially copyable object.
*
* @tparam T Contiguous container or trivially copyable object
*
* @param data Container of T::value_type data or reference to object
*
* @returns Count of T::value_type data or objects successfully read.
*/
template <typename T>
[[nodiscard]] size_t Read(T& data) const {
if constexpr (IsContiguousContainer<T>) {
using ContiguousType = typename T::value_type;
static_assert(std::is_trivially_copyable_v<ContiguousType>,
"Data type must be trivially copyable.");
static_assert(std::is_trivially_copyable_v<ContiguousType>, "Data type must be trivially copyable.");
return ReadSpan<ContiguousType>(data);
} else {
return ReadObject(data) ? 1 : 0;
@@ -234,25 +224,24 @@ public:
}
/**
* Helper function which deduces the value type of a contiguous STL container used in WriteSpan.
* If T is not a contiguous STL container as defined by the concept IsContiguousContainer, this
* calls WriteObject and T must be a trivially copyable object.
*
* See WriteSpan for more details if T is a contiguous container.
* See WriteObject for more details if T is a trivially copyable object.
*
* @tparam T Contiguous container or trivially copyable object
*
* @param data Container of T::value_type data or const reference to object
*
* @returns Count of T::value_type data or objects successfully written.
*/
* Helper function which deduces the value type of a contiguous STL container used in WriteSpan.
* If T is not a contiguous STL container as defined by the concept IsContiguousContainer, this
* calls WriteObject and T must be a trivially copyable object.
*
* See WriteSpan for more details if T is a contiguous container.
* See WriteObject for more details if T is a trivially copyable object.
*
* @tparam T Contiguous container or trivially copyable object
*
* @param data Container of T::value_type data or const reference to object
*
* @returns Count of T::value_type data or objects successfully written.
*/
template <typename T>
[[nodiscard]] size_t Write(const T& data) const {
if constexpr (IsContiguousContainer<T>) {
using ContiguousType = typename T::value_type;
static_assert(std::is_trivially_copyable_v<ContiguousType>,
"Data type must be trivially copyable.");
static_assert(std::is_trivially_copyable_v<ContiguousType>, "Data type must be trivially copyable.");
return WriteSpan<ContiguousType>(data);
} else {
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
@@ -261,199 +250,219 @@ public:
}
/**
* Reads a span of T data from a file sequentially.
* This function reads from the current position of the file pointer and
* advances it by the (count of T * sizeof(T)) bytes successfully read.
*
* Failures occur when:
* - The file is not open
* - The opened file lacks read permissions
* - Attempting to read beyond the end-of-file
*
* @tparam T Data type
*
* @param data Span of T data
*
* @returns Count of T data successfully read.
*/
* Reads a span of T data from a file sequentially.
* This function reads from the current position of the file pointer and
* advances it by the (count of T * sizeof(T)) bytes successfully read.
*
* Failures occur when:
* - The file is not open
* - The opened file lacks read permissions
* - Attempting to read beyond the end-of-file
*
* @tparam T Data type
*
* @param data Span of T data
*
* @returns Count of T data successfully read.
*/
template <typename T>
[[nodiscard]] size_t ReadSpan(std::span<T> data) const {
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
if (!IsOpen()) {
return 0;
if (IsMappedFile()) {
std::memcpy(data.data(), mmap_base + mmap_offset, sizeof(T) * data.size());
return data.size();
}
return std::fread(data.data(), sizeof(T), data.size(), file);
return IsOpen() ? std::fread(data.data(), sizeof(T), data.size(), file) : 0;
}
/**
* Writes a span of T data to a file sequentially.
* This function writes from the current position of the file pointer and
* advances it by the (count of T * sizeof(T)) bytes successfully written.
*
* Failures occur when:
* - The file is not open
* - The opened file lacks write permissions
*
* @tparam T Data type
*
* @param data Span of T data
*
* @returns Count of T data successfully written.
*/
* Writes a span of T data to a file sequentially.
* This function writes from the current position of the file pointer and
* advances it by the (count of T * sizeof(T)) bytes successfully written.
*
* Failures occur when:
* - The file is not open
* - The opened file lacks write permissions
*
* @tparam T Data type
*
* @param data Span of T data
*
* @returns Count of T data successfully written.
*/
template <typename T>
[[nodiscard]] size_t WriteSpan(std::span<const T> data) const {
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
if (!IsOpen()) {
return 0;
if (IsMappedFile()) {
std::memcpy(mmap_base + mmap_offset, data.data(), sizeof(T) * data.size());
return data.size();
}
return std::fwrite(data.data(), sizeof(T), data.size(), file);
return IsOpen() ? std::fwrite(data.data(), sizeof(T), data.size(), file) : 0;
}
/**
* Reads a T object from a file sequentially.
* This function reads from the current position of the file pointer and
* advances it by the sizeof(T) bytes successfully read.
*
* Failures occur when:
* - The file is not open
* - The opened file lacks read permissions
* - Attempting to read beyond the end-of-file
*
* @tparam T Data type
*
* @param object Reference to object
*
* @returns True if the object is successfully read from the file, false otherwise.
*/
* Reads a T object from a file sequentially.
* This function reads from the current position of the file pointer and
* advances it by the sizeof(T) bytes successfully read.
*
* Failures occur when:
* - The file is not open
* - The opened file lacks read permissions
* - Attempting to read beyond the end-of-file
*
* @tparam T Data type
*
* @param object Reference to object
*
* @returns True if the object is successfully read from the file, false otherwise.
*/
template <typename T>
[[nodiscard]] bool ReadObject(T& object) const {
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
static_assert(!std::is_pointer_v<T>, "T must not be a pointer to an object.");
if (!IsOpen()) {
return false;
if (IsMappedFile()) {
std::memcpy(&object, mmap_base + mmap_offset, sizeof(T));
#ifdef _WIN32
return bool(sizeof(T));
#else
return sizeof(T);
#endif
}
return std::fread(&object, sizeof(T), 1, file) == 1;
return IsOpen() ? std::fread(&object, sizeof(T), 1, file) == 1 : false;
}
/**
* Writes a T object to a file sequentially.
* This function writes from the current position of the file pointer and
* advances it by the sizeof(T) bytes successfully written.
*
* Failures occur when:
* - The file is not open
* - The opened file lacks write permissions
*
* @tparam T Data type
*
* @param object Const reference to object
*
* @returns True if the object is successfully written to the file, false otherwise.
*/
* Writes a T object to a file sequentially.
* This function writes from the current position of the file pointer and
* advances it by the sizeof(T) bytes successfully written.
*
* Failures occur when:
* - The file is not open
* - The opened file lacks write permissions
*
* @tparam T Data type
*
* @param object Const reference to object
*
* @returns True if the object is successfully written to the file, false otherwise.
*/
template <typename T>
[[nodiscard]] bool WriteObject(const T& object) const {
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
static_assert(!std::is_pointer_v<T>, "T must not be a pointer to an object.");
if (!IsOpen()) {
return false;
if (IsMappedFile()) {
std::memcpy(mmap_base + mmap_offset, &object, sizeof(T));
#ifdef _WIN32
return sizeof(T) != 0;
#else
return sizeof(T);
#endif
}
return std::fwrite(&object, sizeof(T), 1, file) == 1;
return IsOpen() ? std::fwrite(&object, sizeof(T), 1, file) == 1 : false;
}
/**
* Specialized function to read a string of a given length from a file sequentially.
* This function writes from the current position of the file pointer and
* advances it by the number of characters successfully read.
* The size of the returned string may not match length if not all bytes are successfully read.
*
* @param length Length of the string
*
* @returns A string read from the file.
*/
* Specialized function to read a string of a given length from a file sequentially.
* This function writes from the current position of the file pointer and
* advances it by the number of characters successfully read.
* The size of the returned string may not match length if not all bytes are successfully read.
*
* @param length Length of the string
*
* @returns A string read from the file.
*/
[[nodiscard]] std::string ReadString(size_t length) const;
/**
* Specialized function to write a string to a file sequentially.
* This function writes from the current position of the file pointer and
* advances it by the number of characters successfully written.
*
* @param string Span of const char backed std::string or std::string_view
*
* @returns Number of characters successfully written.
*/
* Specialized function to write a string to a file sequentially.
* This function writes from the current position of the file pointer and
* advances it by the number of characters successfully written.
*
* @param string Span of const char backed std::string or std::string_view
*
* @returns Number of characters successfully written.
*/
[[nodiscard]] size_t WriteString(std::span<const char> string) const;
/**
* Attempts to flush any unwritten buffered data into the file.
*
* @returns True if the flush was successful, false otherwise.
*/
* Attempts to flush any unwritten buffered data into the file.
*
* @returns True if the flush was successful, false otherwise.
*/
bool Flush() const;
/**
* Attempts to commit the file into the disk.
* Note that this is an expensive operation as this forces the operating system to write
* the contents of the file associated with the file descriptor into the disk.
*
* @returns True if the commit was successful, false otherwise.
*/
* Attempts to commit the file into the disk.
* Note that this is an expensive operation as this forces the operating system to write
* the contents of the file associated with the file descriptor into the disk.
*
* @returns True if the commit was successful, false otherwise.
*/
bool Commit() const;
/**
* Resizes the file to a given size.
* If the file is resized to a smaller size, the remainder of the file is discarded.
* If the file is resized to a larger size, the new area appears as if zero-filled.
*
* Failures occur when:
* - The file is not open
*
* @param size File size in bytes
*
* @returns True if the file resize succeeded, false otherwise.
*/
* Resizes the file to a given size.
* If the file is resized to a smaller size, the remainder of the file is discarded.
* If the file is resized to a larger size, the new area appears as if zero-filled.
*
* Failures occur when:
* - The file is not open
*
* @param size File size in bytes
*
* @returns True if the file resize succeeded, false otherwise.
*/
[[nodiscard]] bool SetSize(u64 size) const;
/**
* Gets the size of the file.
*
* Failures occur when:
* - The file is not open
*
* @returns The file size in bytes of the file. Returns 0 on failure.
*/
* Gets the size of the file.
*
* Failures occur when:
* - The file is not open
*
* @returns The file size in bytes of the file. Returns 0 on failure.
*/
[[nodiscard]] u64 GetSize() const;
/**
* Moves the current position of the file pointer with the specified offset and seek origin.
*
* @param offset Offset from seek origin
* @param origin Seek origin
*
* @returns True if the file pointer has moved to the specified offset, false otherwise.
*/
* Moves the current position of the file pointer with the specified offset and seek origin.
*
* @param offset Offset from seek origin
* @param origin Seek origin
*
* @returns True if the file pointer has moved to the specified offset, false otherwise.
*/
[[nodiscard]] bool Seek(s64 offset, SeekOrigin origin = SeekOrigin::SetOrigin) const;
/**
* Gets the current position of the file pointer.
*
* @returns The current position of the file pointer.
*/
* Gets the current position of the file pointer.
*
* @returns The current position of the file pointer.
*/
[[nodiscard]] s64 Tell() const;
private:
#ifdef _WIN32
inline bool IsMappedFile() const noexcept { return mapping_handle != nullptr; }
#else // POSIX
inline bool IsMappedFile() const noexcept { return mmap_fd != -1; }
#endif
std::filesystem::path file_path;
FileAccessMode file_access_mode{};
FileType file_type{};
std::FILE* file = nullptr;
// Any decent system should have mmap() for files
// Systems with artifical mmap() limitations should simply change the logic within file.cpp
// and reduce the threshold for which the mmap() is set to
#ifdef _WIN32
void *mapping_handle = nullptr;
void *file_handle = nullptr;
#else // POSIX
int mmap_fd = -1;
#endif
u8* mmap_base = nullptr;
size_t mmap_size = 0;
mutable s64 mmap_offset = 0; // fuck you
};
} // namespace Common::FS
+9 -13
View File
@@ -62,20 +62,16 @@ std::vector<Asset> Release::GetPlatformAssets() const {
#ifdef _WIN32
#ifdef ARCHITECTURE_x86_64
#ifdef _MSC_VER
find_asset("Standard", {"amd64-msvc-standard.exe", "amd64-msvc-standard.zip"});
#else // _MSC_VER
find_asset("Standard", {BUILD_ID "-gcc-standard.exe", BUILD_ID "-gcc-standard.zip"});
find_asset("PGO", {BUILD_ID "-clang-pgo.exe", BUILD_ID "-clang-pgo.zip"});
#endif // _MSC_VER
find_asset("Standard", {"amd64-msvc-standard.exe", "amd64-msvc-standard.zip", "mingw-amd64-gcc-standard.exe", "mingw-amd64-gcc-standard.zip"});
find_asset("PGO", {"mingw-amd64-clang-pgo.exe", "mingw-amd64-clang-pgo.zip"});
#elif defined(ARCHITECTURE_arm64)
find_asset("Standard", {"arm64-clang-standard.exe", "arm64-clang-standard.zip"});
find_asset("PGO", {"arm64-clang-pgo.exe", "arm64-clang-pgo.zip"});
#endif // ARCHITECTURE_arm64
find_asset("Standard", {"mingw-arm64-clang-standard.exe", "mingw-arm64-clang-standard.zip"});
find_asset("PGO", {"mingw-arm64-clang-pgo.exe", "mingw-arm64-clang-pgo.zip"});
#endif
#elif defined(__APPLE__)
#ifdef ARCHITECTURE_arm64
find_asset("Standard", {".dmg", ".tar.gz"});
#endif // ARCHITECTURE_arm64
#endif
#elif defined(__ANDROID__)
#ifdef ARCHITECTURE_x86_64
find_asset("Standard", {"chromeos.apk"});
@@ -86,9 +82,9 @@ std::vector<Asset> Release::GetPlatformAssets() const {
find_asset("Standard", {"optimized.apk"});
#else
find_asset("Standard", {"standard.apk"});
#endif // GENSHIN_SPOOF
#endif // ARCHITECTURE_arm64
#endif // __APPLE__
#endif
#endif
#endif
return found_assets;
}
-112
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -31,118 +28,9 @@ enum class Type {
/// Protocol values for sockets
enum class Protocol : u8 {
Unspecified, ///< Represents 0, usable in various places
IP,
ICMP,
TCP,
UDP,
IPV6,
RAW,
IGMP,
GGP,
IPV4,
ST,
EGP,
PIGP,
RCCMON,
NVPII,
PUP,
ARGUS,
EMCON,
XNET,
CHAOS,
MUX,
MEAS,
HMP,
PRM,
IDP,
TRUNK1,
TRUNK2,
LEAF1,
LEAF2,
RDP,
IRTP,
TP,
BLT,
NSP,
INP,
DCCP,
//TODO: 3PC,
IDPR,
XTP,
DDP,
CMTP,
TPXX,
IL,
SDRP,
ROUTING,
FRAGMENT,
IDRP,
RSVP,
GRE,
MHRP,
BHA,
ESP,
AH,
INLSP,
SWIPE,
NHRP,
MOBILE,
TLSP,
SKIP,
ICMPV6,
NONE,
DSTOPTS,
AHIP,
CFTP,
HELLO,
SATEXPAK,
KRYPTOLAN,
RVD,
IPPC,
ADFS,
SATMON,
VISA,
IPCV,
CPNX,
CPHB,
WSN,
PVP,
BRSATMON,
ND,
WBMON,
WBEXPAK,
EON,
VMTP,
SVMTP,
VINES,
TTP,
IGP,
DGP,
TCF,
IGRP,
OSPFIGP,
SRPC,
LARP,
MTP,
AX25,
IPEIP,
MICP,
SCCSP,
ETHERIP,
ENCAP,
APES,
GMTP,
IPCOMP,
SCTP,
MH,
UDPLITE,
HIP,
SHIM6,
PIM,
CARP,
PGM,
MPLS,
PFSYNC
};
/// Shutdown mode
+1 -2
View File
@@ -38,8 +38,7 @@ public:
VirtualBuffer& operator=(const VirtualBuffer&) = delete;
VirtualBuffer(VirtualBuffer&& other) noexcept
: alloc_size{std::exchange(other.alloc_size, 0)}
, base_ptr{std::exchange(other.base_ptr, nullptr)}
: alloc_size{std::exchange(other.alloc_size, 0)}, base_ptr{std::exchange(other.base_ptr), nullptr}
{}
VirtualBuffer& operator=(VirtualBuffer&& other) noexcept {
+174 -55
View File
@@ -1,77 +1,196 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/steady_clock.h"
#include "common/uint128.h"
#include "common/wall_clock.h"
#ifdef __ANDROID__
#include <sys/system_properties.h>
#endif
#ifdef ARCHITECTURE_x86_64
#include "common/x64/cpu_detect.h"
#include "common/x64/native_clock.h"
#include "common/x64/rdtsc.h"
#endif
#ifdef HAS_NCE
#include "common/arm64/native_clock.h"
#endif
namespace Common {
class StandardWallClock final : public WallClock {
public:
explicit StandardWallClock() {}
std::chrono::nanoseconds GetTimeNS() const override {
return std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::system_clock::now().time_since_epoch());
}
std::chrono::microseconds GetTimeUS() const override {
return std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::system_clock::now().time_since_epoch());
}
std::chrono::milliseconds GetTimeMS() const override {
return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch());
}
s64 GetCNTPCT() const override {
return GetUptime() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
}
s64 GetGPUTick() const override {
return GetUptime() * NsToGPUTickRatio::num / NsToGPUTickRatio::den;
}
s64 GetUptime() const override {
return std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::steady_clock::now().time_since_epoch())
.count();
}
bool IsNative() const override {
return false;
}
};
std::unique_ptr<WallClock> CreateOptimalClock() {
#if defined(ARCHITECTURE_x86_64)
const auto& caps = GetCPUCaps();
WallClock::WallClock(bool invariant_, u64 rdtsc_frequency_) noexcept
: invariant{invariant_}
, rdtsc_frequency{rdtsc_frequency_}
, ns_rdtsc_factor{GetFixedPoint64Factor(NsRatio::den, rdtsc_frequency_)}
, us_rdtsc_factor{GetFixedPoint64Factor(UsRatio::den, rdtsc_frequency_)}
, ms_rdtsc_factor{GetFixedPoint64Factor(MsRatio::den, rdtsc_frequency_)}
, cntpct_rdtsc_factor{GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency_)}
, gputick_rdtsc_factor{GetFixedPoint64Factor(GPUTickFreq, rdtsc_frequency_)}
{}
if (caps.invariant_tsc && caps.tsc_frequency >= std::nano::den) {
return std::make_unique<X64::NativeClock>(caps.tsc_frequency);
} else {
// Fallback to StandardWallClock if the hardware TSC
// - Is not invariant
// - Is not more precise than 1 GHz (1ns resolution)
return std::make_unique<StandardWallClock>();
}
std::chrono::nanoseconds WallClock::GetTimeNS() const {
if (invariant)
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch());
return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_rdtsc_factor)};
}
std::chrono::microseconds WallClock::GetTimeUS() const {
if (invariant)
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch());
return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_rdtsc_factor)};
}
std::chrono::milliseconds WallClock::GetTimeMS() const {
if (invariant)
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_rdtsc_factor)};
}
s64 WallClock::GetCNTPCT() const {
if (invariant)
return GetUptime() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
return MultiplyHigh(GetUptime(), cntpct_rdtsc_factor);
}
s64 WallClock::GetGPUTick() const {
if (invariant)
return GetUptime() * NsToGPUTickRatio::num / NsToGPUTickRatio::den;
return MultiplyHigh(GetUptime(), gputick_rdtsc_factor);
}
s64 WallClock::GetUptime() const {
if (invariant)
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
return s64(Common::X64::FencedRDTSC());
}
bool WallClock::IsNative() const {
if (invariant)
return false;
return true;
}
#elif defined(HAS_NCE)
return std::make_unique<Arm64::NativeClock>();
namespace {
[[nodiscard]] WallClock::FactorType GetFixedPointFactor(u64 num, u64 den) noexcept {
return (WallClock::FactorType(num) << 64) / den;
}
[[nodiscard]] u64 MultiplyHigh(u64 m, WallClock::FactorType factor) noexcept {
return static_cast<u64>((m * factor) >> 64);
}
[[nodiscard]] s64 GetHostCNTFRQ() noexcept {
u64 cntfrq_el0 = 0;
#ifdef ANDROID
std::string_view board{""};
char buffer[PROP_VALUE_MAX];
int len{__system_property_get("ro.product.board", buffer)};
board = std::string_view(buffer, static_cast<size_t>(len));
if (board == "s5e9925") { // Exynos 2200
cntfrq_el0 = 25600000;
} else if (board == "exynos2100") { // Exynos 2100
cntfrq_el0 = 26000000;
} else if (board == "exynos9810") { // Exynos 9810
cntfrq_el0 = 26000000;
} else if (board == "s5e8825") { // Exynos 1280
cntfrq_el0 = 26000000;
} else {
asm volatile("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0));
}
return cntfrq_el0;
#else
return std::make_unique<StandardWallClock>();
asm volatile("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0));
return cntfrq_el0;
#endif
}
} // namespace
WallClock::WallClock(bool invariant_, u64 rdtsc_frequency_) noexcept {
const u64 host_cntfrq = std::max<u64>(GetHostCNTFRQ(), 1);
ns_cntfrq_factor = GetFixedPointFactor(NsRatio::den, host_cntfrq);
us_cntfrq_factor = GetFixedPointFactor(UsRatio::den, host_cntfrq);
ms_cntfrq_factor = GetFixedPointFactor(MsRatio::den, host_cntfrq);
guest_cntfrq_factor = GetFixedPointFactor(CNTFRQ, host_cntfrq);
gputick_cntfrq_factor = GetFixedPointFactor(GPUTickFreq, host_cntfrq);
}
std::chrono::nanoseconds WallClock::GetTimeNS() const {
return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_cntfrq_factor)};
}
std::chrono::microseconds WallClock::GetTimeUS() const {
return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_cntfrq_factor)};
}
std::chrono::milliseconds WallClock::GetTimeMS() const {
return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_cntfrq_factor)};
}
s64 WallClock::GetCNTPCT() const {
return MultiplyHigh(GetUptime(), guest_cntfrq_factor);
}
s64 WallClock::GetGPUTick() const {
return MultiplyHigh(GetUptime(), gputick_cntfrq_factor);
}
s64 WallClock::GetUptime() const {
s64 cntvct_el0 = 0;
asm volatile(
"dsb ish\n\t"
"mrs %[cntvct_el0], cntvct_el0\n\t"
"dsb ish\n\t"
: [cntvct_el0] "=r"(cntvct_el0)
);
return cntvct_el0;
}
bool WallClock::IsNative() const {
return true;
}
#else
WallClock::WallClock(bool invariant_, u64 rdtsc_frequency_) noexcept {}
std::chrono::nanoseconds WallClock::GetTimeNS() const {
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch());
}
std::chrono::microseconds WallClock::GetTimeUS() const {
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch());
}
std::chrono::milliseconds WallClock::GetTimeMS() const {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
}
s64 WallClock::GetCNTPCT() const {
return GetUptime() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
}
s64 WallClock::GetGPUTick() const {
return GetUptime() * NsToGPUTickRatio::num / NsToGPUTickRatio::den;
}
s64 WallClock::GetUptime() const {
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
}
bool WallClock::IsNative() const {
return false;
}
#endif
WallClock CreateOptimalClock() noexcept {
#if defined(ARCHITECTURE_x86_64)
auto const& caps = GetCPUCaps();
return WallClock(!(caps.invariant_tsc && caps.tsc_frequency >= std::nano::den), std::max<u64>(caps.tsc_frequency, 1));
#elif defined(HAS_NCE)
return WallClock(false, 1);
#else
return WallClock(true, 1);
#endif
}
+35 -10
View File
@@ -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-FileCopyrightText: Copyright 2020 yuzu Emulator Project
@@ -20,28 +20,28 @@ public:
static constexpr u64 GPUTickFreq = 614'400'000; // GM20B GPU Tick Frequency = 614.4 MHz
static constexpr u64 CPUTickFreq = 1'020'000'000; // T210/4 A57 CPU Tick Frequency = 1020.0 MHz
virtual ~WallClock() = default;
explicit WallClock(bool invariant, u64 rdtsc_frequency_) noexcept;
/// @returns The time in nanoseconds since the construction of this clock.
virtual std::chrono::nanoseconds GetTimeNS() const = 0;
std::chrono::nanoseconds GetTimeNS() const;
/// @returns The time in microseconds since the construction of this clock.
virtual std::chrono::microseconds GetTimeUS() const = 0;
std::chrono::microseconds GetTimeUS() const;
/// @returns The time in milliseconds since the construction of this clock.
virtual std::chrono::milliseconds GetTimeMS() const = 0;
std::chrono::milliseconds GetTimeMS() const;
/// @returns The guest CNTPCT ticks since the construction of this clock.
virtual s64 GetCNTPCT() const = 0;
s64 GetCNTPCT() const;
/// @returns The guest GPU ticks since the construction of this clock.
virtual s64 GetGPUTick() const = 0;
s64 GetGPUTick() const;
/// @returns The raw host timer ticks since an indeterminate epoch.
virtual s64 GetUptime() const = 0;
s64 GetUptime() const;
/// @returns Whether the clock directly uses the host's hardware clock.
virtual bool IsNative() const = 0;
bool IsNative() const;
static inline u64 NSToCNTPCT(u64 ns) {
return ns * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
@@ -85,8 +85,33 @@ protected:
using CPUTickToUsRatio = std::ratio<std::micro::den, CPUTickFreq>;
using CPUTickToCNTPCTRatio = std::ratio<CNTFRQ, CPUTickFreq>;
using CPUTickToGPUTickRatio = std::ratio<GPUTickFreq, CPUTickFreq>;
#if defined(ARCHITECTURE_x86_64)
bool invariant;
u64 rdtsc_frequency;
u64 ns_rdtsc_factor;
u64 us_rdtsc_factor;
u64 ms_rdtsc_factor;
u64 cntpct_rdtsc_factor;
u64 gputick_rdtsc_factor;
#elif defined(HAS_NCE)
public:
using FactorType = unsigned __int128;
FactorType GetGuestCNTFRQFactor() const {
return guest_cntfrq_factor;
}
protected:
FactorType ns_cntfrq_factor;
FactorType us_cntfrq_factor;
FactorType ms_cntfrq_factor;
FactorType guest_cntfrq_factor;
FactorType gputick_cntfrq_factor;
#else
#endif
};
[[nodiscard]] std::unique_ptr<WallClock> CreateOptimalClock();
[[nodiscard]] WallClock CreateOptimalClock() noexcept;
} // namespace Common
-46
View File
@@ -1,46 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/uint128.h"
#include "common/x64/native_clock.h"
#include "common/x64/rdtsc.h"
namespace Common::X64 {
NativeClock::NativeClock(u64 rdtsc_frequency_)
: rdtsc_frequency{rdtsc_frequency_}, ns_rdtsc_factor{GetFixedPoint64Factor(NsRatio::den,
rdtsc_frequency)},
us_rdtsc_factor{GetFixedPoint64Factor(UsRatio::den, rdtsc_frequency)},
ms_rdtsc_factor{GetFixedPoint64Factor(MsRatio::den, rdtsc_frequency)},
cntpct_rdtsc_factor{GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency)},
gputick_rdtsc_factor{GetFixedPoint64Factor(GPUTickFreq, rdtsc_frequency)} {}
std::chrono::nanoseconds NativeClock::GetTimeNS() const {
return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_rdtsc_factor)};
}
std::chrono::microseconds NativeClock::GetTimeUS() const {
return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_rdtsc_factor)};
}
std::chrono::milliseconds NativeClock::GetTimeMS() const {
return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_rdtsc_factor)};
}
s64 NativeClock::GetCNTPCT() const {
return MultiplyHigh(GetUptime(), cntpct_rdtsc_factor);
}
s64 NativeClock::GetGPUTick() const {
return MultiplyHigh(GetUptime(), gputick_rdtsc_factor);
}
s64 NativeClock::GetUptime() const {
return static_cast<s64>(FencedRDTSC());
}
bool NativeClock::IsNative() const {
return true;
}
} // namespace Common::X64
-38
View File
@@ -1,38 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/wall_clock.h"
namespace Common::X64 {
class NativeClock final : public WallClock {
public:
explicit NativeClock(u64 rdtsc_frequency_);
std::chrono::nanoseconds GetTimeNS() const override;
std::chrono::microseconds GetTimeUS() const override;
std::chrono::milliseconds GetTimeMS() const override;
s64 GetCNTPCT() const override;
s64 GetGPUTick() const override;
s64 GetUptime() const override;
bool IsNative() const override;
private:
u64 rdtsc_frequency;
u64 ns_rdtsc_factor;
u64 us_rdtsc_factor;
u64 ms_rdtsc_factor;
u64 cntpct_rdtsc_factor;
u64 gputick_rdtsc_factor;
};
} // namespace Common::X64
@@ -1,13 +1,37 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2016 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <type_traits>
#include <bitset>
#include <initializer_list>
#include <xbyak/xbyak.h>
#include "common/assert.h"
// xbyak hates human beings
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wshadow"
#endif
#ifdef __clang__
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wshadow"
#endif
// You must ensure this matches with src/common/x64/xbyak.h on root dir
#include <ankerl/unordered_dense.h>
#include <boost/unordered_map.hpp>
#define XBYAK_STD_UNORDERED_SET ankerl::unordered_dense::set
#define XBYAK_STD_UNORDERED_MAP ankerl::unordered_dense::map
#define XBYAK_STD_UNORDERED_MULTIMAP boost::unordered_multimap
#include <xbyak/xbyak.h>
#include <xbyak/xbyak_util.h>
#include <xbyak/xbyak.h>
namespace Common::X64 {
constexpr size_t RegToIndex(const Xbyak::Reg& reg) {
@@ -174,12 +198,13 @@ inline ABIFrameInfo ABI_CalculateFrameSize(std::bitset<32> regs, size_t rsp_alig
rsp_alignment -= subtraction;
subtraction += rsp_alignment & 0xF;
return ABIFrameInfo{static_cast<s32>(subtraction),
static_cast<s32>(subtraction - xmm_base_subtraction)};
return ABIFrameInfo{
s32(subtraction),
s32(subtraction - xmm_base_subtraction)
};
}
inline size_t ABI_PushRegistersAndAdjustStack(Xbyak::CodeGenerator& code, std::bitset<32> regs,
size_t rsp_alignment, size_t needed_frame_size = 0) {
inline size_t ABI_PushRegistersAndAdjustStack(Xbyak::CodeGenerator& code, std::bitset<32> regs, size_t rsp_alignment, size_t needed_frame_size = 0) {
auto frame_info = ABI_CalculateFrameSize(regs, rsp_alignment, needed_frame_size);
for (size_t i = 0; i < regs.size(); ++i) {
@@ -202,8 +227,7 @@ inline size_t ABI_PushRegistersAndAdjustStack(Xbyak::CodeGenerator& code, std::b
return ABI_SHADOW_SPACE;
}
inline void ABI_PopRegistersAndAdjustStack(Xbyak::CodeGenerator& code, std::bitset<32> regs,
size_t rsp_alignment, size_t needed_frame_size = 0) {
inline void ABI_PopRegistersAndAdjustStack(Xbyak::CodeGenerator& code, std::bitset<32> regs, size_t rsp_alignment, size_t needed_frame_size = 0) {
auto frame_info = ABI_CalculateFrameSize(regs, rsp_alignment, needed_frame_size);
for (size_t i = 0; i < regs.size(); ++i) {
@@ -226,4 +250,38 @@ inline void ABI_PopRegistersAndAdjustStack(Xbyak::CodeGenerator& code, std::bits
}
}
// Constants for use with cmpps/cmpss
enum {
CMP_EQ = 0,
CMP_LT = 1,
CMP_LE = 2,
CMP_UNORD = 3,
CMP_NEQ = 4,
CMP_NLT = 5,
CMP_NLE = 6,
CMP_ORD = 7,
};
constexpr bool IsWithin2G(uintptr_t ref, uintptr_t target) {
const u64 distance = target - (ref + 5);
return !(distance >= 0x8000'0000ULL && distance <= ~0x8000'0000ULL);
}
inline bool IsWithin2G(const Xbyak::CodeGenerator& code, uintptr_t target) {
return IsWithin2G(reinterpret_cast<uintptr_t>(code.getCurr()), target);
}
template <typename T>
inline void CallFarFunction(Xbyak::CodeGenerator& code, const T f) {
static_assert(std::is_pointer_v<T>, "Argument must be a (function) pointer.");
size_t addr = reinterpret_cast<size_t>(f);
if (IsWithin2G(code, addr)) {
code.call(f);
} else {
// ABI_RETURN is a safe temp register to use before a call
code.mov(ABI_RETURN, addr);
code.call(ABI_RETURN);
}
}
} // namespace Common::X64
-46
View File
@@ -1,46 +0,0 @@
// SPDX-FileCopyrightText: 2016 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <type_traits>
#include <xbyak/xbyak.h>
#include "common/x64/xbyak_abi.h"
namespace Common::X64 {
// Constants for use with cmpps/cmpss
enum {
CMP_EQ = 0,
CMP_LT = 1,
CMP_LE = 2,
CMP_UNORD = 3,
CMP_NEQ = 4,
CMP_NLT = 5,
CMP_NLE = 6,
CMP_ORD = 7,
};
constexpr bool IsWithin2G(uintptr_t ref, uintptr_t target) {
const u64 distance = target - (ref + 5);
return !(distance >= 0x8000'0000ULL && distance <= ~0x8000'0000ULL);
}
inline bool IsWithin2G(const Xbyak::CodeGenerator& code, uintptr_t target) {
return IsWithin2G(reinterpret_cast<uintptr_t>(code.getCurr()), target);
}
template <typename T>
inline void CallFarFunction(Xbyak::CodeGenerator& code, const T f) {
static_assert(std::is_pointer_v<T>, "Argument must be a (function) pointer.");
size_t addr = reinterpret_cast<size_t>(f);
if (IsWithin2G(code, addr)) {
code.call(f);
} else {
// ABI_RETURN is a safe temp register to use before a call
code.mov(ABI_RETURN, addr);
code.call(ABI_RETURN);
}
}
} // namespace Common::X64
+1 -3
View File
@@ -1,11 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <dynarmic/interface/halt_reason.h>
#include "core/arm/arm_interface.h"
+3 -6
View File
@@ -113,8 +113,7 @@ void DynarmicCallbacks32::CallSVC(u32 swi) {
}
void DynarmicCallbacks32::AddTicks(u64 ticks) {
ASSERT_MSG(!m_parent.m_uses_wall_clock, "Dynarmic ticking disabled");
ASSERT(!m_parent.m_uses_wall_clock && "Dynarmic ticking disabled");
// Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a
// rough approximation of the amount of executed ticks in the system, it may be thrown off
// if not all cores are doing a similar amount of work. Instead of doing this, we should
@@ -123,14 +122,12 @@ void DynarmicCallbacks32::AddTicks(u64 ticks) {
u64 amortized_ticks = ticks / Core::Hardware::NUM_CPU_CORES;
// Always execute at least one tick.
amortized_ticks = std::max<u64>(amortized_ticks, 1);
m_parent.m_system.CoreTiming().AddTicks(amortized_ticks);
}
u64 DynarmicCallbacks32::GetTicksRemaining() {
ASSERT_MSG(!m_parent.m_uses_wall_clock, "Dynarmic ticking disabled");
return std::max<s64>(m_parent.m_system.CoreTiming().GetDowncount(), 0);
ASSERT(!m_parent.m_uses_wall_clock && "Dynarmic ticking disabled");
return std::max<s64>(m_parent.m_system.CoreTiming().downcount, 0);
}
bool DynarmicCallbacks32::CheckMemoryAccess(u64 addr, u64 size, Kernel::DebugWatchpointType type) {
+2 -4
View File
@@ -150,8 +150,7 @@ void DynarmicCallbacks64::CallSVC(u32 svc) {
}
void DynarmicCallbacks64::AddTicks(u64 ticks) {
ASSERT_MSG(!m_parent.m_uses_wall_clock, "Dynarmic ticking disabled");
ASSERT(!m_parent.m_uses_wall_clock && "Dynarmic ticking disabled");
// Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a
// rough approximation of the amount of executed ticks in the system, it may be thrown off
// if not all cores are doing a similar amount of work. Instead of doing this, we should
@@ -160,13 +159,12 @@ void DynarmicCallbacks64::AddTicks(u64 ticks) {
u64 amortized_ticks = ticks / Core::Hardware::NUM_CPU_CORES;
// Always execute at least one tick.
amortized_ticks = std::max<u64>(amortized_ticks, 1);
m_parent.m_system.CoreTiming().AddTicks(amortized_ticks);
}
u64 DynarmicCallbacks64::GetTicksRemaining() {
ASSERT(!m_parent.m_uses_wall_clock && "Dynarmic ticking disabled");
return std::max<s64>(m_parent.m_system.CoreTiming().GetDowncount(), 0);
return std::max<s64>(m_parent.m_system.CoreTiming().downcount, 0);
}
u64 DynarmicCallbacks64::GetCNTPCT() {
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -7,28 +10,30 @@
namespace Core {
DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(Memory::Memory& memory_, std::size_t core_count_)
: monitor{core_count_}, memory{memory_} {}
: monitor{}
, memory{memory_}
{}
DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default;
u8 DynarmicExclusiveMonitor::ExclusiveRead8(std::size_t core_index, VAddr addr) {
return monitor.ReadAndMark<u8>(core_index, addr, [&]() -> u8 { return memory.Read8(addr); });
return monitor.ReadAndMark<u8>(core_index, addr, [=]() -> u8 { return memory.Read8(addr); });
}
u16 DynarmicExclusiveMonitor::ExclusiveRead16(std::size_t core_index, VAddr addr) {
return monitor.ReadAndMark<u16>(core_index, addr, [&]() -> u16 { return memory.Read16(addr); });
return monitor.ReadAndMark<u16>(core_index, addr, [=]() -> u16 { return memory.Read16(addr); });
}
u32 DynarmicExclusiveMonitor::ExclusiveRead32(std::size_t core_index, VAddr addr) {
return monitor.ReadAndMark<u32>(core_index, addr, [&]() -> u32 { return memory.Read32(addr); });
return monitor.ReadAndMark<u32>(core_index, addr, [=]() -> u32 { return memory.Read32(addr); });
}
u64 DynarmicExclusiveMonitor::ExclusiveRead64(std::size_t core_index, VAddr addr) {
return monitor.ReadAndMark<u64>(core_index, addr, [&]() -> u64 { return memory.Read64(addr); });
return monitor.ReadAndMark<u64>(core_index, addr, [=]() -> u64 { return memory.Read64(addr); });
}
u128 DynarmicExclusiveMonitor::ExclusiveRead128(std::size_t core_index, VAddr addr) {
return monitor.ReadAndMark<u128>(core_index, addr, [&]() -> u128 {
return monitor.ReadAndMark<u128>(core_index, addr, [=]() -> u128 {
u128 result;
result[0] = memory.Read64(addr);
result[1] = memory.Read64(addr + 8);
@@ -41,31 +46,31 @@ void DynarmicExclusiveMonitor::ClearExclusive(std::size_t core_index) {
}
bool DynarmicExclusiveMonitor::ExclusiveWrite8(std::size_t core_index, VAddr vaddr, u8 value) {
return monitor.DoExclusiveOperation<u8>(core_index, vaddr, [&](u8 expected) -> bool {
return monitor.DoExclusiveOperation<u8>(core_index, vaddr, [=](u8 expected) -> bool {
return memory.WriteExclusive8(vaddr, value, expected);
});
}
bool DynarmicExclusiveMonitor::ExclusiveWrite16(std::size_t core_index, VAddr vaddr, u16 value) {
return monitor.DoExclusiveOperation<u16>(core_index, vaddr, [&](u16 expected) -> bool {
return monitor.DoExclusiveOperation<u16>(core_index, vaddr, [=](u16 expected) -> bool {
return memory.WriteExclusive16(vaddr, value, expected);
});
}
bool DynarmicExclusiveMonitor::ExclusiveWrite32(std::size_t core_index, VAddr vaddr, u32 value) {
return monitor.DoExclusiveOperation<u32>(core_index, vaddr, [&](u32 expected) -> bool {
return monitor.DoExclusiveOperation<u32>(core_index, vaddr, [=](u32 expected) -> bool {
return memory.WriteExclusive32(vaddr, value, expected);
});
}
bool DynarmicExclusiveMonitor::ExclusiveWrite64(std::size_t core_index, VAddr vaddr, u64 value) {
return monitor.DoExclusiveOperation<u64>(core_index, vaddr, [&](u64 expected) -> bool {
return monitor.DoExclusiveOperation<u64>(core_index, vaddr, [=](u64 expected) -> bool {
return memory.WriteExclusive64(vaddr, value, expected);
});
}
bool DynarmicExclusiveMonitor::ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) {
return monitor.DoExclusiveOperation<u128>(core_index, vaddr, [&](u128 expected) -> bool {
return monitor.DoExclusiveOperation<u128>(core_index, vaddr, [=](u128 expected) -> bool {
return memory.WriteExclusive128(vaddr, value, expected);
});
}
+1 -1
View File
@@ -388,7 +388,7 @@ void ArmNce::SignalInterrupt(Kernel::KThread* thread) {
}
}
[[maybe_unused]] const std::size_t CACHE_PAGE_SIZE = 4096;
const std::size_t CACHE_PAGE_SIZE = 4096;
void ArmNce::ClearInstructionCache() {
#ifdef __aarch64__
+1 -3
View File
@@ -1,11 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 Skyline Team and Contributors
// SPDX-License-Identifier: MPL-2.0
#pragma once
#include "common/bit_field.h"
#include "common/common_types.h"
+3 -3
View File
@@ -12,9 +12,9 @@ namespace Core {
namespace {
// Prefetch tuning parameters
[[maybe_unused]] constexpr size_t CACHE_LINE_SIZE = 64;
[[maybe_unused]] constexpr size_t PREFETCH_STRIDE = 128; // 2 cache lines ahead
[[maybe_unused]] constexpr size_t SIMD_PREFETCH_THRESHOLD = 32; // Bytes
constexpr size_t CACHE_LINE_SIZE = 64;
constexpr size_t PREFETCH_STRIDE = 128; // 2 cache lines ahead
constexpr size_t SIMD_PREFETCH_THRESHOLD = 32; // Bytes
} // namespace
template <u32 BitSize>
+6 -2
View File
@@ -3,7 +3,7 @@
#include <numeric>
#include <bit>
#include "common/arm64/native_clock.h"
#include "common/wall_clock.h"
#include "common/alignment.h"
#include "common/literals.h"
#include "core/arm/nce/arm_nce.h"
@@ -578,7 +578,11 @@ void Patcher::WriteMsrHandler(ModuleDestLabel module_dest, oaknut::XReg src_reg,
}
void Patcher::WriteCntpctHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg, oaknut::VectorCodeGenerator& cg) {
static Common::Arm64::NativeClock clock{};
#if defined(HAS_NCE)
static Common::WallClock clock(false, 1);
#else
static Common::WallClock clock(true, 1);
#endif
const auto factor = clock.GetGuestCNTFRQFactor();
const auto raw_factor = std::bit_cast<std::array<u64, 2>>(factor);
+67 -88
View File
@@ -57,15 +57,51 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
Reset();
on_thread_init = std::move(on_thread_init_);
event_fifo_id = 0;
shutting_down = false;
cpu_ticks = 0;
if (is_multicore) {
timer_thread.emplace([](CoreTiming& instance) {
timer_thread = std::jthread([this](std::stop_token stop_token) {
Common::SetCurrentThreadName("HostTiming");
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
instance.on_thread_init();
instance.ThreadLoop();
}, std::ref(*this));
on_thread_init();
has_started = true;
while (!stop_token.stop_requested()) {
while (!paused && !stop_token.stop_requested()) {
paused_set = false;
if (auto const next_time = Advance(); next_time) {
// There are more events left in the queue, wait until the next event.
auto wait_time = *next_time - GetGlobalTimeNs().count();
if (wait_time > 0) {
#ifdef _WIN32
while (!paused && !event.IsSet() && wait_time > 0) {
wait_time = *next_time - GetGlobalTimeNs().count();
if (wait_time >= timer_resolution_ns) {
Common::Windows::SleepForOneTick();
} else {
#ifdef ARCHITECTURE_x86_64
Common::X64::MicroSleep();
#else
std::this_thread::yield();
#endif
}
}
if (event.IsSet())
event.Reset();
#else
event.WaitFor(std::chrono::nanoseconds(wait_time));
#endif
}
} else {
// Queue is empty, wait until another event is scheduled and signals us to
// continue.
wait_set = true;
event.Wait();
}
wait_set = false;
}
paused_set = true;
pause_event.Wait();
}
});
}
}
@@ -90,7 +126,7 @@ void CoreTiming::SyncPause(bool is_paused) {
}
Pause(is_paused);
if (timer_thread) {
if (timer_thread.joinable()) {
if (!is_paused) {
pause_event.Set();
}
@@ -190,33 +226,22 @@ void CoreTiming::ResetTicks() {
}
u64 CoreTiming::GetClockTicks() const {
u64 fres;
if (is_multicore) [[likely]] {
fres = clock->GetCNTPCT();
} else {
fres = Common::WallClock::CPUTickToCNTPCT(cpu_ticks);
u64 fres = is_multicore ? clock.GetCNTPCT() : Common::WallClock::CPUTickToCNTPCT(cpu_ticks);
if (auto const overclock = Settings::values.fast_cpu_time.GetValue(); overclock != Settings::CpuClock::Off) {
fres = u64(f64(fres) * (1.7 + 0.3 * u32(overclock)));
}
const auto overclock = Settings::values.fast_cpu_time.GetValue();
if (overclock != Settings::CpuClock::Off) {
fres = (u64) ((double) fres * (1.7 + 0.3 * u32(overclock)));
}
if (Settings::values.sync_core_speed.GetValue()) {
const auto ticks = double(fres);
const auto speed_limit = double(Settings::SpeedLimit())*0.01;
return u64(ticks/speed_limit);
} else {
return fres;
}
if (::Settings::values.sync_core_speed.GetValue()) {
auto const ticks = f64(fres);
auto const speed_limit = f64(Settings::SpeedLimit()) * 0.01;
return u64(ticks / speed_limit);
}
return fres;
}
u64 CoreTiming::GetGPUTicks() const {
if (is_multicore) [[likely]] {
return clock->GetGPUTick();
}
return Common::WallClock::CPUTickToGPUTick(cpu_ticks);
return is_multicore
? clock.GetGPUTick()
: Common::WallClock::CPUTickToGPUTick(cpu_ticks);
}
std::optional<s64> CoreTiming::Advance() {
@@ -278,75 +303,29 @@ std::optional<s64> CoreTiming::Advance() {
}
}
void CoreTiming::ThreadLoop() {
has_started = true;
while (!shutting_down) {
while (!paused) {
paused_set = false;
const auto next_time = Advance();
if (next_time) {
// There are more events left in the queue, wait until the next event.
auto wait_time = *next_time - GetGlobalTimeNs().count();
if (wait_time > 0) {
#ifdef _WIN32
while (!paused && !event.IsSet() && wait_time > 0) {
wait_time = *next_time - GetGlobalTimeNs().count();
if (wait_time >= timer_resolution_ns) {
Common::Windows::SleepForOneTick();
} else {
#ifdef ARCHITECTURE_x86_64
Common::X64::MicroSleep();
#else
std::this_thread::yield();
#endif
}
}
if (event.IsSet()) {
event.Reset();
}
#else
event.WaitFor(std::chrono::nanoseconds(wait_time));
#endif
}
} else {
// Queue is empty, wait until another event is scheduled and signals us to
// continue.
wait_set = true;
event.Wait();
}
wait_set = false;
}
paused_set = true;
pause_event.Wait();
}
}
void CoreTiming::Reset() {
paused = true;
shutting_down = true;
pause_event.Set();
event.Set();
if (timer_thread) {
timer_thread->join();
if (timer_thread.joinable()) {
timer_thread.request_stop();
timer_thread.join();
}
timer_thread.reset();
has_started = false;
}
std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const {
if (is_multicore) [[likely]] {
return clock->GetTimeNS();
}
return std::chrono::nanoseconds{Common::WallClock::CPUTickToNS(cpu_ticks)};
/// @brief Returns current time in nanoseconds.
std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const noexcept {
return is_multicore
? clock.GetTimeNS()
: std::chrono::nanoseconds{Common::WallClock::CPUTickToNS(cpu_ticks)};
}
std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const {
if (is_multicore) [[likely]] {
return clock->GetTimeUS();
}
return std::chrono::microseconds{Common::WallClock::CPUTickToUS(cpu_ticks)};
/// @brief Returns current time in microseconds.
std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const noexcept {
return is_multicore
? clock.GetTimeUS()
: std::chrono::microseconds{Common::WallClock::CPUTickToUS(cpu_ticks)};
}
#ifdef _WIN32
+6 -12
View File
@@ -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-FileCopyrightText: Copyright 2020 yuzu Emulator Project
@@ -118,7 +118,7 @@ public:
void Idle();
s64 GetDowncount() const {
s64 GetDowncount() const noexcept {
return downcount;
}
@@ -128,11 +128,8 @@ public:
/// Returns the current GPU tick value.
u64 GetGPUTicks() const;
/// Returns current time in microseconds.
std::chrono::microseconds GetGlobalTimeUs() const;
/// Returns current time in nanoseconds.
std::chrono::nanoseconds GetGlobalTimeNs() const;
[[nodiscard]] std::chrono::microseconds GetGlobalTimeUs() const noexcept;
[[nodiscard]] std::chrono::nanoseconds GetGlobalTimeNs() const noexcept;
/// Checks for events manually and returns time in nanoseconds for next event, threadsafe.
std::optional<s64> Advance();
@@ -141,13 +138,11 @@ public:
void SetTimerResolutionNs(std::chrono::nanoseconds ns);
#endif
private:
struct Event;
void ThreadLoop();
void Reset();
std::unique_ptr<Common::WallClock> clock;
Common::WallClock clock;
s64 global_timer = 0;
@@ -165,11 +160,10 @@ private:
Common::Event pause_event{};
mutable std::mutex basic_lock;
std::mutex advance_lock;
std::optional<std::jthread> timer_thread;
std::jthread timer_thread;
std::atomic<bool> paused{};
std::atomic<bool> paused_set{};
std::atomic<bool> wait_set{};
std::atomic<bool> shutting_down{};
std::atomic<bool> has_started{};
std::function<void()> on_thread_init{};
@@ -1,86 +1,48 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <span>
#include <vector>
#include "common/swap.h"
#include "core/file_sys/system_archive/time_zone_binary.h"
#include "core/file_sys/vfs/vfs_static.h"
#include "core/file_sys/vfs/vfs_types.h"
#include "core/file_sys/vfs/vfs_vector.h"
#include "nx_tzdb.h"
namespace FileSys::SystemArchive {
const static std::map<std::string, const std::map<const char*, const std::vector<u8>>&>
tzdb_zoneinfo_dirs = {{"Africa", NxTzdb::africa},
{"America", NxTzdb::america},
{"Antarctica", NxTzdb::antarctica},
{"Arctic", NxTzdb::arctic},
{"Asia", NxTzdb::asia},
{"Atlantic", NxTzdb::atlantic},
{"Australia", NxTzdb::australia},
{"Brazil", NxTzdb::brazil},
{"Canada", NxTzdb::canada},
{"Chile", NxTzdb::chile},
{"Etc", NxTzdb::etc},
{"Europe", NxTzdb::europe},
{"Indian", NxTzdb::indian},
{"Mexico", NxTzdb::mexico},
{"Pacific", NxTzdb::pacific},
{"US", NxTzdb::us}};
const static std::map<std::string, const std::map<const char*, const std::vector<u8>>&>
tzdb_america_dirs = {{"Argentina", NxTzdb::america_argentina},
{"Indiana", NxTzdb::america_indiana},
{"Kentucky", NxTzdb::america_kentucky},
{"North_Dakota", NxTzdb::america_north_dakota}};
static void GenerateFiles(std::vector<VirtualFile>& directory,
const std::map<const char*, const std::vector<u8>>& files) {
for (const auto& [filename, data] : files) {
const auto data_copy{data};
const std::string filename_copy{filename};
VirtualFile file{
std::make_shared<VectorVfsFile>(std::move(data_copy), std::move(filename_copy))};
directory.push_back(file);
}
}
static std::vector<VirtualFile> GenerateZoneinfoFiles() {
std::vector<VirtualFile> zoneinfo_files;
GenerateFiles(zoneinfo_files, NxTzdb::zoneinfo);
return zoneinfo_files;
}
VirtualDir TimeZoneBinary() {
std::vector<VirtualDir> america_sub_dirs;
for (const auto& [dir_name, files] : tzdb_america_dirs) {
std::vector<VirtualFile> vfs_files;
GenerateFiles(vfs_files, files);
america_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(
std::move(vfs_files), std::vector<VirtualDir>{}, dir_name));
}
america_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_america_argentina(), std::vector<VirtualDir>{}, "Argentina"));
america_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_america_indiana(), std::vector<VirtualDir>{}, "Indiana"));
america_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_america_kentucky(), std::vector<VirtualDir>{}, "Kentucky"));
america_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_america_north_dakota(), std::vector<VirtualDir>{}, "North_Dakota"));
std::vector<VirtualDir> zoneinfo_sub_dirs;
for (const auto& [dir_name, files] : tzdb_zoneinfo_dirs) {
std::vector<VirtualFile> vfs_files;
GenerateFiles(vfs_files, files);
if (dir_name == "America") {
zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(
std::move(vfs_files), std::move(america_sub_dirs), dir_name));
} else {
zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(
std::move(vfs_files), std::vector<VirtualDir>{}, dir_name));
}
}
std::vector<VirtualDir> zoneinfo_dir{std::make_shared<VectorVfsDirectory>(
GenerateZoneinfoFiles(), std::move(zoneinfo_sub_dirs), "zoneinfo")};
std::vector<VirtualFile> root_files;
GenerateFiles(root_files, NxTzdb::base);
return std::make_shared<VectorVfsDirectory>(std::move(root_files), std::move(zoneinfo_dir),
"data");
zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_africa(), std::vector<VirtualDir>{}, "Africa"));
zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_america(), std::move(america_sub_dirs), "America"));
zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_antarctica(), std::vector<VirtualDir>{}, "Antarctica"));
zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_arctic(), std::vector<VirtualDir>{}, "Arctic"));
zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_asia(), std::vector<VirtualDir>{}, "Asia"));
zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_atlantic(), std::vector<VirtualDir>{}, "Atlantic"));
zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_australia(), std::vector<VirtualDir>{}, "Australia"));
zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_brazil(), std::vector<VirtualDir>{}, "Brazil"));
zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_canada(), std::vector<VirtualDir>{}, "Canada"));
zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_chile(), std::vector<VirtualDir>{}, "Chile"));
zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_etc(), std::vector<VirtualDir>{}, "Etc"));
zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_europe(), std::vector<VirtualDir>{}, "Europe"));
zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_indian(), std::vector<VirtualDir>{}, "Indian"));
zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_mexico(), std::vector<VirtualDir>{}, "Mexico"));
zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_pacific(), std::vector<VirtualDir>{}, "Pacific"));
zoneinfo_sub_dirs.push_back(std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_us(), std::vector<VirtualDir>{}, "US"));
std::vector<VirtualDir> zoneinfo_dir{std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_zoneinfo(), std::move(zoneinfo_sub_dirs), "zoneinfo")};
// last files (root)
return std::make_shared<VectorVfsDirectory>(NxTzdb::CollectFiles_base(), std::move(zoneinfo_dir), "data");
}
} // namespace FileSys::SystemArchive
+1 -1
View File
@@ -33,7 +33,7 @@ namespace FS = Common::FS;
namespace {
constexpr size_t MaxOpenFiles = 8192;
constexpr size_t MaxOpenFiles = 512;
constexpr FS::FileAccessMode ModeFlagsToFileAccessMode(OpenMode mode) {
switch (mode) {

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