248 Commits

Author SHA1 Message Date
ca25cff7fa Merge upstream Horizon-OC main (749fd385)
Some checks failed
Build Horizon OC Zeus / build (push) Failing after 6s
Includes 2.3.1 changes: kip migration, erista GPU workaround, safety
fixes, and Mariko GPU boot voltage patch. Resolve dist binary conflicts
with upstream build artifacts.
2026-05-25 20:54:23 +02:00
Lightos1
749fd385ce revert erista mrf changes 2026-05-24 21:30:05 +02:00
Lightos1
65927cffce Revert "Update misc_gui.cpp"
This reverts commit fae0fa5d5f.
2026-05-24 21:21:00 +02:00
souldbminersmwc
10bcf4542d hocclk: fix safety features 2026-05-24 12:34:37 -04:00
souldbminersmwc
afeee4937c Update horizon-oc-overlay.ovl 2026-05-23 20:09:35 -04:00
souldbminersmwc
66308b152b hocclk: kip migration 2026-05-23 20:07:28 -04:00
souldbminersmwc
72dfdb53fc hocclk: fix small issue 2026-05-23 19:45:47 -04:00
souldbminersmwc
ee730ca68e all: add mariko gpu boot voltage patch 2026-05-23 19:43:54 -04:00
souldbminersmwc
2d0a2c4f6d hocclk: fix edge case with middle freqs 2026-05-23 16:40:04 -04:00
souldbminersmwc
8411a14b26 hocclk: fix ui issue 2026-05-22 17:50:36 -04:00
souldbminersmwc
99e9270314 hocclk: add erista gpu workaround 2026-05-22 17:48:21 -04:00
souldbminersmwc
58488f7f48 chore: add no exosphere build scripts 2026-05-22 17:40:49 -04:00
souldbminersmwc
c2238eb070 hocclk: perfect migration between kip versions 2026-05-22 16:48:48 -04:00
souldbminersmwc
4271efb4a7 hocclk/ldr: add kip migration skeleton 2026-05-22 16:35:56 -04:00
souldbminersmwc
fd9e5a2e08 add more docs and warnings 2026-05-22 16:16:06 -04:00
souldbminersmwc
4587b01152 hocclk: minor configurator changes 2026-05-22 16:13:16 -04:00
souldbminersmwc
fae0fa5d5f Update misc_gui.cpp 2026-05-22 16:10:18 -04:00
souldbminersmwc
059fe40339 hocclk: update configurator for new features 2026-05-22 16:10:12 -04:00
Lightos1
a617a7398a Implement Mariko-style MRF for erista
There is heavy code duplication because I'm lazy, but loader needs to be
refactored anyway at some point and this "works" for now.
2026-05-22 21:57:32 +02:00
souldbminersmwc
2f092f7955 hocclk: fix UV0 with live cpu uv 2026-05-19 17:15:12 -04:00
souldbminersmwc
003854d2bb hocclk: update live cpu uv more often 2026-05-19 17:06:54 -04:00
souldbminersmwc
f49e1a80a0 hocclk: erista finally gets some love
bugfixes and live CPU uv fixed (for erista at least)
2026-05-19 17:04:14 -04:00
souldbminersmwc
16ea883fa8 Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-05-19 16:22:06 -04:00
souldbminersmwc
f787ed7fd8 hocclk: fix tpyos 2026-05-19 16:22:03 -04:00
Lightos1
63c7fb211d Code cleanup and improved dvb tables.
Thanks to: jimmy for testing and b3711 for many additional voltage scale improvements.

Co-Authored-By: halop <4215938+halop@users.noreply.github.com>
2026-05-19 20:02:09 +02:00
Lightos1
52e13f5e1e Merge pull request #81 from IMLeoCat/patch-1
Update README.md
2026-05-18 10:32:13 +02:00
d59f0b5900 build: fix macOS compile and dist packaging
Some checks failed
Build Horizon OC Zeus / build (push) Failing after 4s
Use portable sed for title_id extraction, copy hoc-clk output into dist/
correctly, and ensure overlay output directories exist. Rebuild dist after
upstream merge.
2026-05-17 10:58:03 +02:00
5403c3bdd8 Merge upstream Horizon-OC main (797bcf79) 2026-05-17 10:52:03 +02:00
souldbminersmwc
797bcf79a2 hocclk: fix resolution read bug
thx masa for pointing this out
2026-05-16 15:50:32 -04:00
e962de8373 hocclk: translate user notifications to German
Some checks failed
Build Horizon OC Zeus / build (push) Failing after 1m16s
2026-05-16 11:52:08 +02:00
souldbminersmwc
0d227cfb82 hocclk: add info about new feature 2026-05-13 19:52:11 -04:00
souldbminersmwc
3010c915a7 hocclk: add info to hocclk 2026-05-13 19:49:48 -04:00
souldbminersmwc
196933a6b3 hocclk: read voltage from i2c instead of rgltr 2026-05-12 17:00:46 -04:00
Lightos1
bfc93c6238 ldr: don't be an idiot, remove debug code 2026-05-12 21:29:27 +02:00
Lightos1
6d284d9c2b ldr: fix dvb brackets 2026-05-12 21:26:42 +02:00
Lightos1
7384404ac1 ldr: use DvbMeta struct 2026-05-12 20:05:02 +02:00
IMLeoCat
35de44d3fa Update README.md
The Installation part is outdated. add this line from "https://horizon-oc.github.io/guide.html".
2026-05-13 01:13:30 +08:00
Lightos1
1b07df5f08 Revert "change cust rev back to 2, it shouldn't have been changed in the first place"
This reverts commit d6c2ddf2ea.
2026-05-12 13:40:35 +02:00
Lightos1
34e1f39510 ldr: even more (partially guessed) labeling of CvbMeta 2026-05-12 13:07:46 +02:00
Lightos1
ef830ce3f6 ldr: label more of CvbMeta 2026-05-12 13:03:51 +02:00
Lightos1
d7e22b3ccc ldr: add partially labeled CvbMeta struct 2026-05-12 12:44:52 +02:00
Lightos1
d6c2ddf2ea change cust rev back to 2, it shouldn't have been changed in the first place 2026-05-12 11:22:51 +02:00
Lightos1
b4627ad171 ldr: minVolt -> MinVolt 2026-05-12 10:34:05 +02:00
Lightos1
381a1eafc4 ldr: properly clamp soc voltage 2026-05-12 10:32:14 +02:00
souldbminersmwc
f90ba2ca59 2.3.0 2026-05-11 19:07:44 -04:00
Lightos1
f97fdc9528 conversion script: fix 3200mhz 2026-05-11 21:34:01 +02:00
Lightos1
ed63a95488 conversion script: fix 3200mhz 2026-05-11 21:33:44 +02:00
Lightos1
e24512c9d6 raise vddq min validator to 400 2026-05-11 21:26:31 +02:00
Lightos1
1efd91d535 reaise vddq validator 2026-05-11 21:22:05 +02:00
Lightos1
3337738dcc conversion script: fix silly bugs 2026-05-11 19:58:08 +02:00
Lightos1
7f1f504c36 Merge branch 'main' of https://github.com/horizon-OC/Horizon-OC 2026-05-11 19:36:10 +02:00
Lightos1
2f21f23266 experimental: add improved dvb table (+ conversion script) 2026-05-11 19:35:48 +02:00
Lightos1
3c99ad0186 Update README.md 2026-05-11 17:22:54 +02:00
Lightos1
e4dd690ac9 Update README.md 2026-05-11 17:19:36 +02:00
Lightos1
9122768953 delete ams_patch.bat from the right branch 2026-05-10 22:44:32 +02:00
Lightos1
3539916cfd fix compilation errors 2026-05-10 22:36:29 +02:00
Lightos1
4bd776c8aa kip.cpp: improve version mismatch logging 2026-05-10 18:58:37 +02:00
souldbminersmwc
78cda43054 whoops i forgot code 2026-05-10 12:48:02 -04:00
souldbminersmwc
580db1f167 hocclk: fix gm20b driver 2026-05-10 12:47:49 -04:00
souldbminersmwc
ea9adbfa14 Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-05-10 11:22:33 -04:00
souldbminersmwc
accfea86f1 hocmon: get real freqs from hocclk instead of clkrst 2026-05-10 11:22:31 -04:00
Lightos1
badf182529 build.sh: improve build process 2026-05-10 01:51:22 +02:00
souldbminersmwc
12f12c6b1e hocclk: fix cust rev detection 2026-05-09 19:13:05 -04:00
souldbminersmwc
dde723baee Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-05-09 19:04:44 -04:00
souldbminersmwc
27db54644e hocclk: fix 1267mhz clock voltage 2026-05-09 19:04:41 -04:00
Lightos1
138bcb6dc6 build.sh: alternatively I should consider not being stupid 2026-05-10 00:57:31 +02:00
Lightos1
05fa5034d3 Revert "build.sh: use make -j rather than -j8"
This reverts commit 8a98a57b4b.
Thansk to microslops amazing memory management, make -j sometimes runs
out of ram on my system when compiling libstratosphere. This can hang my
entire system and also corrupt ram??? WTF
2026-05-10 00:44:27 +02:00
Lightos1
8a98a57b4b build.sh: use make -j rather than -j8 2026-05-10 00:31:26 +02:00
souldbminersmwc
c12b0136f8 hocclk: add missing code and small change to overlay 2026-05-09 16:54:39 -04:00
souldbminersmwc
c4f7f0e713 hocclk: add mariko middle freq hack 2026-05-09 16:53:30 -04:00
Lightos1
935dd24129 move exosphere to /dist/Atmosphere/ 2026-05-09 22:51:57 +02:00
Lightos1
d72e05259a Update COMPILING.md 2026-05-09 22:46:33 +02:00
Lightos1
847ae19de9 add hoc notification icon -- thanks ppkantorski! 2026-05-09 22:44:35 +02:00
souldbminersmwc
8651e418ca Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-05-09 16:07:03 -04:00
souldbminersmwc
2e3ef0f3b0 add GM20B GPU clock driver 2026-05-09 16:06:57 -04:00
Lightos1
c018b10a7f soctherm: remove reduntant EnableSensor calls 2026-05-09 21:41:11 +02:00
souldbminersmwc
336ea0eddb hocclk: fix me being a idiot 2026-05-09 15:37:24 -04:00
Lightos1
d561c0e538 add speedo fuse reading and fix wafer coordinates 2026-05-09 14:20:43 +02:00
Lightos1
a7c1fe0d27 ldr: clean formating, fix tRC cap, map erista mtc indexes 2026-05-09 13:39:31 +02:00
Souldbminer
33582678c2 Update README.md 2026-05-08 22:44:06 -04:00
souldbminersmwc
3ca1f17e4d hocclk: major code refactor
move everything into its own directory, clean codebase up a lot
2026-05-08 22:43:14 -04:00
souldbminersmwc
65dfa8f48a Update board_fuse.cpp 2026-05-08 16:38:46 -04:00
souldbminersmwc
90ea18c881 hocclk: better HW info reading 2026-05-08 16:36:49 -04:00
souldbminersmwc
598136c64b hocclk: fixes and other stuff 2026-05-08 15:53:53 -04:00
Lightos1
848a788c5f add kip version detection + version mismatch warning 2026-05-08 20:44:28 +02:00
Lightos1
d443e069fd add more stable max index checks 2026-05-08 18:39:01 +02:00
Lightos1
b7e7f0f720 clarify stable struct 2026-05-08 18:18:32 +02:00
Lightos1
916e5c5ddf add stable max index checks 2026-05-08 18:10:32 +02:00
Lightos1
c766ab1569 add stable struct to HocClkContext 2026-05-08 17:58:27 +02:00
Lightos1
9ee4d79f77 Merge pull request #78 from dominatorul/patch-7
Enhance README with more MEM clock entries
2026-05-07 22:41:37 +02:00
Lightos1
d55d1ab319 Merge pull request #77 from th3-ne0undr5c0r/fr,-fr-CA
Add proper French support
2026-05-07 22:39:18 +02:00
Dominator
3be1eb6149 Enhance README with more MEM clock entries
Added additional memory clock values and clarified JEDEC standards.
2026-05-07 19:57:33 +03:00
th3-ne0undr5c0r
5e4f58975c Remove fr-ca support
remove French Canadian support as it is not supported.
2026-05-07 09:31:28 -06:00
th3-ne0undr5c0r
d0c257dbc0 Add proper French support
As title says, adds proper support for French. please keep in mind I have not yet tested/checked whether or not text clipping or formatting issues may be present.
2026-05-07 09:27:38 -06:00
Lightos1
ffb0ded210 Merge pull request #76 from redraz/patch-1
Update ru.json
2026-05-07 16:48:51 +02:00
redraz
396304c738 Update ru.json
I decided to make a proper translation into Russian
2026-05-07 17:04:22 +03:00
Lightos1
8c6baf9e2f add hocVersion to CustomizeTable in sysmodule 2026-05-06 08:56:25 +02:00
Lightos1
a24eec7256 add versioning to kip 2026-05-06 08:54:23 +02:00
Lightos1
77a45966da Revert cust change
This reverts commit 04d7e2f8e0.
2026-05-06 08:49:31 +02:00
Lightos1
04d7e2f8e0 Change cust rev
This now uses the minimum hoc-clk version the kip is compatible with.
2026-05-06 08:43:33 +02:00
souldbminersmwc
f5481d1c00 hocclk: dvfs bracket fix - thanks jotommy! 2026-05-05 15:41:42 -04:00
Lightos1
2e39421074 Refactor tsensor 2026-05-05 20:43:43 +02:00
souldbminersmwc
9cf901d487 Update aotag.hpp 2026-05-04 14:56:48 -04:00
souldbminersmwc
0cdc96f7f8 Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-05-04 14:28:26 -04:00
souldbminersmwc
73fafa6337 aotag: fix nvidia Z
nvidia made a error with their driver somehow
2026-05-04 14:28:24 -04:00
Lightos1
cfae441656 fix boost mode exit 2026-05-04 18:33:38 +02:00
souldbminersmwc
bf6bfa3e57 aotag: calculate (hopefully) correct coeffs 2026-05-03 15:44:31 -04:00
souldbminersmwc
72f5e11c42 update aotag coeffs 2026-05-03 14:41:37 -04:00
souldbminersmwc
93b6974be5 Update aotag.cpp 2026-05-03 14:14:14 -04:00
th3-ne0undr5c0r
1f545a7030 Add French Canadian language support
As title says, adds support for French Canadian. please keep in mind I have not yet tested/checked whether or not text clipping or formatting issues may be present.
2026-05-02 23:13:51 -06:00
souldbminersmwc
73bcb384b5 add exosphere patch 2026-05-02 22:11:25 -04:00
souldbminersmwc
fab0b76a35 update binaries 2026-05-02 22:06:57 -04:00
souldbminersmwc
2f830bac53 hocclk: better aotag 2026-05-02 22:05:15 -04:00
souldbminersmwc
5bf7fdf60e Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-05-02 21:11:56 -04:00
souldbminersmwc
af4f00f682 hocclk: basic aotag support along with other changes 2026-05-02 21:11:54 -04:00
Lightos1
d4b09f147b add back emc data that I forgot 2026-05-02 16:17:09 +02:00
Lightos1
1b33e9982c update exosphere patches 2026-05-02 16:16:21 +02:00
souldbminersmwc
c998aa78ae hocclk: update credits 2026-05-02 10:12:42 -04:00
Souldbminer
2b5a27f86e Update README.md 2026-05-02 10:11:14 -04:00
Lightos1
52b1b8da81 fix gpu volt hijack logic 2026-05-01 22:49:19 +02:00
souldbminersmwc
f409f5b8c3 hocclk: dvfs logic refactor
make it a lot more stable
2026-04-30 19:58:48 -04:00
souldbminersmwc
77a7470149 fix clock reset bug
Co-Authored-By: ppkantorski <6467366+ppkantorski@users.noreply.github.com>
2026-04-30 19:36:10 -04:00
souldbminersmwc
1d9fa4c091 Update t210.c 2026-04-30 19:29:15 -04:00
souldbminersmwc
a16cf8a2ef hocclk: significantly reduce memory usage 2026-04-30 19:15:05 -04:00
souldbminersmwc
89418b7cd0 hocclk: some refactoring and commenting 2026-04-30 18:48:57 -04:00
Lightos1
00cf05d9c5 ldr: slightly clean up MemFreqMtcTable 2026-04-29 22:14:27 +02:00
Lightos1
39e7ba6b75 ldr: move R_SKIP after verifying mtc table to avoid triggering patch validations 2026-04-29 21:56:25 +02:00
Lightos1
d7f2cee3b1 Update README.md 2026-04-29 19:08:23 +02:00
Lightos1
3848bd7c83 Update README.md 2026-04-29 19:06:51 +02:00
Lightos1
693954930a remove oc_test 2026-04-29 18:55:14 +02:00
Lightos1
de89768c74 ldr:: panic::SmcError is now always included 2026-04-29 18:39:20 +02:00
Lightos1
8f243c8369 ldr: clean up includes 2026-04-29 18:35:42 +02:00
souldbminersmwc
fd91f376c4 bump version 2026-04-27 19:33:20 -04:00
souldbminersmwc
f0fe114303 Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-04-27 19:23:47 -04:00
souldbminersmwc
1c64cf5db8 hocclk: add display color option for aula
this is very very subtle but can def make a difference to your experience
2026-04-27 19:23:44 -04:00
Lightos1
9eea39325d Update about_gui.cpp 2026-04-27 08:52:54 +02:00
Lightos1
9bb6b3383b Update README.md 2026-04-27 08:51:57 +02:00
Lightos1
fb3e976f2e ldr: fix 1333 latency max bug -- index 0 is a valid latency 2026-04-26 22:13:49 +02:00
Lightos1
ec4a1f974b variable should be lowercase 2026-04-25 23:15:39 +02:00
souldbminersmwc
fc4b3b8352 2.1.0 2026-04-25 16:40:55 -04:00
souldbminersmwc
5123f7b1de Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-04-25 16:39:31 -04:00
souldbminersmwc
3251d104c4 hocclk: rename UV tables to correct names 2026-04-25 16:30:10 -04:00
Lightos1
ea2d604c20 fix comment 2026-04-25 22:22:31 +02:00
souldbminersmwc
ae71cd447d ldr: add comment 2026-04-25 16:19:44 -04:00
souldbminersmwc
4261dd83f0 hoc: 133mhz step mode 2026-04-25 16:16:26 -04:00
souldbminersmwc
4dc01c024a hocclk: change capitilization 2026-04-25 15:59:05 -04:00
souldbminersmwc
9e26329173 hocclk: soc max volt dno side voltage 2026-04-25 15:57:37 -04:00
souldbminersmwc
36441e6dea add config support and update build script for soc vmax 2026-04-25 15:44:56 -04:00
Lightos1
cdf28607c9 move loader.json 2026-04-25 20:48:31 +02:00
Lightos1
b383fa7ec2 improve alignment 2026-04-25 20:30:46 +02:00
Lightos1
d7178ddd2c Add soc uncap 2026-04-25 20:22:23 +02:00
souldbminersmwc
9d149f0939 hocclk: fix trackbar reloading issues 2026-04-25 11:20:48 -04:00
souldbminersmwc
170dd79347 hocclk: cpu config rework 2026-04-25 11:06:22 -04:00
souldbminersmwc
d97d359ec2 hocclk: more configurator stuff 2026-04-24 17:00:59 -04:00
souldbminersmwc
9ff9e315a0 hocclk: improve kip saving mechanism 2026-04-24 16:42:59 -04:00
souldbminersmwc
cde560c4bd Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-04-24 16:35:25 -04:00
souldbminersmwc
a15860ba8d hocclk: make dram ti 2026-04-24 16:35:01 -04:00
Lightos1
76e6f1bd27 Merge pull request #71 from dominatorul/patch-4
Update README.md
2026-04-24 17:41:41 +02:00
Lightos1
2c1ad1b755 fix formating 2026-04-24 17:41:21 +02:00
Lightos1
2f2e5e9fb8 add new line 2026-04-24 17:38:28 +02:00
Lightos1
65b77a2d0b make step mode mariko only 2026-04-24 17:34:37 +02:00
Dominator
5d4812bde5 Update README.md
Updated clock specifications for MEM, CPU, and GPU with standardized terms.
2026-04-24 04:24:03 +03:00
souldbminersmwc
addd2de4d9 hocclk: add CPU LUT and add copyright 2026-04-23 18:50:51 -04:00
souldbminersmwc
0df8ce745f use original voltages 2026-04-22 18:06:27 -04:00
souldbminersmwc
62d055f163 hocclk: add missing -35mV step to configurator 2026-04-22 16:58:36 -04:00
souldbminersmwc
fa1510a40d Add B3's low ram freq DVFS
Co-Authored-By: halop <4215938+halop@users.noreply.github.com>
2026-04-22 16:56:09 -04:00
souldbminersmwc
e6942f95e7 hocclk: add BQ24193 temp driver 2026-04-22 16:40:51 -04:00
souldbminersmwc
94b63003ab hocclk: reorder options 2026-04-22 16:14:30 -04:00
souldbminersmwc
8aa20dc0cf hocclk: fix PLL ram mode and default to it 2026-04-22 15:49:07 -04:00
souldbminersmwc
db92c60cd2 hocclk: improve pll ram mode 2026-04-21 20:03:12 -04:00
souldbminersmwc
c8c7b233f5 hocclk: minor refactor 2026-04-21 19:52:31 -04:00
souldbminersmwc
5a9afcbb74 hocmon: rename tabs 2026-04-21 19:48:42 -04:00
souldbminersmwc
8127a0c3b7 hocclk: dram voltage color changes for mariko/erista 2026-04-21 19:48:27 -04:00
souldbminersmwc
7c5e746594 hocclk: ui changes 2026-04-21 19:46:21 -04:00
souldbminersmwc
7d30c4d384 bump version 2026-04-21 19:38:32 -04:00
souldbminersmwc
883b4fc3f4 hocclk: fix pointer dereference 2026-04-21 19:35:05 -04:00
Lightos1
530588a818 bump version 2026-04-21 21:29:18 +02:00
Lightos1
a6402bd5d5 update startPtr AFTER PrepareMtcMemoryRegion 2026-04-21 21:28:18 +02:00
Lightos1
cd3d29ce88 I'm a fucking idiot... remove debug code 2026-04-21 09:58:11 +02:00
souldbminersmwc
192b70dae4 Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-04-20 19:19:44 -04:00
souldbminersmwc
aaa9f90794 hocclk: console specific changes 2026-04-20 19:19:40 -04:00
Lightos1
d5e38b0eb3 Update SECURITY.md 2026-04-20 21:44:44 +02:00
Lightos1
3704d46136 set default step mode to 66MHz 2026-04-20 21:30:02 +02:00
Lightos1
b374117c37 properly fix time stuff - thanks masa! 2026-04-20 20:14:29 +02:00
Lightos1
c9c5d08919 add updated spanish translation by tdrr 2026-04-20 19:57:24 +02:00
Lightos1
c963dd8369 fix auto latency according to spec 2026-04-20 15:18:14 +02:00
Lightos1
7fc9682de0 use max freq in jedec mode regardless of it being jedec or not 2026-04-20 15:06:14 +02:00
Lightos1
0c555f34c3 remove (failing) cust rev check 2026-04-20 14:54:37 +02:00
Lightos1
fb37d5f0e7 reduce context size 2026-04-20 14:37:36 +02:00
Lightos1
a7619c39d2 set read/write latency to 1600 cause it's only used on erista 2026-04-20 07:31:52 +02:00
souldbminersmwc
55b97156ce hocclk: improve kip logging and add failsafe 2026-04-19 19:16:51 -04:00
souldbminersmwc
37ad65e768 final hoc 2.0.0 changes 2026-04-19 19:15:10 -04:00
souldbminersmwc
3b4877b287 update submodules 2026-04-19 15:38:07 -04:00
Lightos1
01d79aab30 fix off by one 2026-04-19 19:57:58 +02:00
Lightos1
3bb7b4cbd5 change colors 2026-04-19 19:17:36 +02:00
Lightos1
9c16f8b2b8 fix typo 2026-04-19 16:12:57 +02:00
Lightos1
78112547b6 prevent switch from combusting into 4 billion volts :D 2026-04-19 15:47:46 +02:00
Lightos1
3c7a42b033 formating 2026-04-19 15:13:35 +02:00
Lightos1
203587523a change result 2026-04-19 15:13:19 +02:00
Lightos1
07d0824c55 Merge pull request #66 from Horizon-OC/mrf-but-no-z-with-z
mrf
2026-04-19 15:07:02 +02:00
Lightos1
f1eab00ce1 revert custom and pcv to default settings 2026-04-19 14:51:15 +02:00
Lightos1
6a851d4095 nso start check, timing tbreak and some horrendous ui code 2026-04-18 23:00:21 +02:00
Lightos1
822e9f2817 add t2 trp cap 2026-04-18 19:02:07 +02:00
Lightos1
55b3a4230c Remove useless comments, yes I cannot be bothered to write ui code myself :D; fuck ui 2026-04-18 16:31:49 +02:00
Lightos1
be61b9df0e add sloppy configurator: todo fix crap 2026-04-18 16:30:24 +02:00
Lightos1
6c8d429c64 add missing configs 2026-04-18 12:21:42 +02:00
Lightos1
aa95f526b8 add mrf latency stuff to configs 2026-04-18 12:19:55 +02:00
Lightos1
638ddb499c add jedec mode 2026-04-18 11:52:06 +02:00
Lightos1
c95b6fde88 assign all mtc tables 2026-04-17 23:40:17 +02:00
Lightos1
2dd726723e add latency switching 2026-04-17 20:26:32 +02:00
Lightos1
119f49a3a4 fix freq list generation and dvb 2026-04-17 16:36:12 +02:00
Lightos1
51f935c252 initial mrf implementation with some bugs to fix 2026-04-16 20:51:26 +02:00
Lightos1
e1003520eb Revert "initial mrf implementation with some bugs to fix"
This reverts commit 819913ffd9.
2026-04-16 20:49:58 +02:00
Lightos1
3b5185df8d Reapply "Partial workflow fixes? (#63)"
This reverts commit 26c1dd1f99.
2026-04-16 20:49:42 +02:00
Lightos1
26c1dd1f99 Revert "Partial workflow fixes? (#63)"
This reverts commit 923bd0c0ba.
2026-04-16 20:49:11 +02:00
Lightos1
819913ffd9 initial mrf implementation with some bugs to fix 2026-04-16 20:48:22 +02:00
Lightos1
923bd0c0ba Partial workflow fixes? (#63)
* Update build.yml

* Update build.yml

* Update build.yml
2026-04-13 16:53:25 +02:00
Lightos1
185e5bcf31 Update build.yml 2026-04-13 15:52:20 +02:00
souldbminersmwc
d1ef905ac5 hocmon: real temps fixes 2026-04-12 20:56:39 -04:00
souldbminersmwc
fad9b5be50 hocmon: fix vdd2/vddq flip and full/mini mode 2026-04-12 20:06:23 -04:00
souldbminersmwc
c6424403b3 hocmon: partially add ram bw 2026-04-12 17:43:45 -04:00
souldbminersmwc
2b23498285 Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-04-12 16:53:01 -04:00
souldbminersmwc
c7db7a7632 hocclk: fix compilation 2026-04-12 16:51:52 -04:00
Lightos1
985ecdc980 add fatal handler payload 2026-04-12 22:04:19 +02:00
Lightos1
e1d75f0084 add oc_log files 2026-04-12 22:00:45 +02:00
souldbminersmwc
f276ca0187 hocclk: rename mem display unit to ram display unit 2026-04-11 21:05:28 -04:00
souldbminersmwc
ae39b1b1bd hocclk: fix MT/s display on 1600mhz 2026-04-11 21:03:31 -04:00
souldbminersmwc
9321aed1d1 bump version 2026-04-11 20:58:22 -04:00
souldbminersmwc
756c44ba82 hocclk: fix compile errors 2026-04-11 20:57:28 -04:00
souldbminersmwc
037f011c9b hocclk: peak emc bw and mem display unit option
also correct bw reading to keep it accurate
2026-04-11 20:56:35 -04:00
souldbminersmwc
d2a46e1202 Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-04-11 19:08:19 -04:00
souldbminersmwc
976f133c97 add MT/S to mem profiles 2026-04-11 19:08:12 -04:00
Lightos1
accdf6dc34 fix Z - thanks masa! 2026-04-12 01:05:11 +02:00
souldbminersmwc
b417099a4a hocclk: add RAM bandwidth monitor 2026-04-11 19:00:22 -04:00
souldbminersmwc
b7440a38a5 hocclk: reduce memory usage for real this time 2026-04-11 18:25:30 -04:00
souldbminersmwc
6369382de1 Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC 2026-04-11 17:59:20 -04:00
souldbminersmwc
65db0b4989 hocclk: 800mV minimum display voltage 2026-04-11 17:59:18 -04:00
Lightos1
19b29b97e1 separate pcv.hpp into erista/mariko files 2026-04-10 17:45:32 +02:00
Lightos1
ec230e35d0 make this pretty 2026-04-09 11:33:44 +02:00
Lightos1
5942cfd68d ldr: refactor asm 2026-04-09 11:32:00 +02:00
souldbminersmwc
66d0109a9a hocclk: autosave kip and reduce uv3 to 675 2026-04-08 19:15:26 -04:00
souldbminersmwc
6334603f9e hocclk: undo alignment
this doesnt help at all, it makes it less aligned
2026-04-08 17:51:20 -04:00
souldbminersmwc
5d12c1721a hocclk: reorganize about section 2026-04-08 17:49:00 -04:00
Lightos1
7e42394894 fix GpuClkOsLimit name 2026-04-08 22:17:28 +02:00
Lightos1
07dd65eebf move GpuClkOsLimit to common 2026-04-08 22:15:52 +02:00
Lightos1
ca8bb25660 add GpuOsLimit verification to mariko; erista will be pushed once verified 2026-04-08 21:30:36 +02:00
souldbminersmwc
90e53b52b2 hocclk: refactoring and ram pll measurement 2026-04-07 19:48:17 -04:00
Lightos1
c6cd863526 Bump ams version 2026-04-07 19:45:16 +02:00
206 changed files with 11307 additions and 6057 deletions

View File

@@ -54,6 +54,9 @@ jobs:
echo $SHORT_SHA > dist/.commit echo $SHORT_SHA > dist/.commit
echo $GITHUB_SHA >> dist/.commit echo $GITHUB_SHA >> dist/.commit
- name: Clone Libnx
run: git clone https://github.com/switchbrew/libnx.git
- name: Clone Atmosphere - name: Clone Atmosphere
run: git clone --depth=1 --single-branch https://github.com/Atmosphere-NX/Atmosphere.git atmosphere -b $(cat ams_ver.txt) run: git clone --depth=1 --single-branch https://github.com/Atmosphere-NX/Atmosphere.git atmosphere -b $(cat ams_ver.txt)
@@ -82,13 +85,22 @@ jobs:
ccache --set-config=compiler_check=content ccache --set-config=compiler_check=content
ccache --zero-stats ccache --zero-stats
- name: Build Libnx
shell: bash
run: |
export CC="ccache aarch64-none-elf-gcc"
export CXX="ccache aarch64-none-elf-g++"
pushd libnx
make -j$(($(nproc) * 4)) install CXX="ccache aarch64-none-elf-g++" CC="ccache aarch64-none-elf-gcc"
popd
- name: Build hoc-clk sysmodule and overlay - name: Build hoc-clk sysmodule and overlay
shell: bash shell: bash
run: | run: |
export CC="ccache aarch64-none-elf-gcc" export CC="ccache aarch64-none-elf-gcc"
export CXX="ccache aarch64-none-elf-g++" export CXX="ccache aarch64-none-elf-g++"
ROOT_DIR="$GITHUB_WORKSPACE/Source/sys-clk" ROOT_DIR="$GITHUB_WORKSPACE/Source/hoc-clk"
DIST_DIR="$ROOT_DIR/dist" DIST_DIR="$ROOT_DIR/dist"
mkdir -p "$DIST_DIR" mkdir -p "$DIST_DIR"
@@ -101,13 +113,14 @@ jobs:
echo "TITLE_ID: $TITLE_ID" echo "TITLE_ID: $TITLE_ID"
pushd "$ROOT_DIR/sysmodule" pushd "$ROOT_DIR/sysmodule"
git config --global --add safe.directory "$GITHUB_WORKSPACE"
make -j$(($(nproc) * 2)) CXX="ccache aarch64-none-elf-g++" CC="ccache aarch64-none-elf-gcc" make -j$(($(nproc) * 2)) CXX="ccache aarch64-none-elf-g++" CC="ccache aarch64-none-elf-gcc"
popd popd
mkdir -p "$DIST_DIR/atmosphere/contents/$TITLE_ID/flags" mkdir -p "$DIST_DIR/atmosphere/contents/$TITLE_ID/flags"
cp -vf \ cp -vf \
"$ROOT_DIR/sysmodule/out/horizon-oc.nsp" \ "$ROOT_DIR/sysmodule/out/hoc-clk.nsp" \
"$DIST_DIR/atmosphere/contents/$TITLE_ID/exefs.nsp" "$DIST_DIR/atmosphere/contents/$TITLE_ID/exefs.nsp"
: >"$DIST_DIR/atmosphere/contents/$TITLE_ID/flags/boot2.flag" : >"$DIST_DIR/atmosphere/contents/$TITLE_ID/flags/boot2.flag"

View File

@@ -1,12 +1,11 @@
Horizon OC Zeus Compilation Instructions Horizon OC Compilation Instructions
1. Install devkitpro (https://devkitpro.org/wiki/Getting_Started) with switch-dev 1. Install devkitpro (https://devkitpro.org/wiki/Getting_Started) with switch-dev
2. Set up a development enviorment for compiling Atmosphere (https://github.com/Atmosphere-NX/Atmosphere/blob/master/docs/building.md) 2. Set up a development enviorment for compiling Atmosphere (https://github.com/Atmosphere-NX/Atmosphere/blob/master/docs/building.md)
3. Install GNU make and ENSURE THAT YOUR ENVIORMENT HAS A PYTHON3 COMMAND AVAILABLE! 3. Install GNU make and ENSURE THAT YOUR ENVIORMENT HAS A PYTHON3 COMMAND AVAILABLE!
4. Git clone atmosphere (git clone https://github.com/Atmosphere-NX/Atmosphere.git) 4. Git clone atmosphere (git clone https://github.com/Atmosphere-NX/Atmosphere.git)
5. Clone the Horizon OC develop branch (git clone -b develop --single-branch https://github.com/Horizon-OC/Horizon-OC.git) 5. Clone the Horizon OC develop branch (git clone https://github.com/Horizon-OC/Horizon-OC.git --recurse-submodules)
6. Create a new folder named "build" in the horizon oc repo 6. Create a new folder named "build" in the horizon oc repo
7. Copy atmosphere files into that build folder 7. Copy atmosphere files into that build folder
8. Copy Source/Atmosphere/stratosphere/loader/source/ldr_process_creation.cpp to build/stratosphere/loader/source/ldr_process_creation.cpp, replacing any files if prompted 8. Copy Source/Atmosphere/stratosphere/loader/source/ldr_process_creation.cpp to build/stratosphere/loader/source/ldr_process_creation.cpp, replacing any files if prompted
9. Grab a copy of libultrahand (https://github.com/ppkantorski/libultrahand) and place it into Source/sys-clk/overlay/lib/libultrahand 9. Run ./build.sh in the root directory
10. Run ./build.sh in the root directory

View File

@@ -11,7 +11,7 @@
![VSCode](https://img.shields.io/badge/VSCode-0078D4?style=for-the-badge\&logo=visual%20studio%20code\&logoColor=white) ![VSCode](https://img.shields.io/badge/VSCode-0078D4?style=for-the-badge\&logo=visual%20studio%20code\&logoColor=white)
![Made with Notepad++](assets/np++.png?raw=true) ![Made with Notepad++](assets/np++.png?raw=true)
![C++](https://img.shields.io/badge/C%2B%2B-00599C?style=for-the-badge\&logo=c%2B%2B\&logoColor=white) ![C++](https://img.shields.io/badge/C%2B%2B-00599C?style=for-the-badge\&logo=c%2B%2B\&logoColor=white)
![Downloads](https://img.shields.io/github/downloads/souldbminersmwc/Horizon-OC/total.svg?style=for-the-badge) ![Downloads](https://img.shields.io/github/downloads/Horizon-OC/Horizon-OC/total.svg?style=for-the-badge)
--- ---
@@ -56,6 +56,7 @@ It enables advanced CPU, GPU, and RAM tuning with user-friendly configuration to
``` ```
kip1=atmosphere/kips/hoc.kip kip1=atmosphere/kips/hoc.kip
secmon=atmosphere/exosphere.bin
``` ```
*(No changes needed if using fusee.)* *(No changes needed if using fusee.)*
@@ -78,21 +79,64 @@ Refer to COMPILATION.md
--- ---
## Clock table ## Clock table
### MEM clocks ### MEM clocks (mhz)
* 3200 → max on mariko, JEDEC. * 3200 → max on mariko, JEDEC.
* 3166
* 3133
* 3100
* 3066
* 3033
* 3000
* 2966
* 2933 → JEDEC. * 2933 → JEDEC.
* 2900
* 2866
* 2833
* 2800
* 2766
* 2733
* 2700
* 2666 → JEDEC. * 2666 → JEDEC.
* 2633
* 2600
* 2566
* 2533
* 2500
* 2466
* 2433
* 2400 → max on erista, JEDEC. * 2400 → max on erista, JEDEC.
* 2133 → mariko safe max (4266 Modules), JEDEC. * 2366
* 1996 → JEDEC. * 2333
* 1866 → mariko safe max (3733 Modules), JEDEC. * 2300
* 1600 → official docked, boost mode, erista safe max, JEDEC. * 2266
* 2233
* 2200
* 2166
* 2133 → Mariko JEDEC standard max (4266 Modules)
* 2100
* 2066
* 2033
* 2000
* 1996 → JEDEC standard
* 1966
* 1933
* 1900
* 1866 → Mariko JEDEC standard max (3733 Modules)
* 1833
* 1800
* 1766
* 1733
* 1700
* 1666
* 1633
* 1600 → official docked, boost mode, Erista JEDEC standard max (3200 Modules), JEDEC.
* 1331 → official handheld, JEDEC. * 1331 → official handheld, JEDEC.
* 1065 * 1065
* 800 * 800
* 665 * 665
### CPU clocks ### CPU clocks (mhz)
* 2703 → mariko absolute max, dangerous * 2703 → mariko absolute max, dangerous
* 2601 → unsafe * 2601 → unsafe
* 2499 * 2499
@@ -115,17 +159,17 @@ Refer to COMPILATION.md
* 714 * 714
* 612 → sleep mode * 612 → sleep mode
### GPU clocks ### GPU clocks (mhz)
* 1536 → absolute max clock on mariko. very dangerous * 1536 → absolute max clock on mariko. very dangerous
* 1459 * 1459
* 1382 * 1382
* 1305 * 1305
* 1267 → NVIDIA T214 rating * 1267 → NVIDIA T214(mariko) rating
* 1228 → mariko HiOPT safe clock * 1228 → mariko High UV safe clock
* 1152 → mariko SLT max clock * 1152 → mariko hiOpt-15mV max clock
* 1075 → mariko no UV max clock. absolute max clock on erista. very dangerous * 1075 → mariko hiOpt max clock. absolute max clock on erista. very dangerous
* 998 → NVIDIA T210 rating * 998 → NVIDIA T210 (erista) rating
* 960 (erista only) → erista slt/hiopt safe max clock * 960 (erista only) → erista high uv/hiOpt-15mV safe max clock
* 921 → erista no UV max clock * 921 → erista no UV max clock
* 844 * 844
* 768 → official docked * 768 → official docked
@@ -142,31 +186,31 @@ Refer to COMPILATION.md
**Notes:** **Notes:**
1. On Erista, CPU in handheld is capped to 1581MHz 1. On Erista, CPU in handheld is capped to 1581MHz
2. GPU overclock is capped at 460MHz on erista in handheld 2. GPU overclock is capped at 460MHz on erista in handheld
3. On Mariko, cap with No uv is 614MHz, with SLT it is 691MHz and with HiOPT it's 768MHz 3. On Mariko, cap with hiOpt is 614MHz, with hiOpt-15mV it is 691MHz and with High UV it's 768MHz
4. Clocks higher than 768MHz on erista need the official charger is plugged in. 4. Clocks higher than 768MHz on erista need the official charger is plugged in.
5. On Mariko, cap with No uv is 844MHz, with SLT it is 921MHz and with HiOPT it's 998MHz
--- ---
## Credits ## Credits
* **Lightos's Cat** - Cat * **Lightos's Cat** - Cat
* **Souldbminer** - hoc-clk and loader development * **Souldbminer** - hoc-clk and loader development
* **Lightos** - Loader patches development, hoc-clk development, guides * **Lightos** - Loader patches development, hoc-clk development, guides
* **TDRR** - HOC Logo Design
* **tetetete-ctrl** - Website design
* **SciresM** - Atmosphere CFW * **SciresM** - Atmosphere CFW
* **CTCaer** - L4T, Hekate, proper RAM timings * **CTCaer** - L4T, Hekate, proper RAM timings
* **KazushiMe** - Switch OC Suite * **KazushiMe** - Switch OC Suite
* **Hanai3bi (Meha)** - Switch OC Suite, EOS, sys-clk-eos * **Hanai3bi (Meha)** - Switch OC Suite, EOS, sys-clk-eos
* **NaGaa95** - L4T-OC kernel, Status Monitor fork * **NaGaa95** - L4T-OC kernel, Status Monitor fork
* **B3711 (halop)** - EOS * **B3711 (halop)** - EOS, contributions
* **sys-clk team (m4xw, p-sam, natinusala)** - sys-clk * **sys-clk team (m4xw, p-sam, natinusala)** - sys-clk
* **Dominatorul** - Soctherm driver, guides, general help * **Dominatorul** - Soctherm driver, guides, general help
* **b0rd2death** - Ultrahand sys-clk & Status Monitor fork * **ppkantorski** - Ultrahand sys-clk & Status Monitor fork
* **MasaGratoR and ZachyCatGames** - General help * **MasaGratoR and ZachyCatGames** - General help
* **MasaGratoR** - Status Monitor & Display Refresh Rate driver * **MasaGratoR** - Status Monitor & Display Refresh Rate driver
* **Dominatorul, Samybigio, Arcdelta, Miki, Happy, Flopsider, Winnerboi77, Blaise, Alvise, TDRR, agjeococh, frost, letum00, and Xenshen** - Testing * **Dominatorul, Samybigio, Arcdelta, Miki, Happy, Winnerboi77, Blaise, Alvise, agjeococh, frost, letum00, and Xenshen** - Testing
* **Samybigio2011, Miki** - Italian translations * **Samybigio2011, Miki** - Italian translations
* **angelblaster** - Korean translations * **angelblaster** - Korean translations
* **q1332348216-glitch** - Chinese translations * **q1332348216-glitch** - Chinese translations
* **th3-ne0undr5c0r** - French translations
* **Nvidia** - [Tegra X1 Technical Reference Manual](https://developer.nvidia.com/embedded/dlc/tegra-x1-technical-reference-manual), soctherm driver, L4T * **Nvidia** - [Tegra X1 Technical Reference Manual](https://developer.nvidia.com/embedded/dlc/tegra-x1-technical-reference-manual), soctherm driver, L4T

View File

@@ -4,8 +4,9 @@
| Version | Supported | | Version | Supported |
| ------- | ------------------ | | ------- | ------------------ |
| 1.x | :white_check_mark: | | 2.x.x | :white_check_mark: |
| 0.x | Not supported | | 1.x.x | Not supported |
| 0.x.x | Not supported |
## Reporting a Vulnerability ## Reporting a Vulnerability

View File

@@ -14,9 +14,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#define __ACCESS_TABLE_NAME__ EmcAccessTable1 #define __ACCESS_TABLE_NAME__ RtcPmcAccessTable
#define __ACCESS_TABLE_ADDRESS__ MemoryRegionPhysicalDeviceExternalMemoryController1.GetAddress() #define __ACCESS_TABLE_ADDRESS__ MemoryRegionPhysicalDeviceRtcPmc.GetAddress()
#define __ACCESS_TABLE_INC__ "secmon_emc_access_table_data.inc" #define __ACCESS_TABLE_INC__ "secmon_rtc_pmc_access_table_data.inc"
#include "secmon_define_access_table.inc" #include "secmon_define_access_table.inc"

File diff suppressed because it is too large Load Diff

View File

@@ -99,18 +99,16 @@ namespace ams::secmon::smc {
#include "secmon_define_pmc_access_table.inc" #include "secmon_define_pmc_access_table.inc"
#include "secmon_define_mc_access_table.inc" #include "secmon_define_mc_access_table.inc"
#include "secmon_define_emc_access_table.inc" #include "secmon_define_emc_access_table.inc"
#include "secmon_define_emc1_access_table.inc" #include "secmon_define_rtc_pmc_access_table.inc"
#include "secmon_define_emc2_access_table.inc"
#include "secmon_define_mc01_access_table.inc" #include "secmon_define_mc01_access_table.inc"
constexpr const AccessTableEntry AccessTables[] = { constexpr const AccessTableEntry AccessTables[] = {
{ PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, }, { PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, },
{ McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, }, { McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, },
{ EmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController.GetAddress(), EmcAccessTable::Address, EmcAccessTable::Size, }, { EmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController.GetAddress(), EmcAccessTable::Address, EmcAccessTable::Size, },
{ EmcAccessTable1::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController1.GetAddress(), EmcAccessTable1::Address, EmcAccessTable1::Size, }, { RtcPmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceRtcPmc.GetAddress(), RtcPmcAccessTable::Address, RtcPmcAccessTable::Size, },
{ EmcAccessTable2::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController2.GetAddress(), EmcAccessTable2::Address, EmcAccessTable2::Size, }, { Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController0.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController0.GetAddress(), Mc01AccessTable::Size, },
{ Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController0.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController0.GetAddress(), Mc01AccessTable::Size, }, { Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController1.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController1.GetAddress(), Mc01AccessTable::Size, },
{ Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController1.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController1.GetAddress(), Mc01AccessTable::Size, },
}; };
constexpr bool IsAccessAllowed(const AccessTableEntry &entry, uintptr_t address) { constexpr bool IsAccessAllowed(const AccessTableEntry &entry, uintptr_t address) {

View File

@@ -0,0 +1,88 @@
{
"name": "Loader",
"title_id": "0x0100000000000001",
"main_thread_stack_size": "0x4000",
"main_thread_priority": 49,
"default_cpu_id": 3,
"process_category": 1,
"use_secure_memory": true,
"immortal": true,
"kernel_capabilities": [
{
"type": "handle_table_size",
"value": 128
},
{
"type": "syscalls",
"value": {
"svcSetHeapSize" : "0x01",
"svcSetMemoryPermission" : "0x02",
"svcSetMemoryAttribute" : "0x03",
"svcMapMemory" : "0x04",
"svcUnmapMemory" : "0x05",
"svcQueryMemory" : "0x06",
"svcExitProcess" : "0x07",
"svcCreateThread" : "0x08",
"svcStartThread" : "0x09",
"svcExitThread" : "0x0A",
"svcSleepThread" : "0x0B",
"svcGetThreadPriority" : "0x0C",
"svcSetThreadPriority" : "0x0D",
"svcGetThreadCoreMask" : "0x0E",
"svcSetThreadCoreMask" : "0x0F",
"svcGetCurrentProcessorNumber" : "0x10",
"svcSignalEvent" : "0x11",
"svcClearEvent" : "0x12",
"svcMapSharedMemory" : "0x13",
"svcUnmapSharedMemory" : "0x14",
"svcCreateTransferMemory" : "0x15",
"svcCloseHandle" : "0x16",
"svcResetSignal" : "0x17",
"svcWaitSynchronization" : "0x18",
"svcCancelSynchronization" : "0x19",
"svcArbitrateLock" : "0x1A",
"svcArbitrateUnlock" : "0x1B",
"svcWaitProcessWideKeyAtomic" : "0x1C",
"svcSignalProcessWideKey" : "0x1D",
"svcGetSystemTick" : "0x1E",
"svcConnectToNamedPort" : "0x1F",
"svcSendSyncRequestLight" : "0x20",
"svcSendSyncRequest" : "0x21",
"svcSendSyncRequestWithUserBuffer" : "0x22",
"svcSendAsyncRequestWithUserBuffer" : "0x23",
"svcGetProcessId" : "0x24",
"svcGetThreadId" : "0x25",
"svcBreak" : "0x26",
"svcOutputDebugString" : "0x27",
"svcReturnFromException" : "0x28",
"svcGetInfo" : "0x29",
"svcWaitForAddress" : "0x34",
"svcSignalToAddress" : "0x35",
"svcSynchronizePreemptionState" : "0x36",
"svcCreateSession" : "0x40",
"svcAcceptSession" : "0x41",
"svcReplyAndReceiveLight" : "0x42",
"svcReplyAndReceive" : "0x43",
"svcReplyAndReceiveWithUserBuffer" : "0x44",
"svcCreateEvent" : "0x45",
"svcReadWriteRegister" : "0x4E",
"svcQueryIoMapping" : "0x55",
"svcSetProcessMemoryPermission" : "0x73",
"svcMapProcessMemory" : "0x74",
"svcUnmapProcessMemory" : "0x75",
"svcMapProcessCodeMemory" : "0x77",
"svcUnmapProcessCodeMemory" : "0x78",
"svcCreateProcess" : "0x79",
"svcCallSecureMonitor" : "0x7F"
}
}, {
"type": "map",
"value": {
"address": "0x7000F000",
"is_ro": false,
"size": "0x00001000",
"is_io": true
}
}
]
}

View File

@@ -1,51 +0,0 @@
TARGET_EXEC := test
BUILD_DIR := ./build
SRC_DIRS := ./
# CXX := clang++ g++-12
# Find all the C and C++ files we want to compile
# Note the single quotes around the * expressions. Make will incorrectly expand these otherwise.
SRCS := $(shell find $(SRC_DIRS) -name '*.cpp' -or -name '*.c' -or -name '*.s')
# String substitution for every C/C++ file.
# As an example, hello.cpp turns into ./build/hello.cpp.o
OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
# String substitution (suffix version without %).
# As an example, ./build/hello.cpp.o turns into ./build/hello.cpp.d
DEPS := $(OBJS:.o=.d)
# Every folder in ./src will need to be passed to GCC so that it can find header files
INC_DIRS := $(shell find $(SRC_DIRS) -type d)
# Add a prefix to INC_DIRS. So moduleA would become -ImoduleA. GCC understands this -I flag
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
CPPFLAGS := $(INC_FLAGS) -Wall -Werror -Wno-unused-result -std=c++20 -Og -g
# The final build step.
$(TARGET_EXEC): $(OBJS)
@echo "Linking $@"
@$(CXX) $(OBJS) -o $@ $(LDFLAGS)
# Build step for C source
$(BUILD_DIR)/%.c.o: %.c
@mkdir -p $(dir $@)
@echo "$<"
@$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
# Build step for C++ source
$(BUILD_DIR)/%.cpp.o: %.cpp
@mkdir -p $(dir $@)
@echo "$<"
@$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
.PHONY: clean
clean:
@rm -r $(BUILD_DIR) $(TARGET_EXEC)
# Include the .d makefiles. The - at the front suppresses the errors of missing
# Makefiles. Initially, all the .d files will be missing, and we don't want those
# errors to show up.
-include $(DEPS)

View File

@@ -31,60 +31,92 @@
namespace ams::ldr::hoc { namespace ams::ldr::hoc {
volatile CustomizeTable C = { volatile CustomizeTable C = {
/* Disables RAM powerdown */ /* Disables RAM powerdown */
.hpMode = DISABLED, .hpMode = DISABLED,
.commonEmcMemVolt = 1175000, /* LPDDR4(X) JEDEC Specification */ .commonEmcMemVolt = 1175000, /* LPDDR4(X) JEDEC Specification */
.eristaEmcMaxClock = 1600000, /* Maximum HB-MGCH ram rating */ .eristaEmcMaxClock = 1600000, /* Maximum HB-MGCH ram rating */
.eristaEmcMaxClock1 = 1600000, .eristaEmcMaxClock1 = 1600000,
.eristaEmcMaxClock2 = 1600000, .eristaEmcMaxClock2 = 1600000,
.marikoEmcMaxClock = 1866000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */ /* Available: 66MHz step rate, 100MHz step rate, 133MHz step rate and jedec. */
.marikoEmcVddqVolt = 600000, /* Micron: 600mV, other manafacturers: 640mV */ /* Jedec freqs are 1333MHz, 1600MHz, 1866MHz, 2133MHz, 2400MHz, 2666MHz, 2933MHz, 3200MHz. */
.emcDvbShift = 0, .stepMode = StepMode_66MHz,
// Primary .marikoEmcMaxClock = 2133000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */
.t1_tRCD = 0, .marikoEmcVddqVolt = 600000,
.t2_tRP = 0,
.t3_tRAS = 0, .emcDvbShift = 0,
// Secondary .marikoSocVmax = 0, /* 0 = stock limits (1450 - 1597 is 1050mV, 1598-1708 is 1025mV, 1709+ is 1000mV). */
.t4_tRRD = 0,
.t5_tRFC = 0, /* Primary. */
.t6_tRTW = 0, .t1_tRCD = 0,
.t7_tWTR = 0, .t2_tRP = 0,
.t8_tREFI = 0, .t3_tRAS = 0,
/* Secondary. */
.t4_tRRD = 0,
.t5_tRFC = 0,
.t6_tRTW = 0,
.t7_tWTR = 0,
.t8_tREFI = 0,
/* At 1333WL, for some reason (incorrect ram timing config in mtc table?), tRP causes crashes at high reductions - 2 seems to be the most common limit. */
/* This is a lazy workaround until I find the issue... */
.t2_tRP_cap = 2,
/* Frequency where non low timings gets used. */
.timingEmcTbreak = DISABLED,
.low_t6_tRTW = 0,
.low_t7_tWTR = 0,
.readLatency = {
/* 1333 */ 0,
/* 1600 */ 0,
/* 1866 */ 0,
/* 2133 */ 0,
},
.writeLatency = {
/* 1333 */ 0,
/* 1600 */ 0,
/* 1866 */ 0,
/* 2133 */ 0,
},
/* You can mix and match different latencies if needed */ /* You can mix and match different latencies if needed */
/* /*
* Read: * Read:
* 2133RL = 40 * 2133RL = 40
* 1866RL = 36 * 1866RL = 36
* 1600RL = 32 * 1600RL = 32
* 1331RL = 28 * 1331RL = 28
* Write: * Write:
* 2133WL = 18 * 2133WL = 18
* 1866WL = 16 * 1866WL = 16
* 1600WL = 14 * 1600WL = 14
* 1331WL = 12 * 1331WL = 12
*/ */
.mem_burst_read_latency = RL_1866, /* Erista only. */
.mem_burst_write_latency = WL_1866, .mem_burst_read_latency = RL_1600,
.mem_burst_write_latency = WL_1600,
.eristaCpuUV = 0, .eristaCpuUV = 0,
.eristaCpuVmin = 800, .eristaCpuVmin = 800,
.eristaCpuMaxVolt = 1200, .eristaCpuMaxVolt = 1200,
/* Unlocks up to 2295 Mhz CPU, usage is not recommended. */ /* Unlocks up to 2397 Mhz CPU, usage is not recommended. */
.eristaCpuUnlock = DISABLED, .eristaCpuUnlock = DISABLED,
.marikoCpuUVLow = 0, // No undervolt .marikoCpuUVLow = 0, // No undervolt
.marikoCpuUVHigh = 0, // No undervolt .marikoCpuUVHigh = 0, // No undervolt
.tableConf = TBREAK_1683, .tableConf = TBREAK_1683,
.marikoCpuLowVmin = 620, .marikoCpuLowVmin = 620,
.marikoCpuHighVmin = 750, .marikoCpuHighVmin = 750,
/* 1120mV is NVIDIA rating */ /* 1120mV is NVIDIA rating */
.marikoCpuMaxVolt = 1120, .marikoCpuMaxVolt = 1120,
/* Supported values: 1963500, 2091000, 2193000, 2295000, 2397000, 2499000, 2601000, 2703000. */ /* Supported values: 1963500, 2091000, 2193000, 2295000, 2397000, 2499000, 2601000, 2703000. */
/* 1963500 is official rating of T214/Mariko, fully safe. */ /* 1963500 is official rating of T214/Mariko, fully safe. */
@@ -95,17 +127,16 @@ volatile CustomizeTable C = {
/* 2703000 is potentially dangerous and not advised. */ /* 2703000 is potentially dangerous and not advised. */
.marikoCpuMaxClock = 1963500, .marikoCpuMaxClock = 1963500,
.eristaCpuBoostClock = 1785000, // Default boost clock .eristaCpuBoostClock = 1785000, /* Default boost clock */
.marikoCpuBoostClock = 1963500, // Default boost clock .marikoCpuBoostClock = 1963500, /* Default boost clock */
.eristaGpuUV = 0, .eristaGpuUV = 0,
.eristaGpuVmin = 810, .eristaGpuVmin = 810,
.marikoGpuUV = 0, .marikoGpuUV = 0,
/* Vmin past 795mV won't work due boot voltage being 800mV (can be adjusted though). */
/* Vmin past 795mV won't work due boot voltage being 800mV. */
.marikoGpuVmin = 610, .marikoGpuVmin = 610,
.marikoGpuBootVolt = 800, /* Used during boot and when temp is <20°C */
.marikoGpuVmax = 800, .marikoGpuVmax = 800,
.commonGpuVoltOffset = 0, .commonGpuVoltOffset = 0,
@@ -117,7 +148,6 @@ volatile CustomizeTable C = {
/* AUTO: Voltage is optimally chosen; with commonGpuVoltOffset applied. */ /* AUTO: Voltage is optimally chosen; with commonGpuVoltOffset applied. */
/* AUTO only works up to 1305 GPU on Mariko and 998 GPU on Erista (it is reccomended to manually set your 998MHz voltage though) */ /* AUTO only works up to 1305 GPU on Mariko and 998 GPU on Erista (it is reccomended to manually set your 998MHz voltage though) */
/* You can overwrite auto with any voltage (in mv) of your choice - offset will not be applied. */ /* You can overwrite auto with any voltage (in mv) of your choice - offset will not be applied. */
.eristaGpuVoltArray = { .eristaGpuVoltArray = {
AUTO /* 76 */, AUTO /* 76 */,
AUTO /* 115 */, AUTO /* 115 */,

View File

@@ -20,34 +20,27 @@
#pragma once #pragma once
#define CUST_REV 1 #define CUST_REV 4
#define KIP_VERSION 240
#include "oc_common.hpp" #include "oc_common.hpp"
#include "pcv/pcv_common.hpp" #include "pcv/pcv_common.hpp"
namespace ams::ldr::hoc { namespace ams::ldr::hoc {
#include "mtc_timing_table.hpp"
enum TableConfig: u32 { enum TableConfig: u32 {
DEFAULT_TABLE = 1, DEFAULT_TABLE = 1,
TBREAK_1581 = 2, TBREAK_1581 = 2,
TBREAK_1683 = 3, TBREAK_1683 = 3,
EXTREME_TABLE = 4, EXTREME_TABLE = 4,
}; };
/* enum StepMode: u32 {
* Read: StepMode_66MHz = 0,
* 2133RL = 40 StepMode_100MHz = 1,
* 1866RL = 36 StepMode_Jedec = 2,
* 1600RL = 32 StepMode_133MHz = 3,
* 1331RL = 28 };
* Write:
* 2133WL = 18
* 1866WL = 16
* 1600WL = 14
* 1331WL = 12
*/
enum ReadLatency: u32 { enum ReadLatency: u32 {
RL_2133 = 40, RL_2133 = 40,
@@ -68,23 +61,23 @@ using CustomizeGpuDvfsTable = pcv::cvb_entry_t[pcv::DvfsTableEntryLimit];
static_assert(sizeof(CustomizeCpuDvfsTable) == sizeof(CustomizeGpuDvfsTable)); static_assert(sizeof(CustomizeCpuDvfsTable) == sizeof(CustomizeGpuDvfsTable));
static_assert(sizeof(CustomizeCpuDvfsTable) == sizeof(pcv::cvb_entry_t) * pcv::DvfsTableEntryLimit); static_assert(sizeof(CustomizeCpuDvfsTable) == sizeof(pcv::cvb_entry_t) * pcv::DvfsTableEntryLimit);
constexpr uint32_t ERISTA_MTC_MAGIC = 0x43544D45; // EMTC struct CustomizeTable {
constexpr uint32_t MARIKO_MTC_MAGIC = 0x43544D4D; // MMTC u8 cust[4] = {'C', 'U', 'S', 'T'};
u32 custRev = CUST_REV;
u32 kipVersion = KIP_VERSION;
typedef struct CustomizeTable {
u8 cust[4] = {'C', 'U', 'S', 'T'};
u32 custRev = CUST_REV;
u32 placeholder;
u32 hpMode; u32 hpMode;
u32 commonEmcMemVolt; u32 commonEmcMemVolt;
u32 eristaEmcMaxClock; u32 eristaEmcMaxClock;
u32 eristaEmcMaxClock1; u32 eristaEmcMaxClock1;
u32 eristaEmcMaxClock2; u32 eristaEmcMaxClock2;
StepMode stepMode;
u32 marikoEmcMaxClock; u32 marikoEmcMaxClock;
u32 marikoEmcVddqVolt; u32 marikoEmcVddqVolt;
u32 emcDvbShift; s32 emcDvbShift;
u32 marikoSocVmax;
// advanced config // advanced config
u32 t1_tRCD; u32 t1_tRCD;
u32 t2_tRP; u32 t2_tRP;
@@ -95,6 +88,15 @@ typedef struct CustomizeTable {
u32 t7_tWTR; u32 t7_tWTR;
u32 t8_tREFI; u32 t8_tREFI;
u32 t2_tRP_cap;
u32 timingEmcTbreak;
u32 low_t6_tRTW;
u32 low_t7_tWTR;
u32 readLatency[4];
u32 writeLatency[4];
u32 mem_burst_read_latency; u32 mem_burst_read_latency;
u32 mem_burst_write_latency; u32 mem_burst_write_latency;
@@ -119,6 +121,7 @@ typedef struct CustomizeTable {
u32 marikoGpuUV; u32 marikoGpuUV;
u32 marikoGpuVmin; u32 marikoGpuVmin;
u32 marikoGpuBootVolt;
u32 marikoGpuVmax; u32 marikoGpuVmax;
u32 commonGpuVoltOffset; u32 commonGpuVoltOffset;
@@ -150,7 +153,7 @@ typedef struct CustomizeTable {
CustomizeGpuDvfsTable marikoGpuDvfsTableSLT; CustomizeGpuDvfsTable marikoGpuDvfsTableSLT;
CustomizeGpuDvfsTable marikoGpuDvfsTableHiOPT; CustomizeGpuDvfsTable marikoGpuDvfsTableHiOPT;
} CustomizeTable; };
extern volatile CustomizeTable C; extern volatile CustomizeTable C;

View File

@@ -14,7 +14,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "../oc_common.hpp"
#include "../mtc_timing_value.hpp" #include "../mtc_timing_value.hpp"
namespace ams::ldr::hoc::pcv::erista { namespace ams::ldr::hoc::pcv::erista {

View File

@@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "../oc_common.hpp" #include <stratosphere.hpp>
#include "../mtc_timing_value.hpp" #include "../mtc_timing_value.hpp"
#include "timing_tables.hpp" #include "timing_tables.hpp"
@@ -26,8 +26,72 @@ namespace ams::ldr::hoc::pcv::mariko {
return; return;
} }
/* Fallback. */ /* > 3200 */
rext = 0x1A; rext = 0x1E;
}
void SwitchLatency(volatile u32 &latency, u32 index, u32 latencyStep) {
latency += index * latencyStep;
}
static s32 GetMaxLatencyIndex(volatile u32 *latencyArray, u32 latencySize) {
s32 maxIndex = -1;
for (u32 i = 0; i < latencySize; ++i) {
if (latencyArray[i]) {
maxIndex = i;
}
}
return maxIndex;
}
void AutoLatency(volatile u32 &latency, u32 freq, u32 latencyStep) {
if (freq > 1600'000 && freq <= 1866'000) { /* 1866tRWL */
latency += latencyStep * 2;
} else { /* 2133tRWL */
latency += latencyStep * 3;
}
}
void HandleLatency(u32 freq, volatile u32 &latency, volatile u32 *latencyArray, u32 indexMax, u32 latencyStep) {
for (u32 i = 0; i <= indexMax; ++i) {
if (latencyArray[i] != 0 && freq <= latencyArray[i]) {
SwitchLatency(latency, i, latencyStep);
return;
}
}
SwitchLatency(latency, indexMax, latencyStep);
}
void HandleLatency(u32 freq) {
static s32 rlIndexMax = GetMaxLatencyIndex(C.readLatency, std::size(C.readLatency));
static s32 wlIndexMax = GetMaxLatencyIndex(C.writeLatency, std::size(C.writeLatency));
constexpr u32 ReadLatencyStep = 4;
constexpr u32 WriteLatencyStep = 2;
bool autoLatencyRead = false, autoLatencyWrite = false;
if (rlIndexMax == -1) {
AutoLatency(RL, freq, ReadLatencyStep);
autoLatencyRead = true;
}
if (wlIndexMax == -1) {
AutoLatency(WL, freq, WriteLatencyStep);
autoLatencyWrite = true;
}
if (autoLatencyRead && autoLatencyWrite) {
return;
}
if (!autoLatencyRead) {
HandleLatency(freq, RL, C.readLatency, rlIndexMax, ReadLatencyStep);
}
if (!autoLatencyWrite) {
HandleLatency(freq, WL, C.writeLatency, wlIndexMax, WriteLatencyStep);
}
} }
void CalculateMrw2() { void CalculateMrw2() {
@@ -56,11 +120,84 @@ namespace ams::ldr::hoc::pcv::mariko {
} }
} }
/* DBI is always enabled. */
mrw2 = static_cast<u8>(((rlIndex & 0x7) | ((wlIndex & 0x7) << 3) | ((0 & 0x1) << 6))); mrw2 = static_cast<u8>(((rlIndex & 0x7) | ((wlIndex & 0x7) << 3) | ((0 & 0x1) << 6)));
} }
void CalculateTimings() { void CalculateTimings(double tCK_avg, u32 freq) {
RL = RL_1331;
WL = WL_1331;
HandleLatency(freq);
GetRext(); GetRext();
/* At 1333WL, for some reason (incorrect ram timing config in mtc table?), tRP causes crashes at high reductions - 2 seems to be the most common limit. */
/* This is a lazy workaround until I find the issue... */
u32 tRPpbIndex = C.t2_tRP;
if (WL == WL_1331) {
tRPpbIndex = MIN(C.t2_tRP_cap, C.t2_tRP);
}
tRCD = tRCD_values[C.t1_tRCD];
tRPpb = tRP_values[tRPpbIndex];
tRAS = tRAS_values[C.t3_tRAS];
tRRD = tRRD_values[C.t4_tRRD];
tRFCpb = tRFC_values[C.t5_tRFC];
u32 tRTW = C.t6_tRTW;
u32 tWTR = 10 - tWTR_values[C.t7_tWTR];
if (freq < C.timingEmcTbreak) {
tRTW = C.low_t6_tRTW;
tWTR = 10 - tWTR_values[C.low_t7_tWTR];
}
s32 finetRTW = C.fineTune_t6_tRTW;
s32 finetWTR = C.fineTune_t7_tWTR;
tRC = tRAS + tRPpb;
tRFCab = tRFCpb * 2;
tXSR = static_cast<double>(tRFCab + 7.5);
tFAW = static_cast<u32>(tRRD * 4.0);
tRPab = tRPpb + 3;
tR2P = CEIL((RL * 0.426) - 2.0);
tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL - (tRTW * 3) + finetRTW;
tRTM = FLOOR((10.0 + RL) + (3.502 / tCK_avg)) + FLOOR(7.489 / tCK_avg);
tRATM = CEIL((tRTM - 10.0) + (RL * 0.426));
rdv = RL + FLOOR((5.105 / tCK_avg) + 17.017);
qpop = rdv - 14;
quse_width = CEIL(((4.897 / tCK_avg) - FLOOR(2.538 / tCK_avg)) + 3.782);
quse = FLOOR(RL + ((5.082 / tCK_avg) + FLOOR(2.560 / tCK_avg))) - CEIL(4.820 / tCK_avg);
einput_duration = FLOOR(9.936 / tCK_avg) + 5.0 + quse_width;
einput = quse - CEIL(9.928 / tCK_avg);
u32 qrst_duration = FLOOR(8.399 - tCK_avg);
u32 qrstLow = MAX(static_cast<s32>(einput - qrst_duration - 2), static_cast<s32>(0));
qrst = PACK_U32(qrst_duration, qrstLow);
ibdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(1, quse - qrst_duration - 2.0);
qsafe = (einput_duration + 3) + MAX(MIN(qrstLow * rdv, qrst_duration + qrst_duration), einput);
tW2P = (CEIL(WL * 1.7303) * 2) - 5;
tWTPDEN = CEIL(((1.803 / tCK_avg) + MAX(RL + (2.694 / tCK_avg), static_cast<double>(tW2P))) + (BL / 2));
tW2R = FLOOR(MAX((5.020 / tCK_avg) + 1.130, WL - MAX(-CEIL(0.258 * (WL - RL)), 1.964)) * 1.964) + WL - CEIL(tWTR / tCK_avg) + finetWTR;
tWTM = CEIL(WL + ((7.570 / tCK_avg) + 8.753));
tWATM = (tWTM + (FLOOR(WL / 0.816) * 2.0)) - 4.0;
wdv = WL;
wsv = WL - 2;
wev = 0xA + (WL - 14);
u32 obdlyHigh = 3 / FLOOR(MIN(static_cast<double>(2), tCK_avg * (WL - 7)));
u32 obdlyLow = MAX(WL - FLOOR((126.0 / CEIL(tCK_avg + 8.601))), 0.0);
obdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(obdlyHigh, obdlyLow);
pdex2rw = CEIL((CEIL(12.335 - tCK_avg) + (7.430 / tCK_avg) - CEIL(tCK_avg * 11.361)));
tCLKSTOP = FLOOR(MIN(8.488 / tCK_avg, 23.0)) + 8.0;
u32 tMMRI = tRCD + (tCK_avg * 3);
pdex2mrr = tMMRI + 10;
CalculateMrw2(); CalculateMrw2();
} }

View File

@@ -18,7 +18,7 @@
namespace ams::ldr::hoc::pcv::mariko { namespace ams::ldr::hoc::pcv::mariko {
void CalculateTimings(); void CalculateTimings(double tCK_avg, u32 freq);
} }

View File

@@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "../mtc_timing_value.hpp" #include "../oc_common.hpp"
#include "timing_tables.hpp" #include "timing_tables.hpp"
namespace ams::ldr::hoc::pcv::mariko { namespace ams::ldr::hoc::pcv::mariko {

View File

@@ -15,7 +15,7 @@
*/ */
#pragma once #pragma once
#include "../mtc_timing_value.hpp" #include <stratosphere.hpp>
namespace ams::ldr::hoc::pcv::mariko { namespace ams::ldr::hoc::pcv::mariko {

View File

@@ -111,60 +111,54 @@ namespace ams::ldr::hoc {
const std::array<u32, 10> tWTR_values = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; const std::array<u32, 10> tWTR_values = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
const std::array<u32, 6> tREFpb_values = { 3900, 5850, 7800, 11700, 15600, 99999 }; const std::array<u32, 6> tREFpb_values = { 3900, 5850, 7800, 11700, 15600, 99999 };
const double tCK_avg = 1000'000.0 / C.marikoEmcMaxClock; inline u32 tRCD;
inline u32 tRPpb;
inline u32 tRAS;
inline double tRRD;
inline u32 tRFCpb;
const u32 tRCD = tRCD_values[C.t1_tRCD]; inline u32 tRC;
const u32 tRPpb = tRP_values[C.t2_tRP]; inline u32 tRFCab;
const u32 tRAS = tRAS_values[C.t3_tRAS]; inline double tXSR;
const double tRRD = tRRD_values[C.t4_tRRD]; inline u32 tFAW;
const u32 tRFCpb = tRFC_values[C.t5_tRFC]; inline double tRPab;
const u32 tWTR = 10 - tWTR_values[C.t7_tWTR];
const s32 finetRTW = C.fineTune_t6_tRTW;
const s32 finetWTR = C.fineTune_t7_tWTR;
const u32 tRC = tRAS + tRPpb; inline u32 RL;
const u32 tRFCab = tRFCpb * 2; inline u32 WL;
const double tXSR = static_cast<double>(tRFCab + 7.5);
const u32 tFAW = static_cast<u32>(tRRD * 4.0);
const double tRPab = tRPpb + 3;
const u32 tR2P = CEIL((RL * 0.426) - 2.0); inline u32 tR2P;
const u32 tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL - (C.t6_tRTW * 3) + finetRTW; inline u32 tR2W;
const u32 tRTM = FLOOR((10.0 + RL) + (3.502 / tCK_avg)) + FLOOR(7.489 / tCK_avg); inline u32 tRTM;
const u32 tRATM = CEIL((tRTM - 10.0) + (RL * 0.426)); inline u32 tRATM;
inline u32 rext; inline u32 rext;
const u32 rdv = RL + FLOOR((5.105 / tCK_avg) + 17.017); inline u32 rdv;
const u32 qpop = rdv - 14; inline u32 qpop;
const u32 quse_width = CEIL(((4.897 / tCK_avg) - FLOOR(2.538 / tCK_avg)) + 3.782); inline u32 quse_width;
const u32 quse = FLOOR(RL + ((5.082 / tCK_avg) + FLOOR(2.560 / tCK_avg))) - CEIL(4.820 / tCK_avg); inline u32 quse;
const u32 einput_duration = FLOOR(9.936 / tCK_avg) + 5.0 + quse_width; inline u32 einput_duration;
const u32 einput = quse - CEIL(9.928 / tCK_avg); inline u32 einput;
const u32 qrst_duration = FLOOR(8.399 - tCK_avg); inline u32 qrst;
const u32 qrstLow = MAX(static_cast<s32>(einput - qrst_duration - 2), static_cast<s32>(0)); inline u32 ibdly;
const u32 qrst = PACK_U32(qrst_duration, qrstLow); inline u32 qsafe;
const u32 ibdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(1, quse - qrst_duration - 2.0);
const u32 qsafe = (einput_duration + 3) + MAX(MIN(qrstLow * rdv, qrst_duration + qrst_duration), einput);
const u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5;
const u32 tWTPDEN = CEIL(((1.803 / tCK_avg) + MAX(RL + (2.694 / tCK_avg), static_cast<double>(tW2P))) + (BL / 2));
const u32 tW2R = FLOOR(MAX((5.020 / tCK_avg) + 1.130, WL - MAX(-CEIL(0.258 * (WL - RL)), 1.964)) * 1.964) + WL - CEIL(tWTR / tCK_avg) + finetWTR;
const u32 tWTM = CEIL(WL + ((7.570 / tCK_avg) + 8.753));
const u32 tWATM = (tWTM + (FLOOR(WL / 0.816) * 2.0)) - 4.0;
const u32 wdv = WL; inline u32 tW2P;
const u32 wsv = WL - 2; inline u32 tWTPDEN;
const u32 wev = 0xA + (WL - 14); inline u32 tW2R;
inline u32 tWTM;
inline u32 tWATM;
const u32 obdlyHigh = 3 / FLOOR(MIN(static_cast<double>(2), tCK_avg * (WL - 7))); inline u32 wdv;
const u32 obdlyLow = MAX(WL - FLOOR((126.0 / CEIL(tCK_avg + 8.601))), 0.0); inline u32 wsv;
const u32 obdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(obdlyHigh, obdlyLow); inline u32 wev;
const u32 pdex2rw = CEIL((CEIL(12.335 - tCK_avg) + (7.430 / tCK_avg) - CEIL(tCK_avg * 11.361))); inline u32 obdly;
const u32 tCLKSTOP = FLOOR(MIN(8.488 / tCK_avg, 23.0)) + 8.0; inline u32 pdex2rw;
const double tMMRI = tRCD + (tCK_avg * 3); inline u32 tCLKSTOP;
const double pdex2mrr = tMMRI + 10; /* Do this properly? */
inline u32 pdex2mrr;
inline u8 mrw2; inline u8 mrw2;
} }

View File

@@ -18,17 +18,17 @@
#pragma once #pragma once
#ifdef ATMOSPHERE_IS_STRATOSPHERE #include <stratosphere.hpp>
#include <stratosphere.hpp> #include <vapours/results/results_common.hpp>
#include <vapours/results/results_common.hpp> #define LOGGING(fmt, ...) ((void)0)
#define LOGGING(fmt, ...) ((void)0) #define CRASH(msg, ...) { ams::diag::AbortImpl(msg, __PRETTY_FUNCTION__, "", 0); __builtin_unreachable(); }
#define CRASH(msg, ...) { ams::diag::AbortImpl(msg, __PRETTY_FUNCTION__, "", 0); __builtin_unreachable(); }
#else
#include "oc_test.hpp"
#endif
#include "customize.hpp" #include "customize.hpp"
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING)
#include "oc_log.hpp"
#endif
#define PATCH_OFFSET(offset, value) \ #define PATCH_OFFSET(offset, value) \
static_assert(sizeof(__typeof__(offset)) <= sizeof(u64)); \ static_assert(sizeof(__typeof__(offset)) <= sizeof(u64)); \
*(offset) = value; *(offset) = value;
@@ -50,6 +50,9 @@ namespace ams::ldr {
R_DEFINE_ERROR_RESULT(UninitializedPatcher, 1013); R_DEFINE_ERROR_RESULT(UninitializedPatcher, 1013);
R_DEFINE_ERROR_RESULT(UnsuccessfulPatcher, 1014); R_DEFINE_ERROR_RESULT(UnsuccessfulPatcher, 1014);
R_DEFINE_ERROR_RESULT(SafetyCheckFailure, 1015); R_DEFINE_ERROR_RESULT(SafetyCheckFailure, 1015);
R_DEFINE_ERROR_RESULT(InvalidMtcTablePattern, 1016);
R_DEFINE_ERROR_RESULT(InvalidSocVoltPattern, 1017);
R_DEFINE_ERROR_RESULT(InvalidSocVoltLimit, 1018);
} }
namespace ams::ldr::hoc { namespace ams::ldr::hoc {
@@ -63,38 +66,42 @@ namespace ams::ldr::hoc {
size_t maximum_patched_count = 0; size_t maximum_patched_count = 0;
patternFn pattern_search_fn = nullptr; patternFn pattern_search_fn = nullptr;
Pointer value_search; Pointer value_search;
size_t patched_count = 0; size_t patched_count = 0;
Result Apply(Pointer* ptr) { Result Apply(Pointer *ptr) {
Result res = patcher_fn(ptr); Result res = patcher_fn(ptr);
if (R_SUCCEEDED(res)) if (R_SUCCEEDED(res)) {
patched_count++; patched_count++;
}
return res; return res;
} }
Result SearchAndApply(Pointer* ptr) { Result SearchAndApply(Pointer *ptr) {
bool searchOk = false; bool searchOk = false;
if (pattern_search_fn) { if (pattern_search_fn) {
if (pattern_search_fn(ptr)) searchOk = true; if (pattern_search_fn(ptr)) {
searchOk = true;
}
} else { } else {
if (value_search == *(ptr)) searchOk = true; if (value_search == *(ptr)) {
searchOk = true;
}
} }
if (searchOk) if (searchOk) {
return Apply(ptr); return Apply(ptr);
}
R_THROW(ldr::ResultUnsuccessfulPatcher()); R_THROW(ldr::ResultUnsuccessfulPatcher());
} }
Result CheckResult() { Result CheckResult() {
#ifndef ATMOSPHERE_IS_STRATOSPHERE
R_UNLESS(patched_count > 0, ldr::ResultUnsuccessfulPatcher()); R_UNLESS(patched_count > 0, ldr::ResultUnsuccessfulPatcher());
#endif
if (maximum_patched_count) if (maximum_patched_count) {
R_UNLESS(patched_count <= maximum_patched_count, ldr::ResultUnsuccessfulPatcher()); R_UNLESS(patched_count <= maximum_patched_count, ldr::ResultUnsuccessfulPatcher());
}
R_SUCCEED(); R_SUCCEED();
} }

View File

@@ -0,0 +1,132 @@
/*
* Copyright (c) 2019 m4xw <m4x@m4xw.net>
* Copyright (c) 2019 Atmosphere-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* See https://github.com/lulle2007200/emuMMC/blob/internal-emummc/source/ */
#include "oc_common.hpp"
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING)
#include "fatal_handler_bin.h"
#endif
namespace ams::ldr::hoc {
#define ATMOSPHERE_REBOOT_TO_FATAL_MAGIC 0x32454641
#define ATMOSPHERE_IRAM_PAYLOAD_BASE 0x40010000
#define ATMOSPHERE_FATAL_ERROR_ADDR 0x4003E000
_Alignas(4096) u8 working_buf[4096];
void SmcRebootToIramPayload() {
SecmonArgs args;
args.X[0] = 0xC3000401;
args.X[1] = 65001;
args.X[2] = 0;
args.X[3] = 2;
svcCallSecureMonitor(&args);
}
Result SmcCopyToIram(uintptr_t dest, const void *src, u32 size) {
SecmonArgs args;
args.X[0] = 0xF0000201;
args.X[1] = (u64)src;
args.X[2] = (u64)dest;
args.X[3] = size;
args.X[4] = 1;
svcCallSecureMonitor(&args);
Result rc = 0;
if (args.X[0] != 0) {
rc = (26u | ((u32)args.X[0] << 9u));
}
return rc;
}
Result SmcCopyFromIram(void *dest, uintptr_t src, u32 size) {
SecmonArgs args;
args.X[0] = 0xF0000201;
args.X[1] = (u64)dest;
args.X[2] = (u64)src;
args.X[3] = size;
args.X[4] = 0;
svcCallSecureMonitor(&args);
Result rc = 0;
if (args.X[0] != 0) {
rc = (26u | ((u32)args.X[0] << 9u));
}
return rc;
}
struct log_ctx_t {
u32 magic;
u32 sz;
u32 start;
u32 end;
char buf[];
};
#define IRAM_LOG_CTX_ADDR 0x4003C000
#define IRAM_LOG_MAX_SZ 4096
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING)
void Log(const char *data, ...) {
static const u32 max_log_sz = sizeof(working_buf) - sizeof(log_ctx_t);
static bool initDone = false;
log_ctx_t *log_ctx = (log_ctx_t*)working_buf;
R_DISCARD(SmcCopyFromIram(working_buf, IRAM_LOG_CTX_ADDR, sizeof(working_buf)));
if (!initDone) {
initDone = true;
log_ctx->buf[0] = '\0';
log_ctx->magic = 0xaabbccdd;
log_ctx->start = 0;
log_ctx->end = 0;
}
va_list args;
va_start(args, data);
s32 res = vsnprintf(log_ctx->buf + log_ctx->end, max_log_sz - log_ctx->end, data, args);
va_end(args);
if (res < 0 || res >= (static_cast<s32>(max_log_sz - log_ctx->end))) {
R_DISCARD(SmcCopyToIram(IRAM_LOG_CTX_ADDR, working_buf, sizeof(working_buf)));
return;
}
log_ctx->end += res;
R_DISCARD(SmcCopyToIram(IRAM_LOG_CTX_ADDR, working_buf, sizeof(working_buf)));
}
#endif
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING)
void ViewLog() {
if (spl::GetSocType() == spl::SocType_Mariko) {
return;
}
constexpr size_t PageSize = 4096;
for (size_t ofs = 0; ofs < fatal_handler_bin_size; ofs += PageSize) {
memcpy(&working_buf, fatal_handler_bin + ofs, std::min(fatal_handler_bin_size - ofs, PageSize));
R_DISCARD(SmcCopyToIram(ATMOSPHERE_IRAM_PAYLOAD_BASE + ofs, &working_buf, std::min(fatal_handler_bin_size - ofs, PageSize)));
}
SmcRebootToIramPayload();
while(true){}
}
#endif
}

View File

@@ -1,5 +1,6 @@
/* /*
* Copyright (c) Atmosphère-NX * Copyright (c) 2019 m4xw <m4x@m4xw.net>
* Copyright (c) 2019 Atmosphere-NX
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
@@ -14,12 +15,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#define __ACCESS_TABLE_NAME__ EmcAccessTable2 /* See https://github.com/lulle2007200/emuMMC/blob/internal-emummc/source/ */
#define __ACCESS_TABLE_ADDRESS__ MemoryRegionPhysicalDeviceExternalMemoryController2.GetAddress()
#define __ACCESS_TABLE_INC__ "secmon_emc_access_table_data.inc"
#include "secmon_define_access_table.inc" #pragma once
#undef __ACCESS_TABLE_INC__ namespace ams::ldr::hoc {
#undef __ACCESS_TABLE_ADDRESS__
#undef __ACCESS_TABLE_NAME__ void Log(const char *data, ...);
void ViewLog();
}

View File

@@ -1,214 +0,0 @@
/*
* Copyright (C) Switch-OC-Suite
*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ATMOSPHERE_IS_STRATOSPHERE
#include "oc_test.hpp"
#include "oc_loader.hpp"
void* loadExec(const char* file_loc, size_t* out_size) {
FILE* fp = fopen(file_loc, "rb");
if (!fp) {
fprintf(stderr, "Cannot open file: \"%s\"\n", file_loc);
exit(-1);
}
if (fseek(fp, 0, SEEK_END) < 0) {
fprintf(stderr, "fseek error\n");
exit(-1);
}
long size = ftell(fp);
if (size == -1L) {
fprintf(stderr, "\"%s\" is a directory", file_loc);
exit(-1);
}
fseek(fp, 0, SEEK_SET);
void* buf = malloc(size);
fread(buf, size, 1, fp);
fclose(fp);
if (size < 8192) {
fprintf(stderr, "File is too small to process: \"%s\" (%ld B)\n", file_loc, size);
exit(-1);
}
*out_size = size;
return buf;
}
void saveExec(const char* file_loc, const void* buf, size_t size) {
FILE* fp = fopen(file_loc, "wb");
if (!fp) {
fprintf(stderr, "Cannot write to \"%s\"\n", file_loc);
exit(-1);
}
printf("Saving to \"%s\"...\n", file_loc);
fwrite(buf, size, 1, fp);
fclose(fp);
}
Result Test_PcvDvfsTable() {
using namespace ams::ldr::hoc::pcv;
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&mariko::CpuCvbTableDefault)) == 18);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&erista::CpuCvbTableDefault)) == 16);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&mariko::GpuCvbTableDefault)) == 17);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&erista::GpuCvbTableDefault)) == 12);
cvb_entry_t last_mariko_cpu_cvb_entry_default = { 1963500, { 1675751, -38635, 27 }, { 1120000 } };
assert(memcmp(GetDvfsTableLastEntry((cvb_entry_t *)(&mariko::CpuCvbTableDefault)), (void *)&last_mariko_cpu_cvb_entry_default, sizeof(last_mariko_cpu_cvb_entry_default)) == 0);
assert(GetDvfsTableLastEntry((cvb_entry_t *)(&erista::GpuCvbTableDefault))->freq == 921600);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.marikoCpuDvfsTableSLT)) == 25);
// Customized table default
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.eristaCpuDvfsTable)) == 19);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.marikoCpuDvfsTable)) == 21);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.marikoCpuDvfsTableSLT)) == 22);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.eristaGpuDvfsTable)) == 12);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.marikoGpuDvfsTable)) == 17);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.marikoGpuDvfsTableSLT)) == 17);
assert(GetDvfsTableEntryCount((cvb_entry_t *)(&ams::ldr::hoc::C.marikoGpuDvfsTableHiOPT)) == 17);
constexpr size_t limit = ams::ldr::hoc::pcv::DvfsTableEntryLimit;
cvb_entry_t customized_table[limit] = {};
for (size_t i = 0; i < limit; i++) {
assert(GetDvfsTableEntryCount(customized_table) == i);
auto p = GetDvfsTableLastEntry(customized_table);
if (p)
assert(p->freq == i);
customized_table[i].freq = i + 1;
}
R_SUCCEED();
}
void unitTest() {
UnitTest test[] = {
{ "PCV DVFS Table", &Test_PcvDvfsTable }
};
for (auto &t : test) {
t.Test();
}
}
int main(int argc, char** argv) {
unitTest();
const char* pcv_opt = "pcv";
const char* ptm_opt = "ptm";
const char* save_opt = "-s";
const char* mariko_ext = ".mariko";
const char* erista_ext = ".erista";
enum EXE_OPTION {
EXE_PCV,
EXE_PTM,
UNKNOWN
};
EXE_OPTION exe_opt = UNKNOWN;
if (argc > 2) {
if (!strcmp(argv[1], pcv_opt))
exe_opt = EXE_PCV;
if (!strcmp(argv[1], ptm_opt))
exe_opt = EXE_PTM;
}
if ((argc != 3 && argc != 4) || exe_opt == UNKNOWN) {
fprintf(stderr, "Usage:\n"\
" %s %s | %s [%s] <exec_path>\n\n"\
" %s : Save patched executable with extension \"%s\" / \"%s\"\n"
, argv[0], pcv_opt, ptm_opt, save_opt
, save_opt, mariko_ext, erista_ext);
return -1;
}
bool save_patched = false;
char* exec_path = argv[2];
if (argc == 4 && !strcmp(argv[2], save_opt)) {
save_patched = true;
exec_path = argv[3];
}
size_t file_size;
void* file_buffer = loadExec(exec_path, &file_size);
size_t exec_path_len = strlen(reinterpret_cast<const char *>(exec_path));
size_t exec_path_patched_len = exec_path_len + std::max(strlen(mariko_ext), strlen(erista_ext)) + 1;
if (exe_opt == EXE_PCV) {
ams::ldr::hoc::pcv::SafetyCheck();
{
void* erista_buf = malloc(file_size);
std::memcpy(erista_buf, file_buffer, file_size);
printf("Patching %s for Erista...\n", pcv_opt);
ams::ldr::hoc::pcv::erista::Patch(reinterpret_cast<uintptr_t>(erista_buf), file_size);
if (save_patched) {
char* exec_path_erista = reinterpret_cast<char *>(malloc(exec_path_patched_len));
strncpy(exec_path_erista, exec_path, exec_path_patched_len);
strncat(exec_path_erista, erista_ext, exec_path_patched_len);
saveExec(exec_path_erista, erista_buf, file_size);
free(exec_path_erista);
}
free(erista_buf);
}
{
void* mariko_buf = malloc(file_size);
std::memcpy(mariko_buf, file_buffer, file_size);
printf("Patching %s for Mariko...\n", pcv_opt);
ams::ldr::hoc::pcv::mariko::Patch(reinterpret_cast<uintptr_t>(mariko_buf), file_size);
if (save_patched) {
char* exec_path_mariko = reinterpret_cast<char *>(malloc(exec_path_patched_len));
strncpy(exec_path_mariko, exec_path, exec_path_patched_len);
strncat(exec_path_mariko, mariko_ext, exec_path_patched_len);
saveExec(exec_path_mariko, mariko_buf, file_size);
free(exec_path_mariko);
}
free(mariko_buf);
}
}
if (exe_opt == EXE_PTM) {
void* mariko_buf = malloc(file_size);
std::memcpy(mariko_buf, file_buffer, file_size);
printf("Patching %s (Mariko Only)...\n", ptm_opt);
ams::ldr::hoc::ptm::Patch(reinterpret_cast<uintptr_t>(mariko_buf), file_size);
if (save_patched) {
char* exec_path_mariko = reinterpret_cast<char *>(malloc(exec_path_patched_len));
strncpy(exec_path_mariko, exec_path, exec_path_patched_len);
strncat(exec_path_mariko, mariko_ext, exec_path_patched_len);
saveExec(exec_path_mariko, mariko_buf, file_size);
free(exec_path_mariko);
}
free(mariko_buf);
}
free(file_buffer);
printf("Passed!\n\n");
return 0;
}
#endif

View File

@@ -1,81 +0,0 @@
/*
* Copyright (C) Switch-OC-Suite
*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef ATMOSPHERE_IS_STRATOSPHERE
#include <cassert>
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef int32_t s32;
typedef uint64_t u64;
typedef int Result;
#define R_SUCCEEDED(arg) (arg == 0)
#define R_FAILED(arg) (arg != 0)
#define LOGGING(fmt, ...) { printf(fmt "\n", ##__VA_ARGS__); }
#define CRASH(msg, ...) { fprintf(stderr, "%s\nFailed in %s!\n", msg, __PRETTY_FUNCTION__); exit(-1); }
#define R_SUCCEED() { return 0; }
#define R_THROW(err) { return err; }
#define R_TRY(expr) { Result _rc = (expr); if (R_FAILED(_rc)) { return _rc; } }
#define R_UNLESS(expr, rc) { if (!(expr)) { return rc; } }
#define R_DEFINE_ERROR_RESULT(name, rc) \
inline Result Result##name() { return rc; }
#define HEXDUMP(ptr, len) \
{ \
const uint8_t* p = reinterpret_cast<const uint8_t *>(ptr); \
size_t i, j; \
for (i = 0; i < len; i += 16) { \
printf("%06zx: ", i); \
for (j = 0; j < 16 && i + j < len; j++) \
printf("%02x ", p[i + j]); \
for (; j < 16; j++) \
printf(" "); \
for (j = 0; j < 16 && i + j < len; j++) \
printf("%c", isprint(p[i + j]) ? p[i + j] : '.'); \
printf("\n"); \
} \
} \
typedef struct UnitTest {
using Func = Result(*)();
const char* description;
Func fun = nullptr;
void Test() {
Result res = fun();
if (R_FAILED(res)) {
CRASH(description);
}
}
} UnitTest;
#endif

View File

@@ -22,20 +22,20 @@
namespace ams::ldr::hoc::pcv { namespace ams::ldr::hoc::pcv {
Result MemFreqPllmLimit(u32* ptr) { Result MemFreqPllmLimit(u32 *ptr) {
clk_pll_param* entry = reinterpret_cast<clk_pll_param *>(ptr); clk_pll_param *entry = reinterpret_cast<clk_pll_param *>(ptr);
R_UNLESS(entry->freq == entry->vco_max, ldr::ResultInvalidMemPllmEntry()); R_UNLESS(entry->freq == entry->vco_max, ldr::ResultInvalidMemPllmEntry());
// Double the max clk simply // Double the max clk simply
u32 max_clk = entry->freq * 2; u32 max_clk = entry->freq * 2;
entry->freq = max_clk; entry->freq = max_clk;
entry->vco_max = max_clk; entry->vco_max = max_clk;
R_SUCCEED(); R_SUCCEED();
} }
Result MemVoltHandler(u32* ptr) { Result MemVoltHandler(u32 *ptr) {
// ptr value might be default_uv or max_uv // ptr value might be default_uv or max_uv
regulator* entries[2] = { regulator *entries[2] = {
reinterpret_cast<regulator *>(reinterpret_cast<u8 *>(ptr) - offsetof(regulator, type_1.default_uv)), reinterpret_cast<regulator *>(reinterpret_cast<u8 *>(ptr) - offsetof(regulator, type_1.default_uv)),
reinterpret_cast<regulator *>(reinterpret_cast<u8 *>(ptr) - offsetof(regulator, type_1.max_uv)), reinterpret_cast<regulator *>(reinterpret_cast<u8 *>(ptr) - offsetof(regulator, type_1.max_uv)),
}; };
@@ -44,16 +44,16 @@ namespace ams::ldr::hoc::pcv {
constexpr u32 uv_min = 600'000; constexpr u32 uv_min = 600'000;
auto validator = [](regulator* entry) { auto validator = [](regulator* entry) {
R_UNLESS(entry->id == 1, ldr::ResultInvalidRegulatorEntry()); R_UNLESS(entry->id == 1, ldr::ResultInvalidRegulatorEntry());
R_UNLESS(entry->type == 1, ldr::ResultInvalidRegulatorEntry()); R_UNLESS(entry->type == 1, ldr::ResultInvalidRegulatorEntry());
R_UNLESS(entry->type_1.volt_reg == 0x17, ldr::ResultInvalidRegulatorEntry()); R_UNLESS(entry->type_1.volt_reg == 0x17, ldr::ResultInvalidRegulatorEntry());
R_UNLESS(entry->type_1.step_uv == uv_step, ldr::ResultInvalidRegulatorEntry()); R_UNLESS(entry->type_1.step_uv == uv_step, ldr::ResultInvalidRegulatorEntry());
R_UNLESS(entry->type_1.min_uv == uv_min, ldr::ResultInvalidRegulatorEntry()); R_UNLESS(entry->type_1.min_uv == uv_min, ldr::ResultInvalidRegulatorEntry());
R_SUCCEED(); R_SUCCEED();
}; };
regulator* entry = nullptr; regulator *entry = nullptr;
for (auto& i : entries) { for (auto &i : entries) {
if (R_SUCCEEDED(validator(i))) { if (R_SUCCEEDED(validator(i))) {
entry = i; entry = i;
} }
@@ -76,24 +76,25 @@ namespace ams::ldr::hoc::pcv {
} }
void SafetyCheck() { void SafetyCheck() {
// if (C.custRev != CUST_REV)
// CRASH("Triggered");
struct sValidator { struct sValidator {
volatile u32 value; volatile u32 value;
u32 min; u32 min;
u32 max; u32 max;
bool value_required = false;
u32 panic; u32 panic;
bool value_required = false;
Result check() { Result check() {
if (!value_required && !value) if (!value_required && !value) {
R_SUCCEED(); R_SUCCEED();
}
if (min && value < min) if (min && value < min) {
R_THROW(ldr::ResultSafetyCheckFailure()); R_THROW(ldr::ResultSafetyCheckFailure());
if (max && value > max) }
if (max && value > max) {
R_THROW(ldr::ResultSafetyCheckFailure()); R_THROW(ldr::ResultSafetyCheckFailure());
}
R_SUCCEED(); R_SUCCEED();
} }
@@ -102,28 +103,24 @@ namespace ams::ldr::hoc::pcv {
u32 eristaCpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaCpuDvfsTable)->freq); u32 eristaCpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaCpuDvfsTable)->freq);
u32 marikoCpuDvfsMaxFreq; u32 marikoCpuDvfsMaxFreq;
if (C.marikoCpuUVHigh) { if (C.marikoCpuUVHigh) {
marikoCpuDvfsMaxFreq = static_cast<u32>( marikoCpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.marikoCpuDvfsTableSLT)->freq);
GetDvfsTableLastEntry(C.marikoCpuDvfsTableSLT)->freq
);
} else { } else {
marikoCpuDvfsMaxFreq = static_cast<u32>( marikoCpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.marikoCpuDvfsTable)->freq);
GetDvfsTableLastEntry(C.marikoCpuDvfsTable)->freq
);
} }
u32 eristaGpuDvfsMaxFreq; u32 eristaGpuDvfsMaxFreq;
switch (C.eristaGpuUV) { switch (C.eristaGpuUV) {
case 0: case 0:
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq); eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq);
break; break;
case 1: case 1:
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTableSLT)->freq); eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTableSLT)->freq);
break; break;
case 2: case 2:
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTableHiOPT)->freq); eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTableHiOPT)->freq);
break; break;
default: default:
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq); eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq);
break; break;
} }
u32 marikoGpuDvfsMaxFreq; u32 marikoGpuDvfsMaxFreq;
@@ -142,43 +139,40 @@ namespace ams::ldr::hoc::pcv {
break; break;
} }
using namespace ams::ldr::hoc::pcv;
sValidator validators[] = { sValidator validators[] = {
{ C.eristaCpuBoostClock, 1020'000, 2397'000, true, panic::Cpu }, { C.eristaCpuBoostClock, 1020'000, 2397'000, panic::Cpu, true },
{ C.marikoCpuBoostClock, 1020'000, 2703'000, true, panic::Cpu }, { C.marikoCpuBoostClock, 1020'000, 2703'000, panic::Cpu, true },
{ C.eristaCpuMaxVolt, 1000, 1260, false, panic::Cpu }, { C.eristaCpuMaxVolt, 1000, 1260, panic::Cpu, },
{ C.marikoCpuMaxVolt, 1000, 1200, false, panic::Cpu }, { C.marikoCpuMaxVolt, 1000, 1200, panic::Cpu, },
{ eristaCpuDvfsMaxFreq, 1785'000, 2397'000, false, panic::Cpu }, { eristaCpuDvfsMaxFreq, 1785'000, 2397'000, panic::Cpu, },
{ marikoCpuDvfsMaxFreq, 1785'000, 2703'000, false, panic::Cpu }, { marikoCpuDvfsMaxFreq, 1785'000, 2703'000, panic::Cpu, },
{ C.commonEmcMemVolt, 912'500, 1350'000, false, panic::Emc }, // Official burst vmax for the RAMs is 1500mV { C.commonEmcMemVolt, 912'500, 1350'000, panic::Emc, }, /* Official vmax for the RAMs is 1400-1500mV */
{ GET_MAX_OF_ARR(erista::maxEmcClocks), 1600'000, 2600'000, false, panic::Emc }, { GET_MAX_OF_ARR(erista::maxEmcClocks), 1600'000, 2600'000, panic::Emc, },
{ C.marikoEmcMaxClock, 1600'000, 3500'000, false, panic::Emc }, { C.marikoEmcMaxClock, 1600'000, 3500'000, panic::Emc, },
{ C.marikoEmcVddqVolt, 250'000, 700'000, false, panic::Emc }, { C.marikoEmcVddqVolt, 400'000, 750'000, panic::Emc, },
{ eristaGpuDvfsMaxFreq, 768'000, 1152'000, false, panic::Gpu }, { C.marikoSocVmax, 1000, 1200, panic::Emc, },
{ marikoGpuDvfsMaxFreq, 768'000, 1536'000, false, panic::Gpu }, { eristaGpuDvfsMaxFreq, 768'000, 1152'000, panic::Gpu, },
{ C.marikoGpuVmax, 800, 960, false, panic::Gpu }, { marikoGpuDvfsMaxFreq, 768'000, 1536'000, panic::Gpu, },
{ C.marikoGpuVmax, 800, 960, panic::Gpu, },
}; };
for (auto &v : validators) { for (auto &v : validators) {
if (R_FAILED(v.check())) { if (R_FAILED(v.check())) {
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING) panic::SmcError(v.panic);
panic::SmcError(v.panic);
#endif
CRASH("Validation FAIL"); CRASH("Validation FAIL");
} }
} }
} }
void Patch(uintptr_t mapped_nso, size_t nso_size) { void Patch(uintptr_t mapped_nso, size_t nso_size) {
#ifdef ATMOSPHERE_IS_STRATOSPHERE
SafetyCheck(); SafetyCheck();
bool isMariko = (spl::GetSocType() == spl::SocType_Mariko); bool isMariko = (spl::GetSocType() == spl::SocType_Mariko);
if (isMariko) if (isMariko) {
mariko::Patch(mapped_nso, nso_size); mariko::Patch(mapped_nso, nso_size);
else } else {
erista::Patch(mapped_nso, nso_size); erista::Patch(mapped_nso, nso_size);
#endif }
} }
} }

View File

@@ -22,244 +22,11 @@
#include "../oc_common.hpp" #include "../oc_common.hpp"
#include "pcv_common.hpp" #include "pcv_common.hpp"
#include "pcv_erista.hpp"
#include "pcv_mariko.hpp"
namespace ams::ldr::hoc::pcv { namespace ams::ldr::hoc::pcv {
namespace mariko {
constexpr cvb_entry_t CpuCvbTableDefault[] = {
{ 204000, { 721589, -12695, 27 }, { } },
{ 306000, { 747134, -14195, 27 }, { } },
{ 408000, { 776324, -15705, 27 }, { } },
{ 510000, { 809160, -17205, 27 }, { } },
{ 612000, { 845641, -18715, 27 }, { } },
{ 714000, { 885768, -20215, 27 }, { } },
{ 816000, { 929540, -21725, 27 }, { } },
{ 918000, { 976958, -23225, 27 }, { } },
{ 1020000, { 1028021, -24725, 27 }, { 1120000 } },
{ 1122000, { 1082730, -26235, 27 }, { 1120000 } },
{ 1224000, { 1141084, -27735, 27 }, { 1120000 } },
{ 1326000, { 1203084, -29245, 27 }, { 1120000 } },
{ 1428000, { 1268729, -30745, 27 }, { 1120000 } },
{ 1581000, { 1374032, -33005, 27 }, { 1120000 } },
{ 1683000, { 1448791, -34505, 27 }, { 1120000 } },
{ 1785000, { 1527196, -36015, 27 }, { 1120000 } },
{ 1887000, { 1609246, -37515, 27 }, { 1120000 } },
{ 1963500, { 1675751, -38635, 27 }, { 1120000 } },
{ },
};
constexpr u32 CpuClkOfficial = 1963'500;
constexpr u32 CpuVoltOfficial = 1120;
constexpr u32 CpuVminOfficial = 620;
static const u32 cpuVoltagePatchValues[] = { 850, 38, 1120, 1000, 100, 1000, 0 };
static const s32 cpuVoltagePatchOffsets[] = { -2, -1, 5, 6, 7, 8, 9 };
static_assert(sizeof(cpuVoltagePatchValues) == sizeof(cpuVoltagePatchOffsets), "Invalid cpuVoltagePatch size");
static const u32 cpuVoltThermalData[] = { 620, 1120, 20000, 620, 1120, 70000, 950, 1132, 0, 950, 1227, 0 };
static const u32 allowedCpuMaxFrequencies[] = { 1'963'500, 2'091'000, 2'193'000, 2'295'000, 2'397'000, 2'499'000, 2'601'000, 2'703'000, };
constexpr cvb_entry_t GpuCvbTableDefault[] = {
// GPUB01_NA_CVB_TABLE
{ 76800, {}, { 610000, } },
{ 153600, {}, { 610000, } },
{ 230400, {}, { 610000, } },
{ 307200, {}, { 610000, } },
{ 384000, {}, { 610000, } },
{ 460800, {}, { 610000, } },
{ 537600, {}, { 801688, -10900, -163, 298, -10599, 162, } },
{ 614400, {}, { 824214, -5743, -452, 238, -6325, 81, } },
{ 691200, {}, { 848830, -3903, -552, 119, -4030, -2, } },
{ 768000, {}, { 891575, -4409, -584, 0, -2849, 39, } },
{ 844800, {}, { 940071, -5367, -602, -60, -63, -93, } },
{ 921600, {}, { 986765, -6637, -614, -179, 1905, -13, } },
{ 998400, {}, { 1098475, -13529, -497, -179, 3626, 9, } },
{ 1075200, {}, { 1163644, -12688, -648, 0, 1077, 40, } },
{ 1152000, {}, { 1204812, -9908, -830, 0, 1469, 110, } },
{ 1228800, {}, { 1277303, -11675, -859, 0, 3722, 313, } },
{ 1267200, {}, { 1335531, -12567, -867, 0, 3681, 559, } },
{ },
};
constexpr u32 GpuClkPllMax = 1300'000'000;
constexpr u32 GpuClkPllLimit = 2'600'000;
constexpr u32 GpuVminOfficial = 610;
static const u32 gpuDVFSPattern[] = { 1050, 1000, 100, 1000, 10, };
static const u32 gpuVoltThermalPattern[] = { 800, 1120, 0, 610, 1120, 20000, 610, 1120, 30000, 610, 1120, 50000, 610, 1120, 70000, 610, 1120, 90000, };
static_assert(sizeof(gpuVoltThermalPattern) == 72, "Invalid gpuVoltThermalPattern");
/* GPU Max Clock asm Pattern:
*
* MOV W11, #0x1000 MOV (wide immediate) 0x1000 0xB (11)
* sf | opc | | hw | imm16 | Rd
* #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0
* 0 | 1 0 | 1 0 0 1 0 1| 0 0| 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 |0 1 0 1 1
*
* MOVK W11, #0xE, LSL#16 <shift>16 0xE 0xB (11)
* sf | opc | | hw | imm16 | Rd
* #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0
* 0 | 1 1 | 1 0 0 1 0 1| 0 1| 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 |0 1 0 1 1
*/
inline constexpr u32 asm_pattern[] = {0x52820000, 0x72A001C0};
inline auto asm_compare_no_rd = [](u32 ins1, u32 ins2) {
return ((ins1 ^ ins2) >> 5) == 0;
};
inline auto asm_get_rd = [](u32 ins) {
return ins & ((1 << 5) - 1);
};
inline auto asm_set_rd = [](u32 ins, u8 rd) {
return (ins & 0xFFFFFFE0) | (rd & 0x1F);
};
inline auto asm_set_imm16 = [](u32 ins, u16 imm) {
return (ins & 0xFFE0001F) | ((imm & 0xFFFF) << 5);
};
inline bool GpuMaxClockPatternFn(u32 *ptr32) {
return asm_compare_no_rd(*ptr32, asm_pattern[0]);
}
constexpr emc_dvb_dvfs_table_t EmcDvbTableDefault[] = {
{ 204000, { 637, 637, 637, } },
{ 408000, { 637, 637, 637, } },
{ 800000, { 637, 637, 637, } },
{ 1065600, { 637, 637, 637, } },
{ 1331200, { 650, 637, 637, } },
{ 1600000, { 675, 650, 637, } },
};
constexpr u32 EmcClkOSAlt = 1331'200;
constexpr u32 EmcClkPllmLimit = 2133'000'000;
constexpr u32 EmcVddqDefault = 600'000;
constexpr u32 MemVdd2Default = 1100'000;
constexpr u32 MTC_TABLE_REV = 3;
void Patch(uintptr_t mapped_nso, size_t nso_size);
}
namespace erista {
static u32 maxEmcClocks[] = { C.eristaEmcMaxClock2, C.eristaEmcMaxClock1, C.eristaEmcMaxClock, };
#define GET_MAX_OF_ARR(ARR) (*std::max_element(ARR, ARR + std::size(ARR)))
constexpr cvb_entry_t CpuCvbTableDefault[] = {
// CPU_PLL_CVB_TABLE_ODN
{ 204000, {721094}, { } },
{ 306000, {754040}, { } },
{ 408000, {786986}, { } },
{ 510000, {819932}, { } },
{ 612000, {852878}, { } },
{ 714000, {885824}, { } },
{ 816000, {918770}, { } },
{ 918000, {951716}, { } },
{ 1020000, {984662}, { -2875621, 358099, -8585} },
{ 1122000, {1017608}, { -52225, 104159, -2816} },
{ 1224000, {1050554}, { 1076868, 8356, -727} },
{ 1326000, {1083500}, { 2208191, -84659, 1240} },
{ 1428000, {1116446}, { 2519460, -105063, 1611} },
{ 1581000, {1130000}, { 2889664, -122173, 1834} },
{ 1683000, {1168000}, { 5100873, -279186, 4747} },
{ 1785000, {1227500}, { 5100873, -279186, 4747} },
{ },
};
constexpr u32 CpuVoltOfficial = 1227;
constexpr u32 CpuVminOfficial = 825;
constexpr u32 CpuVoltL4T = 1257'000;
static const u32 cpuVoltDvfsPattern[] = { 1227, 1000, 100, 1000, 0 };
static_assert(sizeof(cpuVoltDvfsPattern) == 0x14, "invalid cpuVoltDvfsPattern size");
static const u32 cpuVoltageThermalPattern[] = { 950, 1132, 0, 950, 1227, 0, 825, 1227, 15000, 825, 1170, 60000, 825, 1132, 80000 };
static_assert(sizeof(cpuVoltageThermalPattern) == 0x3c, "invalid cpuVoltageThermalPattern size");
constexpr u32 GpuClkPllLimit = 2'600'000;
constexpr u32 GpuClkPllMax = 921'600'000;
constexpr u32 GpuVminOfficial = 810;
constexpr u16 CpuMinVolts[] = { 950, 850, 825, 810 };
inline bool CpuMaxVoltPatternFn(u32* ptr32) {
u32 val = *ptr32;
return (val == 1132 || val == 1170 || val == 1227);
}
static const u32 gpuVoltDvfsPattern[] = { 810, 1150, 1000, 100, 1000, 10, };
static_assert(sizeof(gpuVoltDvfsPattern) == (sizeof(u32) * 6), "Invalid gpuVoltDvfsPattern");
static const u32 gpuVoltThermalPattern[] = { 950, 1132, 0, 810, 1132, 15000, 810, 1132, 30000, 810, 1132, 50000, 810, 1132, 70000, 810, 1132, 105000 };
static_assert(sizeof(gpuVoltThermalPattern) == 0x48, "invalid gpuVoltageThermalPattern size");
/* GPU Max Clock asm Pattern:
*
* MOV W11, #0x1000 MOV (wide immediate) 0x1000 0xB (11)
* sf | opc | | hw | imm16 | Rd
* #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0
* 0 | 1 0 | 1 0 0 1 0 1| 0 0| 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 |0 1 0 1 1
*
* MOVK W11, #0xE, LSL#16 <shift>16 0xE 0xB (11)
* sf | opc | | hw | imm16 | Rd
* #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0
* 0 | 1 1 | 1 0 0 1 0 1| 0 1| 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 |0 1 0 1 1
*/
inline constexpr u32 asm_pattern[] = {
0x52820000, 0x72A001C0
};
inline auto asm_compare_no_rd = [](u32 ins1, u32 ins2) {
return ((ins1 ^ ins2) >> 5) == 0;
};
inline auto asm_get_rd = [](u32 ins) {
return ins & ((1 << 5) - 1);
};
inline auto asm_set_rd = [](u32 ins, u8 rd) {
return (ins & 0xFFFFFFE0) | (rd & 0x1F);
};
inline auto asm_set_imm16 = [](u32 ins, u16 imm) {
return (ins & 0xFFE0001F) | ((imm & 0xFFFF) << 5);
};
inline bool GpuMaxClockPatternFn(u32 *ptr32) {
return asm_compare_no_rd(*ptr32, asm_pattern[0]);
};
constexpr cvb_entry_t GpuCvbTableDefault[] = {
// NA_FREQ_CVB_TABLE
{ 76800, {}, { 814294, 8144, -940, 808, -21583, 226, } },
{ 153600, {}, { 856185, 8144, -940, 808, -21583, 226, } },
{ 230400, {}, { 898077, 8144, -940, 808, -21583, 226, } },
{ 307200, {}, { 939968, 8144, -940, 808, -21583, 226, } },
{ 384000, {}, { 981860, 8144, -940, 808, -21583, 226, } },
{ 460800, {}, { 1023751, 8144, -940, 808, -21583, 226, } },
{ 537600, {}, { 1065642, 8144, -940, 808, -21583, 226, } },
{ 614400, {}, { 1107534, 8144, -940, 808, -21583, 226, } },
{ 691200, {}, { 1149425, 8144, -940, 808, -21583, 226, } },
{ 768000, {}, { 1191317, 8144, -940, 808, -21583, 226, } },
{ 844800, {}, { 1233208, 8144, -940, 808, -21583, 226, } },
{ 921600, {}, { 1275100, 8144, -940, 808, -21583, 226, } },
{ },
};
constexpr u32 MemVoltHOS = 1125'000;
constexpr u32 EmcClkMinFreq = 40800; /* 40.8 MHz table only exists on erista. */
constexpr u32 EmcClkPllmLimit = 1866'000'000;
constexpr u32 MTC_TABLE_REV = 7;
void Patch(uintptr_t mapped_nso, size_t nso_size);
}
inline auto MatchesPattern = [](u32 *base, const auto &offsets, const auto &values) { inline auto MatchesPattern = [](u32 *base, const auto &offsets, const auto &values) {
for (size_t i = 0; i < std::size(values); ++i) { for (size_t i = 0; i < std::size(values); ++i) {
if (*(base + offsets[i]) != values[i]) { if (*(base + offsets[i]) != values[i]) {
@@ -351,34 +118,34 @@ namespace ams::ldr::hoc::pcv {
cvb_entry_t *customize_table; cvb_entry_t *customize_table;
if (isMariko) { if (isMariko) {
switch (C.marikoGpuUV) { switch (C.marikoGpuUV) {
case 0: case 0:
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTable); customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTable);
break; break;
case 1: case 1:
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTableSLT); customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTableSLT);
break; break;
case 2: case 2:
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTableHiOPT); customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTableHiOPT);
break; break;
default: default:
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTable); customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTable);
break; break;
} }
} else { } else {
switch (C.eristaGpuUV) { switch (C.eristaGpuUV) {
case 0: case 0:
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTable); customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTable);
break; break;
case 1: case 1:
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTableSLT); customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTableSLT);
break; break;
case 2: case 2:
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTableHiOPT); customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTableHiOPT);
break; break;
default: default:
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTable); customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTable);
break; break;
} }
} }
size_t default_entry_count = GetDvfsTableEntryCount(default_table); size_t default_entry_count = GetDvfsTableEntryCount(default_table);
@@ -428,26 +195,6 @@ namespace ams::ldr::hoc::pcv {
Result MemFreqPllmLimit(u32 *ptr); Result MemFreqPllmLimit(u32 *ptr);
Result MemVoltHandler(u32 *ptr); // Used for Erista MEM Vdd2 + EMC Vddq or Mariko MEM Vdd2 Result MemVoltHandler(u32 *ptr); // Used for Erista MEM Vdd2 + EMC Vddq or Mariko MEM Vdd2
template <typename T>
Result MemMtcCustomizeTable(T *dst, T *src) {
constexpr u32 mtc_magic = std::is_same_v<T, MarikoMtcTable> ? MARIKO_MTC_MAGIC : ERISTA_MTC_MAGIC;
R_UNLESS(src->rev == mtc_magic, ldr::ResultInvalidMtcMagic());
constexpr u32 ZERO_VAL = UINT32_MAX;
// Skip params from dvfs_ver to clock_src;
for (size_t offset = offsetof(T, clk_src_emc); offset < sizeof(T); offset += sizeof(u32)) {
u32 *src_ent = reinterpret_cast<u32 *>(reinterpret_cast<size_t>(src) + offset);
u32 *dst_ent = reinterpret_cast<u32 *>(reinterpret_cast<size_t>(dst) + offset);
u32 src_val = *src_ent;
if (src_val){
PATCH_OFFSET(dst_ent, src_val == ZERO_VAL ? 0 : src_val);
}
}
R_SUCCEED();
};
void SafetyCheck(); void SafetyCheck();
void Patch(uintptr_t mapped_nso, size_t nso_size); void Patch(uintptr_t mapped_nso, size_t nso_size);

View File

@@ -0,0 +1,145 @@
/*
* Copyright (C) Switch-OC-Suite
*
* Copyright (c) 2023 hanai3Bi
*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stratosphere.hpp>
namespace ams::ldr::hoc::pcv {
constexpr u32 NopIns = 0x1f2003d5;
template <typename Compare>
u32 *ScanAssembly(u32 *ptr, u32 scanLimit, u32 pattern, Compare comp) {
for (u32 i = 0; i < scanLimit; ++i) {
if (comp(pattern, ptr[i])) {
return ptr + i;
}
}
return nullptr;
}
inline auto asm_compare_no_rd = [](u32 ins1, u32 ins2) {
return ((ins1 ^ ins2) >> 5) == 0;
};
inline auto asm_get_rd = [](u32 ins) {
return ins & ((1 << 5) - 1);
};
inline auto asm_set_rd = [](u32 ins, u8 rd) {
return (ins & 0xFFFFFFE0) | (rd & 0x1F);
};
inline auto asm_set_imm16 = [](u32 ins, u16 imm) {
return (ins & 0xFFE0001F) | ((imm & 0xFFFF) << 5);
};
inline auto AsmGetImm16 = [](u32 ins) {
return static_cast<u16>((ins >> 5) & 0xFFFF);
};
inline auto AsmCompareBrNoRd = [](u32 ins1, u32 ins2) {
constexpr u32 RegMask = ~(((1 << 5) - 1) << 5);
return ((ins1 & RegMask) ^ (ins2 & RegMask)) == 0;
};
inline auto AsmCompareAddNoImm12 = [](u32 ins1, u32 ins2) {
constexpr u32 Imm12Mask = ~(((1 << 12) - 1) << 10);
return ((ins1 & Imm12Mask) ^ (ins2 & Imm12Mask)) == 0;
};
inline auto AsmCompareAdrpNoImm = [](u32 ins1, u32 ins2) {
constexpr u32 ImmMask = ~((((1 << 2) - 1) << 29) | (((1 << 19) - 1) << 5));
return ((ins1 & ImmMask) ^ (ins2 & ImmMask)) == 0;
};
/* Csel (Conditional Select) */
/*
SF | Op | S | | RM | Cond | 0 | 0 | Rn | Rd
31 | 30 | 29 | 28 27 26 25 24 23 | 20 19 18 17 16 | 15 14 13 12 | 11 | 10 | 9 8 7 6 5 | 4 3 2 1 0
*/
inline auto AsmCompareCselNoReg = [](u32 ins1, u32 ins2) {
constexpr u32 ClearReg = ~(((1 << 10) - 1) | (((1 << 5) - 1) << 16));
return ((ins1 & ClearReg) ^ (ins2 & ClearReg)) == 0;
};
/* Mul */
/*
SF | Op54 | Op31 | RM | o0 | RA | RN | RD
31 | 30 29 28 27 26 25 24 | 23 22 21 | 20 19 18 17 16 | 15 | 14 13 12 11 10 | 9 8 7 6 5 | 4 3 2 1 0
*/
inline auto AsmCompareMullNoReg = [](u32 ins1, u32 ins2) {
constexpr u32 ClearReg = ~(((1 << 10) - 1) | (((1 << 5) - 1) << 16));
return ((ins1 & ClearReg) ^ (ins2 & ClearReg)) == 0;
};
/* Mul */
/* MUL W11, W24, W26 */
/* multiplies by 1000, mV -> uV */
/*
SF | Op54 | Op31 | RM | o0 | RA | RN | RD
31 | 30 29 28 27 26 25 24 | 23 22 21 | 20 19 18 17 16 | 15 | 14 13 12 11 10 | 9 8 7 6 5 | 4 3 2 1 0
*/
inline auto AsmGetMullRn = [](u32 ins) {
constexpr u32 Mask = ((1 << 5) - 1) << 5;
return (ins & Mask) >> 5;
};
inline auto AsmGetMullRm = [](u32 ins) {
constexpr u32 Mask = ((1 << 5) - 1) << 16;
return (ins & Mask) >> 16;
};
/* Subs (Shifted register) */
/*
SF | Op | S | | Shift | 0 | RM | Imm6 | Rn | Rd
31 | 30 | 29 | 28 27 26 25 24 | 23 22 | 21 | 20 19 18 17 16 | 15 14 13 12 11 10 | 9 8 7 6 5 | 4 3 2 1 0
*/
inline auto AsmSubsSetRn = [](u32 ins, u8 rn) {
constexpr u32 RnMaskClear = ~(((1u << 5) - 1u) << 5);
constexpr u32 RnMaskSet = (1u << 5) - 1u;
return (ins & RnMaskClear) | ((static_cast<u32>(rn) & RnMaskSet) << 5);
};
/* Subs (Immediate) */
/*
SF | Op | S | | Sh | Imm12 | Rn | Rd
31 | 30 | 29 | 28 27 26 25 24 23 | 22 | 21 20 19 18 17 16 15 14 13 12 11 10 | 9 8 7 6 5 | 4 3 2 1 0
*/
inline auto AsmSubsSetImm12 = [](u32 ins, u16 imm12) {
constexpr u32 ClearMask = ~(((1u << 12) - 1) << 10);
constexpr u32 SetImm12Mask = ( 1u << 12) - 1;
return (ins & ClearMask) | ((imm12 & SetImm12Mask) << 10);
};
inline auto AsmSubsCompareNoReg = [](u32 ins1, u32 ins2) {
return ((ins1 ^ ins2) >> 10) == 0;
};
inline auto AsmCompareBrConNoImm19 = [](u32 ins1, u32 ins2) {
constexpr u32 ClearImm19 = ~(((1 << 19) - 1) << 5);
return (ins1 & ClearImm19) == (ins2 & ClearImm19);
};
}

View File

@@ -18,40 +18,37 @@
#pragma once #pragma once
#include "../mtc_timing_table.hpp"
namespace ams::ldr::hoc::pcv { namespace ams::ldr::hoc::pcv {
typedef struct cvb_coefficients { struct cvb_coefficients {
s32 c0 = 0; s32 c0 = 0;
s32 c1 = 0; s32 c1 = 0;
s32 c2 = 0; s32 c2 = 0;
s32 c3 = 0; s32 c3 = 0;
s32 c4 = 0; s32 c4 = 0;
s32 c5 = 0; s32 c5 = 0;
} cvb_coefficients; };
typedef struct cvb_entry_t { struct cvb_entry_t {
u64 freq; u64 freq;
cvb_coefficients cvb_dfll_param; cvb_coefficients cvb_dfll_param;
cvb_coefficients cvb_pll_param; cvb_coefficients cvb_pll_param;
} cvb_entry_t; };
static_assert(sizeof(cvb_entry_t) == 0x38); static_assert(sizeof(cvb_entry_t) == 0x38);
typedef struct cvb_cpu_dfll_data { struct CvbCpuDfllData {
u32 tune0_low; u32 tune0_low;
u32 tune0_high; u32 tune0_high;
u32 tune1_low; u32 tune1_low;
u32 tune1_high; u32 tune1_high;
unsigned int tune_high_min_millivolts; u32 tune_high_min_millivolts;
unsigned int tune_high_margin_millivolts; u32 tune_high_margin_millivolts;
unsigned long dvco_calibration_max; u64 dvco_calibration_max;
} cvb_cpu_dfll_data; };
typedef struct emc_dvb_dvfs_table_t { struct __attribute__((packed)) div_nmp {
u64 freq;
s32 volt[4] = {0};
} emc_dvb_dvfs_table_t;
typedef struct __attribute__((packed)) div_nmp {
u8 divn_shift; u8 divn_shift;
u8 divn_width; u8 divn_width;
u8 divm_shift; u8 divm_shift;
@@ -61,9 +58,9 @@ namespace ams::ldr::hoc::pcv {
u8 override_divn_shift; u8 override_divn_shift;
u8 override_divm_shift; u8 override_divm_shift;
u8 override_divp_shift; u8 override_divp_shift;
} div_nmp; };
typedef struct __attribute__((packed)) clk_pll_param { struct __attribute__((packed)) clk_pll_param {
u32 freq; u32 freq;
u32 input_min; u32 input_min;
u32 input_max; u32 input_max;
@@ -77,9 +74,9 @@ namespace ams::ldr::hoc::pcv {
struct div_nmp *div_nmp; struct div_nmp *div_nmp;
u32 unk_1[4]; u32 unk_1[4];
void (*unk_fn)(u64* unk_struct); // set_defaults? void (*unk_fn)(u64* unk_struct); // set_defaults?
} clk_pll_param; };
typedef struct __attribute__((packed)) dvfs_rail { struct __attribute__((packed)) dvfs_rail {
u32 id; u32 id;
u32 unk_0[5]; u32 unk_0[5];
u32 freq; u32 freq;
@@ -89,9 +86,9 @@ namespace ams::ldr::hoc::pcv {
u32 step_mv; u32 step_mv;
u32 max_mv; u32 max_mv;
u32 unk_2[11]; u32 unk_2[11];
} dvfs_rail; };
typedef struct __attribute__((packed)) regulator { struct __attribute__((packed)) regulator {
u64 id; u64 id;
const char* name; const char* name;
u32 type; u32 type;
@@ -115,11 +112,30 @@ namespace ams::ldr::hoc::pcv {
} type_2_3; } type_2_3;
}; };
u32 unk_x[60]; u32 unk_x[60];
} regulator; };
static_assert(sizeof(regulator) == 0x120); static_assert(sizeof(regulator) == 0x120);
constexpr u32 CpuClkOSLimit = 1785'000; struct __attribute__((packed)) CvbMeta {
u64 socType;
CvbCpuDfllData dfllData; /* Maybe? */
u32 unkZero2[6];
u32 unkMagic;
u32 unkZero3;
u32 highVmin;
u32 unkStepMaybe;
u32 vmin;
u32 unkZero4[3];
u32 pllMinMilliVolts;
u32 vmax;
u32 unkScale2;
u32 speedoScale;
u32 voltageScale;
u32 unkZero5;
};
static_assert(sizeof(CvbMeta) == 0x78);
constexpr u32 CpuClkOSLimit = 1785'000;
constexpr u32 GpuClkOsLimit = 921'600;
constexpr u32 EmcClkOSLimit = 1600'000; constexpr u32 EmcClkOSLimit = 1600'000;
#define R_SKIP() R_SUCCEED() #define R_SKIP() R_SUCCEED()
@@ -129,11 +145,11 @@ namespace ams::ldr::hoc::pcv {
constexpr size_t DvfsTableEntryLimit = DvfsTableEntryCount - 1; constexpr size_t DvfsTableEntryLimit = DvfsTableEntryCount - 1;
template<typename T> template<typename T>
size_t GetDvfsTableEntryCount(T* table_head) { size_t GetDvfsTableEntryCount(T *table_head) {
using NT = std::remove_const_t<std::remove_volatile_t<T>>; using NT = std::remove_const_t<std::remove_volatile_t<T>>;
auto is_empty = [](NT* entry) { auto is_empty = [](NT* entry) {
uint8_t* m = reinterpret_cast<uint8_t *>(entry); u8 *m = reinterpret_cast<u8 *>(entry);
for (size_t i = 0; i < sizeof(NT); i++) { for (size_t i = 0; i < sizeof(NT); i++) {
if (*(m + i)) { if (*(m + i)) {
return false; return false;
@@ -142,7 +158,7 @@ namespace ams::ldr::hoc::pcv {
return true; return true;
}; };
NT* table = const_cast<NT *>(table_head); NT *table = const_cast<NT *>(table_head);
size_t count = 0; size_t count = 0;
while (count < DvfsTableEntryLimit) { while (count < DvfsTableEntryLimit) {
if (is_empty(table++)) { if (is_empty(table++)) {
@@ -154,10 +170,10 @@ namespace ams::ldr::hoc::pcv {
} }
template<typename T> template<typename T>
T* GetDvfsTableLastEntry(T* table_head) { T *GetDvfsTableLastEntry(T *table_head) {
using NT = std::remove_const_t<std::remove_volatile_t<T>>; using NT = std::remove_const_t<std::remove_volatile_t<T>>;
NT* table = const_cast<NT *>(table_head); NT *table = const_cast<NT *>(table_head);
size_t count = GetDvfsTableEntryCount(table_head); size_t count = GetDvfsTableEntryCount(table_head);
if (!count) { if (!count) {
return nullptr; return nullptr;

View File

@@ -66,11 +66,12 @@ namespace ams::ldr::hoc::pcv::erista {
} }
Result CpuVoltDfll(u32* ptr) { Result CpuVoltDfll(u32* ptr) {
cvb_cpu_dfll_data *entry = reinterpret_cast<cvb_cpu_dfll_data *>(ptr); CvbCpuDfllData *entry = reinterpret_cast<CvbCpuDfllData *>(ptr);
R_UNLESS(entry->tune0_low == 0xFFEAD0FF, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune0_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry()); R_UNLESS(entry->tune0_low == 0xFFEAD0FF, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune1_low == 0x0, ldr::ResultInvalidCpuVoltDfllEntry()); R_UNLESS(entry->tune0_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune1_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry()); R_UNLESS(entry->tune1_low == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune1_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
if (!C.eristaCpuUV) { if (!C.eristaCpuUV) {
R_SKIP(); R_SKIP();
@@ -100,6 +101,7 @@ namespace ams::ldr::hoc::pcv::erista {
default: default:
break; break;
} }
R_SUCCEED(); R_SUCCEED();
} }
@@ -121,10 +123,10 @@ namespace ams::ldr::hoc::pcv::erista {
} }
if (C.eristaGpuVmin) { if (C.eristaGpuVmin) {
PATCH_OFFSET(ptr , C.eristaGpuVmin); PATCH_OFFSET(ptr, C.eristaGpuVmin);
PATCH_OFFSET(ptr + 3, C.eristaGpuVmin); PATCH_OFFSET(ptr + 3, C.eristaGpuVmin);
PATCH_OFFSET(ptr + 6, C.eristaGpuVmin); PATCH_OFFSET(ptr + 6, C.eristaGpuVmin);
PATCH_OFFSET(ptr + 9, C.eristaGpuVmin); PATCH_OFFSET(ptr + 9, C.eristaGpuVmin);
PATCH_OFFSET(ptr + 12, C.eristaGpuVmin); PATCH_OFFSET(ptr + 12, C.eristaGpuVmin);
} }
@@ -134,13 +136,15 @@ namespace ams::ldr::hoc::pcv::erista {
Result GpuFreqMaxAsm(u32 *ptr32) { Result GpuFreqMaxAsm(u32 *ptr32) {
// Check if both two instructions match the pattern // Check if both two instructions match the pattern
u32 ins1 = *ptr32, ins2 = *(ptr32 + 1); u32 ins1 = *ptr32, ins2 = *(ptr32 + 1);
if (!(asm_compare_no_rd(ins1, asm_pattern[0]) && asm_compare_no_rd(ins2, asm_pattern[1]))) if (!(asm_compare_no_rd(ins1, GpuAsmPattern[0]) && asm_compare_no_rd(ins2, GpuAsmPattern[1]))) {
R_THROW(ldr::ResultInvalidGpuFreqMaxPattern()); R_THROW(ldr::ResultInvalidGpuFreqMaxPattern());
}
// Both instructions should operate on the same register // Both instructions should operate on the same register
u8 rd = asm_get_rd(ins1); u8 rd = asm_get_rd(ins1);
if (rd != asm_get_rd(ins2)) if (rd != asm_get_rd(ins2)) {
R_THROW(ldr::ResultInvalidGpuFreqMaxPattern()); R_THROW(ldr::ResultInvalidGpuFreqMaxPattern());
}
u32 max_clock; u32 max_clock;
switch (C.eristaGpuUV) { switch (C.eristaGpuUV) {
@@ -157,10 +161,13 @@ namespace ams::ldr::hoc::pcv::erista {
max_clock = GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq; max_clock = GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq;
break; break;
} }
u32 asm_patch[2] = { u32 asm_patch[2] = {
asm_set_rd(asm_set_imm16(asm_pattern[0], max_clock), rd), asm_set_rd(asm_set_imm16(GpuAsmPattern[0], max_clock), rd),
asm_set_rd(asm_set_imm16(asm_pattern[1], max_clock >> 16), rd)}; asm_set_rd(asm_set_imm16(GpuAsmPattern[1], max_clock >> 16), rd)
PATCH_OFFSET(ptr32, asm_patch[0]); };
PATCH_OFFSET(ptr32, asm_patch[0]);
PATCH_OFFSET(ptr32 + 1, asm_patch[1]); PATCH_OFFSET(ptr32 + 1, asm_patch[1]);
R_SUCCEED(); R_SUCCEED();
@@ -204,13 +211,15 @@ namespace ams::ldr::hoc::pcv::erista {
} }
u32 trefbw = refresh_raw + 0x40; u32 trefbw = refresh_raw + 0x40;
trefbw = MIN(trefbw, static_cast<u32>(0x3FFF)); trefbw = MIN(trefbw, static_cast<u32>(0x3FFF));
const u32 dyn_self_ref_control = (static_cast<u32>(7605.0 / tCK_avg) + 260) | (table->burst_regs.emc_dyn_self_ref_control & 0xffff0000);
CalculateTimings(tCK_avg); CalculateTimings(tCK_avg);
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD)); WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD));
WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(tRCD)); WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(tRCD));
WRITE_PARAM_ALL_REG(table, emc_rc, MIN(GET_CYCLE_CEIL(tRC), static_cast<u32>(0xB8))); WRITE_PARAM_ALL_REG(table, emc_rc, MIN(GET_CYCLE_CEIL(tRC), static_cast<u32>(0xB9)));
WRITE_PARAM_ALL_REG(table, emc_ras, MIN(GET_CYCLE_CEIL(tRAS), static_cast<u32>(0x7F))); WRITE_PARAM_ALL_REG(table, emc_ras, MIN(GET_CYCLE_CEIL(tRAS), static_cast<u32>(0x7F)));
WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(tRRD)); WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(tRRD));
WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(tRFCpb)); WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(tRFCpb));
@@ -233,7 +242,6 @@ namespace ams::ldr::hoc::pcv::erista {
WRITE_PARAM_ALL_REG(table, emc_refresh, refresh_raw); WRITE_PARAM_ALL_REG(table, emc_refresh, refresh_raw);
WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, refresh_raw / 4); WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, refresh_raw / 4);
WRITE_PARAM_ALL_REG(table, emc_trefbw, trefbw); WRITE_PARAM_ALL_REG(table, emc_trefbw, trefbw);
const u32 dyn_self_ref_control = (static_cast<u32>(7605.0 / tCK_avg) + 260) | (table->burst_regs.emc_dyn_self_ref_control & 0xffff0000);
WRITE_PARAM_ALL_REG(table, emc_dyn_self_ref_control, dyn_self_ref_control); WRITE_PARAM_ALL_REG(table, emc_dyn_self_ref_control, dyn_self_ref_control);
WRITE_PARAM_ALL_REG(table, emc_pdex2wr, pdex2rw); WRITE_PARAM_ALL_REG(table, emc_pdex2wr, pdex2rw);
WRITE_PARAM_ALL_REG(table, emc_pdex2rd, pdex2rw); WRITE_PARAM_ALL_REG(table, emc_pdex2rd, pdex2rw);
@@ -268,22 +276,20 @@ namespace ams::ldr::hoc::pcv::erista {
// WRITE_PARAM_ALL_REG(table, emc_rdv_early_mask, rdv); // WRITE_PARAM_ALL_REG(table, emc_rdv_early_mask, rdv);
// WRITE_PARAM_ALL_REG(table, emc_rdv_mask, rdv + 2); // WRITE_PARAM_ALL_REG(table, emc_rdv_mask, rdv + 2);
// WRITE_PARAM_ALL_REG(table, emc_tr_rdv, rdv); // WRITE_PARAM_ALL_REG(table, emc_tr_rdv, rdv);
// ams::ldr::hoc::pcv::mariko::CalculateMrw2();
// table->emc_mrw2 = (table->emc_mrw2 & ~0xFFu) | static_cast<u32>(mrw2); // table->emc_mrw2 = (table->emc_mrw2 & ~0xFFu) | static_cast<u32>(mrw2);
// table->dram_timings.rl = RL; // table->dram_timings.rl = RL;
/* This needs some clean up. */
constexpr double MC_ARB_DIV = 4.0; constexpr double MC_ARB_DIV = 4.0;
constexpr u32 MC_ARB_SFA = 2; constexpr u32 MC_ARB_SFA = 2;
table->burst_mc_regs.mc_emem_arb_cfg = table->rate_khz / (33.3 * 1000) / MC_ARB_DIV; table->burst_mc_regs.mc_emem_arb_cfg = table->rate_khz / (33.3 * 1000) / MC_ARB_DIV;
table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2; table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2;
table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1; table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1; table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV) - 2; table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV) - 2;
table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1; table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1; table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV) - 1; table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(tR2P / MC_ARB_DIV); table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(tR2P / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(tW2P / MC_ARB_DIV) + MC_ARB_SFA; table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(tW2P / MC_ARB_DIV) + MC_ARB_SFA;
@@ -319,8 +325,8 @@ namespace ams::ldr::hoc::pcv::erista {
table->la_scale_regs.mc_ptsa_grant_decrement = grant_decrement; table->la_scale_regs.mc_ptsa_grant_decrement = grant_decrement;
constexpr u32 MaskHigh = 0xFF00FFFF; constexpr u32 MaskHigh = 0xFF00FFFF;
constexpr u32 Mask2 = 0xFFFFFF00; constexpr u32 Mask2 = 0xFFFFFF00;
constexpr u32 Mask3 = 0xFF00FF00; constexpr u32 Mask3 = 0xFF00FF00;
const u32 allowance1 = static_cast<u32>(0x32000 / (table->rate_khz / 0x3E8)) & 0xFF; const u32 allowance1 = static_cast<u32>(0x32000 / (table->rate_khz / 0x3E8)) & 0xFF;
const u32 allowance2 = static_cast<u32>(0x9C40 / (table->rate_khz / 0x3E8)) & 0xFF; const u32 allowance2 = static_cast<u32>(0x9C40 / (table->rate_khz / 0x3E8)) & 0xFF;
@@ -348,18 +354,14 @@ namespace ams::ldr::hoc::pcv::erista {
table->la_scale_regs.mc_latency_allowance_hc_1 = (table->la_scale_regs.mc_latency_allowance_hc_1 & Mask2) | allowance1; table->la_scale_regs.mc_latency_allowance_hc_1 = (table->la_scale_regs.mc_latency_allowance_hc_1 & Mask2) | allowance1;
table->la_scale_regs.mc_latency_allowance_vi2_0 = (table->la_scale_regs.mc_latency_allowance_vi2_0 & Mask2) | allowance1; table->la_scale_regs.mc_latency_allowance_vi2_0 = (table->la_scale_regs.mc_latency_allowance_vi2_0 & Mask2) | allowance1;
table->dram_timings.t_rp = tRFCpb; table->dram_timings.t_rp = tRFCpb;
table->dram_timings.t_rfc = tRFCab; table->dram_timings.t_rfc = tRFCab;
table->emc_cfg_2 = 0x11083D; table->emc_cfg_2 = 0x11083D;
table->min_volt = std::min(static_cast<u32>(1050), 900 + C.emcDvbShift * 25); table->min_volt = std::clamp(900 + (C.emcDvbShift * 25), 900, 1050);
} }
/* Probably more intuitive to point to 40800 rather than 1600000, but oh well. */ /* Probably more intuitive to point to 40800 rather than 1600000, but oh well. */
Result MemFreqMtcTable(u32 *ptr) { Result MemFreqMtcTable(u32 *ptr) {
if (GET_MAX_OF_ARR(maxEmcClocks) <= EmcClkOSLimit) {
R_SKIP();
}
u32 khz_list[] = { 40800, 68000, 102000, 204000, 408000, 665600, 800000, 1065600, 1331200, 1600000 }; u32 khz_list[] = { 40800, 68000, 102000, 204000, 408000, 665600, 800000, 1065600, 1331200, 1600000 };
std::sort(maxEmcClocks, maxEmcClocks + std::size(maxEmcClocks)); std::sort(maxEmcClocks, maxEmcClocks + std::size(maxEmcClocks));
u32 khz_list_size = std::size(khz_list); u32 khz_list_size = std::size(khz_list);
@@ -374,6 +376,10 @@ namespace ams::ldr::hoc::pcv::erista {
R_UNLESS(table_list[mtcIndex]->rev == MTC_TABLE_REV, ldr::ResultInvalidMtcTable()); R_UNLESS(table_list[mtcIndex]->rev == MTC_TABLE_REV, ldr::ResultInvalidMtcTable());
} }
if (GET_MAX_OF_ARR(maxEmcClocks) <= EmcClkOSLimit) {
R_SKIP();
}
/* If we oc ram at all, tables are always shifted by at least 1. */ /* If we oc ram at all, tables are always shifted by at least 1. */
u32 tableShifts = 1; u32 tableShifts = 1;
for (u32 i = 0; i < std::size(maxEmcClocks) - 1; ++i) { for (u32 i = 0; i < std::size(maxEmcClocks) - 1; ++i) {
@@ -445,21 +451,24 @@ namespace ams::ldr::hoc::pcv::erista {
// } // }
void Patch(uintptr_t mapped_nso, size_t nso_size) { void Patch(uintptr_t mapped_nso, size_t nso_size) {
u32 CpuCvbDefaultMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(CpuCvbTableDefault)->freq);
u32 GpuCvbDefaultMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(GpuCvbTableDefault)->freq);
PatcherEntry<u32> patches[] = { PatcherEntry<u32> patches[] = {
{"CPU Freq Table", CpuFreqCvbTable<false>, 1, nullptr, static_cast<u32>(GetDvfsTableLastEntry(CpuCvbTableDefault)->freq)}, {"CPU Freq Table", CpuFreqCvbTable<false>, 1, nullptr, CpuCvbDefaultMaxFreq },
{"CPU Volt DVFS", &CpuVoltDvfs, 1, nullptr, CpuVminOfficial}, {"CPU Volt DVFS", &CpuVoltDvfs, 1, nullptr, CpuVminOfficial },
{"CPU Volt Thermals", &CpuVoltThermals, 1, nullptr, CpuVminOfficial}, {"CPU Volt Thermals", &CpuVoltThermals, 1, nullptr, CpuVminOfficial },
{"CPU Volt Dfll", &CpuVoltDfll, 1, nullptr, 0xFFEAD0FF}, {"CPU Volt Dfll", &CpuVoltDfll, 1, nullptr, CpuTune0Low },
{"GPU Volt DVFS", &GpuVoltDVFS, 1, nullptr, GpuVminOfficial}, {"GPU Volt DVFS", &GpuVoltDVFS, 1, nullptr, GpuVminOfficial },
{"GPU Volt Thermals", &GpuVoltThermals, 1, nullptr, GpuVminOfficial}, {"GPU Volt Thermals", &GpuVoltThermals, 1, nullptr, GpuVminOfficial },
{"GPU Freq Table", GpuFreqCvbTable<false>, 1, nullptr, static_cast<u32>(GetDvfsTableLastEntry(GpuCvbTableDefault)->freq)}, {"GPU Freq Table", GpuFreqCvbTable<false>, 1, nullptr, GpuCvbDefaultMaxFreq },
{"GPU Freq Asm", &GpuFreqMaxAsm, 2, &GpuMaxClockPatternFn}, {"GPU Freq Asm", &GpuFreqMaxAsm, 2, &GpuMaxClockPatternFn },
{"GPU PLL Max", &GpuFreqPllMax, 1, nullptr, GpuClkPllMax}, {"GPU PLL Max", & GpuFreqPllMax, 1, nullptr, GpuClkPllMax },
// {"GPU PLL Limit", &GpuFreqPllLimit, 4, nullptr, GpuClkPllLimit}, // {"GPU PLL Limit", &GpuFreqPllLimit, 4, nullptr, GpuClkPllLimit },
{"MEM Freq Mtc", &MemFreqMtcTable, 0, nullptr, EmcClkOSLimit}, {"MEM Freq Mtc", &MemFreqMtcTable, 0, nullptr, EmcClkOSLimit },
{"MEM Freq Max", &MemFreqMax, 0, nullptr, EmcClkOSLimit}, {"MEM Freq Max", &MemFreqMax, 0, nullptr, EmcClkOSLimit },
{"MEM Freq PLLM", &MemFreqPllmLimit, 2, nullptr, EmcClkPllmLimit}, {"MEM Freq PLLM", &MemFreqPllmLimit, 2, nullptr, EmcClkPllmLimit },
{"MEM Volt", &MemVoltHandler, 2, nullptr, MemVoltHOS}, {"MEM Volt", &MemVoltHandler, 2, nullptr, MemVoltHOS },
}; };
for (uintptr_t ptr = mapped_nso; ptr <= mapped_nso + nso_size - sizeof(EristaMtcTable); ptr += sizeof(u32)) { for (uintptr_t ptr = mapped_nso; ptr <= mapped_nso + nso_size - sizeof(EristaMtcTable); ptr += sizeof(u32)) {
@@ -474,9 +483,7 @@ namespace ams::ldr::hoc::pcv::erista {
for (auto &entry : patches) { for (auto &entry : patches) {
LOGGING("%s Count: %zu", entry.description, entry.patched_count); LOGGING("%s Count: %zu", entry.description, entry.patched_count);
if (R_FAILED(entry.CheckResult())) { if (R_FAILED(entry.CheckResult())) {
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING) panic::SmcError(panic::Patch);
panic::SmcError(panic::Patch);
#endif
CRASH(entry.description); CRASH(entry.description);
} }

View File

@@ -0,0 +1,152 @@
/*
* Copyright (C) Switch-OC-Suite
*
* Copyright (c) 2023 hanai3Bi
*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "../oc_common.hpp"
#include "pcv_common.hpp"
#include "pcv_asm.hpp"
namespace ams::ldr::hoc::pcv::erista {
static u32 maxEmcClocks[] = { C.eristaEmcMaxClock2, C.eristaEmcMaxClock1, C.eristaEmcMaxClock, };
#define GET_MAX_OF_ARR(ARR) (*std::max_element(ARR, ARR + std::size(ARR)))
constexpr cvb_entry_t CpuCvbTableDefault[] = {
// CPU_PLL_CVB_TABLE_ODN
{ 204000, {721094}, { } },
{ 306000, {754040}, { } },
{ 408000, {786986}, { } },
{ 510000, {819932}, { } },
{ 612000, {852878}, { } },
{ 714000, {885824}, { } },
{ 816000, {918770}, { } },
{ 918000, {951716}, { } },
{ 1020000, {984662}, { -2875621, 358099, -8585} },
{ 1122000, {1017608}, { -52225, 104159, -2816} },
{ 1224000, {1050554}, { 1076868, 8356, -727} },
{ 1326000, {1083500}, { 2208191, -84659, 1240} },
{ 1428000, {1116446}, { 2519460, -105063, 1611} },
{ 1581000, {1130000}, { 2889664, -122173, 1834} },
{ 1683000, {1168000}, { 5100873, -279186, 4747} },
{ 1785000, {1227500}, { 5100873, -279186, 4747} },
{ },
};
constexpr u32 CpuVoltOfficial = 1227;
constexpr u32 CpuVminOfficial = 825;
constexpr u32 CpuTune0Low = 0xFFEAD0FF;
constexpr u32 CpuVoltL4T = 1257'000;
static const u32 cpuVoltDvfsPattern[] = { 1227, 1000, 100, 1000, 0 };
static_assert(sizeof(cpuVoltDvfsPattern) == 0x14, "Invalid cpuVoltDvfsPattern size");
static const u32 cpuVoltageThermalPattern[] = { 950, 1132, 0, 950, 1227, 0, 825, 1227, 15000, 825, 1170, 60000, 825, 1132, 80000 };
static_assert(sizeof(cpuVoltageThermalPattern) == 0x3c, "Invalid cpuVoltageThermalPattern size");
constexpr u32 GpuClkPllLimit = 2'600'000;
constexpr u32 GpuClkPllMax = 921'600'000;
constexpr u32 GpuVminOfficial = 810;
constexpr u16 CpuMinVolts[] = { 950, 850, 825, 810 };
static const u32 gpuVoltDvfsPattern[] = { 810, 1150, 1000, 100, 1000, 10, };
static_assert(sizeof(gpuVoltDvfsPattern) == (sizeof(u32) * 6), "Invalid gpuVoltDvfsPattern");
static const u32 gpuVoltThermalPattern[] = { 950, 1132, 0, 810, 1132, 15000, 810, 1132, 30000, 810, 1132, 50000, 810, 1132, 70000, 810, 1132, 105000 };
static_assert(sizeof(gpuVoltThermalPattern) == 0x48, "Invalid gpuVoltageThermalPattern size");
/* GPU Max Clock asm Pattern:
*
* MOV W11, #0x1000 MOV (wide immediate) 0x1000 0xB (11)
* sf | opc | | hw | imm16 | Rd
* #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0
* 0 | 1 0 | 1 0 0 1 0 1| 0 0| 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 |0 1 0 1 1
*
* MOVK W11, #0xE, LSL#16 <shift>16 0xE 0xB (11)
* sf | opc | | hw | imm16 | Rd
* #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0
* 0 | 1 1 | 1 0 0 1 0 1| 0 1| 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 |0 1 0 1 1
*/
inline constexpr u32 GpuAsmPattern[] = { 0x52820000, 0x72A001C0 };
inline bool GpuMaxClockPatternFn(u32 *ptr32) {
return asm_compare_no_rd(*ptr32, GpuAsmPattern[0]);
};
constexpr cvb_entry_t GpuCvbTableDefault[] = {
// NA_FREQ_CVB_TABLE
{ 76800, {}, { 814294, 8144, -940, 808, -21583, 226, } },
{ 153600, {}, { 856185, 8144, -940, 808, -21583, 226, } },
{ 230400, {}, { 898077, 8144, -940, 808, -21583, 226, } },
{ 307200, {}, { 939968, 8144, -940, 808, -21583, 226, } },
{ 384000, {}, { 981860, 8144, -940, 808, -21583, 226, } },
{ 460800, {}, { 1023751, 8144, -940, 808, -21583, 226, } },
{ 537600, {}, { 1065642, 8144, -940, 808, -21583, 226, } },
{ 614400, {}, { 1107534, 8144, -940, 808, -21583, 226, } },
{ 691200, {}, { 1149425, 8144, -940, 808, -21583, 226, } },
{ 768000, {}, { 1191317, 8144, -940, 808, -21583, 226, } },
{ 844800, {}, { 1233208, 8144, -940, 808, -21583, 226, } },
{ 921600, {}, { 1275100, 8144, -940, 808, -21583, 226, } },
{ },
};
constexpr u32 MemVoltHOS = 1125'000;
constexpr u32 EmcClkMinFreq = 40800; /* 40.8 MHz table only exists on erista. */
constexpr u32 EmcClkPllmLimit = 1866'000'000;
constexpr u32 MTC_TABLE_REV = 7;
constexpr u32 MtcTableCountDefault = 10;
constexpr size_t MtcFullTableSize = sizeof(EristaMtcTable) * MtcTableCountDefault;
constexpr u32 MtcFullTableCount = 3;
/* These dramids were copied from Hekate -- see /bdk/mem/sdram.h */
enum DramId {
ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH = 0,
ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE = 1,
ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WTC = 2,
ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH = 4,
ICOSA_8GB_SAMSUNG_K4FBE3D4HM_MGXX = 7,
};
enum MtcTableIndex {
T210SdevEmcDvfsTableS4gb01 = 0, /* HB-MGCH, WT:C */
T210SdevEmcDvfsTableS6gb01 = 1, /* HM-MGCH */
T210SdevEmcDvfsTableH4gb01 = 2, /* HR-NLE */
MtcTableIndex_Invalid = 3,
};
struct MtcDramIndex {
DramId dramId;
MtcTableIndex index;
};
const inline MtcDramIndex mtcIndexTable[] = {
{ ICOSA_4GB_SAMSUNG_K4F6E304HB_MGCH, T210SdevEmcDvfsTableS4gb01, },
{ ICOSA_4GB_MICRON_MT53B512M32D2NP_062_WTC, T210SdevEmcDvfsTableS4gb01, },
{ ICOSA_6GB_SAMSUNG_K4FHE3D4HM_MGCH, T210SdevEmcDvfsTableS6gb01, },
{ ICOSA_4GB_HYNIX_H9HCNNNBPUMLHR_NLE, T210SdevEmcDvfsTableH4gb01, },
};
void Patch(uintptr_t mapped_nso, size_t nso_size);
}

View File

@@ -0,0 +1,306 @@
/*
* Copyright (C) Switch-OC-Suite
*
* Copyright (c) 2023 hanai3Bi
*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "../oc_common.hpp"
#include "pcv_common.hpp"
#include "pcv_asm.hpp"
namespace ams::ldr::hoc::pcv::mariko {
constexpr cvb_entry_t CpuCvbTableDefault[] = {
{ 204000, { 721589, -12695, 27 }, { } },
{ 306000, { 747134, -14195, 27 }, { } },
{ 408000, { 776324, -15705, 27 }, { } },
{ 510000, { 809160, -17205, 27 }, { } },
{ 612000, { 845641, -18715, 27 }, { } },
{ 714000, { 885768, -20215, 27 }, { } },
{ 816000, { 929540, -21725, 27 }, { } },
{ 918000, { 976958, -23225, 27 }, { } },
{ 1020000, { 1028021, -24725, 27 }, { 1120000 } },
{ 1122000, { 1082730, -26235, 27 }, { 1120000 } },
{ 1224000, { 1141084, -27735, 27 }, { 1120000 } },
{ 1326000, { 1203084, -29245, 27 }, { 1120000 } },
{ 1428000, { 1268729, -30745, 27 }, { 1120000 } },
{ 1581000, { 1374032, -33005, 27 }, { 1120000 } },
{ 1683000, { 1448791, -34505, 27 }, { 1120000 } },
{ 1785000, { 1527196, -36015, 27 }, { 1120000 } },
{ 1887000, { 1609246, -37515, 27 }, { 1120000 } },
{ 1963500, { 1675751, -38635, 27 }, { 1120000 } },
{ },
};
constexpr u32 CpuClkOfficial = 1963'500;
constexpr u32 CpuVoltOfficial = 1120;
constexpr u32 CpuHighVminOfficial = 850;
constexpr u32 CpuVminOfficial = 620;
constexpr u32 CpuTune0Low = 0xFFCF;
static const u32 cpuVoltagePatchValues[] = { 850, 38, 1120, 1000, 100, 1000, 0 };
static const s32 cpuVoltagePatchOffsets[] = { -2, -1, 5, 6, 7, 8, 9 };
static_assert(sizeof(cpuVoltagePatchValues) == sizeof(cpuVoltagePatchOffsets), "Invalid cpuVoltagePatch size");
static const u32 cpuVoltThermalData[] = { 620, 1120, 20000, 620, 1120, 70000, 950, 1132, 0, 950, 1227, 0 };
static const u32 allowedCpuMaxFrequencies[] = { 1'963'500, 2'091'000, 2'193'000, 2'295'000, 2'397'000, 2'499'000, 2'601'000, 2'703'000, };
constexpr cvb_entry_t GpuCvbTableDefault[] = {
// GPUB01_NA_CVB_TABLE
{ 76800, {}, { 610000, } },
{ 153600, {}, { 610000, } },
{ 230400, {}, { 610000, } },
{ 307200, {}, { 610000, } },
{ 384000, {}, { 610000, } },
{ 460800, {}, { 610000, } },
{ 537600, {}, { 801688, -10900, -163, 298, -10599, 162, } },
{ 614400, {}, { 824214, -5743, -452, 238, -6325, 81, } },
{ 691200, {}, { 848830, -3903, -552, 119, -4030, -2, } },
{ 768000, {}, { 891575, -4409, -584, 0, -2849, 39, } },
{ 844800, {}, { 940071, -5367, -602, -60, -63, -93, } },
{ 921600, {}, { 986765, -6637, -614, -179, 1905, -13, } },
{ 998400, {}, { 1098475, -13529, -497, -179, 3626, 9, } },
{ 1075200, {}, { 1163644, -12688, -648, 0, 1077, 40, } },
{ 1152000, {}, { 1204812, -9908, -830, 0, 1469, 110, } },
{ 1228800, {}, { 1277303, -11675, -859, 0, 3722, 313, } },
{ 1267200, {}, { 1335531, -12567, -867, 0, 3681, 559, } },
{ },
};
constexpr u32 GpuClkPllMax = 1300'000'000;
constexpr u32 GpuClkPllLimit = 2'600'000;
constexpr u32 GpuVminOfficial = 610;
static const u32 gpuDVFSPattern[] = { 1050, 1000, 100, 1000, 10, };
static const u32 gpuVoltThermalPattern[] = { 800, 1120, 0, 610, 1120, 20000, 610, 1120, 30000, 610, 1120, 50000, 610, 1120, 70000, 610, 1120, 90000, };
static_assert(sizeof(gpuVoltThermalPattern) == 72, "Invalid gpuVoltThermalPattern");
/* GPU Max Clock asm Pattern:
*
* MOV W11, #0x1000 MOV (wide immediate) 0x1000 0xB (11)
* sf | opc | | hw | imm16 | Rd
* #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0
* 0 | 1 0 | 1 0 0 1 0 1| 0 0| 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 |0 1 0 1 1
*
* MOVK W11, #0xE, LSL#16 <shift>16 0xE 0xB (11)
* sf | opc | | hw | imm16 | Rd
* #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0
* 0 | 1 1 | 1 0 0 1 0 1| 0 1| 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 |0 1 0 1 1
*/
inline constexpr u32 GpuAsmPattern[] = { 0x52820000, 0x72A001C0 };
inline bool GpuMaxClockPatternFn(u32 *ptr32) {
return asm_compare_no_rd(*ptr32, GpuAsmPattern[0]);
}
struct DvbEntry {
u64 freq;
u32 volt[4] = {};
};
constexpr DvbEntry EmcDvbTableDefault[] = {
{ 204000, { 637, 637, 637, } },
{ 408000, { 637, 637, 637, } },
{ 800000, { 637, 637, 637, } },
{ 1065600, { 637, 637, 637, } },
{ 1331200, { 650, 637, 637, } },
{ 1600000, { 675, 650, 637, } },
};
/* Movz */
/*
SF | OPC | HW | Imm16 | RD
31 | 30 29 28 27 26 25 24 23 | 22 21 | 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 | 4 3 2 1 0
*/
constexpr u32 SocVoltCompareSpeedoAsm = 0x7118FAFF; /* subs imm, compares to >=1598 max speedo and then goes down process id 1 route. */
constexpr u32 SocVoltWriteProcessIdAsm = 0x2A1F03F4; /* orr, writes id 0. */
constexpr u32 SocVoltWriteVoltageAsm = 0x52808358; /* Movz imm, writes 1050mV. */
constexpr u32 SocVoltSelectRegisterAsm = 0x1A9A3118; /* Csel, selects the voltage -- we need the register of this. */
constexpr u32 SocVoltMultiplyVoltsAsm = 0x1B1A7F0B; /* Mul, converts from mV -> uV */
constexpr u32 SocVoltValidateLimitAsm = 0x6B0A017F; /* Subs, checks limits */
constexpr u32 SocVoltBranchToAbortAsm = 0x540020AC; /* B.ge Branches to abort if limits are invalid. */
ALWAYS_INLINE bool SocVoltPatternFn(u32 *ptr) {
return asm_compare_no_rd(*ptr, SocVoltCompareSpeedoAsm);
}
constexpr u32 SocVoltLimitOfficial = 1050;
constexpr u32 SocVoltLimitMaxDefaultIndex = 17;
static const u32 socVoltLimitArray[DvfsTableEntryCount] = { 637, 650, 675, 700, 725, 750, 775, 800, 825, 850, 875, 900, 925, 950, 975, 1000, 1025, 1050, };
constexpr u32 EmcListDefault[] = { 204000, 1331200, 1600000, };
constexpr u32 EmcListSizeDefault = std::size(EmcListDefault);
constexpr u32 EmcListEndDefault = EmcListSizeDefault - 1;
constexpr u32 EmcRateStep = 33'000;
constexpr u32 EmcRateStepScale = 33'200;
constexpr u32 EmcClkOSAlt = 1331'200;
constexpr u32 EmcClkPllmLimit = 2133'000'000;
constexpr u32 EmcVddqDefault = 600'000;
constexpr u32 MemVdd2Default = 1100'000;
constexpr u32 MTC_TABLE_REV = 3;
constexpr u32 MtcTableCountDefault = 3;
constexpr size_t MtcFullTableSize = sizeof(MarikoMtcTable) * MtcTableCountDefault;
constexpr u32 MtcFullTableCount = 17;
/* These dramids were copied from Hekate -- see /bdk/mem/sdram.h */
enum DramId : u64 {
HOAG_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 3,
AULA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 5,
IOWA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 6,
IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 8,
IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 9,
IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 10,
IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTE = 11,
HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 12,
HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 13,
HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 14,
HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTE = 15,
IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 17,
IOWA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 18,
HOAG_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 19,
IOWA_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 20,
HOAG_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 21,
AULA_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 22,
HOAG_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 23,
AULA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 24,
IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 25,
HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTF = 26,
AULA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 27,
AULA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 28,
IOWA_4GB_HYNIX_H54G46CYRBX267 = 29,
HOAG_4GB_HYNIX_H54G46CYRBX267 = 30,
AULA_4GB_HYNIX_H54G46CYRBX267 = 31,
IOWA_4GB_MICRON_MT53E512M32D1NP_046_WTB = 32,
HOAG_4GB_MICRON_MT53E512M32D1NP_046_WTB = 33,
AULA_4GB_MICRON_MT53E512M32D1NP_046_WTB = 34,
};
enum MtcTableIndex {
T210b0SdevEmcDvfsTableS4gb01 = 0, /* (Unused) Samsung 4Gb */
T210b0SdevEmcDvfsTableS4gb03 = 1, /* Samsung AM-MGCJ 4Gb */
T210b0SdevEmcDvfsTableS8gb03 = 2, /* (Unused) Samsung 4Gb */
T210b0SdevEmcDvfsTableH4gb03 = 3, /* Hynix NME 4Gb */
T210b0SdevEmcDvfsTableM4gb03 = 4, /* Micron WT:F 4Gb */
T210b0SdevEmcDvfsTableS4gbY01 = 5, /* (Unused) Samsung 4Gb */
T210b0SdevEmcDvfsTableS1y4gbY01 = 6, /* (Unused) Samsung 4Gb */
T210b0SdevEmcDvfsTableS1y8gbY01 = 7, /* (Unused) Samsung 4Gb */
T210b0SdevEmcDvfsTableS1y4gbX03 = 8, /* Samsung AA-MGCL 4Gb */
T210b0SdevEmcDvfsTableS1y8gbX03 = 9, /* Samsung AA-MGCL 8Gb */
T210b0SdevEmcDvfsTableS1y4gb01 = 10, /* (Unused) Samsung 4Gb */
T210b0SdevEmcDvfsTableM1y4gb01 = 11, /* Micron WT:E 4Gb */
T210b0SdevEmcDvfsTableH1y4gb01 = 12, /* Hynix NEE 4Gb */
T210b0SdevEmcDvfsTableS1y8gb04 = 13, /* Samsung AM-MGCJ 8Gb */
T210b0SdevEmcDvfsTableS1z4gb01 = 14, /* Samsung AB-MGCL 4Gb */
T210b0SdevEmcDvfsTableH1a4gb01 = 15, /* Hynix x267 4Gb */
T210b0SdevEmcDvfsTableM1a4gb01 = 16, /* Micron WT:B 8Gb */
MtcTableIndex_Invalid = 17,
};
struct MtcDramIndex {
DramId dramId;
MtcTableIndex index;
};
const inline MtcDramIndex mtcIndexTable[] = {
{ HOAG_4GB_HYNIX_H9HCNNNBKMMLXR_NEE, T210b0SdevEmcDvfsTableH1y4gb01, },
{ AULA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE, T210b0SdevEmcDvfsTableH1y4gb01, },
{ IOWA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE, T210b0SdevEmcDvfsTableH1y4gb01, },
{ IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ, T210b0SdevEmcDvfsTableS4gb03, },
{ IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ, T210b0SdevEmcDvfsTableS1y8gb04, },
{ IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME, T210b0SdevEmcDvfsTableH4gb03, },
{ IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTE, T210b0SdevEmcDvfsTableM1y4gb01, },
{ HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ, T210b0SdevEmcDvfsTableS4gb03, },
{ HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ, T210b0SdevEmcDvfsTableS1y8gb04, },
{ HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME, T210b0SdevEmcDvfsTableH4gb03, },
{ HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTE, T210b0SdevEmcDvfsTableM1y4gb01, },
{ IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL, T210b0SdevEmcDvfsTableS1y4gbX03, },
{ IOWA_8GB_SAMSUNG_K4UBE3D4AA_MGCL, T210b0SdevEmcDvfsTableS1y8gbX03, },
{ HOAG_4GB_SAMSUNG_K4U6E3S4AA_MGCL, T210b0SdevEmcDvfsTableS1y4gbX03, },
{ IOWA_4GB_SAMSUNG_K4U6E3S4AB_MGCL, T210b0SdevEmcDvfsTableS1z4gb01, },
{ HOAG_4GB_SAMSUNG_K4U6E3S4AB_MGCL, T210b0SdevEmcDvfsTableS1y8gb04, },
{ AULA_4GB_SAMSUNG_K4U6E3S4AB_MGCL, T210b0SdevEmcDvfsTableS1y8gb04, },
{ HOAG_8GB_SAMSUNG_K4UBE3D4AA_MGCL, T210b0SdevEmcDvfsTableS1y8gbX03, },
{ AULA_4GB_SAMSUNG_K4U6E3S4AA_MGCL, T210b0SdevEmcDvfsTableS1y4gbX03, },
{ IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTF, T210b0SdevEmcDvfsTableM4gb03, },
{ HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTF, T210b0SdevEmcDvfsTableM4gb03, },
{ AULA_4GB_MICRON_MT53E512M32D2NP_046_WTF, T210b0SdevEmcDvfsTableM4gb03, },
{ AULA_8GB_SAMSUNG_K4UBE3D4AA_MGCL, T210b0SdevEmcDvfsTableS1y8gbX03, },
{ IOWA_4GB_HYNIX_H54G46CYRBX267, T210b0SdevEmcDvfsTableH1a4gb01, },
{ HOAG_4GB_HYNIX_H54G46CYRBX267, T210b0SdevEmcDvfsTableH1a4gb01, },
{ AULA_4GB_HYNIX_H54G46CYRBX267, T210b0SdevEmcDvfsTableH1a4gb01, },
{ IOWA_4GB_MICRON_MT53E512M32D1NP_046_WTB, T210b0SdevEmcDvfsTableM1a4gb01, },
{ HOAG_4GB_MICRON_MT53E512M32D1NP_046_WTB, T210b0SdevEmcDvfsTableM1a4gb01, },
{ AULA_4GB_MICRON_MT53E512M32D1NP_046_WTB, T210b0SdevEmcDvfsTableM1a4gb01, },
};
/*
710006abfc 40 01 1f d6 br x10
*/
/*
710006ac28 a0 03 00 90 adrp x0,0x71000de000
710006ac2c 00 80 16 91 add x0=>SdevEmcDvfsTableS4gb01,x0,#0x5a0
*/
/* Br */
/*
| Z | OP | Fixed | A | M | RN | RM
31 30 29 28 27 26 25 | 24 23 | 22 | 21 20 19 18 17 16 15 14 13 12 |11 | 10 | 9 8 7 6 5 | 4 3 2 1 0
1 1 0 1 0 1 1 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 Rn 0 0 0 0 0
Z op A M Rm
*/
/* Adrp */
/*
OP | ImmLow | | ImmHigh | RD
31 | 30 29 | 28 27 26 25 24 | 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 | 4 3 2 1 0
*/
/* ADD (immediate) */
/*
SF | OP | S | Fixed value | Sh | Imm12 | RN | RD
31 | 30 | 29 | 28 27 26 25 24 23 | 22 | 21 20 19 18 17 16 15 14 13 12 11 10 | 9 8 7 6 5 | 4 3 2 1 0
*/
constexpr u32 MtcBrAsm = 0xD61F0140;
constexpr u32 MtcMovAsm = 0x52800068;
constexpr u32 MtcAdrpAsm = 0x900003A0;
constexpr u32 MtcAddAsm = 0x91168000;
ALWAYS_INLINE bool MemMtcGetGetTablePatternFn(u32 *ptr) {
/* This builds an address that gets returned, so the register must be x0 by convention. */
return AsmCompareAddNoImm12(*ptr, MtcAddAsm);
}
void Patch(uintptr_t mapped_nso, size_t nso_size);
}

View File

@@ -21,11 +21,7 @@
namespace ams::ldr::hoc::ptm { namespace ams::ldr::hoc::ptm {
Result CpuPtmBoost(perf_conf_entry* entry) { Result CpuPtmBoost(perf_conf_entry* entry) {
#ifdef ATMOSPHERE_IS_STRATOSPHERE
bool isMariko = (spl::GetSocType() == spl::SocType_Mariko); bool isMariko = (spl::GetSocType() == spl::SocType_Mariko);
#else
bool isMariko = true;
#endif
if (!C.eristaCpuBoostClock || !C.marikoCpuBoostClock) { if (!C.eristaCpuBoostClock || !C.marikoCpuBoostClock) {
R_SUCCEED(); R_SUCCEED();
@@ -76,11 +72,7 @@ namespace ams::ldr::hoc::ptm {
PatcherEntry<perf_conf_entry> cpuPtmBoostPatch = { "CPU Ptm Boost", &CpuPtmBoost, 2, }; PatcherEntry<perf_conf_entry> cpuPtmBoostPatch = { "CPU Ptm Boost", &CpuPtmBoost, 2, };
PatcherEntry<perf_conf_entry> memPtmPatch = { "MEM Ptm", &MemPtm, 16, }; PatcherEntry<perf_conf_entry> memPtmPatch = { "MEM Ptm", &MemPtm, 16, };
#ifdef ATMOSPHERE_IS_STRATOSPHERE
bool isMariko = (spl::GetSocType() == spl::SocType_Mariko); bool isMariko = (spl::GetSocType() == spl::SocType_Mariko);
#else
bool isMariko = true;
#endif
for (u32 i = 0; i < entryCnt; i++) { for (u32 i = 0; i < entryCnt; i++) {
perf_conf_entry *entry = confTable + i; perf_conf_entry *entry = confTable + i;

View File

@@ -38,7 +38,7 @@ include $(DEVKITPRO)/libnx/switch_rules
# NACP building is skipped as well. # NACP building is skipped as well.
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
APP_TITLE := Horizon OC Monitor APP_TITLE := Horizon OC Monitor
APP_VERSION := 1.3.2+r4-hoc-r3 APP_VERSION := 1.3.2+r4-hoc-r4
TARGET := $(notdir $(CURDIR)) TARGET := $(notdir $(CURDIR))
BUILD := build BUILD := build
SOURCES := source SOURCES := source
@@ -65,6 +65,7 @@ IS_STATUS_MONITOR_DIRECTIVE := 1
CFLAGS += -DIS_STATUS_MONITOR_DIRECTIVE=$(IS_STATUS_MONITOR_DIRECTIVE) CFLAGS += -DIS_STATUS_MONITOR_DIRECTIVE=$(IS_STATUS_MONITOR_DIRECTIVE)
# Enable appearance overriding # Enable appearance overriding
export MSYS2_ARG_CONV_EXCL := -DUI_OVERRIDE_PATH
UI_OVERRIDE_PATH := /config/status-monitor/ UI_OVERRIDE_PATH := /config/status-monitor/
CFLAGS += -DUI_OVERRIDE_PATH="\"$(UI_OVERRIDE_PATH)\"" CFLAGS += -DUI_OVERRIDE_PATH="\"$(UI_OVERRIDE_PATH)\""

View File

@@ -69,9 +69,7 @@ MmuRequest nvencRequest;
MmuRequest nvjpgRequest; MmuRequest nvjpgRequest;
//Checks //Checks
Result clkrstCheck = 1;
Result nvCheck = 1; Result nvCheck = 1;
Result pcvCheck = 1;
Result i2cCheck = 1; Result i2cCheck = 1;
Result pwmCheck = 1; Result pwmCheck = 1;
Result tcCheck = 1; Result tcCheck = 1;
@@ -554,28 +552,6 @@ void Misc(void*) {
do { do {
mutexLock(&mutex_Misc); mutexLock(&mutex_Misc);
// CPU, GPU and RAM Frequency
if (R_SUCCEEDED(clkrstCheck)) {
ClkrstSession clkSession;
if (R_SUCCEEDED(clkrstOpenSession(&clkSession, PcvModuleId_CpuBus, 3))) {
clkrstGetClockRate(&clkSession, &CPU_Hz);
clkrstCloseSession(&clkSession);
}
if (R_SUCCEEDED(clkrstOpenSession(&clkSession, PcvModuleId_GPU, 3))) {
clkrstGetClockRate(&clkSession, &GPU_Hz);
clkrstCloseSession(&clkSession);
}
if (R_SUCCEEDED(clkrstOpenSession(&clkSession, PcvModuleId_EMC, 3))) {
clkrstGetClockRate(&clkSession, &RAM_Hz);
clkrstCloseSession(&clkSession);
}
}
else if (R_SUCCEEDED(pcvCheck)) {
pcvGetClockRate(PcvModule_CpuBus, &CPU_Hz);
pcvGetClockRate(PcvModule_GPU, &GPU_Hz);
pcvGetClockRate(PcvModule_EMC, &RAM_Hz);
}
// Get sys-clk data // Get sys-clk data
if (R_SUCCEEDED(hocclkCheck)) { if (R_SUCCEEDED(hocclkCheck)) {
HocClkContext hocclkCTX; HocClkContext hocclkCTX;
@@ -583,8 +559,12 @@ void Misc(void*) {
realCPU_Hz = hocclkCTX.realFreqs[HocClkModule_CPU]; realCPU_Hz = hocclkCTX.realFreqs[HocClkModule_CPU];
realGPU_Hz = hocclkCTX.realFreqs[HocClkModule_GPU]; realGPU_Hz = hocclkCTX.realFreqs[HocClkModule_GPU];
realRAM_Hz = hocclkCTX.realFreqs[HocClkModule_MEM]; realRAM_Hz = hocclkCTX.realFreqs[HocClkModule_MEM];
partLoad[HocClkPartLoad_EMC] = hocclkCTX.partLoad[HocClkPartLoad_EMC]; partLoad[HocClkPartLoad_EMC] = hocclkCTX.partLoad[HocClkPartLoad_EMC];
partLoad[HocClkPartLoad_EMCCpu] = hocclkCTX.partLoad[HocClkPartLoad_EMCCpu]; partLoad[HocClkPartLoad_EMCCpu] = hocclkCTX.partLoad[HocClkPartLoad_EMCCpu];
partLoad[HocClkPartLoad_RamBWAll] = hocclkCTX.partLoad[HocClkPartLoad_RamBWAll];
partLoad[HocClkPartLoad_RamBWCpu] = hocclkCTX.partLoad[HocClkPartLoad_RamBWCpu];
partLoad[HocClkPartLoad_RamBWGpu] = hocclkCTX.partLoad[HocClkPartLoad_RamBWGpu];
partLoad[HocClkPartLoad_RamBWPeak] = hocclkCTX.partLoad[HocClkPartLoad_RamBWPeak];
realCPU_Temp = hocclkCTX.temps[HocClkThermalSensor_CPU]; realCPU_Temp = hocclkCTX.temps[HocClkThermalSensor_CPU];
realGPU_Temp = hocclkCTX.temps[HocClkThermalSensor_GPU]; realGPU_Temp = hocclkCTX.temps[HocClkThermalSensor_GPU];
realPLLX_Temp = hocclkCTX.temps[HocClkThermalSensor_PLLX]; realPLLX_Temp = hocclkCTX.temps[HocClkThermalSensor_PLLX];
@@ -595,6 +575,9 @@ void Misc(void*) {
realSOC_mV = hocclkCTX.voltages[HocClkVoltage_SOC]; realSOC_mV = hocclkCTX.voltages[HocClkVoltage_SOC];
realVDD2_mV = hocclkCTX.voltages[HocClkVoltage_EMCVDD2]; realVDD2_mV = hocclkCTX.voltages[HocClkVoltage_EMCVDD2];
realVDDQ_mV = hocclkCTX.voltages[HocClkVoltage_EMCVDDQ]; realVDDQ_mV = hocclkCTX.voltages[HocClkVoltage_EMCVDDQ];
CPU_Hz = hocclkCTX.freqs[HocClkModule_CPU];
GPU_Hz = hocclkCTX.freqs[HocClkModule_GPU];
RAM_Hz = hocclkCTX.freqs[HocClkModule_MEM];
} }
} }
@@ -714,8 +697,12 @@ void Misc3(void*) {
if (R_SUCCEEDED(hocclkCheck)) { if (R_SUCCEEDED(hocclkCheck)) {
HocClkContext hocclkCTX; HocClkContext hocclkCTX;
if (R_SUCCEEDED(hocclkIpcGetCurrentContext(&hocclkCTX))) { if (R_SUCCEEDED(hocclkIpcGetCurrentContext(&hocclkCTX))) {
partLoad[HocClkPartLoad_EMC] = hocclkCTX.partLoad[HocClkPartLoad_EMC]; partLoad[HocClkPartLoad_EMC] = hocclkCTX.partLoad[HocClkPartLoad_EMC];
partLoad[HocClkPartLoad_EMCCpu] = hocclkCTX.partLoad[HocClkPartLoad_EMCCpu]; partLoad[HocClkPartLoad_EMCCpu] = hocclkCTX.partLoad[HocClkPartLoad_EMCCpu];
partLoad[HocClkPartLoad_RamBWAll] = hocclkCTX.partLoad[HocClkPartLoad_RamBWAll];
partLoad[HocClkPartLoad_RamBWCpu] = hocclkCTX.partLoad[HocClkPartLoad_RamBWCpu];
partLoad[HocClkPartLoad_RamBWGpu] = hocclkCTX.partLoad[HocClkPartLoad_RamBWGpu];
partLoad[HocClkPartLoad_RamBWPeak] = hocclkCTX.partLoad[HocClkPartLoad_RamBWPeak];
realCPU_Temp = hocclkCTX.temps[HocClkThermalSensor_CPU]; realCPU_Temp = hocclkCTX.temps[HocClkThermalSensor_CPU];
realGPU_Temp = hocclkCTX.temps[HocClkThermalSensor_GPU]; realGPU_Temp = hocclkCTX.temps[HocClkThermalSensor_GPU];
@@ -1274,6 +1261,7 @@ struct FullSettings {
bool showFPS; bool showFPS;
bool showRES; bool showRES;
bool showRDSD; bool showRDSD;
std::string ramInfoMode;
bool useDynamicColors; bool useDynamicColors;
bool disableScreenshots; bool disableScreenshots;
uint16_t separatorColor; uint16_t separatorColor;
@@ -1309,6 +1297,7 @@ struct MiniSettings {
std::string show; std::string show;
bool showpartLoad; bool showpartLoad;
bool showpartLoadCPUGPU; bool showpartLoadCPUGPU;
std::string ramInfoMode;
bool invertBatteryDisplay; bool invertBatteryDisplay;
bool disableScreenshots; bool disableScreenshots;
bool sleepExit; bool sleepExit;
@@ -1343,6 +1332,7 @@ struct MicroSettings {
uint16_t textColor; uint16_t textColor;
std::string show; std::string show;
bool showpartLoad; bool showpartLoad;
std::string ramInfoMode;
bool setPosBottom; bool setPosBottom;
bool disableScreenshots; bool disableScreenshots;
bool sleepExit; bool sleepExit;
@@ -1430,6 +1420,7 @@ ALWAYS_INLINE void GetConfigSettings(MiniSettings* settings) {
settings->show = "DTC+BAT+CPU+GPU+RAM+TMP+FPS+RES"; settings->show = "DTC+BAT+CPU+GPU+RAM+TMP+FPS+RES";
settings->showpartLoad = true; settings->showpartLoad = true;
settings->showpartLoadCPUGPU = false; settings->showpartLoadCPUGPU = false;
settings->ramInfoMode = "LOAD";
settings->invertBatteryDisplay = true; settings->invertBatteryDisplay = true;
settings->refreshRate = 1; settings->refreshRate = 1;
settings->disableScreenshots = false; settings->disableScreenshots = false;
@@ -1639,6 +1630,12 @@ ALWAYS_INLINE void GetConfigSettings(MiniSettings* settings) {
settings->showpartLoadCPUGPU = (key != "FALSE"); settings->showpartLoadCPUGPU = (key != "FALSE");
} }
// Process RAM info mode
it = section.find("ram_info_mode");
if (it != section.end()) {
settings->ramInfoMode = it->second;
}
// Invert the battery display value // Invert the battery display value
it = section.find("invert_battery_display"); it = section.find("invert_battery_display");
if (it != section.end()) { if (it != section.end()) {
@@ -1727,6 +1724,7 @@ ALWAYS_INLINE void GetConfigSettings(MicroSettings* settings) {
convertStrToRGBA4444("#FFFF", &(settings->textColor)); convertStrToRGBA4444("#FFFF", &(settings->textColor));
settings->show = "FPS+CPU+GPU+RAM+SOC+BAT+DTC"; settings->show = "FPS+CPU+GPU+RAM+SOC+BAT+DTC";
settings->showpartLoad = true; settings->showpartLoad = true;
settings->ramInfoMode = "LOAD";
settings->setPosBottom = false; settings->setPosBottom = false;
settings->disableScreenshots = false; settings->disableScreenshots = false;
settings->sleepExit = false; settings->sleepExit = false;
@@ -1926,6 +1924,12 @@ ALWAYS_INLINE void GetConfigSettings(MicroSettings* settings) {
settings->showpartLoad = (key != "FALSE"); settings->showpartLoad = (key != "FALSE");
} }
// Process RAM info mode
it = section.find("ram_info_mode");
if (it != section.end()) {
settings->ramInfoMode = it->second;
}
// Process show string // Process show string
it = section.find("show"); it = section.find("show");
if (it != section.end()) { if (it != section.end()) {
@@ -2257,6 +2261,7 @@ ALWAYS_INLINE void GetConfigSettings(FullSettings* settings) {
settings->showFPS = true; settings->showFPS = true;
settings->showRES = true; settings->showRES = true;
settings->showRDSD = true; settings->showRDSD = true;
settings->ramInfoMode = "LOAD";
settings->useDynamicColors = true; settings->useDynamicColors = true;
settings->disableScreenshots = false; settings->disableScreenshots = false;
convertStrToRGBA4444("#888F", &(settings->separatorColor)); convertStrToRGBA4444("#888F", &(settings->separatorColor));
@@ -2352,6 +2357,11 @@ ALWAYS_INLINE void GetConfigSettings(FullSettings* settings) {
settings->showRDSD = !(key == "FALSE"); settings->showRDSD = !(key == "FALSE");
} }
it = section.find("ram_info_mode");
if (it != section.end()) {
settings->ramInfoMode = it->second;
}
it = section.find("use_dynamic_colors"); it = section.find("use_dynamic_colors");
if (it != section.end()) { if (it != section.end()) {
key = it->second; key = it->second;

View File

@@ -419,8 +419,6 @@ public:
tsl::hlp::doWithSmSession([this]{ tsl::hlp::doWithSmSession([this]{
apmInitialize(); apmInitialize();
if (hosversionAtLeast(8,0,0)) clkrstCheck = clkrstInitialize();
else pcvCheck = pcvInitialize();
if (hosversionAtLeast(5,0,0)) tcCheck = tcInitialize(); if (hosversionAtLeast(5,0,0)) tcCheck = tcInitialize();
@@ -473,8 +471,6 @@ public:
} }
shmemClose(&_sharedmemory); shmemClose(&_sharedmemory);
//Exit services //Exit services
clkrstExit();
pcvExit();
tsExit(); tsExit();
tcExit(); tcExit();
pwmChannelSessionClose(&g_ICon); pwmChannelSessionClose(&g_ICon);
@@ -502,8 +498,6 @@ public:
//Initialize services //Initialize services
tsl::hlp::doWithSmSession([this]{ tsl::hlp::doWithSmSession([this]{
apmInitialize(); apmInitialize();
if (hosversionAtLeast(8,0,0)) clkrstCheck = clkrstInitialize();
else pcvCheck = pcvInitialize();
if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu"); if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu");
@@ -556,8 +550,6 @@ public:
hocclkIpcExit(); hocclkIpcExit();
} }
//Exit services //Exit services
clkrstExit();
pcvExit();
tsExit(); tsExit();
tcExit(); tcExit();
pwmChannelSessionClose(&g_ICon); pwmChannelSessionClose(&g_ICon);
@@ -589,8 +581,6 @@ public:
// Same serviceinit as before // Same serviceinit as before
tsl::hlp::doWithSmSession([this]{ tsl::hlp::doWithSmSession([this]{
apmInitialize(); apmInitialize();
if (hosversionAtLeast(8,0,0)) clkrstCheck = clkrstInitialize();
else pcvCheck = pcvInitialize();
if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu"); if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu");
@@ -644,8 +634,6 @@ public:
hocclkIpcExit(); hocclkIpcExit();
} }
// Exit services // Exit services
clkrstExit();
pcvExit();
tsExit(); tsExit();
tcExit(); tcExit();
pwmChannelSessionClose(&g_ICon); pwmChannelSessionClose(&g_ICon);
@@ -679,8 +667,6 @@ public:
virtual void initServices() override { virtual void initServices() override {
tsl::hlp::doWithSmSession([this]{ tsl::hlp::doWithSmSession([this]{
apmInitialize(); apmInitialize();
if (hosversionAtLeast(8,0,0)) clkrstCheck = clkrstInitialize();
else pcvCheck = pcvInitialize();
if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu"); if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu");
@@ -732,8 +718,6 @@ public:
if (R_SUCCEEDED(hocclkCheck)) { if (R_SUCCEEDED(hocclkCheck)) {
hocclkIpcExit(); hocclkIpcExit();
} }
clkrstExit();
pcvExit();
tsExit(); tsExit();
tcExit(); tcExit();
pwmChannelSessionClose(&g_ICon); pwmChannelSessionClose(&g_ICon);
@@ -762,8 +746,6 @@ public:
virtual void initServices() override { virtual void initServices() override {
tsl::hlp::doWithSmSession([this]{ tsl::hlp::doWithSmSession([this]{
apmInitialize(); apmInitialize();
if (hosversionAtLeast(8,0,0)) clkrstCheck = clkrstInitialize();
else pcvCheck = pcvInitialize();
if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu"); if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu");
@@ -815,8 +797,6 @@ public:
if (R_SUCCEEDED(hocclkCheck)) { if (R_SUCCEEDED(hocclkCheck)) {
hocclkIpcExit(); hocclkIpcExit();
} }
clkrstExit();
pcvExit();
tsExit(); tsExit();
tcExit(); tcExit();
pwmChannelSessionClose(&g_ICon); pwmChannelSessionClose(&g_ICon);
@@ -845,8 +825,6 @@ public:
virtual void initServices() override { virtual void initServices() override {
tsl::hlp::doWithSmSession([this]{ tsl::hlp::doWithSmSession([this]{
apmInitialize(); apmInitialize();
if (hosversionAtLeast(8,0,0)) clkrstCheck = clkrstInitialize();
else pcvCheck = pcvInitialize();
if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu"); if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu");
@@ -898,8 +876,6 @@ public:
if (R_SUCCEEDED(hocclkCheck)) { if (R_SUCCEEDED(hocclkCheck)) {
hocclkIpcExit(); hocclkIpcExit();
} }
clkrstExit();
pcvExit();
tsExit(); tsExit();
tcExit(); tcExit();
pwmChannelSessionClose(&g_ICon); pwmChannelSessionClose(&g_ICon);

View File

@@ -142,7 +142,7 @@ public:
}); });
// tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release); // tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release);
tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("Status Monitor Pro", APP_VERSION, true); tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("Horizon OC Monitor", APP_VERSION, true);
rootFrame->setContent(Status); rootFrame->setContent(Status);
return rootFrame; return rootFrame;

View File

@@ -377,6 +377,21 @@ public:
}); });
list->addItem(showRDSD); list->addItem(showRDSD);
{
const std::string curRamInfoMode = getCurrentRamInfoMode("full");
auto* ramInfoModeItem = new tsl::elm::ListItem("RAM Info Mode");
ramInfoModeItem->setValue(curRamInfoMode);
ramInfoModeItem->setClickListener([this, ramInfoModeItem](u64 keys) -> bool {
if (!(keys & KEY_A)) return false;
const std::string cur = ult::parseValueFromIniSection(configIniPath, "full", "ram_info_mode");
const std::string next = cur == "Bandwidth" ? "Load" : "Bandwidth";
ult::setIniFileValue(configIniPath, "full", "ram_info_mode", next);
ramInfoModeItem->setValue(next);
return true;
});
list->addItem(ramInfoModeItem);
}
auto* dynamicColors = new tsl::elm::ToggleListItem("Use Dynamic Colors", getCurrentUseDynamicColors()); auto* dynamicColors = new tsl::elm::ToggleListItem("Use Dynamic Colors", getCurrentUseDynamicColors());
dynamicColors->setStateChangedListener([this](bool state) { dynamicColors->setStateChangedListener([this](bool state) {
ult::setIniFileValue(configIniPath, "fps-graph", "use_dynamic_colors", state ? "true" : "false"); ult::setIniFileValue(configIniPath, "fps-graph", "use_dynamic_colors", state ? "true" : "false");
@@ -417,13 +432,13 @@ public:
}); });
list->addItem(showFullCPU); list->addItem(showFullCPU);
auto* showVDDQ = new tsl::elm::ToggleListItem("VDD2", getCurrentShowVDDQ()); auto* showVDDQ = new tsl::elm::ToggleListItem("VDDQ", getCurrentShowVDDQ());
showVDDQ->setStateChangedListener([this, section](bool state) { showVDDQ->setStateChangedListener([this, section](bool state) {
ult::setIniFileValue(configIniPath, section, "show_vddq", state ? "true" : "false"); ult::setIniFileValue(configIniPath, section, "show_vddq", state ? "true" : "false");
}); });
list->addItem(showVDDQ); list->addItem(showVDDQ);
auto* showVDD2 = new tsl::elm::ToggleListItem("VDDQ", getCurrentShowVDD2()); auto* showVDD2 = new tsl::elm::ToggleListItem("VDD2", getCurrentShowVDD2());
showVDD2->setStateChangedListener([this, section](bool state) { showVDD2->setStateChangedListener([this, section](bool state) {
ult::setIniFileValue(configIniPath, section, "show_vdd2", state ? "true" : "false"); ult::setIniFileValue(configIniPath, section, "show_vdd2", state ? "true" : "false");
}); });
@@ -449,6 +464,21 @@ public:
list->addItem(partLoadCPUGPU); list->addItem(partLoadCPUGPU);
} }
if (isMiniMode || isMicroMode) {
const std::string curRamInfoMode = getCurrentRamInfoMode(section);
auto* ramInfoModeItem = new tsl::elm::ListItem("RAM Info Mode");
ramInfoModeItem->setValue(curRamInfoMode);
ramInfoModeItem->setClickListener([this, section, ramInfoModeItem](u64 keys) -> bool {
if (!(keys & KEY_A)) return false;
const std::string cur = ult::parseValueFromIniSection(configIniPath, section, "ram_info_mode");
const std::string next = cur == "Bandwidth" ? "Load" : "Bandwidth";
ult::setIniFileValue(configIniPath, section, "ram_info_mode", next);
ramInfoModeItem->setValue(next);
return true;
});
list->addItem(ramInfoModeItem);
}
if (isMiniMode || isMicroMode) { if (isMiniMode || isMicroMode) {
auto* invertBatteryDisplay = new tsl::elm::ToggleListItem("Invert Battery Display", getCurrentInvertBatteryDisplay()); auto* invertBatteryDisplay = new tsl::elm::ToggleListItem("Invert Battery Display", getCurrentInvertBatteryDisplay());
invertBatteryDisplay->setStateChangedListener([this, section](bool state) { invertBatteryDisplay->setStateChangedListener([this, section](bool state) {
@@ -616,6 +646,11 @@ private:
return value != "FALSE"; return value != "FALSE";
} }
std::string getCurrentRamInfoMode(const std::string& section) {
const std::string value = ult::parseValueFromIniSection(configIniPath, section, "ram_info_mode");
return (value == "Bandwidth") ? "Bandwidth" : "Load";
}
bool getCurrentInvertBatteryDisplay() { bool getCurrentInvertBatteryDisplay() {
const std::string section = isMiniMode ? "mini" : "micro"; const std::string section = isMiniMode ? "mini" : "micro";
std::string value = ult::parseValueFromIniSection(configIniPath, section, "invert_battery_display"); std::string value = ult::parseValueFromIniSection(configIniPath, section, "invert_battery_display");

View File

@@ -26,6 +26,11 @@ private:
char BatteryDraw_c[64] = ""; char BatteryDraw_c[64] = "";
char FPS_var_compressed_c[64] = ""; char FPS_var_compressed_c[64] = "";
char RAM_load_c[64] = ""; char RAM_load_c[64] = "";
char RAM_load2_c[64] = "";
char RAM_bw_peak_c[16] = "";
char RAM_bw_total_c[16] = "";
char RAM_bw_gpu_c[16] = "";
char RAM_bw_cpu_c[16] = "";
char Resolutions_c[64] = ""; char Resolutions_c[64] = "";
char readSpeed_c[32] = ""; char readSpeed_c[32] = "";
@@ -120,7 +125,7 @@ public:
//Print strings //Print strings
///CPU ///CPU
if (R_SUCCEEDED(clkrstCheck) || R_SUCCEEDED(pcvCheck)) { if (1) {
uint32_t height_offset = 155; uint32_t height_offset = 155;
if (realCPU_Hz && settings.showRealFreqs) { if (realCPU_Hz && settings.showRealFreqs) {
@@ -168,7 +173,7 @@ public:
} }
///GPU ///GPU
if (R_SUCCEEDED(clkrstCheck) || R_SUCCEEDED(pcvCheck) || R_SUCCEEDED(nvCheck)) { if (R_SUCCEEDED(nvCheck)) {
uint32_t height_offset = 320-8; uint32_t height_offset = 320-8;
if (realGPU_Hz && settings.showRealFreqs) { if (realGPU_Hz && settings.showRealFreqs) {
@@ -176,7 +181,7 @@ public:
} }
renderer->drawString("GPU Usage", false, COMMON_MARGIN, 285-8, 20, (settings.catColor1)); renderer->drawString("GPU Usage", false, COMMON_MARGIN, 285-8, 20, (settings.catColor1));
if (R_SUCCEEDED(clkrstCheck) || R_SUCCEEDED(pcvCheck)) { if (1) {
if (settings.showTargetFreqs) { if (settings.showTargetFreqs) {
//static auto targetFreqWidth = renderer->getTextDimensions("Target Frequency: ", false, 15).first; //static auto targetFreqWidth = renderer->getTextDimensions("Target Frequency: ", false, 15).first;
renderer->drawString("Target Frequency", false, COMMON_MARGIN, height_offset, 15, (settings.catColor2)); renderer->drawString("Target Frequency", false, COMMON_MARGIN, height_offset, 15, (settings.catColor2));
@@ -208,7 +213,7 @@ public:
static std::vector<std::string> specialChars = {""}; static std::vector<std::string> specialChars = {""};
///RAM ///RAM
if (R_SUCCEEDED(clkrstCheck) || R_SUCCEEDED(pcvCheck) || R_SUCCEEDED(Hinted)) { if (R_SUCCEEDED(Hinted)) {
uint32_t height_offset = 410; uint32_t height_offset = 410;
if (realRAM_Hz && settings.showRealFreqs) { if (realRAM_Hz && settings.showRealFreqs) {
@@ -216,7 +221,7 @@ public:
} }
renderer->drawString("RAM Usage", false, COMMON_MARGIN, 375, 20, (settings.catColor1)); renderer->drawString("RAM Usage", false, COMMON_MARGIN, 375, 20, (settings.catColor1));
if (R_SUCCEEDED(clkrstCheck) || R_SUCCEEDED(pcvCheck)) { if (1) {
if (settings.showTargetFreqs) { if (settings.showTargetFreqs) {
//static auto targetFreqWidth = renderer->getTextDimensions("Target Frequency: ", false, 15).first; //static auto targetFreqWidth = renderer->getTextDimensions("Target Frequency: ", false, 15).first;
renderer->drawString("Target Frequency", false, COMMON_MARGIN, height_offset, 15, (settings.catColor2)); renderer->drawString("Target Frequency", false, COMMON_MARGIN, height_offset, 15, (settings.catColor2));
@@ -237,17 +242,40 @@ public:
renderer->drawString(DeltaRAM_c, false, COMMON_MARGIN + deltaOffset, height_offset, 15, (settings.textColor)); renderer->drawString(DeltaRAM_c, false, COMMON_MARGIN + deltaOffset, height_offset, 15, (settings.textColor));
} }
if (R_SUCCEEDED(hocclkCheck)) { if (R_SUCCEEDED(hocclkCheck)) {
static std::vector<std::string> partLoadColoredChars = {"CPU", "GPU"}; if (settings.ramInfoMode == "Bandwidth") {
//static auto loadLabelWidth = renderer->getTextDimensions("Load: ", false, 15).first; // Fixed column layout: labels at fixed x, values at fixed x after max label width
renderer->drawString("Load", false, COMMON_MARGIN, height_offset+15, 15, (settings.catColor2)); // Col1: Peak/GPU labels, Col2: Total/CPU labels
renderer->drawStringWithColoredSections(RAM_load_c, false, partLoadColoredChars, COMMON_MARGIN + valueOffset, height_offset+15, 15, (settings.textColor), settings.catColor2); // Values start at a fixed offset so columns don't shift with different digit counts
static const uint32_t bwLbl1W = renderer->getTextDimensions("Peak ", false, 15).first;
static const uint32_t bwLbl2W = renderer->getTextDimensions("Total ", false, 15).first;
static const uint32_t bwValW = renderer->getTextDimensions("99.9 GB/s", false, 15).first;
static const uint32_t bwGap = renderer->getTextDimensions(" ", false, 15).first;
const uint32_t xV1 = COMMON_MARGIN + bwLbl1W;
const uint32_t xL2 = xV1 + bwValW + bwGap;
const uint32_t xV2 = xL2 + bwLbl2W;
// Row 1: Peak ... Total
renderer->drawString("Peak", false, COMMON_MARGIN, height_offset+15, 15, settings.catColor2);
renderer->drawString(RAM_bw_peak_c, false, xV1, height_offset+15, 15, settings.textColor);
renderer->drawString("Total", false, xL2, height_offset+15, 15, settings.catColor2);
renderer->drawString(RAM_bw_total_c, false, xV2, height_offset+15, 15, settings.textColor);
// Row 2: GPU ... CPU
renderer->drawString("GPU", false, COMMON_MARGIN, height_offset+30, 15, settings.catColor2);
renderer->drawString(RAM_bw_gpu_c, false, xV1, height_offset+30, 15, settings.textColor);
renderer->drawString("CPU", false, xL2, height_offset+30, 15, settings.catColor2);
renderer->drawString(RAM_bw_cpu_c, false, xV2, height_offset+30, 15, settings.textColor);
} else {
static std::vector<std::string> partLoadColoredChars = {"CPU", "GPU"};
renderer->drawString("Load", false, COMMON_MARGIN, height_offset+15, 15, (settings.catColor2));
renderer->drawStringWithColoredSections(RAM_load_c, false, partLoadColoredChars, COMMON_MARGIN + valueOffset, height_offset+15, 15, (settings.textColor), settings.catColor2);
}
} }
} }
if (R_SUCCEEDED(Hinted)) { if (R_SUCCEEDED(Hinted)) {
const uint32_t ramUsageOffset = (R_SUCCEEDED(hocclkCheck) && settings.ramInfoMode == "Bandwidth") ? height_offset + 50 : height_offset + 40;
//static auto textWidth = renderer->getTextDimensions("Total \nApplication \nApplet \nSystem \nSystem Unsafe ", false, 15).first; //static auto textWidth = renderer->getTextDimensions("Total \nApplication \nApplet \nSystem \nSystem Unsafe ", false, 15).first;
renderer->drawString("Total\nApplication\nApplet\nSystem\nSystem Unsafe", false, COMMON_MARGIN, height_offset + 40, 15, (settings.catColor2)); renderer->drawString("Total\nApplication\nApplet\nSystem\nSystem Unsafe", false, COMMON_MARGIN, ramUsageOffset, 15, (settings.catColor2));
renderer->drawString(RAM_var_compressed_c, false, COMMON_MARGIN + valueOffset, height_offset + 40, 15, (settings.textColor)); renderer->drawString(RAM_var_compressed_c, false, COMMON_MARGIN + valueOffset, ramUsageOffset, 15, (settings.textColor));
renderer->drawString(RAM_percentage_var_compressed_c, false, ramPercentageOffset, height_offset + 40, 15, (settings.textColor)); renderer->drawString(RAM_percentage_var_compressed_c, false, ramPercentageOffset, ramUsageOffset, 15, (settings.textColor));
} }
} }
@@ -484,12 +512,27 @@ public:
); );
if (R_SUCCEEDED(hocclkCheck)) { if (R_SUCCEEDED(hocclkCheck)) {
const int RAM_GPU_Load = partLoad[HocClkPartLoad_EMC] - partLoad[HocClkPartLoad_EMCCpu]; if (settings.ramInfoMode == "Bandwidth") {
snprintf(RAM_load_c, sizeof RAM_load_c, const unsigned bwAll = partLoad[HocClkPartLoad_RamBWAll] / 1000;
"%u.%u%% CPU %u.%u%% GPU %u.%u%%", const unsigned bwAllD = (partLoad[HocClkPartLoad_RamBWAll] % 1000) / 100;
partLoad[HocClkPartLoad_EMC] / 10, partLoad[HocClkPartLoad_EMC] % 10, const unsigned bwPeak = partLoad[HocClkPartLoad_RamBWPeak] / 1000;
partLoad[HocClkPartLoad_EMCCpu] / 10, partLoad[HocClkPartLoad_EMCCpu] % 10, const unsigned bwPeakD= (partLoad[HocClkPartLoad_RamBWPeak]% 1000) / 100;
RAM_GPU_Load / 10, RAM_GPU_Load % 10); const unsigned bwCpu = partLoad[HocClkPartLoad_RamBWCpu] / 1000;
const unsigned bwCpuD = (partLoad[HocClkPartLoad_RamBWCpu] % 1000) / 100;
const unsigned bwGpu = partLoad[HocClkPartLoad_RamBWGpu] / 1000;
const unsigned bwGpuD = (partLoad[HocClkPartLoad_RamBWGpu] % 1000) / 100;
snprintf(RAM_bw_peak_c, sizeof RAM_bw_peak_c, "%u.%u GB/s", bwPeak, bwPeakD);
snprintf(RAM_bw_total_c, sizeof RAM_bw_total_c, "%u.%u GB/s", bwAll, bwAllD);
snprintf(RAM_bw_gpu_c, sizeof RAM_bw_gpu_c, "%u.%u GB/s", bwGpu, bwGpuD);
snprintf(RAM_bw_cpu_c, sizeof RAM_bw_cpu_c, "%u.%u GB/s", bwCpu, bwCpuD);
} else {
const int RAM_GPU_Load = partLoad[HocClkPartLoad_EMC] - partLoad[HocClkPartLoad_EMCCpu];
snprintf(RAM_load_c, sizeof RAM_load_c,
"%u.%u%% CPU %u.%u%% GPU %u.%u%%",
partLoad[HocClkPartLoad_EMC] / 10, partLoad[HocClkPartLoad_EMC] % 10,
partLoad[HocClkPartLoad_EMCCpu] / 10, partLoad[HocClkPartLoad_EMCCpu] % 10,
RAM_GPU_Load / 10, RAM_GPU_Load % 10);
}
} }
///Thermal ///Thermal
snprintf(SOC_temperature_c, sizeof SOC_temperature_c, "%.1f\u00B0C", SOC_temperatureF); snprintf(SOC_temperature_c, sizeof SOC_temperature_c, "%.1f\u00B0C", SOC_temperatureF);

View File

@@ -955,6 +955,11 @@ public:
const float RAM_Total_all_f = (RAM_Total_application_u + RAM_Total_applet_u + RAM_Total_system_u + RAM_Total_systemunsafe_u) / (1024.0f * 1024.0f * 1024.0f); const float RAM_Total_all_f = (RAM_Total_application_u + RAM_Total_applet_u + RAM_Total_system_u + RAM_Total_systemunsafe_u) / (1024.0f * 1024.0f * 1024.0f);
const float RAM_Used_all_f = (RAM_Used_application_u + RAM_Used_applet_u + RAM_Used_system_u + RAM_Used_systemunsafe_u) / (1024.0f * 1024.0f * 1024.0f); const float RAM_Used_all_f = (RAM_Used_application_u + RAM_Used_applet_u + RAM_Used_system_u + RAM_Used_systemunsafe_u) / (1024.0f * 1024.0f * 1024.0f);
snprintf(MICRO_RAM_all_c, sizeof(MICRO_RAM_all_c), "%.0f%.0fGB", RAM_Used_all_f, RAM_Total_all_f); snprintf(MICRO_RAM_all_c, sizeof(MICRO_RAM_all_c), "%.0f%.0fGB", RAM_Used_all_f, RAM_Total_all_f);
} else if (settings.ramInfoMode == "Bandwidth" && R_SUCCEEDED(hocclkCheck)) {
// Bandwidth mode: show GB/s from context (partLoad values are in MB/s)
const unsigned bwAll = partLoad[HocClkPartLoad_RamBWAll] / 1000;
const unsigned bwAllD = (partLoad[HocClkPartLoad_RamBWAll] % 1000) / 100;
snprintf(MICRO_RAM_all_c, sizeof(MICRO_RAM_all_c), "%u.%uGB/s", bwAll, bwAllD);
} else { } else {
// User wants percentage display // User wants percentage display
if (R_SUCCEEDED(hocclkCheck)) { if (R_SUCCEEDED(hocclkCheck)) {

View File

@@ -362,8 +362,32 @@ public:
width = renderer->getTextDimensions("100%@4444.4444 mV", false, fontsize).first; width = renderer->getTextDimensions("100%@4444.4444 mV", false, fontsize).first;
} }
if (settings.realTemps) { if (settings.realTemps) {
width += renderer->getTextDimensions(" 888.8°C", false, fontsize).first; width += renderer->getTextDimensions(" 88.8°C ", false, fontsize).first;
} }
} else if (key == "RAM" && settings.ramInfoMode == "Bandwidth" && R_SUCCEEDED(hocclkCheck)) {
width = renderer->getTextDimensions("99.9GB/s@4444.4", false, fontsize).first;
if (settings.realVolts) {
if (isMariko) {
if (settings.showVDD2 && settings.decimalVDD2 && settings.showVDDQ)
width += renderer->getTextDimensions("4444.4444 mV 4444 mV", false, fontsize).first;
else if (settings.showVDD2 && !settings.decimalVDD2 && settings.showVDDQ)
width += renderer->getTextDimensions("4444 mV 4444 mV", false, fontsize).first;
else if (settings.showVDD2 && settings.decimalVDD2)
width += renderer->getTextDimensions("4444.4 mV", false, fontsize).first;
else if (settings.showVDD2 && !settings.decimalVDD2)
width += renderer->getTextDimensions("4444 mV", false, fontsize).first;
else if (settings.showVDDQ)
width += renderer->getTextDimensions("4444 mV", false, fontsize).first;
} else {
if (settings.decimalVDD2)
width += renderer->getTextDimensions("4444.44 mV", false, fontsize).first;
else
width += renderer->getTextDimensions("4444 mV", false, fontsize).first;
}
}
if (settings.realTemps) {
width += renderer->getTextDimensions(" 88.8°C ", false, fontsize).first;
}
} else if (key == "GPU" || (key == "RAM" && settings.showpartLoad && R_SUCCEEDED(hocclkCheck))) { } else if (key == "GPU" || (key == "RAM" && settings.showpartLoad && R_SUCCEEDED(hocclkCheck))) {
//dimensions = renderer->drawString("100.0%@4444.4", false, 0, 0, fontsize, renderer->a(0x0000)); //dimensions = renderer->drawString("100.0%@4444.4", false, 0, 0, fontsize, renderer->a(0x0000));
@@ -380,15 +404,15 @@ public:
width = renderer->getTextDimensions("100%[100%,100%]@4444.4444 mV", false, fontsize).first; width = renderer->getTextDimensions("100%[100%,100%]@4444.4444 mV", false, fontsize).first;
} }
} }
if (key == "GPU" && settings.realTemps) { if (settings.realTemps) {
width += renderer->getTextDimensions(" 88.8°C", false, fontsize).first; width += renderer->getTextDimensions(" 88.8°C ", false, fontsize).first;
} }
} else if (key == "RAM" && (!settings.showpartLoad || R_FAILED(hocclkCheck))) { } else if (key == "RAM" && (!settings.showpartLoad || R_FAILED(hocclkCheck))) {
//dimensions = renderer->drawString("44444444MB@4444.4", false, 0, 0, fontsize, renderer->a(0x0000)); //dimensions = renderer->drawString("44444444MB@4444.4", false, 0, 0, fontsize, renderer->a(0x0000));
if (!settings.realVolts) { if (!settings.realVolts) {
width = renderer->getTextDimensions("100%@4444.4", false, fontsize).first; width = renderer->getTextDimensions("100%@4444.4", false, fontsize).first;
if (settings.realTemps) { if (settings.realTemps) {
width += renderer->getTextDimensions(" 88.8°C", false, fontsize).first; width += renderer->getTextDimensions(" 88.8°C ", false, fontsize).first;
} }
} else { } else {
if (isMariko) { if (isMariko) {
@@ -1142,53 +1166,64 @@ public:
RAM_Hz / 1000000, (RAM_Hz / 100000) % 10); RAM_Hz / 1000000, (RAM_Hz / 100000) % 10);
} }
} else { } else {
unsigned partLoadInt; if (settings.ramInfoMode == "Bandwidth" && R_SUCCEEDED(hocclkCheck)) {
// Bandwidth mode: show GB/s from context (partLoad values are in MB/s)
if (R_SUCCEEDED(hocclkCheck)) { const uint32_t ramFreq = settings.realFrequencies && realRAM_Hz ? realRAM_Hz : RAM_Hz;
partLoadInt = partLoad[HocClkPartLoad_EMC] / 10; const unsigned bwAll = partLoad[HocClkPartLoad_RamBWAll] / 1000;
const unsigned bwAllD = (partLoad[HocClkPartLoad_RamBWAll] % 1000) / 100;
if (settings.showpartLoadCPUGPU) { snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c),
unsigned ramCpuLoadInt = partLoad[HocClkPartLoad_EMCCpu] / 10; "%u.%uGB/s@%hu.%hhu",
int RAM_GPU_Load = partLoad[HocClkPartLoad_EMC] - partLoad[HocClkPartLoad_EMCCpu]; bwAll, bwAllD,
unsigned ramGpuLoadInt = RAM_GPU_Load / 10; ramFreq / 1000000, (ramFreq / 100000) % 10);
if (settings.realFrequencies && realRAM_Hz) {
snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c),
"%u%%[%u%%,%u%%]@%hu.%hhu",
partLoadInt, ramCpuLoadInt, ramGpuLoadInt,
realRAM_Hz / 1000000, (realRAM_Hz / 100000) % 10);
} else {
snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c),
"%u%%[%u%%,%u%%]@%hu.%hhu",
partLoadInt, ramCpuLoadInt, ramGpuLoadInt,
RAM_Hz / 1000000, (RAM_Hz / 100000) % 10);
}
} else {
if (settings.realFrequencies && realRAM_Hz) {
snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c),
"%u%%@%hu.%hhu", partLoadInt,
realRAM_Hz / 1000000, (realRAM_Hz / 100000) % 10);
} else {
snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c),
"%u%%@%hu.%hhu", partLoadInt,
RAM_Hz / 1000000, (RAM_Hz / 100000) % 10);
}
}
} else { } else {
const uint64_t RAM_Total_all = RAM_Total_application_u + RAM_Total_applet_u + unsigned partLoadInt;
RAM_Total_system_u + RAM_Total_systemunsafe_u;
const uint64_t RAM_Used_all = RAM_Used_application_u + RAM_Used_applet_u +
RAM_Used_system_u + RAM_Used_systemunsafe_u;
partLoadInt = (RAM_Total_all > 0) ? (unsigned)((RAM_Used_all * 100) / RAM_Total_all) : 0;
if (settings.realFrequencies && realRAM_Hz) { if (R_SUCCEEDED(hocclkCheck)) {
snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c), partLoadInt = partLoad[HocClkPartLoad_EMC] / 10;
"%u%%@%hu.%hhu", partLoadInt,
realRAM_Hz / 1000000, (realRAM_Hz / 100000) % 10); if (settings.showpartLoadCPUGPU) {
unsigned ramCpuLoadInt = partLoad[HocClkPartLoad_EMCCpu] / 10;
int RAM_GPU_Load = partLoad[HocClkPartLoad_EMC] - partLoad[HocClkPartLoad_EMCCpu];
unsigned ramGpuLoadInt = RAM_GPU_Load / 10;
if (settings.realFrequencies && realRAM_Hz) {
snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c),
"%u%%[%u%%,%u%%]@%hu.%hhu",
partLoadInt, ramCpuLoadInt, ramGpuLoadInt,
realRAM_Hz / 1000000, (realRAM_Hz / 100000) % 10);
} else {
snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c),
"%u%%[%u%%,%u%%]@%hu.%hhu",
partLoadInt, ramCpuLoadInt, ramGpuLoadInt,
RAM_Hz / 1000000, (RAM_Hz / 100000) % 10);
}
} else {
if (settings.realFrequencies && realRAM_Hz) {
snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c),
"%u%%@%hu.%hhu", partLoadInt,
realRAM_Hz / 1000000, (realRAM_Hz / 100000) % 10);
} else {
snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c),
"%u%%@%hu.%hhu", partLoadInt,
RAM_Hz / 1000000, (RAM_Hz / 100000) % 10);
}
}
} else { } else {
snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c), const uint64_t RAM_Total_all = RAM_Total_application_u + RAM_Total_applet_u +
"%u%%@%hu.%hhu", partLoadInt, RAM_Total_system_u + RAM_Total_systemunsafe_u;
RAM_Hz / 1000000, (RAM_Hz / 100000) % 10); const uint64_t RAM_Used_all = RAM_Used_application_u + RAM_Used_applet_u +
RAM_Used_system_u + RAM_Used_systemunsafe_u;
partLoadInt = (RAM_Total_all > 0) ? (unsigned)((RAM_Used_all * 100) / RAM_Total_all) : 0;
if (settings.realFrequencies && realRAM_Hz) {
snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c),
"%u%%@%hu.%hhu", partLoadInt,
realRAM_Hz / 1000000, (realRAM_Hz / 100000) % 10);
} else {
snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c),
"%u%%@%hu.%hhu", partLoadInt,
RAM_Hz / 1000000, (RAM_Hz / 100000) % 10);
}
} }
} }
} }

View File

@@ -122,7 +122,7 @@ public:
}); });
// tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release); // tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release);
tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("Status Monitor Pro", APP_VERSION, true); tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("Horizon OC Monitor", APP_VERSION, true);
rootFrame->setContent(Status); rootFrame->setContent(Status);
return rootFrame; return rootFrame;

View File

@@ -0,0 +1,81 @@
ifeq ($(strip $(DEVKITARM)),)
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
endif
include $(DEVKITARM)/base_rules
################################################################################
IPL_LOAD_ADDR := 0x40010000
################################################################################
THIS_MAKEFILE := $(abspath $(lastword $(MAKEFILE_LIST)))
CURRENT_DIRECTORY := $(abspath $(dir $(THIS_MAKEFILE)))
BUILDDIR := build
OUTPUTDIR := out
SOURCEDIR = fatal_handler
BDKDIR := bdk
GFXDIR := fatal_handler/gfx
TARGET := fatal_handler
BDKINC := -I$(BDKDIR)
GFXINC := -I$(GFXDIR)
GFX_INC := '"gfx.h"'
VPATH = $(dir ./$(SOURCEDIR)/) $(dir $(wildcard ./$(SOURCEDIR)/*/)) $(dir $(wildcard ./$(SOURCEDIR)/*/*/))
VPATH += $(dir $(wildcard ./$(BDKDIR)/)) $(dir $(wildcard ./$(BDKDIR)/*/)) $(dir $(wildcard ./$(BDKDIR)/*/*/))
OBJS = $(addprefix $(BUILDDIR)/$(TARGET)/, \
start.o exception_handlers.o irq.o main.o \
timer.o heap.o hw_init.o clock.o i2c.o gpio.o \
max7762x.o di.o util.o fuse.o pinmux.o \
secmon_exo.o gfx.o bpmp.o sdram.o minerva.o btn.o max77620-rtc.o se.o mc.o)
################################################################################
# BDK defines.
CUSTOMDEFINES := -DGFX_INC=$(GFX_INC)
CUSTOMDEFINES += -DBDK_MALLOC_NO_DEFRAG -DBDK_MC_ENABLE_AHB_REDIRECT -DBDK_EMUMMC_ENABLE
CUSTOMDEFINES += -DBDK_WATCHDOG_FIQ_ENABLE -DBDK_RESTART_BL_ON_WDT
INCDIRS := $(BDKINC) $(GFXINC)
WARNINGS := -Wall -Wsign-compare -Wno-array-bounds -Wno-stringop-overflow
ARCH := -march=armv4t -mtune=arm7tdmi -mthumb-interwork
CFLAGS = $(ARCH) -O2 -g -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -std=gnu11 $(WARNINGS) $(CUSTOMDEFINES)
LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections -Xlinker --defsym=IPL_LOAD_ADDR=$(IPL_LOAD_ADDR)
################################################################################
BIN_TARGET := $(OUTPUTDIR)/$(TARGET).bin
BIN_OBJ := $(OUTPUTDIR)/$(TARGET).bin.o
BIN_HEADER := $(OUTPUTDIR)/$(TARGET)_bin.h
BIN_SYM := $(subst .,_,$(subst /,_,$(TARGET)))_bin
define bin2o
$(eval SYM := $(BIN_SYM))
$(eval BIN_SIZE := $(shell wc -c < $(BIN_TARGET)))
@$(OBJCOPY) --input-target binary --output-target elf32-littlearm --binary-architecture arm \
--redefine-sym _binary_$(shell echo $(BIN_TARGET) | tr '/.-' '___')_start=$(SYM) \
--redefine-sym _binary_$(shell echo $(BIN_TARGET) | tr '/.-' '___')_end=$(SYM)_end \
--redefine-sym _binary_$(shell echo $(BIN_TARGET) | tr '/.-' '___')_size=$(SYM)_size \
$(BIN_TARGET) $(BIN_OBJ)
@printf '#pragma once\n#include <stddef.h>\n#include <stdint.h>\nextern const uint8_t $(SYM)[];\nextern const uint8_t $(SYM)_end[];\n#if __cplusplus >= 201103L\nstatic constexpr size_t $(SYM)_size=$(BIN_SIZE);\n#else\nstatic const size_t $(SYM)_size=$(BIN_SIZE);\n#endif\n' > $(BIN_HEADER)
endef
################################################################################
.PHONY: all clean
all: $(BIN_OBJ) $(BIN_HEADER)
$(BIN_OBJ) $(BIN_HEADER): $(BIN_TARGET)
$(bin2o)
$(BIN_TARGET): $(BUILDDIR)/$(TARGET)/$(TARGET).elf
$(OBJCOPY) -S -O binary $< $(BIN_TARGET)
clean:
@rm -rf $(OBJS) $(BIN_OBJ) $(BIN_HEADER)
$(BUILDDIR)/$(TARGET)/$(TARGET).elf: $(OBJS)
@$(CC) $(LDFLAGS) -T $(SOURCEDIR)/link.ld $^ -o $@
$(BUILDDIR)/$(TARGET)/%.o: %.c
@$(CC) $(CFLAGS) $(INCDIRS) -c $< -o $@
$(BUILDDIR)/$(TARGET)/%.o: %.S
@$(CC) $(CFLAGS) -c $< -o $@
$(OBJS): $(BUILDDIR)/$(TARGET)
$(BUILDDIR)/$(TARGET):
@mkdir -p "$(BUILDDIR)"
@mkdir -p "$(BUILDDIR)/$(TARGET)"
@mkdir -p "$(OUTPUTDIR)"

View File

@@ -0,0 +1,558 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2022 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdarg.h>
#include <string.h>
#include "gfx.h"
// Global gfx console and context.
gfx_ctxt_t gfx_ctxt;
gfx_con_t gfx_con;
static bool gfx_con_init_done = false;
static const u8 _gfx_font[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Char 032 ( )
0x00, 0x30, 0x30, 0x18, 0x18, 0x00, 0x0C, 0x00, // Char 033 (!)
0x00, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, // Char 034 (")
0x00, 0x66, 0x66, 0xFF, 0x66, 0xFF, 0x66, 0x66, // Char 035 (#)
0x00, 0x18, 0x7C, 0x06, 0x3C, 0x60, 0x3E, 0x18, // Char 036 ($)
0x00, 0x46, 0x66, 0x30, 0x18, 0x0C, 0x66, 0x62, // Char 037 (%)
0x00, 0x3C, 0x66, 0x3C, 0x1C, 0xE6, 0x66, 0xFC, // Char 038 (&)
0x00, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, // Char 039 (')
0x00, 0x30, 0x18, 0x0C, 0x0C, 0x18, 0x30, 0x00, // Char 040 (()
0x00, 0x0C, 0x18, 0x30, 0x30, 0x18, 0x0C, 0x00, // Char 041 ())
0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, // Char 042 (*)
0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, // Char 043 (+)
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0C, 0x00, // Char 044 (,)
0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, // Char 045 (-)
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, // Char 046 (.)
0x00, 0x40, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, // Char 047 (/)
0x00, 0x3C, 0x66, 0x76, 0x6E, 0x66, 0x3C, 0x00, // Char 048 (0)
0x00, 0x18, 0x1C, 0x18, 0x18, 0x18, 0x7E, 0x00, // Char 049 (1)
0x00, 0x3C, 0x62, 0x30, 0x0C, 0x06, 0x7E, 0x00, // Char 050 (2)
0x00, 0x3C, 0x62, 0x38, 0x60, 0x66, 0x3C, 0x00, // Char 051 (3)
0x00, 0x6C, 0x6C, 0x66, 0xFE, 0x60, 0x60, 0x00, // Char 052 (4)
0x00, 0x7E, 0x06, 0x7E, 0x60, 0x66, 0x3C, 0x00, // Char 053 (5)
0x00, 0x3C, 0x06, 0x3E, 0x66, 0x66, 0x3C, 0x00, // Char 054 (6)
0x00, 0x7E, 0x30, 0x30, 0x18, 0x18, 0x18, 0x00, // Char 055 (7)
0x00, 0x3C, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0x00, // Char 056 (8)
0x00, 0x3C, 0x66, 0x7C, 0x60, 0x66, 0x3C, 0x00, // Char 057 (9)
0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, // Char 058 (:)
0x00, 0x00, 0x18, 0x00, 0x18, 0x18, 0x0C, 0x00, // Char 059 (;)
0x00, 0x70, 0x1C, 0x06, 0x06, 0x1C, 0x70, 0x00, // Char 060 (<)
0x00, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x00, 0x00, // Char 061 (=)
0x00, 0x0E, 0x38, 0x60, 0x60, 0x38, 0x0E, 0x00, // Char 062 (>)
0x00, 0x3C, 0x66, 0x30, 0x18, 0x00, 0x18, 0x00, // Char 063 (?)
0x00, 0x3C, 0x66, 0x76, 0x76, 0x06, 0x46, 0x3C, // Char 064 (@)
0x00, 0x3C, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, // Char 065 (A)
0x00, 0x3E, 0x66, 0x3E, 0x66, 0x66, 0x3E, 0x00, // Char 066 (B)
0x00, 0x3C, 0x66, 0x06, 0x06, 0x66, 0x3C, 0x00, // Char 067 (C)
0x00, 0x1E, 0x36, 0x66, 0x66, 0x36, 0x1E, 0x00, // Char 068 (D)
0x00, 0x7E, 0x06, 0x1E, 0x06, 0x06, 0x7E, 0x00, // Char 069 (E)
0x00, 0x3E, 0x06, 0x1E, 0x06, 0x06, 0x06, 0x00, // Char 070 (F)
0x00, 0x3C, 0x66, 0x06, 0x76, 0x66, 0x3C, 0x00, // Char 071 (G)
0x00, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, // Char 072 (H)
0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, // Char 073 (I)
0x00, 0x78, 0x30, 0x30, 0x30, 0x36, 0x1C, 0x00, // Char 074 (J)
0x00, 0x66, 0x36, 0x1E, 0x1E, 0x36, 0x66, 0x00, // Char 075 (K)
0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x7E, 0x00, // Char 076 (L)
0x00, 0x46, 0x6E, 0x7E, 0x56, 0x46, 0x46, 0x00, // Char 077 (M)
0x00, 0x66, 0x6E, 0x7E, 0x76, 0x66, 0x66, 0x00, // Char 078 (N)
0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, // Char 079 (O)
0x00, 0x3E, 0x66, 0x3E, 0x06, 0x06, 0x06, 0x00, // Char 080 (P)
0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x70, 0x00, // Char 081 (Q)
0x00, 0x3E, 0x66, 0x3E, 0x1E, 0x36, 0x66, 0x00, // Char 082 (R)
0x00, 0x3C, 0x66, 0x0C, 0x30, 0x66, 0x3C, 0x00, // Char 083 (S)
0x00, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, // Char 084 (T)
0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, // Char 085 (U)
0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, // Char 086 (V)
0x00, 0x46, 0x46, 0x56, 0x7E, 0x6E, 0x46, 0x00, // Char 087 (W)
0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x66, 0x00, // Char 088 (X)
0x00, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x00, // Char 089 (Y)
0x00, 0x7E, 0x30, 0x18, 0x0C, 0x06, 0x7E, 0x00, // Char 090 (Z)
0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, // Char 091 ([)
0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00, // Char 092 (\)
0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, // Char 093 (])
0x00, 0x18, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, // Char 094 (^)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, // Char 095 (_)
0x00, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, // Char 096 (`)
0x00, 0x00, 0x3C, 0x60, 0x7C, 0x66, 0x7C, 0x00, // Char 097 (a)
0x00, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3E, 0x00, // Char 098 (b)
0x00, 0x00, 0x3C, 0x06, 0x06, 0x06, 0x3C, 0x00, // Char 099 (c)
0x00, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00, // Char 100 (d)
0x00, 0x00, 0x3C, 0x66, 0x7E, 0x06, 0x3C, 0x00, // Char 101 (e)
0x00, 0x38, 0x0C, 0x3E, 0x0C, 0x0C, 0x0C, 0x00, // Char 102 (f)
0x00, 0x00, 0x7C, 0x66, 0x7C, 0x40, 0x3C, 0x00, // Char 103 (g)
0x00, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x00, // Char 104 (h)
0x00, 0x18, 0x00, 0x1C, 0x18, 0x18, 0x3C, 0x00, // Char 105 (i)
0x00, 0x30, 0x00, 0x30, 0x30, 0x30, 0x1E, 0x00, // Char 106 (j)
0x00, 0x06, 0x06, 0x36, 0x1E, 0x36, 0x66, 0x00, // Char 107 (k)
0x00, 0x1C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, // Char 108 (l)
0x00, 0x00, 0x66, 0xFE, 0xFE, 0xD6, 0xC6, 0x00, // Char 109 (m)
0x00, 0x00, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x00, // Char 110 (n)
0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00, // Char 111 (o)
0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x00, // Char 112 (p)
0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x00, // Char 113 (q)
0x00, 0x00, 0x3E, 0x66, 0x06, 0x06, 0x06, 0x00, // Char 114 (r)
0x00, 0x00, 0x7C, 0x06, 0x3C, 0x60, 0x3E, 0x00, // Char 115 (s)
0x00, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x70, 0x00, // Char 116 (t)
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x00, // Char 117 (u)
0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, // Char 118 (v)
0x00, 0x00, 0xC6, 0xD6, 0xFE, 0x7C, 0x6C, 0x00, // Char 119 (w)
0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x00, // Char 120 (x)
0x00, 0x00, 0x66, 0x66, 0x7C, 0x60, 0x3C, 0x00, // Char 121 (y)
0x00, 0x00, 0x7E, 0x30, 0x18, 0x0C, 0x7E, 0x00, // Char 122 (z)
0x00, 0x18, 0x08, 0x08, 0x04, 0x08, 0x08, 0x18, // Char 123 ({)
0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, // Char 124 (|)
0x00, 0x0C, 0x08, 0x08, 0x10, 0x08, 0x08, 0x0C, // Char 125 (})
0x00, 0x00, 0x00, 0x4C, 0x32, 0x00, 0x00, 0x00 // Char 126 (~)
};
void gfx_clear_grey(u8 color)
{
memset(gfx_ctxt.fb, color, gfx_ctxt.width * gfx_ctxt.height * 4);
}
void gfx_clear_partial_grey(u8 color, u32 pos_x, u32 height)
{
memset(gfx_ctxt.fb + pos_x * gfx_ctxt.stride, color, height * 4 * gfx_ctxt.stride);
}
void gfx_clear_color(u32 color)
{
for (u32 i = 0; i < gfx_ctxt.width * gfx_ctxt.height; i++)
gfx_ctxt.fb[i] = color;
}
void gfx_init_ctxt(u32 *fb, u32 width, u32 height, u32 stride)
{
gfx_ctxt.fb = fb;
gfx_ctxt.width = width;
gfx_ctxt.height = height;
gfx_ctxt.stride = stride;
}
void gfx_con_init()
{
gfx_con.gfx_ctxt = &gfx_ctxt;
gfx_con.fntsz = 16;
gfx_con.x = 0;
gfx_con.y = 0;
gfx_con.savedx = 0;
gfx_con.savedy = 0;
gfx_con.fgcol = TXT_CLR_DEFAULT;
gfx_con.fillbg = 1;
gfx_con.bgcol = TXT_CLR_BG;
gfx_con.mute = 0;
gfx_con_init_done = true;
}
void gfx_con_setcol(u32 fgcol, int fillbg, u32 bgcol)
{
gfx_con.fgcol = fgcol;
gfx_con.fillbg = fillbg;
gfx_con.bgcol = bgcol;
}
void gfx_con_getpos(u32 *x, u32 *y)
{
*x = gfx_con.x;
*y = gfx_con.y;
}
void gfx_con_setpos(u32 x, u32 y)
{
gfx_con.x = x;
gfx_con.y = y;
}
void gfx_putc(char c)
{
// Duplicate code for performance reasons.
switch (gfx_con.fntsz)
{
case 16:
if (c >= 32 && c <= 126)
{
u8 *cbuf = (u8 *)&_gfx_font[8 * (c - 32)];
u32 *fb = gfx_ctxt.fb + gfx_con.x + gfx_con.y * gfx_ctxt.stride;
for (u32 i = 0; i < 16; i += 2)
{
u8 v = *cbuf;
for (u32 k = 0; k < 2; k++)
{
for (u32 j = 0; j < 8; j++)
{
if (v & 1)
{
*fb = gfx_con.fgcol;
fb++;
*fb = gfx_con.fgcol;
}
else if (gfx_con.fillbg)
{
*fb = gfx_con.bgcol;
fb++;
*fb = gfx_con.bgcol;
}
else
fb++;
v >>= 1;
fb++;
}
fb += gfx_ctxt.stride - 16;
v = *cbuf;
}
cbuf++;
}
gfx_con.x += 16;
}
else if (c == '\n')
{
gfx_con.x = 0;
gfx_con.y += 16;
if (gfx_con.y > gfx_ctxt.height - 16)
gfx_con.y = 0;
}
break;
case 8:
default:
if (c >= 32 && c <= 126)
{
u8 *cbuf = (u8 *)&_gfx_font[8 * (c - 32)];
u32 *fb = gfx_ctxt.fb + gfx_con.x + gfx_con.y * gfx_ctxt.stride;
for (u32 i = 0; i < 8; i++)
{
u8 v = *cbuf++;
for (u32 j = 0; j < 8; j++)
{
if (v & 1)
*fb = gfx_con.fgcol;
else if (gfx_con.fillbg)
*fb = gfx_con.bgcol;
v >>= 1;
fb++;
}
fb += gfx_ctxt.stride - 8;
}
gfx_con.x += 8;
}
else if (c == '\n')
{
gfx_con.x = 0;
gfx_con.y += 8;
if (gfx_con.y > gfx_ctxt.height - 8)
gfx_con.y = 0;
}
break;
}
}
void gfx_puts(const char *s)
{
if (!s || !gfx_con_init_done || gfx_con.mute)
return;
for (; *s; s++)
gfx_putc(*s);
}
static void _gfx_putn(u32 v, int base, char fill, int fcnt)
{
static const char digits[] = "0123456789ABCDEF";
char *p;
char buf[65];
int c = fcnt;
bool negative = false;
if (base != 10 && base != 16)
return;
// Account for negative numbers.
if (base == 10 && v & 0x80000000)
{
negative = true;
v = (int)v * -1;
c--;
}
p = buf + 64;
*p = 0;
do
{
c--;
*--p = digits[v % base];
v /= base;
} while (v);
if (negative)
*--p = '-';
if (fill != 0)
{
while (c > 0 && p > buf)
{
*--p = fill;
c--;
}
}
gfx_puts(p);
}
void gfx_put_small_sep()
{
u8 prevFontSize = gfx_con.fntsz;
gfx_con.fntsz = 8;
gfx_putc('\n');
gfx_con.fntsz = prevFontSize;
}
void gfx_put_big_sep()
{
u8 prevFontSize = gfx_con.fntsz;
gfx_con.fntsz = 16;
gfx_putc('\n');
gfx_con.fntsz = prevFontSize;
}
void gfx_printf(const char *fmt, ...)
{
if (!gfx_con_init_done || gfx_con.mute)
return;
va_list ap;
int fill, fcnt;
va_start(ap, fmt);
while (*fmt)
{
if (*fmt == '%')
{
fmt++;
fill = 0;
fcnt = 0;
if ((*fmt >= '0' && *fmt <= '9') || *fmt == ' ')
{
fcnt = *fmt;
fmt++;
if (*fmt >= '0' && *fmt <= '9')
{
fill = fcnt;
fcnt = *fmt - '0';
fmt++;
}
else
{
fill = ' ';
fcnt -= '0';
}
}
switch(*fmt)
{
case 'c':
gfx_putc(va_arg(ap, u32));
break;
case 's':
gfx_puts(va_arg(ap, char *));
break;
case 'd':
_gfx_putn(va_arg(ap, u32), 10, fill, fcnt);
break;
case 'p':
case 'P':
case 'x':
case 'X':
_gfx_putn(va_arg(ap, u32), 16, fill, fcnt);
break;
case 'k':
gfx_con.fgcol = va_arg(ap, u32);
break;
case 'K':
gfx_con.bgcol = va_arg(ap, u32);
gfx_con.fillbg = 1;
break;
case '%':
gfx_putc('%');
break;
case '\0':
goto out;
default:
gfx_putc('%');
gfx_putc(*fmt);
break;
}
}
else
gfx_putc(*fmt);
fmt++;
}
out:
va_end(ap);
}
static void _gfx_cputs(u32 color, const char *s)
{
gfx_con.fgcol = color;
gfx_puts(s);
gfx_putc('\n');
gfx_con.fgcol = TXT_CLR_DEFAULT;
}
void gfx_wputs(const char *s) { _gfx_cputs(TXT_CLR_WARNING, s); }
void gfx_eputs(const char *s) { _gfx_cputs(TXT_CLR_ERROR, s); }
void gfx_hexdump(u32 base, const void *buf, u32 len)
{
if (!gfx_con_init_done || gfx_con.mute)
return;
u8 *buff = (u8 *)buf;
u8 prevFontSize = gfx_con.fntsz;
gfx_con.fntsz = 8;
for (u32 i = 0; i < len; i++)
{
if (i % 0x10 == 0)
{
if (i != 0)
{
gfx_puts("| ");
for (u32 j = 0; j < 0x10; j++)
{
u8 c = buff[i - 0x10 + j];
if (c >= 32 && c <= 126)
gfx_putc(c);
else
gfx_putc('.');
}
gfx_putc('\n');
}
gfx_printf("%08x: ", base + i);
}
gfx_printf("%02x ", buff[i]);
if (i == len - 1)
{
int ln = len % 0x10 != 0;
u32 k = 0x10 - 1;
if (ln)
{
k = (len & 0xF) - 1;
for (u32 j = 0; j < 0x10 - k; j++)
gfx_puts(" ");
}
gfx_puts("| ");
for (u32 j = 0; j < (ln ? k : k + 1); j++)
{
u8 c = buff[i - k + j];
if (c >= 32 && c <= 126)
gfx_putc(c);
else
gfx_putc('.');
}
gfx_putc('\n');
}
}
gfx_putc('\n');
gfx_con.fntsz = prevFontSize;
}
static int abs(int x)
{
if (x < 0)
return -x;
return x;
}
void gfx_set_pixel(u32 x, u32 y, u32 color)
{
gfx_ctxt.fb[x + y * gfx_ctxt.stride] = color;
}
void gfx_line(int x0, int y0, int x1, int y1, u32 color)
{
int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
int dy = abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
int err = (dx > dy ? dx : -dy) / 2, e2;
while (1)
{
gfx_set_pixel(x0, y0, color);
if (x0 == x1 && y0 == y1)
break;
e2 = err;
if (e2 >-dx)
{
err -= dy;
x0 += sx;
}
if (e2 < dy)
{
err += dx;
y0 += sy;
}
}
}
void gfx_set_rect_grey(const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
{
u32 pos = 0;
for (u32 y = pos_y; y < (pos_y + size_y); y++)
{
for (u32 x = pos_x; x < (pos_x + size_x); x++)
{
memset(&gfx_ctxt.fb[x + y*gfx_ctxt.stride], buf[pos], 4);
pos++;
}
}
}
void gfx_set_rect_rgb(const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
{
u32 pos = 0;
for (u32 y = pos_y; y < (pos_y + size_y); y++)
{
for (u32 x = pos_x; x < (pos_x + size_x); x++)
{
gfx_ctxt.fb[x + y * gfx_ctxt.stride] = buf[pos + 2] | (buf[pos + 1] << 8) | (buf[pos] << 16);
pos+=3;
}
}
}
void gfx_set_rect_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
{
u32 *ptr = (u32 *)buf;
for (u32 y = pos_y; y < (pos_y + size_y); y++)
for (u32 x = pos_x; x < (pos_x + size_x); x++)
gfx_ctxt.fb[x + y * gfx_ctxt.stride] = *ptr++;
}
void gfx_render_bmp_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y)
{
for (u32 y = pos_y; y < (pos_y + size_y); y++)
{
for (u32 x = pos_x; x < (pos_x + size_x); x++)
gfx_ctxt.fb[x + y * gfx_ctxt.stride] = buf[(size_y + pos_y - 1 - y ) * size_x + x - pos_x];
}
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright (c) 2018 naehrwert
* Copyright (c) 2018-2021 CTCaer
* Copyright (c) 2018 M4xw
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _GFX_H_
#define _GFX_H_
#include <bdk.h>
#define TXT_CLR_BG 0xFF1B1B1B // Dark Grey.
#define TXT_CLR_DEFAULT 0xFFCCCCCC // Light Grey.
#define TXT_CLR_WARNING 0xFFFFDD00 // Yellow.
#define TXT_CLR_ERROR 0xFFFF0000 // Red.
#define TXT_CLR_CYAN_L 0xFF00CCFF // Light Cyan.
#define TXT_CLR_TURQUOISE 0xFF00FFCC // Turquoise.
#define TXT_CLR_ORANGE 0xFFFFBA00 // Orange.
#define TXT_CLR_GREENISH 0xFF96FF00 // Toxic Green.
#define TXT_CLR_GREEN_D 0xFF008800 // Dark Green.
#define TXT_CLR_RED_D 0xFF880000 // Dark Red.
#define TXT_CLR_GREY_D 0xFF303030 // Darkest Grey.
#define TXT_CLR_GREY_DM 0xFF444444 // Darker Grey.
#define TXT_CLR_GREY_M 0xFF555555 // Dark Grey.
#define TXT_CLR_GREY 0xFF888888 // Grey.
#define EPRINTF(text) gfx_eputs(text)
#define EPRINTFARGS(text, args...) gfx_printf("%k"text"%k\n", TXT_CLR_ERROR, args, TXT_CLR_DEFAULT)
#define WPRINTF(text) gfx_wputs(text)
#define WPRINTFARGS(text, args...) gfx_printf("%k"text"%k\n", TXT_CLR_WARNING, args, TXT_CLR_DEFAULT)
typedef struct _gfx_ctxt_t
{
u32 *fb;
u32 width;
u32 height;
u32 stride;
} gfx_ctxt_t;
typedef struct _gfx_con_t
{
gfx_ctxt_t *gfx_ctxt;
u32 fntsz;
u32 x;
u32 y;
u32 savedx;
u32 savedy;
u32 fgcol;
int fillbg;
u32 bgcol;
bool mute;
} gfx_con_t;
// Global gfx console and context.
extern gfx_ctxt_t gfx_ctxt;
extern gfx_con_t gfx_con;
void gfx_init_ctxt(u32 *fb, u32 width, u32 height, u32 stride);
void gfx_clear_grey(u8 color);
void gfx_clear_partial_grey(u8 color, u32 pos_x, u32 height);
void gfx_clear_color(u32 color);
void gfx_con_init();
void gfx_con_setcol(u32 fgcol, int fillbg, u32 bgcol);
void gfx_con_getpos(u32 *x, u32 *y);
void gfx_con_setpos(u32 x, u32 y);
void gfx_putc(char c);
void gfx_puts(const char *s);
void gfx_wputs(const char *s);
void gfx_eputs(const char *s);
void gfx_printf(const char *fmt, ...) /* __attribute__((format(printf, 1, 2))) */;
void gfx_hexdump(u32 base, const void *buf, u32 len);
void gfx_set_pixel(u32 x, u32 y, u32 color);
void gfx_line(int x0, int y0, int x1, int y1, u32 color);
void gfx_put_small_sep();
void gfx_put_big_sep();
void gfx_set_rect_grey(const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
void gfx_set_rect_rgb(const u8 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
void gfx_set_rect_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
void gfx_render_bmp_argb(const u32 *buf, u32 size_x, u32 size_y, u32 pos_x, u32 pos_y);
#endif

View File

@@ -0,0 +1,114 @@
/*
* Copyright (c) 2018-2024 CTCaer
* Copyright (c) 2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <bdk.h>
#include "secmon_exo.h"
// Atmosphère reboot-to-fatal-error.
typedef struct _atm_fatal_error_ctx
{
u32 magic;
u32 error_desc;
u64 title_id;
union
{
u64 gprs[32];
struct
{
u64 _gprs[29];
u64 fp;
u64 lr;
u64 sp;
};
};
u64 pc;
u64 module_base;
u32 pstate;
u32 afsr0;
u32 afsr1;
u32 esr;
u64 far;
u64 report_identifier; // Normally just system tick.
u64 stack_trace_size;
u64 stack_dump_size;
u64 stack_trace[0x20];
u8 stack_dump[0x100];
u8 tls[0x100];
} atm_fatal_error_ctx;
#define ATM_FATAL_ERR_CTX_ADDR 0x4003E000
#define ATM_FATAL_MAGIC 0x30454641 // AFE0
#define HOS_PID_BOOT2 0x8
static const char *get_error_desc(u32 error_desc)
{
switch (error_desc)
{
case 0x100:
return "IABRT"; // Instruction Abort.
case 0x101:
return "DABRT"; // Data Abort.
case 0x102:
return "IUA"; // Instruction Unaligned Access.
case 0x103:
return "DUA"; // Data Unaligned Access.
case 0x104:
return "UDF"; // Undefined Instruction.
case 0x106:
return "SYS"; // System Error.
case 0x301:
return "SVC"; // Bad arguments or unimplemented SVC.
case 0xF00:
return "KRNL"; // Kernel panic.
case 0xFFD:
return "SO"; // Stack Overflow.
case 0xFFE:
return "std::abort";
default:
return "UNK";
}
}
void secmon_exo_check_panic()
{
volatile atm_fatal_error_ctx *rpt = (atm_fatal_error_ctx *)ATM_FATAL_ERR_CTX_ADDR;
// Mask magic to maintain compatibility with any AFE version, thanks to additive struct members.
if ((rpt->magic & 0xF0FFFFFF) != ATM_FATAL_MAGIC)
return;
gfx_clear_grey(0x1B);
gfx_con_setpos(0, 0);
WPRINTF("Panic occurred while running Atmosphere.\n\n");
WPRINTFARGS("Title ID: %08X%08X", (u32)((u64)rpt->title_id >> 32), (u32)rpt->title_id);
WPRINTFARGS("Error: %s (0x%x)\n", get_error_desc(rpt->error_desc), rpt->error_desc);
// Check if mixed atmosphere sysmodules.
if ((u32)rpt->title_id == HOS_PID_BOOT2)
WPRINTF("Mismatched Atmosphere files?\n");
// Change magic to invalid, to prevent double-display of error/bootlooping.
rpt->magic = 0;
display_backlight_brightness(100, 1000);
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright (c) 2018-2021 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SECMON_EXO_H_
#define _SECMON_EXO_H_
#include <bdk.h>
void secmon_exo_check_panic();
#endif

View File

@@ -0,0 +1,25 @@
ENTRY(_start)
SECTIONS {
PROVIDE(__ipl_start = IPL_LOAD_ADDR);
. = __ipl_start;
.text : {
*(.text._start);
KEEP(*(._boot_cfg));
KEEP(*(._ipl_version));
*(.text._irq_setup);
*(.text*);
}
.data : {
*(.data*);
*(.rodata*);
}
. = ALIGN(0x10);
__ipl_end = .;
.bss : {
__bss_start = .;
*(COMMON)
*(.bss*)
__bss_end = .;
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (c) 2018 naehrwert
*
* Copyright (c) 2018-2024 CTCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <bdk.h>
#include "hos/secmon_exo.h"
typedef struct _log_ctx
{
u32 magic;
u32 sz;
u32 start;
u32 end;
char buf[];
} log_ctx_t;
#define IRAM_LOG_CTX_ADDR 0x4003C000
static void check_log(){
volatile log_ctx_t *log_ctx = (log_ctx_t*)IRAM_LOG_CTX_ADDR;
if(log_ctx->magic == 0xaabbccdd){
gfx_printf("\nLogs:\n");
gfx_printf((char*)log_ctx->buf);
}
}
volatile nyx_storage_t *nyx_str = (nyx_storage_t *)NYX_STORAGE_ADDR;
extern void pivot_stack(u32 stack_top);
void ipl_main()
{
// Do initial HW configuration. This is compatible with consecutive reruns without a reset.
hw_init();
// Pivot the stack under IPL. (Only max 4KB is needed).
pivot_stack(IPL_LOAD_ADDR);
// Place heap at a place outside of L4T/HOS configuration and binaries.
heap_init((void *)IPL_HEAP_START);
// Prep RTC regs for read. Needed for T210B01 R2C.
max77620_rtc_prep_read();
// Initialize display.
display_init();
u32 *fb = display_init_window_a_pitch();
gfx_init_ctxt(fb, 720, 1280, 720);
gfx_con_init();
// Initialize backlight PWM.
display_backlight_pwm_init();
display_backlight_brightness(100, 0);
// Show AMS errors
secmon_exo_check_panic();
check_log();
gfx_printf("\n\nPress POWER to power off\nPress VOLUME to boot RCM\n");
msleep(250);
do{
u8 btn = btn_read();
if(btn & BTN_POWER){
power_set_state(POWER_OFF);
}
if(btn & (BTN_VOL_DOWN | BTN_VOL_UP)){
power_set_state(REBOOT_RCM);
}
}while(true);
// Halt BPMP if we managed to get out of execution.
while (true)
bpmp_halt();
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2018 naehrwert
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
.section .text._start
.arm
.extern _reloc_ipl
.type _reloc_ipl, %function
.extern memset
.type memset, %function
.extern _irq_setup
.type _irq_setup, %function
.globl _start
.type _start, %function
_start:
ADR R0, _start
LDR R1, =__ipl_start
CMP R0, R1
BEQ _real_start
/* If we are not in the right location already, copy a relocator to upper IRAM. */
ADR R2, _reloc_ipl
LDR R3, =0x4003FF00
MOV R4, #(_real_start - _reloc_ipl)
_copy_loop:
LDMIA R2!, {R5}
STMIA R3!, {R5}
SUBS R4, #4
BNE _copy_loop
/* Use the relocator to copy ourselves into the right place. */
LDR R2, =__ipl_end
SUB R2, R2, R1
LDR R3, =_real_start
LDR R4, =0x4003FF00
BX R4
_reloc_ipl:
LDMIA R0!, {R4-R7}
STMIA R1!, {R4-R7}
SUBS R2, #0x10
BNE _reloc_ipl
/* Jump to the relocated entry. */
BX R3
_real_start:
/* Initially, we place our stack under relocator but will move it to under the payload. */
/* This depends on application scope. */
LDR SP, =0x4003FF00
LDR R0, =__bss_start
EOR R1, R1, R1
LDR R2, =__bss_end
SUB R2, R2, R0
BL memset
BL _irq_setup
B .
.globl pivot_stack
.type pivot_stack, %function
pivot_stack:
MOV SP, R0
BX LR

View File

@@ -1,6 +1,5 @@
# hoc-clk # hoc-clk
Switch sysmodule allowing you to set cpu/gpu/mem clocks according to the running application and docked state. Overclocking suite for Nintendo Switch.
Modified for Horizon OC
Support is only provided for FW 16.0.0+. This MAY work on older firmwares but support is NOT guaranteed Support is only provided for FW 17.0.0+. This MAY work on older firmwares but support is NOT guaranteed

Binary file not shown.

23
Source/hoc-clk/build.sh Normal file → Executable file
View File

@@ -9,11 +9,9 @@ if [[ -n "$1" ]]; then
DIST_DIR="$1" DIST_DIR="$1"
fi fi
echo "DIST_DIR: $DIST_DIR" echo
echo "CORES: $CORES" echo "*** Compiling hoc-clk ***"
TITLE_ID="$(sed -n 's/.*"title_id"[[:space:]]*:[[:space:]]*"0x\([^"]*\)".*/\1/p' "$ROOT_DIR/sysmodule/perms.json")"
echo "*** sysmodule ***"
TITLE_ID="$(grep -oP '"title_id":\s*"0x\K(\w+)' "$ROOT_DIR/sysmodule/perms.json")"
pushd "$ROOT_DIR/sysmodule" pushd "$ROOT_DIR/sysmodule"
make -j$CORES make -j$CORES
@@ -24,18 +22,23 @@ cp -vf "$ROOT_DIR/sysmodule/out/hoc-clk.nsp" "$DIST_DIR/atmosphere/contents/$TIT
>"$DIST_DIR/atmosphere/contents/$TITLE_ID/flags/boot2.flag" >"$DIST_DIR/atmosphere/contents/$TITLE_ID/flags/boot2.flag"
cp -vf "$ROOT_DIR/sysmodule/toolbox.json" "$DIST_DIR/atmosphere/contents/$TITLE_ID/toolbox.json" cp -vf "$ROOT_DIR/sysmodule/toolbox.json" "$DIST_DIR/atmosphere/contents/$TITLE_ID/toolbox.json"
echo "*** overlay ***" echo
echo "*** Compiling hoc-clk-overlay ***"
pushd "$ROOT_DIR/overlay" pushd "$ROOT_DIR/overlay"
make -j$CORES make -j$CORES
popd > /dev/null popd > /dev/null
mkdir -p "$DIST_DIR/switch/.overlays" mkdir -p "$DIST_DIR/switch/.overlays"
cp -vf "$ROOT_DIR/overlay/out/horizon-oc-overlay.ovl" "$DIST_DIR/switch/.overlays/horizon-oc-overlay.ovl" cp -vf "$ROOT_DIR/overlay/out/horizon-oc-overlay.ovl" "$DIST_DIR/switch/.overlays/horizon-oc-overlay.ovl"
echo
echo "*** assets ***" echo "*** Copying assets ***"
mkdir -p "$DIST_DIR/config/horizon-oc" mkdir -p "$DIST_DIR/config/horizon-oc"
cp -vf "$ROOT_DIR/config.ini.template" "$DIST_DIR/config/horizon-oc/config.ini.template" cp -vf "$ROOT_DIR/config.ini.template" "$DIST_DIR/config/horizon-oc/config.ini.template"
cp -vf "$ROOT_DIR/../../README.md" "$DIST_DIR/README.md" mkdir -p "$DIST_DIR/config/ultrahand/assets/notifications"
cp -vf "$ROOT_DIR/assets/hoc.rgba" "$DIST_DIR/config/ultrahand/assets/notifications/hoc.rgba"
echo "*** lang ***" echo
cp -r "$ROOT_DIR/overlay/lang/" "$DIST_DIR/config/horizon-oc/lang/" echo "*** Copying lang ***"
cp -vr "$ROOT_DIR/overlay/lang/" "$DIST_DIR/config/horizon-oc/lang/"
echo

View File

@@ -48,7 +48,7 @@ extern "C" {
#include "hocclk/apm.h" #include "hocclk/apm.h"
#include "hocclk/config.h" #include "hocclk/config.h"
#include "hocclk/errors.h" #include "hocclk/errors.h"
#include "hocclk/psm_ext.h" #include "hocclk/result.hpp"
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -33,40 +33,39 @@
#include <switch/types.h> #include <switch/types.h>
typedef enum typedef enum
{ {
HocClkSocType_Erista = 0, HocClkSocType_Erista = 0, // T210, found in Icosa and Copper
HocClkSocType_Mariko, HocClkSocType_Mariko, // T214/T210B01, found in Hoag, Iowa, Calcio and Aula
// HocClkSocType_Drake, // T239, found in Switch 2. Maybe someday...
HocClkSocType_EnumMax HocClkSocType_EnumMax
} HocClkSocType; } HocClkSocType;
typedef enum typedef enum
{ {
HocClkConsoleType_Icosa = 0, HocClkConsoleType_Icosa = 0, // V1
HocClkConsoleType_Copper, HocClkConsoleType_Iowa, // V2
HocClkConsoleType_Hoag, HocClkConsoleType_Hoag, // Lite
HocClkConsoleType_Iowa, HocClkConsoleType_Aula, // OLED
HocClkConsoleType_Calcio,
HocClkConsoleType_Aula,
HocClkConsoleType_EnumMax, HocClkConsoleType_EnumMax,
} HocClkConsoleType; } HocClkConsoleType;
typedef enum { typedef enum {
HocClkVoltage_SOC = 0, HocClkVoltage_SOC = 0, // VDD_SOC rail.
HocClkVoltage_EMCVDD2, HocClkVoltage_EMCVDD2, // DRAM VDD2 rail
HocClkVoltage_CPU, HocClkVoltage_CPU, // CPU rail
HocClkVoltage_GPU, HocClkVoltage_GPU, // GPU rail
HocClkVoltage_EMCVDDQ, HocClkVoltage_EMCVDDQ, // DRAM VDDQ rail
HocClkVoltage_Display, HocClkVoltage_Display, // Display rail
HocClkVoltage_Battery, HocClkVoltage_Battery, // Battery voltage
HocClkVoltage_EnumMax, HocClkVoltage_EnumMax,
} HocClkVoltage; } HocClkVoltage;
typedef enum typedef enum
{ {
HocClkProfile_Handheld = 0, HocClkProfile_Handheld = 0,
HocClkProfile_HandheldCharging, HocClkProfile_HandheldCharging, // Not a real profile, just a marker
HocClkProfile_HandheldChargingUSB, HocClkProfile_HandheldChargingUSB,
HocClkProfile_HandheldChargingOfficial, HocClkProfile_HandheldChargingOfficial,
HocClkProfile_Docked, HocClkProfile_Docked, // Not shown on Lites
HocClkProfile_EnumMax HocClkProfile_EnumMax
} HocClkProfile; } HocClkProfile;
@@ -82,15 +81,17 @@ typedef enum
typedef enum typedef enum
{ {
HocClkThermalSensor_SOC = 0, HocClkThermalSensor_SOC = 0, // SoC temperature in millicelcius
HocClkThermalSensor_PCB, HocClkThermalSensor_PCB, // PCB temperature in millicelcius
HocClkThermalSensor_Skin, HocClkThermalSensor_Skin, // "Skin" temperature in millicelcius
HocClkThermalSensor_Battery, HocClkThermalSensor_Battery, // Battery temperature in millicelcius
HocClkThermalSensor_PMIC, HocClkThermalSensor_PMIC, // Always return 50.0C, as thats the only reasonable value the PMIC sensor can generate
HocClkThermalSensor_CPU, HocClkThermalSensor_CPU, // CPU temperature in millicelcius
HocClkThermalSensor_GPU, HocClkThermalSensor_GPU, // GPU temperature in millicelcius
HocClkThermalSensor_MEM, HocClkThermalSensor_MEM, // MEM temperature in millicelcius. Returns the PLLX sensor value on Mariko
HocClkThermalSensor_PLLX, HocClkThermalSensor_PLLX, // PLLX temperature in millicelcius
HocClkThermalSensor_AO, // AOTAG
HocClkThermalSensor_BQ24193, // BQ24193 temperature. Refer to BQ24193Temp for returned values
HocClkThermalSensor_EnumMax HocClkThermalSensor_EnumMax
} HocClkThermalSensor; } HocClkThermalSensor;
@@ -107,8 +108,12 @@ typedef enum
HocClkPartLoad_EMCCpu, HocClkPartLoad_EMCCpu,
HocClkPartLoad_GPU, HocClkPartLoad_GPU,
HocClkPartLoad_CPUMax, HocClkPartLoad_CPUMax,
HocClkPartLoad_BAT, HocClkPartLoad_BAT, // Battery raw charge percentage
HocClkPartLoad_FAN, HocClkPartLoad_FAN,
HocClkPartLoad_RamBWAll,
HocClkPartLoad_RamBWCpu,
HocClkPartLoad_RamBWGpu,
HocClkPartLoad_RamBWPeak, // Maximum possible RAM bandwidth
HocClkPartLoad_EnumMax HocClkPartLoad_EnumMax
} HocClkPartLoad; } HocClkPartLoad;
@@ -120,15 +125,15 @@ typedef enum {
} HocClkSpeedo; } HocClkSpeedo;
typedef enum { typedef enum {
GPUUVLevel_NoUV = 0, GPUUVLevel_HiOPT = 0,
GPUUVLevel_SLT, GPUUVLevel_HiOPT15,
GPUUVLevel_HiOPT, GPUUVLevel_HighUV,
GPUUVLevel_EnumMax, GPUUVLevel_EnumMax,
} GPUUndervoltLevel; } GPUUndervoltLevel;
enum { enum {
DVFSMode_Disabled = 0, DVFSMode_Disabled = 0,
DVFSMode_Hijack, DVFSMode_Hijack, // PCV hijack dvfs
// DVFSMode_OfficialService, // DVFSMode_OfficialService,
// DVFSMode_Hack, // DVFSMode_Hack,
DVFSMode_EnumMax, DVFSMode_EnumMax,
@@ -158,6 +163,64 @@ typedef enum {
RamDisplayMode_EnumMax, RamDisplayMode_EnumMax,
} RamDisplayMode; } RamDisplayMode;
typedef enum {
MemoryFrequencyMeasurementMode_PLL = 0,
MemoryFrequencyMeasurementMode_Actmon,
MemoryFrequencyMeasurementMode_EnumMax,
} MemoryFrequencyMeasurementMode;
typedef enum {
RamDisplayUnit_MHz = 0,
RamDisplayUnit_MTs,
RamDisplayUnit_MHzMTs,
RamDisplayUnit_EnumMax,
} RamDisplayUnit;
typedef enum {
BQ24193Temp_Normal = 0,
BQ24193Temp_Warm,
BQ24193Temp_Hot,
BQ24193Temp_Overheat,
BQ24193Temp_EnumMax
} BQ24193Temp;
typedef enum AulaColorMode {
AulaDisplayColorMode_DoNotOverride = 0xFF,
AulaDisplayColorMode_Saturated = 0x0,
AulaDisplayColorMode_Washed = 0x45,
AulaDisplayColorMode_Basic = 0x03, // Default
AulaDisplayColorMode_PowerReset = 0x20, // Reset to on power on
AulaDisplayColorMode_Natural = 0x23,
AulaDisplayColorMode_Vivid = 0x65,
AulaDisplayColorMode_Night0 = 0x43,
AulaDisplayColorMode_Night1 = 0x15,
AulaDisplayColorMode_Night2 = 0x35,
AulaDisplayColorMode_Night3 = 0x75,
} AulaColorMode;
// typedef enum {
// PANEL_JDI_XXX062M = 0x10,
// PANEL_JDI_LAM062M109A = 0x0910, // SI.
// PANEL_JDI_LPM062M326A = 0x2610, // LTPS.
// PANEL_INL_P062CCA_AZ1 = 0x0F20,
// PANEL_AUO_A062TAN01 = 0x0F30,
// PANEL_INL_2J055IA_27A = 0x1020,
// PANEL_AUO_A055TAN01 = 0x1030,
// PANEL_SHP_LQ055T1SW10 = 0x1040,
// PANEL_SAM_AMS699VC01 = 0x2050,
// PANEL_RR_SUPER5_OLED_V1 = 0x10E0,
// PANEL_RR_SUPER5_OLED_HD_V1 = 0x10E1,
// PANEL_RR_SUPER7_IPS_V1 = 0x0FE0,
// PANEL_RR_SUPER7_IPS_HD_V1 = 0x0FE1
// // Found on 6/2" clones. Unknown markings. Clone of AUO A062TAN01.
// // Quality seems JDI like. Has bad low backlight scaling. ID: [83] 94 [0F]. Sometimes reports [30] 94 [0F]. Both IDs have correct CRC16.
// PANEL_OEM_CLONE_6_2 = 0x0F83,
// // Found on 5.5" clones with AUO A055TAN02 (59.05A30.001) fake markings.
// PANEL_OEM_CLONE_5_5 = 0x00B3,
// // Found on 5.5" clones with AUO A055TAN02 (59.05A30.001) fake markings.
// PANEL_OEM_CLONE = 0x0000
// //0x0F40 [40] 94 [0F], 5.5" clone
// } HocClkDisplayPanel;
#define HOCCLK_ENUM_VALID(n, v) ((v) < n##_EnumMax) #define HOCCLK_ENUM_VALID(n, v) ((v) < n##_EnumMax)
// Packed u32 // Packed u32
@@ -219,8 +282,12 @@ static inline const char* hocclkFormatThermalSensor(HocClkThermalSensor thermSen
return pretty ? "MEM" : "mem"; return pretty ? "MEM" : "mem";
case HocClkThermalSensor_PLLX: case HocClkThermalSensor_PLLX:
return pretty ? "PLLX" : "pllx"; return pretty ? "PLLX" : "pllx";
case HocClkThermalSensor_AO:
return pretty ? "AO" : "ao";
case HocClkThermalSensor_BQ24193:
return pretty ? "BQ24193" : "bq24193";
default: default:
return NULL; return "unknown";
} }
} }
@@ -233,7 +300,7 @@ static inline const char* hocclkFormatPowerSensor(HocClkPowerSensor powSensor, b
case HocClkPowerSensor_Avg: case HocClkPowerSensor_Avg:
return pretty ? "Avg" : "avg"; return pretty ? "Avg" : "avg";
default: default:
return NULL; return "unknown";
} }
} }
@@ -252,7 +319,7 @@ static inline const char* hocclkFormatProfile(HocClkProfile profile, bool pretty
case HocClkProfile_HandheldChargingOfficial: case HocClkProfile_HandheldChargingOfficial:
return pretty ? "PD Charger" : "handheld_charging_official"; return pretty ? "PD Charger" : "handheld_charging_official";
default: default:
return NULL; return "unknown";
} }
} }
@@ -266,7 +333,7 @@ static inline const char* hocClkFormatVoltage(HocClkVoltage voltage, bool pretty
case HocClkVoltage_GPU: case HocClkVoltage_GPU:
return pretty ? "GPU" : "gpu"; return pretty ? "GPU" : "gpu";
case HocClkVoltage_EMCVDD2: case HocClkVoltage_EMCVDD2:
return pretty ? "VDD2" : "emcvdd2"; return pretty ? "VDD2" : "vdd2";
case HocClkVoltage_EMCVDDQ: case HocClkVoltage_EMCVDDQ:
return pretty ? "VDDQ" : "vddq"; return pretty ? "VDDQ" : "vddq";
case HocClkVoltage_SOC: case HocClkVoltage_SOC:
@@ -274,6 +341,64 @@ static inline const char* hocClkFormatVoltage(HocClkVoltage voltage, bool pretty
case HocClkVoltage_Display: case HocClkVoltage_Display:
return pretty ? "Display" : "display"; return pretty ? "Display" : "display";
default: default:
return NULL; return "unknown";
} }
} }
static inline const char* hocClkFormatConsoleType(HocClkConsoleType consoleType, bool pretty)
{
switch(consoleType)
{
case HocClkConsoleType_Icosa:
return pretty ? "Icosa (V1)" : "icosa";
case HocClkConsoleType_Iowa:
return pretty ? "Iowa (V2)" : "iowa";
case HocClkConsoleType_Hoag:
return pretty ? "Hoag (Lite)" : "hoag";
case HocClkConsoleType_Aula:
return pretty ? "Aula (OLED)" : "aula";
default:
return "unknown";
}
}
// static inline const char* hocClkFormatPanel(HocClkDisplayPanel panel, bool pretty)
// {
// switch(panel)
// {
// case PANEL_JDI_XXX062M:
// return pretty ? "JDI XXX062M" : "jdi_xxx062m";
// case PANEL_JDI_LAM062M109A:
// return pretty ? "JDI LAM062M109A" : "jdi_lam062m109a";
// case PANEL_JDI_LPM062M326A:
// return pretty ? "JDI LPM062M326A" : "jdi_lpm062m326a";
// case PANEL_INL_P062CCA_AZ1:
// return pretty ? "INL P062CCA-AZ1" : "inl_p062cca_az1";
// case PANEL_AUO_A062TAN01:
// return pretty ? "AUO A062TAN01" : "auo_a062tan01";
// case PANEL_INL_2J055IA_27A:
// return pretty ? "INL 2J055IA-27A" : "inl_2j055ia_27a";
// case PANEL_AUO_A055TAN01:
// return pretty ? "AUO A055TAN01" : "auo_a055tan01";
// case PANEL_SHP_LQ055T1SW10:
// return pretty ? "SHP LQ055T1SW10" : "shp_lq055t1sw10";
// case PANEL_SAM_AMS699VC01:
// return pretty ? "SAM AMS699VC01" : "sam_ams699vc01";
// case PANEL_RR_SUPER5_OLED_V1:
// return pretty ? "SUPER5 OLED" : "rr_super5_oled_v1";
// case PANEL_RR_SUPER5_OLED_HD_V1:
// return pretty ? "SUPER5 OLED HD" : "rr_super5_oled_hd_v1";
// case PANEL_RR_SUPER7_IPS_V1:
// return pretty ? "SUPER7 IPS" : "rr_super7_ips_v1";
// case PANEL_RR_SUPER7_IPS_HD_V1:
// return pretty ? "RR Super7 IPS HD V1" : "rr_super7_ips_hd_v1";
// case PANEL_OEM_CLONE_6_2:
// return pretty ? "OEM Clone 6.2" : "oem_clone_6_2";
// case PANEL_OEM_CLONE_5_5:
// return pretty ? "OEM Clone 5.5" : "oem_clone_5_5";
// case PANEL_OEM_CLONE:
// return pretty ? "OEM Clone" : "oem_clone";
// default:
// return "unknown";
// }
// }

View File

@@ -30,21 +30,41 @@
#include <stdint.h> #include <stdint.h>
#include "board.h" #include "board.h"
typedef struct typedef struct {
{
/*
* This "stable struct" must never be modified. It provides a fixed memory layout so external clients can safely read the expected fields even
* if HocClkContext changes in newer versions and the client is not recompiled.
*/
struct {
#define HocClkModuleStable_EnumMax 5
#define HocClkThermalSensorStable_EnumMax 11
#define HocClkPowerSensorStable_EnumMax 2
#define HocClkPartLoadStable_EnumMax 10
#define HocClkVoltageStable_EnumMax 7
u32 freqs[HocClkModuleStable_EnumMax];
u32 realFreqs[HocClkModuleStable_EnumMax];
u32 overrideFreqs[HocClkModuleStable_EnumMax];
s32 temps[HocClkThermalSensorStable_EnumMax];
s32 power[HocClkPowerSensorStable_EnumMax];
u32 partLoad[HocClkPartLoadStable_EnumMax];
u32 voltages[HocClkVoltageStable_EnumMax];
} stable;
uint64_t applicationId; uint64_t applicationId;
HocClkProfile profile; HocClkProfile profile;
uint32_t freqs[HocClkModule_EnumMax]; uint32_t freqs[HocClkModule_EnumMax];
uint32_t realFreqs[HocClkModule_EnumMax]; uint32_t realFreqs[HocClkModule_EnumMax];
uint32_t overrideFreqs[HocClkModule_EnumMax]; uint32_t overrideFreqs[HocClkModule_EnumMax];
uint32_t temps[HocClkThermalSensor_EnumMax]; int32_t temps[HocClkThermalSensor_EnumMax];
int32_t power[HocClkPowerSensor_EnumMax]; int32_t power[HocClkPowerSensor_EnumMax];
uint32_t partLoad[HocClkPartLoad_EnumMax]; uint32_t partLoad[HocClkPartLoad_EnumMax];
uint32_t voltages[HocClkVoltage_EnumMax]; uint32_t voltages[HocClkVoltage_EnumMax];
u16 speedos[HocClkSpeedo_EnumMax]; u16 speedos[HocClkSpeedo_EnumMax];
u16 iddq[HocClkSpeedo_EnumMax]; u16 iddq[HocClkSpeedo_EnumMax];
u16 waferX; s16 waferX;
u16 waferY; s16 waferY;
// Misc stuff // Misc stuff
GpuSchedulingMode gpuSchedulingMode; GpuSchedulingMode gpuSchedulingMode;
@@ -54,10 +74,16 @@ typedef struct
u8 maxDisplayFreq; u8 maxDisplayFreq;
u8 dramID; u8 dramID;
bool isDram8GB; bool isDram8GB;
HocClkConsoleType consoleType;
// FPS / Resolution // FPS / Resolution
u8 fps; u8 fps;
u16 resolutionHeight; u16 resolutionHeight;
u8 custRev;
u16 kipVersion;
// Reserved for future use
u8 reserved[0x35B];
} HocClkContext; } HocClkContext;
typedef struct typedef struct
@@ -68,6 +94,8 @@ typedef struct
}; };
} HocClkTitleProfileList; } HocClkTitleProfileList;
#define HOCCLK_FREQ_LIST_MAX 32 #define HOCCLK_FREQ_LIST_MAX 48
#define GLOBAL_PROFILE_ID 0xA111111111111111 #define HOCCLK_GLOBAL_PROFILE_TID 0xA111111111111111
static_assert(sizeof(HocClkContext) == 0x500);

View File

@@ -29,7 +29,7 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include "board.h"
typedef enum { typedef enum {
HocClkConfigValue_PollingIntervalMs = 0, HocClkConfigValue_PollingIntervalMs = 0,
HocClkConfigValue_TempLogIntervalMs, HocClkConfigValue_TempLogIntervalMs,
@@ -68,7 +68,15 @@ typedef enum {
HocClkConfigValue_CpuGovernorMinimumFreq, HocClkConfigValue_CpuGovernorMinimumFreq,
HocClkConfigValue_DisplayVoltage, HocClkConfigValue_DisplayVoltage,
HocClkConfigValue_MemoryFrequencyMeasurementMode,
HocClkConfigValue_RamDisplayUnit,
HocClkConfigValue_IsFirstLoad,
HocClkConfigValue_AulaDisplayColorPreset,
HocClkConfigValue_MarikoMiddleFreqs,
KipConfigValue_custRev, KipConfigValue_custRev,
KipConfigValue_KipVersion,
// KipConfigValue_mtcConf, // KipConfigValue_mtcConf,
KipConfigValue_hpMode, KipConfigValue_hpMode,
@@ -76,9 +84,12 @@ typedef enum {
KipConfigValue_eristaEmcMaxClock, KipConfigValue_eristaEmcMaxClock,
KipConfigValue_eristaEmcMaxClock1, KipConfigValue_eristaEmcMaxClock1,
KipConfigValue_eristaEmcMaxClock2, KipConfigValue_eristaEmcMaxClock2,
KipConfigValue_stepMode,
KipConfigValue_marikoEmcMaxClock, KipConfigValue_marikoEmcMaxClock,
KipConfigValue_marikoEmcVddqVolt, KipConfigValue_marikoEmcVddqVolt,
KipConfigValue_emcDvbShift, KipConfigValue_emcDvbShift,
KipConfigValue_marikoSocVmax,
KipConfigValue_t1_tRCD, KipConfigValue_t1_tRCD,
KipConfigValue_t2_tRP, KipConfigValue_t2_tRP,
@@ -88,6 +99,23 @@ typedef enum {
KipConfigValue_t6_tRTW, KipConfigValue_t6_tRTW,
KipConfigValue_t7_tWTR, KipConfigValue_t7_tWTR,
KipConfigValue_t8_tREFI, KipConfigValue_t8_tREFI,
KipConfigValue_timingEmcTbreak,
KipConfigValue_low_t6_tRTW,
KipConfigValue_low_t7_tWTR,
KipConfigValue_t2_tRP_cap,
KipConfigValue_read_latency_1333,
KipConfigValue_read_latency_1600,
KipConfigValue_read_latency_1866,
KipConfigValue_read_latency_2133,
KipConfigValue_write_latency_1333,
KipConfigValue_write_latency_1600,
KipConfigValue_write_latency_1866,
KipConfigValue_write_latency_2133,
KipConfigValue_mem_burst_read_latency, KipConfigValue_mem_burst_read_latency,
KipConfigValue_mem_burst_write_latency, KipConfigValue_mem_burst_write_latency,
@@ -111,6 +139,7 @@ typedef enum {
KipConfigValue_marikoGpuUV, KipConfigValue_marikoGpuUV,
KipConfigValue_marikoGpuVmin, KipConfigValue_marikoGpuVmin,
KipConfigValue_marikoGpuBootVolt,
KipConfigValue_marikoGpuVmax, KipConfigValue_marikoGpuVmax,
KipConfigValue_commonGpuVoltOffset, KipConfigValue_commonGpuVoltOffset,
@@ -173,7 +202,6 @@ typedef enum {
KipConfigValue_t7_tWTR_fine_tune, KipConfigValue_t7_tWTR_fine_tune,
KipCrc32, KipCrc32,
HocClkConfigValue_IsFirstLoad,
HocClkConfigValue_EnumMax, HocClkConfigValue_EnumMax,
} HocClkConfigValue; } HocClkConfigValue;
@@ -257,9 +285,20 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr
case HocClkConfigValue_DisplayVoltage: case HocClkConfigValue_DisplayVoltage:
return pretty ? "Display Voltage" : "display_voltage"; return pretty ? "Display Voltage" : "display_voltage";
case HocClkConfigValue_MemoryFrequencyMeasurementMode:
return pretty ? "RAM Frequency Measurement Mode" : "mem_freq_measurement_mode";
case HocClkConfigValue_RamDisplayUnit:
return pretty ? "RAM Frequency Display Unit" : "RAM_display_unit";
case HocClkConfigValue_AulaDisplayColorPreset:
return pretty ? "Aula Display Color Preset" : "aula_color_preset";
case HocClkConfigValue_MarikoMiddleFreqs:
return pretty ? "Mariko Middle Clocks" : "mariko_middle_freqs";
// KIP config values // KIP config values
case KipConfigValue_custRev: case KipConfigValue_custRev:
return pretty ? "Custom Revision" : "kip_cust_rev"; return pretty ? "Custom Revision" : "kip_cust_rev";
case KipConfigValue_KipVersion:
return pretty ? "KIP Version" : "kip_version";
// case KipConfigValue_mtcConf: // case KipConfigValue_mtcConf:
// return pretty ? "MTC Config" : "kip_mtc_conf"; // return pretty ? "MTC Config" : "kip_mtc_conf";
case KipConfigValue_hpMode: case KipConfigValue_hpMode:
@@ -274,13 +313,16 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr
return pretty ? "Erista EMC Max Clock 2" : "erista_emc_max_clock1"; return pretty ? "Erista EMC Max Clock 2" : "erista_emc_max_clock1";
case KipConfigValue_eristaEmcMaxClock2: case KipConfigValue_eristaEmcMaxClock2:
return pretty ? "Erista EMC Max Clock 3" : "erista_emc_max_clock2"; return pretty ? "Erista EMC Max Clock 3" : "erista_emc_max_clock2";
case KipConfigValue_stepMode:
return pretty ? "Step Mode:" : "step_mode";
case KipConfigValue_marikoEmcMaxClock: case KipConfigValue_marikoEmcMaxClock:
return pretty ? "Mariko EMC Max Clock" : "mariko_emc_max_clock"; return pretty ? "Mariko EMC Max Clock" : "mariko_emc_max_clock";
case KipConfigValue_marikoEmcVddqVolt: case KipConfigValue_marikoEmcVddqVolt:
return pretty ? "Mariko EMC VDDQ Voltage" : "mariko_emc_vddq_volt"; return pretty ? "Mariko EMC VDDQ Voltage" : "mariko_emc_vddq_volt";
case KipConfigValue_emcDvbShift: case KipConfigValue_emcDvbShift:
return pretty ? "EMC DVB Shift" : "emc_dvb_shift"; return pretty ? "EMC DVB Shift" : "emc_dvb_shift";
case KipConfigValue_marikoSocVmax:
return pretty ? "SOC Vmax" : "soc_vmax";
// Memory timings // Memory timings
case KipConfigValue_t1_tRCD: case KipConfigValue_t1_tRCD:
return pretty ? "t1 - tRCD" : "t1_trcd"; return pretty ? "t1 - tRCD" : "t1_trcd";
@@ -298,6 +340,35 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr
return pretty ? "t7 - tWTR" : "t7_twtr"; return pretty ? "t7 - tWTR" : "t7_twtr";
case KipConfigValue_t8_tREFI: case KipConfigValue_t8_tREFI:
return pretty ? "t8 - tREFI" : "t8_trefi"; return pretty ? "t8 - tREFI" : "t8_trefi";
case KipConfigValue_timingEmcTbreak:
return pretty ? "Timing Emc Tbreak" : "timingEmcTbreak";
case KipConfigValue_low_t6_tRTW:
return pretty ? "Low T6 - tRTW" : "low_t6_tRTW";
case KipConfigValue_low_t7_tWTR:
return pretty ? "Low T7 - tWTR" : "low_t7_tWTR";
case KipConfigValue_t2_tRP_cap:
return pretty ? "t2 - trp 1333WL Cap" : "t2_tRP_cap";
case KipConfigValue_read_latency_1333:
return pretty ? "1333 Read Latency" : "read_latency_1333";
case KipConfigValue_read_latency_1600:
return pretty ? "1600 Read Latency" : "read_latency_1600";
case KipConfigValue_read_latency_1866:
return pretty ? "1866 Read Latency" : "read_latency_1866";
case KipConfigValue_read_latency_2133:
return pretty ? "2133 Read Latency" : "read_latency_2133";
case KipConfigValue_write_latency_1333:
return pretty ? "1333 Write Latency" : "write_latency_1333";
case KipConfigValue_write_latency_1600:
return pretty ? "1600 Write Latency" : "write_latency_1600";
case KipConfigValue_write_latency_1866:
return pretty ? "1866 Write Latency" : "write_latency_1866";
case KipConfigValue_write_latency_2133:
return pretty ? "2133 Write Latency" : "write_latency_2133";
case KipConfigValue_mem_burst_read_latency: case KipConfigValue_mem_burst_read_latency:
return pretty ? "Memory Burst Read Latency" : "mem_burst_read_latency"; return pretty ? "Memory Burst Read Latency" : "mem_burst_read_latency";
case KipConfigValue_mem_burst_write_latency: case KipConfigValue_mem_burst_write_latency:
@@ -346,6 +417,8 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr
return pretty ? "Mariko GPU Undervolt" : "mariko_gpu_uv"; return pretty ? "Mariko GPU Undervolt" : "mariko_gpu_uv";
case KipConfigValue_marikoGpuVmin: case KipConfigValue_marikoGpuVmin:
return pretty ? "Mariko GPU Vmin" : "mariko_gpu_vmin"; return pretty ? "Mariko GPU Vmin" : "mariko_gpu_vmin";
case KipConfigValue_marikoGpuBootVolt:
return pretty ? "Mariko GPU Boot Voltage" : "mariko_gpu_boot_volt";
case KipConfigValue_marikoGpuVmax: case KipConfigValue_marikoGpuVmax:
return pretty ? "Mariko GPU Vmax" : "mariko_gpu_vmax"; return pretty ? "Mariko GPU Vmax" : "mariko_gpu_vmax";
@@ -408,7 +481,7 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr
case KipConfigValue_g_volt_e_998400: return pretty ? "Erista GPU Volt 998 MHz" : "g_volt_e_998400"; case KipConfigValue_g_volt_e_998400: return pretty ? "Erista GPU Volt 998 MHz" : "g_volt_e_998400";
case KipConfigValue_g_volt_e_1036800: return pretty ? "Erista GPU Volt 1036 MHz" : "g_volt_e_1036800"; case KipConfigValue_g_volt_e_1036800: return pretty ? "Erista GPU Volt 1036 MHz" : "g_volt_e_1036800";
case KipConfigValue_g_volt_e_1075200: return pretty ? "Erista GPU Volt 1075 MHz" : "g_volt_e_1075200"; case KipConfigValue_g_volt_e_1075200: return pretty ? "Erista GPU Volt 1075 MHz" : "g_volt_e_1075200";
case KipConfigValue_t6_tRTW_fine_tune: return pretty ? "t6 - tRTW Fine Tune" : "t6_tRTW_fine_fune"; case KipConfigValue_t6_tRTW_fine_tune: return pretty ? "t6 - tRTW Fine Tune" : "t6_tRTW_fine_tune";
case KipConfigValue_t7_tWTR_fine_tune: return pretty ? "t7 - tWTR Fine Tune" : "t7_tWTR_fine_tune"; case KipConfigValue_t7_tWTR_fine_tune: return pretty ? "t7 - tWTR Fine Tune" : "t7_tWTR_fine_tune";
case KipCrc32: case KipCrc32:
return pretty ? "CRC32" : "crc32"; return pretty ? "CRC32" : "crc32";
@@ -436,7 +509,11 @@ static inline uint64_t hocclkDefaultConfigValue(HocClkConfigValue val)
case HocClkConfigValue_GPUScheduling: case HocClkConfigValue_GPUScheduling:
case HocClkConfigValue_LiveCpuUv: case HocClkConfigValue_LiveCpuUv:
case HocClkConfigValue_GPUSchedulingMethod: case HocClkConfigValue_GPUSchedulingMethod:
case HocClkConfigValue_MemoryFrequencyMeasurementMode:
case HocClkConfigValue_MarikoMiddleFreqs:
return 0ULL; return 0ULL;
case HocClkConfigValue_RamDisplayUnit:
return (uint64_t)RamDisplayUnit_MHz;
case HocClkConfigValue_EristaMaxCpuClock: case HocClkConfigValue_EristaMaxCpuClock:
return 1785ULL; return 1785ULL;
@@ -460,6 +537,8 @@ static inline uint64_t hocclkDefaultConfigValue(HocClkConfigValue val)
return 60ULL; return 60ULL;
case HocClkConfigValue_DisplayVoltage: case HocClkConfigValue_DisplayVoltage:
return 1200ULL; // Auto return 1200ULL; // Auto
case HocClkConfigValue_AulaDisplayColorPreset:
return AulaDisplayColorMode_DoNotOverride;
default: default:
return 0ULL; return 0ULL;
} }
@@ -491,8 +570,9 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in
case HocClkConfigValue_EnableExperimentalSettings: case HocClkConfigValue_EnableExperimentalSettings:
case HocClkConfigValue_LiveCpuUv: case HocClkConfigValue_LiveCpuUv:
case HocClkConfigValue_GPUSchedulingMethod: case HocClkConfigValue_GPUSchedulingMethod:
case HocClkConfigValue_MarikoMiddleFreqs:
return (input & 0x1) == input; return (input & 0x1) == input;
case KipConfigValue_KipVersion:
case KipConfigValue_custRev: case KipConfigValue_custRev:
// case KipConfigValue_mtcConf: // case KipConfigValue_mtcConf:
case KipConfigValue_hpMode: case KipConfigValue_hpMode:
@@ -500,9 +580,11 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in
case KipConfigValue_eristaEmcMaxClock: case KipConfigValue_eristaEmcMaxClock:
case KipConfigValue_eristaEmcMaxClock1: case KipConfigValue_eristaEmcMaxClock1:
case KipConfigValue_eristaEmcMaxClock2: case KipConfigValue_eristaEmcMaxClock2:
case KipConfigValue_stepMode:
case KipConfigValue_marikoEmcMaxClock: case KipConfigValue_marikoEmcMaxClock:
case KipConfigValue_marikoEmcVddqVolt: case KipConfigValue_marikoEmcVddqVolt:
case KipConfigValue_emcDvbShift: case KipConfigValue_emcDvbShift:
case KipConfigValue_marikoSocVmax:
case KipConfigValue_t1_tRCD: case KipConfigValue_t1_tRCD:
case KipConfigValue_t2_tRP: case KipConfigValue_t2_tRP:
case KipConfigValue_t3_tRAS: case KipConfigValue_t3_tRAS:
@@ -511,6 +593,18 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in
case KipConfigValue_t6_tRTW: case KipConfigValue_t6_tRTW:
case KipConfigValue_t7_tWTR: case KipConfigValue_t7_tWTR:
case KipConfigValue_t8_tREFI: case KipConfigValue_t8_tREFI:
case KipConfigValue_timingEmcTbreak:
case KipConfigValue_low_t6_tRTW:
case KipConfigValue_low_t7_tWTR:
case KipConfigValue_t2_tRP_cap:
case KipConfigValue_read_latency_1333:
case KipConfigValue_read_latency_1600:
case KipConfigValue_read_latency_1866:
case KipConfigValue_read_latency_2133:
case KipConfigValue_write_latency_1333:
case KipConfigValue_write_latency_1600:
case KipConfigValue_write_latency_1866:
case KipConfigValue_write_latency_2133:
case KipConfigValue_mem_burst_read_latency: case KipConfigValue_mem_burst_read_latency:
case KipConfigValue_mem_burst_write_latency: case KipConfigValue_mem_burst_write_latency:
case KipConfigValue_eristaCpuUV: case KipConfigValue_eristaCpuUV:
@@ -528,6 +622,7 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in
case KipConfigValue_eristaGpuVmin: case KipConfigValue_eristaGpuVmin:
case KipConfigValue_marikoGpuUV: case KipConfigValue_marikoGpuUV:
case KipConfigValue_marikoGpuVmin: case KipConfigValue_marikoGpuVmin:
case KipConfigValue_marikoGpuBootVolt:
case KipConfigValue_marikoGpuVmax: case KipConfigValue_marikoGpuVmax:
case KipConfigValue_commonGpuVoltOffset: case KipConfigValue_commonGpuVoltOffset:
case KipConfigValue_gpuSpeedo: case KipConfigValue_gpuSpeedo:
@@ -592,13 +687,16 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in
case HocClkConfigValue_GPUScheduling: case HocClkConfigValue_GPUScheduling:
case HocClkConfigValue_RAMVoltDisplayMode: case HocClkConfigValue_RAMVoltDisplayMode:
case HocClkConfigValue_CpuGovernorMinimumFreq: case HocClkConfigValue_CpuGovernorMinimumFreq:
case HocClkConfigValue_MemoryFrequencyMeasurementMode:
case HocClkConfigValue_RamDisplayUnit:
case HocClkConfigValue_AulaDisplayColorPreset:
return true; return true;
case HocClkConfigValue_BatteryChargeCurrent: case HocClkConfigValue_BatteryChargeCurrent:
return ((input >= 1024) && (input <= 3072)) || !input; return ((input >= 1024) && (input <= 3072)) || !input;
case HocClkConfigValue_DisplayVoltage: case HocClkConfigValue_DisplayVoltage:
return ((input >= 900) && (input <= 1325)); return ((input >= 800) && (input <= 1325));
default: default:
return false; return true;
} }
} }

View File

@@ -31,7 +31,7 @@
#include "board.h" #include "board.h"
#include "clock_manager.h" #include "clock_manager.h"
#define HOCCLK_IPC_API_VERSION 1 #define HOCCLK_IPC_API_VERSION 2
#define HOCCLK_IPC_SERVICE_NAME "hoc:clk" #define HOCCLK_IPC_SERVICE_NAME "hoc:clk"
enum HocClkIpcCmd enum HocClkIpcCmd

View File

@@ -0,0 +1,11 @@
#pragma once
#include <switch.h>
#define R_UNLESS(rc) \
do { \
if (R_FAILED(rc)) { \
return; \
} \
} while (0)
/* TODO: Add more Result macros. */

View File

@@ -27,7 +27,7 @@ INCLUDES := ../common/include
EXEFS_SRC := exefs_src EXEFS_SRC := exefs_src
IS_MINIMAL := 0 IS_MINIMAL := 0
APP_TITLE := Horizon OC Zeus APP_TITLE := Horizon OC Gaea
NO_ICON := 1 NO_ICON := 1
@@ -39,7 +39,7 @@ include ${TOPDIR}/lib/libultrahand/ultrahand.mk
# version control constants # version control constants
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
#TARGET_VERSION := $(shell git describe --dirty --always --tags) #TARGET_VERSION := $(shell git describe --dirty --always --tags)
APP_VERSION := 1.2.1 APP_VERSION := 2.4.0 # ensure to set KIP_VERSION and CUST_REV in sysmodule Makefile when updating this
TARGET_VERSION := $(APP_VERSION) TARGET_VERSION := $(APP_VERSION)
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------

View File

@@ -2,140 +2,140 @@
"Information": "Información", "Information": "Información",
"IDDQ:": "IDDQ:", "IDDQ:": "IDDQ:",
"Module: ": "Módulo:", "Module: ": "Módulo:",
"sys-dock status:": "estado del sys-dock:", "sys-dock status:": "Estado de sys-dock:",
"SaltyNX status:": "Estado de SaltyNX:", "SaltyNX status:": "Estado de SaltyNX:",
"RR Display status:": "Estado de visualización RR:", "RR Display status:": "Estado de pantalla RR:",
"Wafer Position:": "Posición de la oblea:", "Wafer Position:": "Posición del wafer:",
"Credits": "Créditos", "Credits": "Créditos",
"Developers": "Desarrolladores", "Developers": "Desarrolladores",
"Contributors": "Colaboradores", "Contributors": "Colaboradores",
"Testers": "Probadores", "Testers": "Testers",
"Special Thanks": "agradecimiento especial", "Special Thanks": "Agradecimientos especiales",
"Unknown": "Desconocido", "Unknown": "Desconocido",
"Installed": "Instalado", "Installed": "Instalado",
"Not Installed": "No instalado", "Not Installed": "No instalado",
"X: %u Y: %u": "X: %u Y: %u", "X: %u Y: %u": "X: %u Y: %u",
"THE BEER-WARE LICENSE": "LA LICENCIA DE CERVEZA", "THE BEER-WARE LICENSE": "LICENCIA BEER-WARE",
"Default": "Predeterminado", "Default": "Predeterminado",
"Do Not Override": "No anular", "Do Not Override": "No sobrescribir",
"Disabled": "Discapacitado", "Disabled": "Desactivado",
"Enabled": "Habilitado", "Enabled": "Activado",
" \\ue0e3 Reset": "\\ue0e3 Restablecer", " \\ue0e3 Reset": "\\ue0e3 Restablecer",
"Display": "Pantalla", "Display": "Pantalla",
"Application changed\\n\\n": "Aplicación modificada\\n\\n", "Application changed\\n\\n": "Aplicación cambiada\\n\\n",
"The running application changed\\n\\n": "La aplicación en ejecución cambió\\n\\n", "The running application changed\\n\\n": "La aplicación en ejecución ha cambiado\\n\\n",
"while editing was going on.": "mientras se realizaba la edición.", "while editing was going on.": "mientras se estaba editando.",
"Board": "tablero", "Board": "Placa",
"%u.%u%u mV": "%u.%u%u mV", "%u.%u%u mV": "%u.%u%u mV",
"Could not connect to hoc-clk sysmodule.\\n\\n": "No se pudo conectar al módulo del sistema hoc-clk.\\n\\n", "Could not connect to hoc-clk sysmodule.\\n\\n": "No se pudo conectar al sysmodule hoc-clk.\\n\\n",
"Please make sure everything is\\n\\n": "Por favor asegúrese de que todo esté\\n\\n", "Please make sure everything is\\n\\n": "Asegúrate de que todo esté\\n\\n",
"correctly installed and enabled.": "correctamente instalado y habilitado.", "correctly installed and enabled.": "correctamente instalado y activado.",
"Fatal error": "error fatal", "Fatal error": "Error fatal",
"Temporary Overrides ": "Anulaciones temporales", "Temporary Overrides ": "Ajustes temporales",
"Sleep Mode": "Modo de suspensión", "Sleep Mode": "Modo reposo",
"Stock": "Valores", "Stock": "Valores de fábrica",
"Dev OC": "Desarrollador OC", "Dev OC": "OC de desarrollo",
"Boost Mode": "Modo de impulso", "Boost Mode": "Modo boost",
"Safe Max": "Máximo seguro", "Safe Max": "Máximo seguro",
"Unsafe Max": "Máximo inseguro", "Unsafe Max": "Máximo no seguro",
"Absolute Max": "Máximo absoluto", "Absolute Max": "Máximo absoluto",
"Handheld Safe Max": "Caja fuerte de mano máx.", "Handheld Safe Max": "Máximo seguro en portátil",
"Enable": "Habilitar", "Enable": "Activar",
"Edit App Profile": "Editar perfil de aplicación", "Edit App Profile": "Editar perfil de aplicación",
"Edit Global Profile": "Editar perfil global", "Edit Global Profile": "Editar perfil global",
"Temporary Overrides": "Anulaciones temporales", "Temporary Overrides": "Ajustes temporales",
"Settings": "Configuración", "Settings": "Configuración",
"About": "Acerca de", "About": "Acerca de",
"Compiling with minimal features": "Compilando con características mínimas", "Compiling with minimal features": "Compilado con funciones mínimas",
"General Settings": "Configuraciones generales", "General Settings": "Configuración general",
"Governor Settings": "Configuración del gobernador", "Governor Settings": "Configuración del governor",
"Safety Settings": "Configuraciones de seguridad", "Safety Settings": "Configuración de seguridad",
"Save KIP Settings": "Guardar configuración de KIP", "Save KIP Settings": "Guardar configuración KIP",
"RAM Settings": "Configuración de RAM", "RAM Settings": "Configuración de RAM",
"CPU Settings": "Configuración de la CPU", "CPU Settings": "Configuración de CPU",
"GPU Settings": "Configuración de GPU", "GPU Settings": "Configuración de GPU",
"Display Settings": "Configuración de pantalla", "Display Settings": "Configuración de pantalla",
"Experimental": "Experimental", "Experimental": "Experimental",
"GPU Scheduling Override Method": "Método de anulación de programación de GPU", "GPU Scheduling Override Method": "Método de sobrescritura del scheduling de GPU",
"can be dangerous and may cause": "puede ser peligroso y puede causar", "can be dangerous and may cause": "puede ser peligroso y causar",
"damage to your battery or charger!": "¡Daños a su batería o cargador!", "damage to your battery or charger!": "daños a la batería o al cargador.",
"Charge Current Override": "Anulación de corriente de carga", "Charge Current Override": "Sobrescritura de corriente de carga",
"RAM Voltage Display Mode": "Modo de visualización de voltaje de RAM", "RAM Voltage Display Mode": "Modo de visualización de voltaje de RAM",
"Polling Interval": "Intervalo de sondeo", "Polling Interval": "Intervalo de sondeo",
"CPU Governor Minimum Frequency": "Frecuencia mínima del gobernador de CPU", "CPU Governor Minimum Frequency": "Frecuencia mínima del governor de CPU",
"refresh rates may cause stress": "Las frecuencias de actualización pueden causar estrés.", "refresh rates may cause stress": "las tasas de refresco pueden causar estrés",
"or damage to your display! ": "o daños a su pantalla!", "or damage to your display! ": "o dañar la pantalla.",
"Proceed at your own risk!": Continúe bajo su propio riesgo!", "Proceed at your own risk!": Úsalo bajo tu propio riesgo!",
"Max Handheld Display": "Pantalla portátil máxima", "Max Handheld Display": "Frecuencia máxima de pantalla en portátil",
"Display Clock": "Reloj de pantalla", "Display Clock": "Frecuencia de pantalla",
"Official Rating": "Calificación oficial", "Official Rating": "Valor oficial",
"TDP Threshold": "Umbral de TDP", "TDP Threshold": "Umbral de TDP",
"Power": "poder", "Power": "Potencia",
"Thermal Throttle Limit": "Límite del acelerador térmico", "Thermal Throttle Limit": "Límite de thermal throttling",
"HP Mode": "Modo HP", "HP Mode": "Modo alto rendimiento",
"Default (Mariko)": "Predeterminado (Mariko)", "Default (Mariko)": "Predeterminado (Mariko)",
"Default (Erista)": "Predeterminado (Erista)", "Default (Erista)": "Predeterminado (Erista)",
"Rating": "Calificación", "Rating": "Valor",
"Safe Max (Mariko)": "Max seguro (Mariko)", "Safe Max (Mariko)": "Máximo seguro (Mariko)",
"Safe Max (Erista)": "Safe Max (Erista)", "Safe Max (Erista)": "Máximo seguro (Erista)",
"RAM VDD2 Voltage": "Voltaje RAM VDD2", "RAM VDD2 Voltage": "Voltaje VDD2 de RAM",
"Voltage": "voltaje", "Voltage": "Voltaje",
"RAM VDDQ Voltage": "Voltaje RAM VDDQ", "RAM VDDQ Voltage": "Voltaje VDDQ de RAM",
"RAM Frequency Editor": "Editor de frecuencia RAM", "RAM Frequency Editor": "Editor de frecuencia de RAM",
"JEDEC.": "JEDEC.", "JEDEC.": "JEDEC",
"High speedo needed!": "¡Se necesita alta velocidad!", "High speedo needed!": "¡Se necesita alto speedo!",
"3333MHz (Needs extreme Speedo/PLL)": "3333MHz (Necesita Speedo/PLL extremo)", "3333MHz (Needs extreme Speedo/PLL)": "3333MHz (requiere Speedo/PLL extremo)",
"3366MHz (Needs extreme Speedo/PLL)": "3366MHz (Necesita Speedo/PLL extremo)", "3366MHz (Needs extreme Speedo/PLL)": "3366MHz (requiere Speedo/PLL extremo)",
"3400MHz (Needs extreme Speedo/PLL)": "3400MHz (Necesita Speedo/PLL extremo)", "3400MHz (Needs extreme Speedo/PLL)": "3400MHz (requiere Speedo/PLL extremo)",
"3433MHz (Needs ridiculous Speedo/PLL)": "3433MHz (Necesita Speedo/PLL ridículo)", "3433MHz (Needs ridiculous Speedo/PLL)": "3433MHz (requiere Speedo/PLL muy alto)",
"3466MHz (Needs ridiculous Speedo/PLL)": "3466MHz (Necesita Speedo/PLL ridículo)", "3466MHz (Needs ridiculous Speedo/PLL)": "3466MHz (requiere Speedo/PLL muy alto)",
"3500MHz (Needs ridiculous Speedo/PLL)": "3500MHz (Necesita Speedo/PLL ridículo)", "3500MHz (Needs ridiculous Speedo/PLL)": "3500MHz (requiere Speedo/PLL muy alto)",
"Ram Max Clock": "Ram Max Reloj", "Ram Max Clock": "Frecuencia máxima de RAM",
"RAM Latency Editor": "Editor de latencia de RAM", "RAM Latency Editor": "Editor de latencias de RAM",
"RAM Timing Reductions": "Reducciones de tiempo de RAM", "RAM Timing Reductions": "Reducción de timings de RAM",
"Memory Timings": "Tiempos de memoria", "Memory Timings": "Timings de memoria",
"Advanced": "Avanzado", "Advanced": "Avanzado",
"t6 tRTW Fine Tune": "t6 tRTW Ajuste fino", "t6 tRTW Fine Tune": "Ajuste fino t6 tRTW",
"tRTW Fine Tune": "Ajuste fino tRTW", "tRTW Fine Tune": "Ajuste fino tRTW",
"t7 tWTR Fine Tune": "t7 tWTR Ajuste fino", "t7 tWTR Fine Tune": "Ajuste fino t7 tWTR",
"tWTR Fine Tune": "Ajuste fino de tWTR", "tWTR Fine Tune": "Ajuste fino tWTR",
"Memory Latencies": "Latencias de la memoria", "Memory Latencies": "Latencias de memoria",
"Read Latency": "Leer latencia", "Read Latency": "Latencia de lectura",
"Write Latency": "Latencia de escritura", "Write Latency": "Latencia de escritura",
"CPU Boost Clock": "Reloj de aumento de CPU", "CPU Boost Clock": "Frecuencia boost de CPU",
"CPU UV": "procesador ultravioleta", "CPU UV": "Undervolt de CPU",
"CPU Unlock": "Desbloqueo de CPU", "CPU Unlock": "Desbloqueo de CPU",
"CPU VMIN": "CPU VMIN", "CPU VMIN": "VMIN de CPU",
"CPU Max Voltage": "Voltaje máximo de la CPU", "CPU Max Voltage": "Voltaje máximo de CPU",
"CPU Max Clock": "Reloj máximo de CPU", "CPU Max Clock": "Frecuencia máxima de CPU",
"Extreme UV Table": "Mesa UV extrema", "Extreme UV Table": "Tabla de undervolt extrema",
"CPU UV Table": "Tabla UV de CPU", "CPU UV Table": "Tabla de undervolt de CPU",
"CPU Low UV": "CPU baja radiación ultravioleta", "CPU Low UV": "Undervolt bajo de CPU",
"CPU High UV": "CPU alta UV", "CPU High UV": "Undervolt alto de CPU",
"CPU Low VMIN": "VMIN bajo de CPU", "CPU Low VMIN": "VMIN bajo de CPU",
"CPU High VMIN": "VMIN alto de CPU", "CPU High VMIN": "VMIN alto de CPU",
"No Undervolt": "Sin subvoltaje", "No Undervolt": "Sin undervolt",
"SLT Table": "Mesa TR", "SLT Table": "Tabla SLT",
"HiOPT Table": "Tabla HiOPT", "HiOPT Table": "Tabla HiOPT",
"GPU Undervolt Table": "Tabla de subvoltaje de GPU", "GPU Undervolt Table": "Tabla de undervolt de GPU",
"GPU Minimum Voltage": "Voltaje mínimo de GPU", "GPU Minimum Voltage": "Voltaje mínimo de GPU",
"Calculate GPU Vmin": "Calcular GPU Vmin", "Calculate GPU Vmin": "Calcular Vmin de GPU",
"GPU VMIN": "GPU VMIN", "GPU VMIN": "VMIN de GPU",
"GPU Maximum Voltage": "Voltaje máximo de GPU", "GPU Maximum Voltage": "Voltaje máximo de GPU",
"GPU Voltage Offset": "Compensación de voltaje de GPU", "GPU Voltage Offset": "Offset de voltaje de GPU",
"Do not override": "no anular", "Do not override": "No sobrescribir",
"Enabled (Default)": "Habilitado (predeterminado)", "Enabled (Default)": "Activado (predeterminado)",
"96.6% limit": "límite del 96,6%", "96.6% limit": "Límite 96,6%",
"99.7% limit": "límite del 99,7%", "99.7% limit": "Límite 99,7%",
"GPU Scheduling Override": "Anulación de programación de GPU", "GPU Scheduling Override": "Sobrescritura de scheduling de GPU",
"Official Service": "Servicio Oficial", "Official Service": "Servicio oficial",
"GPU DVFS Mode": "Modo GPU DVFS", "GPU DVFS Mode": "Modo DVFS de GPU",
"GPU DVFS Offset": "Compensación DVFS de GPU", "GPU DVFS Offset": "Offset DVFS de GPU",
"GPU Voltage Table": "Tabla de voltaje de GPU", "GPU Voltage Table": "Tabla de voltaje de GPU",
"GPU Custom Table (mV)": "Tabla personalizada de GPU (mV)", "GPU Custom Table (mV)": "Tabla personalizada de GPU (mV)",
"1075MHz without UV, 1152MHz on SLT": "1075MHz sin UV, 1152MHz en SLT", "1075MHz without UV, 1152MHz on SLT": "1075MHz sin undervolt, 1152MHz en SLT",
"or 1228MHz on HiOPT can cause ": "o 1228MHz en HiOPT pueden causar", "or 1228MHz on HiOPT can cause ": "o 1228MHz en HiOPT pueden causar ",
"permanent damage to your Switch!": Daño permanente a tu Switch!", "permanent damage to your Switch!": daño permanente a tu Switch!",
"921MHz without UV and 960MHz on": "921MHz sin UV y 960MHz encendido", "921MHz without UV and 960MHz on": "921MHz sin undervolt y 960MHz en",
"SLT or HiOPT can cause ": "SLT o HiOPT pueden causar" "SLT or HiOPT can cause ": "SLT o HiOPT pueden causar "
} }

View File

@@ -1,11 +1,11 @@
{ {
"Information": "Informations", "Information": "Informations",
"IDDQ:": "IDDQ :", "IDDQ:": "IDDQ :",
"Module: ": "Module :", "Module: ": "Module :",
"sys-dock status:": "état du dock système :", "sys-dock status:": "Statut de sys-dock :",
"SaltyNX status:": "Statut SaltyNX :", "SaltyNX status:": "Statut de SaltyNX :",
"RR Display status:": "Etat d'affichage RR :", "RR Display status:": "Statut de l'affichage RR :",
"Wafer Position:": "Position de la plaquette :", "Wafer Position:": "Position du wafer :",
"Credits": "Crédits", "Credits": "Crédits",
"Developers": "Développeurs", "Developers": "Développeurs",
"Contributors": "Contributeurs", "Contributors": "Contributeurs",
@@ -15,127 +15,127 @@
"Installed": "Installé", "Installed": "Installé",
"Not Installed": "Non installé", "Not Installed": "Non installé",
"X: %u Y: %u": "X : %u Y : %u", "X: %u Y: %u": "X : %u Y : %u",
"THE BEER-WARE LICENSE": "LA LICENCE DE LA BIÈRE", "THE BEER-WARE LICENSE": "LA LICENCE BEER-WARE",
"Default": "Par défaut", "Default": "Par défaut",
"Do Not Override": "Ne pas remplacer", "Do Not Override": "Ne pas remplacer",
"Disabled": "Désactivé", "Disabled": "Désactivé",
"Enabled": "Activé", "Enabled": "Activé",
" \\ue0e3 Reset": "\\ue0e3 Réinitialiser", " \\ue0e3 Reset": "\\ue0e3 Réinitialiser",
"Display": "Affichage", "Display": "Écran",
"Application changed\\n\\n": "Application modifiée\\n\\n", "Application changed\\n\\n": "Application modifiée\\n\\n",
"The running application changed\\n\\n": "L'application en cours d'exécution a changé\\n\\n", "The running application changed\\n\\n": "L'application en cours d'exécution a changé\\n\\n",
"while editing was going on.": "pendant le montage.", "while editing was going on.": "pendant la modification.",
"Board": "Conseil", "Board": "Carte",
"%u.%u%u mV": "%u.%u%u mV", "%u.%u%u mV": "%u.%u%u mV",
"Could not connect to hoc-clk sysmodule.\\n\\n": "Impossible de se connecter au module système hoc-clk.\\n\\n", "Could not connect to hoc-clk sysmodule.\\n\\n": "Impossible de se connecter au sysmodule hoc-clk.\\n\\n",
"Please make sure everything is\\n\\n": "Veuillez vous assurer que tout est\\n\\n", "Please make sure everything is\\n\\n": "Veuillez vous assurer que tout est\\n\\n",
"correctly installed and enabled.": "correctement installé et activé.", "correctly installed and enabled.": "correctement installé et activé.",
"Fatal error": "Erreur fatale", "Fatal error": "Erreur fatale",
"Temporary Overrides ": "Remplacements temporaires", "Temporary Overrides ": "Forçages temporaires ",
"Sleep Mode": "Mode veille", "Sleep Mode": "Mode veille",
"Stock": "Actions", "Stock": "D'origine",
"Dev OC": "Développeur OC", "Dev OC": "OC Développeur",
"Boost Mode": "Mode Boost", "Boost Mode": "Mode Boost",
"Safe Max": "Coffre-fort maximum", "Safe Max": "Max sûr",
"Unsafe Max": "Dangereux Max", "Unsafe Max": "Max non sûr",
"Absolute Max": "Max absolu", "Absolute Max": "Max absolu",
"Handheld Safe Max": "Coffre-fort portatif Max", "Handheld Safe Max": "Max sûr (mode portable)",
"Enable": "Activer", "Enable": "Activer",
"Edit App Profile": "Modifier le profil de l'application", "Edit App Profile": "Modifier le profil de l'app",
"Edit Global Profile": "Modifier le profil global", "Edit Global Profile": "Modifier le profil global",
"Temporary Overrides": "Remplacements temporaires", "Temporary Overrides": "Forçages temporaires",
"Settings": "Paramètres", "Settings": "Paramètres",
"About": "À propos", "About": "À propos",
"Compiling with minimal features": "Compilation avec des fonctionnalités minimales", "Compiling with minimal features": "Compilation avec fonctionnalités minimales",
"General Settings": "Paramètres généraux", "General Settings": "Paramètres généraux",
"Governor Settings": "Paramètres du gouverneur", "Governor Settings": "Paramètres du gouverneur",
"Safety Settings": "Paramètres de sécurité", "Safety Settings": "Paramètres de sécurité",
"Save KIP Settings": "Enregistrer les paramètres KIP", "Save KIP Settings": "Enregistrer les paramètres KIP",
"RAM Settings": "Paramètres de la RAM", "RAM Settings": "Paramètres RAM",
"CPU Settings": "Paramètres du processeur", "CPU Settings": "Paramètres CPU",
"GPU Settings": "Paramètres du processeur graphique", "GPU Settings": "Paramètres GPU",
"Display Settings": "Paramètres d'affichage", "Display Settings": "Paramètres d'affichage",
"Experimental": "Expérimental", "Experimental": "Expérimental",
"GPU Scheduling Override Method": "Méthode de remplacement de la planification GPU", "GPU Scheduling Override Method": "Méthode de Forçage de l'ordonnancement GPU",
"can be dangerous and may cause": "peut être dangereux et provoquer", "can be dangerous and may cause": "peut être dangereux et causer des",
"damage to your battery or charger!": "dommages à votre batterie ou à votre chargeur !", "damage to your battery or charger!": "dommages à votre batterie ou chargeur !",
"Charge Current Override": "Remplacement du courant de charge", "Charge Current Override": "Forçage du courant de charge",
"RAM Voltage Display Mode": "Mode d'affichage de la tension de la RAM", "RAM Voltage Display Mode": "Mode d'affichage de la tension RAM",
"Polling Interval": "Intervalle d'interrogation", "Polling Interval": "Intervalle d'interrogation",
"CPU Governor Minimum Frequency": "Fréquence minimale du gouverneur du processeur", "CPU Governor Minimum Frequency": "Fréquence minimale du gouverneur CPU",
"refresh rates may cause stress": "les taux de rafraîchissement peuvent causer du stress", "refresh rates may cause stress": "les taux de rafraîchissement peuvent stresser",
"or damage to your display! ": "ou endommager votre écran !", "or damage to your display! ": "ou endommager votre écran !",
"Proceed at your own risk!": "Procédez à vos propres risques !", "Proceed at your own risk!": "À utiliser à vos propres risques !",
"Max Handheld Display": "Affichage portable maximum", "Max Handheld Display": "Affichage portable max",
"Display Clock": "Affichage de l'horloge", "Display Clock": "Fréquence d'affichage",
"Official Rating": "Classement officiel", "Official Rating": "Classement officiel",
"TDP Threshold": "Seuil TDP", "TDP Threshold": "Seuil TDP",
"Power": "Puissance", "Power": "Alimentation",
"Thermal Throttle Limit": "Limite d'accélérateur thermique", "Thermal Throttle Limit": "Limite d'étranglement thermique",
"HP Mode": "Mode HP", "HP Mode": "Mode HP",
"Default (Mariko)": "Par défaut (Mariko)", "Default (Mariko)": "Par défaut (Mariko)",
"Default (Erista)": "Par défaut (Erista)", "Default (Erista)": "Par défaut (Erista)",
"Rating": "Note", "Rating": "Évaluation",
"Safe Max (Mariko)": "Coffre-fort Max (Mariko)", "Safe Max (Mariko)": "Max sûr (Mariko)",
"Safe Max (Erista)": "Coffre-fort Max (Erista)", "Safe Max (Erista)": "Max sûr (Erista)",
"RAM VDD2 Voltage": "Tension de la RAM VDD2", "RAM VDD2 Voltage": "Tension RAM VDD2",
"Voltage": "Tension", "Voltage": "Tension",
"RAM VDDQ Voltage": "Tension VDDQ de la RAM", "RAM VDDQ Voltage": "Tension RAM VDDQ",
"RAM Frequency Editor": "Éditeur de fréquence RAM", "RAM Frequency Editor": "Éditeur de fréquence RAM",
"JEDEC.": "JEDEC.", "JEDEC.": "JEDEC.",
"High speedo needed!": "Besoin d'un speedo haut !", "High speedo needed!": "Speedo élevé requis !",
"3333MHz (Needs extreme Speedo/PLL)": "3333 MHz (nécessite un Speedo/PLL extrême)", "3333MHz (Needs extreme Speedo/PLL)": "3333 MHz (nécessite Speedo/PLL extrême)",
"3366MHz (Needs extreme Speedo/PLL)": "3366 MHz (nécessite un Speedo/PLL extrême)", "3366MHz (Needs extreme Speedo/PLL)": "3366 MHz (nécessite Speedo/PLL extrême)",
"3400MHz (Needs extreme Speedo/PLL)": "3400 MHz (nécessite un Speedo/PLL extrême)", "3400MHz (Needs extreme Speedo/PLL)": "3400 MHz (nécessite Speedo/PLL extrême)",
"3433MHz (Needs ridiculous Speedo/PLL)": "3433 MHz (nécessite un Speedo/PLL ridicule)", "3433MHz (Needs ridiculous Speedo/PLL)": "3433 MHz (nécessite Speedo/PLL ridicule)",
"3466MHz (Needs ridiculous Speedo/PLL)": "3466 MHz (nécessite un Speedo/PLL ridicule)", "3466MHz (Needs ridiculous Speedo/PLL)": "3466 MHz (nécessite Speedo/PLL ridicule)",
"3500MHz (Needs ridiculous Speedo/PLL)": "3500 MHz (nécessite un Speedo/PLL ridicule)", "3500MHz (Needs ridiculous Speedo/PLL)": "3500 MHz (nécessite Speedo/PLL ridicule)",
"Ram Max Clock": "Ram Max Horloge", "Ram Max Clock": "Fréquence RAM max",
"RAM Latency Editor": "Éditeur de latence RAM", "RAM Latency Editor": "Éditeur de latence RAM",
"RAM Timing Reductions": "Réductions de synchronisation de la RAM", "RAM Timing Reductions": "Réductions des timings RAM",
"Memory Timings": "Horaires de mémoire", "Memory Timings": "Timings mémoire",
"Advanced": "Avancé", "Advanced": "Avancé",
"t6 tRTW Fine Tune": "t6 tRTW réglage fin", "t6 tRTW Fine Tune": "Ajustement précis t6 tRTW",
"tRTW Fine Tune": "tRTW Réglage fin", "tRTW Fine Tune": "Ajustement précis tRTW",
"t7 tWTR Fine Tune": "t7 tWTR réglage fin", "t7 tWTR Fine Tune": "Ajustement précis t7 tWTR",
"tWTR Fine Tune": "Réglage fin du tWTR", "tWTR Fine Tune": "Ajustement précis tWTR",
"Memory Latencies": "Latences de mémoire", "Memory Latencies": "Latences mémoire",
"Read Latency": "Latence de lecture", "Read Latency": "Latence de lecture",
"Write Latency": "Latence d'écriture", "Write Latency": "Latence d'écriture",
"CPU Boost Clock": "Horloge d'augmentation du processeur", "CPU Boost Clock": "Fréquence Boost CPU",
"CPU UV": "UV du processeur", "CPU UV": "UV CPU",
"CPU Unlock": "Déverrouillage du processeur", "CPU Unlock": "Déverrouillage CPU",
"CPU VMIN": "CPU VMIN", "CPU VMIN": "CPU VMIN",
"CPU Max Voltage": "Tension maximale du processeur", "CPU Max Voltage": "Tension CPU max",
"CPU Max Clock": "Horloge maximale du processeur", "CPU Max Clock": "Fréquence CPU max",
"Extreme UV Table": "Table UV Extrême", "Extreme UV Table": "Table d'UV extrême",
"CPU UV Table": "Tableau UV du processeur", "CPU UV Table": "Table d'UV CPU",
"CPU Low UV": "CPU faible UV", "CPU Low UV": "UV CPU faible",
"CPU High UV": "CPU UV élevé", "CPU High UV": "UV CPU élevé",
"CPU Low VMIN": "CPU faible VMIN", "CPU Low VMIN": "VMIN CPU faible",
"CPU High VMIN": "Processeur VMIN élevé", "CPU High VMIN": "VMIN CPU élevé",
"No Undervolt": "Pas de sous-tension", "No Undervolt": "Aucun Undervolt",
"SLT Table": "Tableau SLT", "SLT Table": "Table SLT",
"HiOPT Table": "Tableau HiOPT", "HiOPT Table": "Table HiOPT",
"GPU Undervolt Table": "Tableau de sous-tension GPU", "GPU Undervolt Table": "Table d'undervolt GPU",
"GPU Minimum Voltage": "Tension minimale du GPU", "GPU Minimum Voltage": "Tension GPU minimale",
"Calculate GPU Vmin": "Calculer la Vmin du GPU", "Calculate GPU Vmin": "Calculer Vmin GPU",
"GPU VMIN": "GPU VMIN", "GPU VMIN": "GPU VMIN",
"GPU Maximum Voltage": "Tension maximale du GPU", "GPU Maximum Voltage": "Tension GPU maximale",
"GPU Voltage Offset": "Décalage de tension du GPU", "GPU Voltage Offset": "Offset de tension GPU",
"Do not override": "Ne remplacez pas", "Do not override": "Ne pas remplacer",
"Enabled (Default)": "Activé (par défaut)", "Enabled (Default)": "Activé (par défaut)",
"96.6% limit": "Limite de 96,6 %", "96.6% limit": "Limite de 96,6 %",
"99.7% limit": "Limite de 99,7 %", "99.7% limit": "Limite de 99,7 %",
"GPU Scheduling Override": "Remplacement de la planification GPU", "GPU Scheduling Override": "Forçage de l'ordonnancement GPU",
"Official Service": "Service officiel", "Official Service": "Service officiel",
"GPU DVFS Mode": "Mode GPU DVFS", "GPU DVFS Mode": "Mode GPU DVFS",
"GPU DVFS Offset": "Décalage GPU DVFS", "GPU DVFS Offset": "Offset GPU DVFS",
"GPU Voltage Table": "Tableau de tension du GPU", "GPU Voltage Table": "Table de tension GPU",
"GPU Custom Table (mV)": "Tableau personnalisé GPU (mV)", "GPU Custom Table (mV)": "Table de GPU personnalisée (mV)",
"1075MHz without UV, 1152MHz on SLT": "1075 MHz sans UV, 1152 MHz sur SLT", "1075MHz without UV, 1152MHz on SLT": "1075 MHz sans UV, 1152 MHz sur SLT",
"or 1228MHz on HiOPT can cause ": "ou 1228 MHz sur HiOPT peut provoquer", "or 1228MHz on HiOPT can cause ": "ou 1228 MHz sur HiOPT peut causer des",
"permanent damage to your Switch!": "dommages permanents à votre Switch !", "permanent damage to your Switch!": "dommages permanents à votre Switch !",
"921MHz without UV and 960MHz on": "921 MHz sans UV et 960 MHz activé", "921MHz without UV and 960MHz on": "921 MHz sans UV et 960 MHz sur",
"SLT or HiOPT can cause ": "SLT ou HiOPT peuvent provoquer" "SLT or HiOPT can cause ": "SLT ou HiOPT peuvent causer des"
} }

View File

@@ -1,141 +1,179 @@
{ {
"Information": "Информация", "Information": "Информация",
"IDDQ:": "ИДДК:", "IDDQ:": "IDDQ:",
"Module: ": "Модуль:", "Module: ": "Module:",
"sys-dock status:": "Статус системной док-станции:", "sys-dock status:": "Статус sys-dock:",
"SaltyNX status:": "Статус SaltyNX:", "SaltyNX status:": "Статус SaltyNX:",
"RR Display status:": "Статус отображения RR:", "RR Display status:": "Статус RR Display:",
"Wafer Position:": "Позиция вафли:", "Wafer Position:": "Wafer Position:",
"Credits": "Кредиты", "Credits": "Благодарности",
"Developers": "Разработчики", "Developers": "Разработчики",
"Contributors": "Авторы", "Contributors": "Внесли вклад",
"Testers": "Тестеры", "Testers": "Тестеры",
"Special Thanks": "Особая благодарность", "Special Thanks": "Особая благодарность",
"Unknown": "Неизвестно", "Unknown": "Неизвестно",
"Installed": "Установлено", "Installed": "Установлено",
"Not Installed": "Не установлено", "Not Installed": "Не установлено",
"X: %u Y: %u": "X: %u Y: %u", "X: %u Y: %u": "X: %u Y: %u",
"THE BEER-WARE LICENSE": "ЛИЦЕНЗИЯ НА ПРОДАЖУ ПИВА", "THE BEER-WARE LICENSE": "BEER-WARE LICENSE",
"Default": "По умолчанию", "Default": "По умолчанию",
"Do Not Override": "Не переопределять", "Do Not Override": "Не менять",
"Disabled": "Отключено", "Disabled": "Отключено",
"Enabled": "Включено", "Enabled": "Включено",
"Auto": "Авто",
" \\ue0e3 Reset": "\\ue0e3 Сброс", " \\ue0e3 Reset": "\\ue0e3 Сброс",
"Display": "Дисплей", "Display": "Дисплей",
"Application changed\\n\\n": "Приложение изменено\\n\\n", "Application changed\\n\\n": "Приложение изменено\\n\\n",
"The running application changed\\n\\n": "Запущенное приложение изменилось\\n\\n", "The running application changed\\n\\n": "Запущенное приложение изменилось\\n\\n",
"while editing was going on.": "пока шло редактирование.", "while editing was going on.": "пока шло редактирование.",
"Board": "Совет", "Board": "Board",
"%u.%u%u mV": "%u.%u%u мВ", "%u.%u%u mV": "%u.%u%u мВ",
"Could not connect to hoc-clk sysmodule.\\n\\n": "Не удалось подключиться к системному модулю hoc-clk.\\n\\n", "Could not connect to hoc-clk sysmodule.\\n\\n": "Не удалось подключиться к сис-модулю hoc-clk.\\n\\n",
"Please make sure everything is\\n\\n": "Пожалуйста, убедитесь, что все в порядке\\n\\n", "Please make sure everything is\\n\\n": "Пожалуйста, убедитесь, что все\\n\\n",
"correctly installed and enabled.": "правильно установлен и включен.", "correctly installed and enabled.": "правильно установлено и включено.",
"Fatal error": "Неустранимая ошибка", "Fatal error": "Фатальная ошибка",
"Temporary Overrides ": "Временные переопределения", "Temporary Overrides ": "Временный профиль",
"Sleep Mode": "Спящий режим", "Sleep Mode": "Спящий режим",
"Stock": "Акции", "Stock": "Стандарт",
"Dev OC": "Разработчик OC", "Dev OC": "Разгон dev-кита",
"Boost Mode": "Режим повышения", "Boost Mode": "Режим буста",
"Safe Max": "Сейф Макс", "Safe Max": "Безопасный макс.",
"Unsafe Max": "Небезопасный Макс", "Unsafe Max": "Опасный макс.",
"Absolute Max": "Абсолютный Макс", "Absolute Max": "Абсолютный макс.",
"Handheld Safe Max": "Ручной сейф Макс", "Handheld Safe Max": "Портативный безопасный макс.",
"Enable": "Включить", "Enable": "Включено",
"Edit App Profile": "Редактировать профиль приложения", "Edit App Profile": "Профиль приложения",
"Edit Global Profile": "Редактировать глобальный профиль", "Edit Global Profile": "Глобальный профиль",
"Temporary Overrides": "Временные переопределения", "Temporary Overrides": "Временный профиль",
"Settings": "Настройки", "Settings": "Настройки",
"About": "О", "About": "Сведения",
"Compiling with minimal features": "Компиляция с минимальными возможностями", "Compiling with minimal features": "Собрано с урезанием функций",
"General Settings": "Общие настройки", "\uE150 Settings marked in blue": "Настройки помеченные синим",
"Governor Settings": "Настройки губернатора", "don't require a reboot to apply!": "Синие настройки применяются сразу!",
"General Settings": "Основные настройки",
"Governor Settings": "Настройки говернора",
"Safety Settings": "Настройки безопасности", "Safety Settings": "Настройки безопасности",
"Save KIP Settings": "Сохранить настройки КИП", "Save KIP Settings": "Сохранить настройки KIP",
"RAM Settings": "Настройки ОЗУ", "RAM Settings": "Настройки RAM",
"CPU Settings": "Настройки процессора", "CPU Settings": "Настройки CPU",
"GPU Settings": "Настройки графического процессора", "GPU Settings": "Настройки GPU",
"Display Settings": "Настройки дисплея", "Display Settings": "Настройки дисплея",
"Experimental": "Экспериментальный", "Experimental": "Экспериментальный",
"GPU Scheduling Override Method": "Метод переопределения планирования графического процессора", "Enable Experimental Settings": "Экспериментальные настройки",
"can be dangerous and may cause": "может быть опасным и может вызвать", "\uE150 Experimental Settings are incomplete ": "Экспериментальные настройки не закончены",
"damage to your battery or charger!": "повреждение аккумулятора или зарядного устройства!", "and may not work correctly or at all!": "Экспериментальные настройки не",
"Charge Current Override": "Блокировка зарядного тока", "Here be dragons!": "закончены и могут не работать!",
"RAM Voltage Display Mode": "Режим отображения напряжения ОЗУ", "Experimental Settings": "Экспериментальные",
"Live CPU Undervolt": "Мгновенный андервольт CPU",
"GPU Scheduling Override Method": "Метод перезаписи планировщика GPU",
"Memory Frequency Measurement Mode": "Режим измерения частоты RAM",
"\uE150 Overriding the charge current": "Перезапись зарядного тока может",
"can be dangerous and may cause": "Перезапись зарядного тока может",
"damage to your battery or charger!": "повреждить аккумулятор или зарядку!",
"Charge Current Override": "Перезапись зарядного тока",
"RAM Voltage Display Mode": "Показ вольтажа RAM",
"RAM Display Unit": "Показ единицы измерения RAM",
"Polling Interval": "Интервал опроса", "Polling Interval": "Интервал опроса",
"CPU Governor Minimum Frequency": "Минимальная частота регулятора ЦП", "CPU Governor Minimum Frequency": "Минимальная частота говернора CPU",
"refresh rates may cause stress": "частота обновления может вызвать стресс", "\uE150 Usage of unsafe display": "\uE150 Использование не безопасной",
"or damage to your display! ": "или повреждение дисплея!", "refresh rates may cause stress": "Не безопасная частота",
"or damage to your display! ": "может повредить ваш экран",
"Proceed at your own risk!": "Действуйте на свой страх и риск!", "Proceed at your own risk!": "Действуйте на свой страх и риск!",
"Max Handheld Display": "Макс. портативный дисплей", "Max Handheld Display Hz": "Макс. в портативе",
"Display Clock": "Дисплей Часы", "Display Clock": "Частота экрана",
"Official Rating": "Официальный рейтинг", "Official Rating": "Официальный рейтинг",
"TDP Threshold": "Порог TDP", "TDP Threshold": "Порог TDP",
"Power": "Мощность", "Power": "Мощность",
"Thermal Throttle Limit": "Температурный предел дроссельной заслонки", "Thermal Throttle Limit": "Предел троттлинга",
"HP Mode": "Режим HP", "HP Mode": "Режим HP",
"Default (Mariko)": "По умолчанию (Марико)", "Default (Mariko)": "По умолчанию (M)",
"Default (Erista)": "По умолчанию (Эриста)", "Default (Erista)": "По умолчанию (E)",
"Rating": "Рейтинг", "Rating": "Рейтинг",
"Safe Max (Mariko)": "Сейф Макс (Марико)", "Safe Max (Mariko)": "Сейф Макс (M)",
"Safe Max (Erista)": "Сейф Макс (Эриста)", "Safe Max (Erista)": "Сейф Макс (E)",
"RAM VDD2 Voltage": "Напряжение ОЗУ VDD2", "RAM VDD2 Voltage": "Вольтаж VDD2",
"Voltage": "Напряжение", "Voltage": "Вольтаж",
"RAM VDDQ Voltage": "Напряжение ОЗУ VDDQ", "RAM VDDQ Voltage": "Вольтаж VDDQ",
"RAM Frequency Editor": "Редактор частоты оперативной памяти", "Step Mode": "Частотный шаг",
"JEDEC.": "ДЖЕДЕК.", "RAM Frequency Editor": "Редактор частоты",
"High speedo needed!": "Нужен высокий спидометр!", "JEDEC.": "JEDEC.",
"3333MHz (Needs extreme Speedo/PLL)": "3333 МГц (требуется экстремальный спидометр/PLL)", "High speedo needed!": "Для высоких speedo",
"3366MHz (Needs extreme Speedo/PLL)": "3366 МГц (требуется экстремальный спидометр/PLL)", "3333MHz (Needs extreme Speedo/PLL)": "3333 MHz (нужны невероятные speedo/PLL)",
"3400MHz (Needs extreme Speedo/PLL)": "3400 МГц (требуется экстремальный спидометр/PLL)", "3366MHz (Needs extreme Speedo/PLL)": "3366 MHz (нужны невероятные speedo/PLL)",
"3433MHz (Needs ridiculous Speedo/PLL)": "3433 МГц (нужен нелепый спидометр/PLL)", "3400MHz (Needs extreme Speedo/PLL)": "3400 MHz (нужны невероятные speedo/PLL)",
"3466MHz (Needs ridiculous Speedo/PLL)": "3466 МГц (нужен нелепый спидометр/PLL)", "3433MHz (Needs ridiculous Speedo/PLL)": "3433 MHz (нужны безумные speedo/PLL)",
"3500MHz (Needs ridiculous Speedo/PLL)": "3500 МГц (нужен нелепый спидометр/PLL)", "3466MHz (Needs ridiculous Speedo/PLL)": "3466 MHz (нужны безумные speedo/PLL)",
"Ram Max Clock": "Рам Макс Часы", "3500MHz (Needs ridiculous Speedo/PLL)": "3500 MHz (нужны безумные speedo/PLL)",
"RAM Latency Editor": "Редактор задержки оперативной памяти", "Ram Max Clock": "Макс. частота",
"RAM Timing Reductions": "Сокращение таймингов ОЗУ", "RAM Latency Editor": "Редактор задержек",
"Memory Timings": "Тайминги памяти", "1333 Latency Max": "1333 задержка",
"Advanced": "Расширенный", "1600 Latency Max": "1600 задержка",
"t6 tRTW Fine Tune": "t6 tRTW Точная настройка", "1866 Latency Max": "1866 задержка",
"tRTW Fine Tune": "tRTW Точная настройка", "2133 Latency Max": "2133 задержка",
"t7 tWTR Fine Tune": "t7 tWTR Тонкая настройка", "RAM Timing Reductions": "Настройка таймингов",
"tWTR Fine Tune": "tWTR Тонкая настройка", "Memory Timings": "Тайминги RAM",
"RAM-Timing tBreak": "Разбитие таблицы таймингов",
"Memory": "RAM",
"mem": "RAM",
"MEM": "RAM",
"Profile": "Профиль",
"Governor": "Говернор",
"Advanced": "Расширенные",
"Docked": "В доке",
"Handheld": "Портатив",
"Charging": "На зарядке",
"USB Charger": "USB Зарядка",
"PD Charger": "PD Зарядка",
"Handheld TDP": "TPD в портативе",
"Thermal Throttle": "Троттлинг",
"Uncapped Clocks": "Максимальные частоты",
"SoC DVB Shift": "SoC DVB сдвиг",
"SoC Max Volt": "Макс. вольт SoC",
"Overwrite Boost Mode": "Перезапись буста",
"Display Refresh Rate Changing": "Изменение частоты экрана",
"Low t6 tRTW": "Нижний t6 tRTW",
"Low t7 tWTR": "Нижний t7 tWTR",
"1333WL t2 RP Cap": "Предел 1333WL t2 RP",
"t6 tRTW Fine Tune": " Точная настройка t6 tRTW",
"tRTW Fine Tune": " Точная настройка tRTW",
"t7 tWTR Fine Tune": " Точная настройка t7 tWTR",
"tWTR Fine Tune": " Точная настройка tWTR",
"Memory Latencies": "Задержки памяти", "Memory Latencies": "Задержки памяти",
"Read Latency": "Задержка чтения", "Read Latency": "Задержка чтения",
"Write Latency": "Задержка записи", "Write Latency": "Задержка записи",
"CPU Boost Clock": "Тактовая частота процессора", "CPU Boost Clock": "Частота буста",
"CPU UV": "УФ процессора", "CPU UV": "Андервольт CPU",
"CPU Unlock": "Разблокировка процессора", "CPU Unlock": "Разблокировка CPU",
"CPU VMIN": "ЦП VMIN", "CPU VMIN": "Мин. вольтаж",
"CPU Max Voltage": "Максимальное напряжение процессора", "CPU Max Voltage": "Макс. вольтаж",
"CPU Max Clock": "Максимальная частота процессора", "CPU Max Clock": "Макс. частота",
"Extreme UV Table": "Стол для экстремального УФ-излучения", "Extreme UV Table": "Экстримальная",
"CPU UV Table": "UV-таблица процессора", "CPU UV Table": "Таблица андервольта",
"CPU Low UV": "ЦП с низким УФ-излучением", "CPU Low UV": "Андервольт нижних частот",
"CPU High UV": "Процессор с высоким УФ", "CPU High UV": "Андервольт верхних частот",
"CPU Low VMIN": "Низкий VMIN процессора", "CPU Low VMIN": "Мин. вольт. нижних частот",
"CPU High VMIN": "Высокий VMIN процессора", "CPU High VMIN": "Мин. вольт. верхних частот",
"No Undervolt": "Нет Андервольта", "No Undervolt": "Без андервольта",
"SLT Table": "Таблица ТА", "SLT Table": "Таблица SLT",
"HiOPT Table": "Таблица HiOPT", "HiOPT Table": "Таблица HiOPT",
"GPU Undervolt Table": "Таблица пониженного напряжения графического процессора", "GPU Undervolt Table": "Таблица андервольта",
"GPU Minimum Voltage": "Минимальное напряжение графического процессора", "GPU Minimum Voltage": "Мин. вольтаж",
"Calculate GPU Vmin": "Рассчитать Vmin графического процессора", "Calculate GPU Vmin": "Вычисление мин. вольтаж",
"GPU VMIN": "Вмин графического процессора", "GPU VMIN": "Мин. вольтаж",
"GPU Maximum Voltage": "Максимальное напряжение графического процессора", "GPU Maximum Voltage": "Макс. вольтаж",
"GPU Voltage Offset": "Смещение напряжения графического процессора", "GPU Voltage Offset": "Смещение вольтажа",
"Do not override": "Не переопределять", "Do not override": "Не менять",
"Enabled (Default)": "Включено (по умолчанию)", "Enabled (Default)": "Включено (По умолчанию)",
"96.6% limit": "Предел 96,6%", "96.6% limit": "96,6%",
"99.7% limit": "лимит 99,7%", "99.7% limit": "99,7%",
"GPU Scheduling Override": "Переопределение планирования графического процессора", "GPU Scheduling Override": "Перезапись планировщика",
"Official Service": "Официальная служба", "Official Service": "Официальная служба",
"GPU DVFS Mode": "Режим графического процессора DVFS", "GPU DVFS Mode": "Режим DVFS",
"GPU DVFS Offset": "Смещение DVFS графического процессора", "GPU DVFS Offset": "Смещение DVFS",
"GPU Voltage Table": "Таблица напряжений графического процессора", "GPU Voltage Table": "Таблица вольтажей",
"GPU Custom Table (mV)": "Пользовательская таблица графического процессора (мВ)", "GPU Custom Table (mV)": "Ручная таблица (мВ)",
"1075MHz without UV, 1152MHz on SLT": "1075 МГц без УФ, 1152 МГц на SLT", "\uE150 Setting GPU Clocks past": "\uE150 Установка частот GPU выше",
"or 1228MHz on HiOPT can cause ": "или 1228 МГц на HiOPT может привести к", "1228MHz without a proper undervolt": "Установка частот GPU выше 1228 МГц",
"permanent damage to your Switch!": "необратимое повреждение вашего коммутатора!", "can cause degradation or damage": "без хорошего андервольта может",
"921MHz without UV and 960MHz on": "921 МГц без УФ и 960 МГц с включенным", "to your console!": "повредить вашу консоль!"
"SLT or HiOPT can cause ": "SLT или HiOPT могут вызвать"
} }

View File

@@ -29,7 +29,6 @@
#include <tesla.hpp> #include <tesla.hpp>
#include "ui/gui/fatal_gui.h" #include "ui/gui/fatal_gui.h"
#include "ui/gui/main_gui.h" #include "ui/gui/main_gui.h"
#include "rgltr_services.h" // for extern Service g_rgltrSrv, etc.
class AppOverlay : public tsl::Overlay class AppOverlay : public tsl::Overlay
{ {
@@ -42,7 +41,6 @@ class AppOverlay : public tsl::Overlay
//} //}
virtual void exitServices() override { virtual void exitServices() override {
rgltrExit();
hocclkIpcExit(); hocclkIpcExit();
} }

View File

@@ -30,6 +30,7 @@
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include <cstdint> #include <cstdint>
#include <hocclk/board.h>
#define FREQ_DEFAULT_TEXT "Do not override" #define FREQ_DEFAULT_TEXT "Do not override"
@@ -44,4 +45,53 @@ static inline std::string formatListFreqMHz(std::uint32_t mhz)
return std::string(buf, snprintf(buf, sizeof(buf), "%u MHz", mhz)); return std::string(buf, snprintf(buf, sizeof(buf), "%u MHz", mhz));
} }
static inline std::string formatListFreqHz(std::uint32_t hz) { return formatListFreqMHz(hz / 1000000); } static inline std::string formatListFreqHz(uint32_t hz) { return formatListFreqMHz(hz / 1000000); }
static inline std::string formatListFreqMem(uint32_t mhz, RamDisplayUnit unit)
{
if(mhz == 0)
return FREQ_DEFAULT_TEXT;
uint32_t mts = mhz * 2;
char buf[24];
switch(unit)
{
case RamDisplayUnit_MHz:
snprintf(buf, sizeof(buf), "%u MHz", mhz);
break;
case RamDisplayUnit_MHzMTs:
snprintf(buf, sizeof(buf), "%u MHz (%u MT/s)", mhz, mts);
break;
case RamDisplayUnit_MTs:
default:
snprintf(buf, sizeof(buf), "%u MT/s", mts);
break;
}
return buf;
}
static inline std::string formatListFreqHzMem(uint32_t hz, RamDisplayUnit unit)
{
return formatListFreqMem(hz / 1000000, unit);
}
static inline std::string formatMemClockKhzLabel(uint32_t khz, RamDisplayUnit unit)
{
uint32_t mhz = khz / 1000;
uint32_t mts = khz / 500;
char buf[32];
switch(unit)
{
case RamDisplayUnit_MHz:
snprintf(buf, sizeof(buf), "%u MHz", mhz);
break;
case RamDisplayUnit_MHzMTs:
snprintf(buf, sizeof(buf), "%u MHz (%u MT/s)", mhz, mts);
break;
case RamDisplayUnit_MTs:
default:
snprintf(buf, sizeof(buf), "%u MT/s", mts);
break;
}
return buf;
}

View File

@@ -22,6 +22,8 @@
#include "cat.h" #include "cat.h"
#include "ult_ext.h" #include "ult_ext.h"
// tsl::elm::ListItem* custRevItem = NULL;
tsl::elm::ListItem* kipVersionItem = NULL;
tsl::elm::ListItem* SpeedoItem = NULL; tsl::elm::ListItem* SpeedoItem = NULL;
tsl::elm::ListItem* IddqItem = NULL; tsl::elm::ListItem* IddqItem = NULL;
tsl::elm::ListItem* DramModule = NULL; tsl::elm::ListItem* DramModule = NULL;
@@ -32,6 +34,13 @@ tsl::elm::ListItem* waferCordsItem = NULL;
tsl::elm::ListItem* ramVoltItem = NULL; tsl::elm::ListItem* ramVoltItem = NULL;
tsl::elm::ListItem* eristaPLLXItem = NULL; tsl::elm::ListItem* eristaPLLXItem = NULL;
tsl::elm::ListItem* dispVoltItem = NULL; tsl::elm::ListItem* dispVoltItem = NULL;
tsl::elm::ListItem* ramBWItemAll = NULL;
tsl::elm::ListItem* ramBWItemCpu = NULL;
tsl::elm::ListItem* ramBWItemGpu = NULL;
tsl::elm::ListItem* ramBWItemMax = NULL;
tsl::elm::ListItem* bqtempitem = NULL;
tsl::elm::ListItem* aotagTempItem = NULL;
tsl::elm::ListItem* cTypeItem = NULL;
ImageElement* CatImage = NULL; ImageElement* CatImage = NULL;
HideableCategoryHeader* CatHeader = NULL; HideableCategoryHeader* CatHeader = NULL;
@@ -49,24 +58,71 @@ AboutGui::~AboutGui()
void AboutGui::listUI() void AboutGui::listUI()
{ {
BaseMenuGui::refresh();
if (!this->context)
return;
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::CategoryHeader("Information") new tsl::elm::CategoryHeader("Voltages")
); );
ramVoltItem = ramVoltItem =
new tsl::elm::ListItem("RAM Voltage:"); new tsl::elm::ListItem("RAM Voltage:");
this->listElement->addItem(ramVoltItem);
if(IsMariko()) {
this->listElement->addItem(ramVoltItem);
}
dispVoltItem = dispVoltItem =
new tsl::elm::ListItem("Display Voltage:"); new tsl::elm::ListItem("Display Voltage:");
this->listElement->addItem(dispVoltItem); this->listElement->addItem(dispVoltItem);
this->listElement->addItem(
new tsl::elm::CategoryHeader("Temperatures")
);
eristaPLLXItem = eristaPLLXItem =
new tsl::elm::ListItem("PLLX Temp:"); new tsl::elm::ListItem("PLLX Temp:");
if(IsErista()) { if(this->context->temps[HocClkThermalSensor_AO] > 0) { // Only show if the value is valid (not -126, which means not patched)
this->listElement->addItem(eristaPLLXItem); this->listElement->addItem(eristaPLLXItem);
} }
aotagTempItem =
new tsl::elm::ListItem("AOTAG Temp:");
this->listElement->addItem(aotagTempItem);
bqtempitem =
new tsl::elm::ListItem("BQ24193 Temp:");
this->listElement->addItem(bqtempitem);
this->listElement->addItem(
new tsl::elm::CategoryHeader("RAM Bandwidth")
);
ramBWItemMax =
new tsl::elm::ListItem("RAM BW (Peak):");
this->listElement->addItem(ramBWItemMax);
ramBWItemAll =
new tsl::elm::ListItem("RAM BW (All):");
this->listElement->addItem(ramBWItemAll);
ramBWItemCpu =
new tsl::elm::ListItem("RAM BW (CPU):");
this->listElement->addItem(ramBWItemCpu);
ramBWItemGpu =
new tsl::elm::ListItem("RAM BW (GPU):");
this->listElement->addItem(ramBWItemGpu);
this->listElement->addItem(
new tsl::elm::CategoryHeader("Hardware Info")
);
cTypeItem =
new tsl::elm::ListItem("Console Type:");
this->listElement->addItem(cTypeItem);
SpeedoItem = SpeedoItem =
new tsl::elm::ListItem("Speedo:"); new tsl::elm::ListItem("Speedo:");
this->listElement->addItem(SpeedoItem); this->listElement->addItem(SpeedoItem);
@@ -76,9 +132,29 @@ void AboutGui::listUI()
this->listElement->addItem(IddqItem); this->listElement->addItem(IddqItem);
DramModule = DramModule =
new tsl::elm::ListItem("Module: "); new tsl::elm::ListItem("DRAM Module: ");
this->listElement->addItem(DramModule); this->listElement->addItem(DramModule);
waferCordsItem =
new tsl::elm::ListItem("Wafer Position:");
this->listElement->addItem(waferCordsItem);
if(IsHoag()) {
RETROStatusItem =
new tsl::elm::ListItem("RR Display status:");
this->listElement->addItem(RETROStatusItem);
}
this->listElement->addItem(
new tsl::elm::CategoryHeader("Software Info")
);
// custRevItem = new tsl::elm::ListItem("CUST revision:");
// this->listElement->addItem(custRevItem);
kipVersionItem = new tsl::elm::ListItem("KIP version:");
this->listElement->addItem(kipVersionItem);
if(!IsHoag()) { if(!IsHoag()) {
sysdockStatusItem = sysdockStatusItem =
new tsl::elm::ListItem("sys-dock status:"); new tsl::elm::ListItem("sys-dock status:");
@@ -89,16 +165,6 @@ void AboutGui::listUI()
new tsl::elm::ListItem("SaltyNX status:"); new tsl::elm::ListItem("SaltyNX status:");
this->listElement->addItem(saltyNXStatusItem); this->listElement->addItem(saltyNXStatusItem);
if(IsHoag()) {
RETROStatusItem =
new tsl::elm::ListItem("RR Display status:");
this->listElement->addItem(RETROStatusItem);
}
waferCordsItem =
new tsl::elm::ListItem("Wafer Position:");
this->listElement->addItem(waferCordsItem);
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::CategoryHeader("Credits") new tsl::elm::CategoryHeader("Credits")
); );
@@ -140,13 +206,25 @@ void AboutGui::listUI()
new tsl::elm::ListItem("Blaise25") new tsl::elm::ListItem("Blaise25")
); );
// ---- Testers ----
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::CategoryHeader("Testers") new tsl::elm::ListItem("tetetete-ctrl")
); );
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("Dom") new tsl::elm::ListItem("B3711")
);
this->listElement->addItem(
new tsl::elm::ListItem("TDRR")
);
this->listElement->addItem(
new tsl::elm::ListItem("MasaGratoR")
);
// ---- Testers ----
this->listElement->addItem(
new tsl::elm::CategoryHeader("Testers")
); );
this->listElement->addItem( this->listElement->addItem(
@@ -154,7 +232,7 @@ void AboutGui::listUI()
); );
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("Delta") new tsl::elm::ListItem("arcdelta")
); );
this->listElement->addItem( this->listElement->addItem(
@@ -165,10 +243,6 @@ void AboutGui::listUI()
new tsl::elm::ListItem("Happy") new tsl::elm::ListItem("Happy")
); );
this->listElement->addItem(
new tsl::elm::ListItem("Flopsider")
);
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("Winnerboi77") new tsl::elm::ListItem("Winnerboi77")
); );
@@ -185,10 +259,6 @@ void AboutGui::listUI()
new tsl::elm::ListItem("Alvise") new tsl::elm::ListItem("Alvise")
); );
this->listElement->addItem(
new tsl::elm::ListItem("TDRR")
);
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("agjeococh") new tsl::elm::ListItem("agjeococh")
); );
@@ -207,7 +277,7 @@ void AboutGui::listUI()
); );
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("ScriesM - Atmosphere CFW") new tsl::elm::ListItem("SciresM - Atmosphere CFW")
); );
this->listElement->addItem( this->listElement->addItem(
@@ -215,27 +285,23 @@ void AboutGui::listUI()
); );
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("hanai3bi - Switch OC Suite & EOS") new tsl::elm::ListItem("hanai3Bi - Switch OC Suite & EOS")
); );
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("NaGaa95 - L4T-OC-Kernel") new tsl::elm::ListItem("NaGaa95 - L4T-OC-Kernel")
); );
this->listElement->addItem(
new tsl::elm::ListItem("B3711 - EOS")
);
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("RetroNX - sys-clk") new tsl::elm::ListItem("RetroNX - sys-clk")
); );
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("b0rd2death - Ultrahand") new tsl::elm::ListItem("ppkantorski - Ultrahand")
); );
this->listElement->addItem( this->listElement->addItem(
new tsl::elm::ListItem("MasaGratoR - Status Monitor") new tsl::elm::ListItem("CtCaer - Hekate, L4T and Proper Timings")
); );
// Create cat elements but hide them initially // Create cat elements but hide them initially
@@ -313,6 +379,10 @@ void AboutGui::refresh()
SpeedoItem->setValue(strings[0]); SpeedoItem->setValue(strings[0]);
IddqItem->setValue(strings[1]); IddqItem->setValue(strings[1]);
DramModule->setValue(formatRamModule()); DramModule->setValue(formatRamModule());
// custRevItem->setValue(std::to_string(this->context->custRev));
kipVersionItem->setValue(std::to_string((this->context->kipVersion / 100) % 10) + "." + std::to_string((this->context->kipVersion / 10) % 10) + "." + std::to_string( this->context->kipVersion % 10) + " (Cust Rev " + std::to_string(this->context->custRev) + ")");
if(!IsHoag()) if(!IsHoag())
sysdockStatusItem->setValue(this->context->isSysDockInstalled ? "Installed" : "Not Installed"); sysdockStatusItem->setValue(this->context->isSysDockInstalled ? "Installed" : "Not Installed");
@@ -321,14 +391,22 @@ void AboutGui::refresh()
if(IsHoag()) if(IsHoag())
RETROStatusItem->setValue(this->context->isUsingRetroSuper ? "Installed" : "Not Installed"); RETROStatusItem->setValue(this->context->isUsingRetroSuper ? "Installed" : "Not Installed");
sprintf(strings[2], "X: %u Y: %u", this->context->waferX, this->context->waferY); sprintf(strings[2], "X: %d Y: %d", this->context->waferX, this->context->waferY);
waferCordsItem->setValue(strings[2]); waferCordsItem->setValue(strings[2]);
if(IsErista()) { s32 millis = context->temps[HocClkThermalSensor_PLLX];
u32 millis = context->temps[HocClkThermalSensor_PLLX]; sprintf(strings[3], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
sprintf(strings[3], "%u.%u", millis / 1000U, (millis % 1000U) / 100U); eristaPLLXItem->setValue(strings[3]);
eristaPLLXItem->setValue(strings[3]);
millis = context->temps[HocClkThermalSensor_AO];
if(millis > 0) {
sprintf(strings[11], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
} else if (millis == -125) {
sprintf(strings[11], "Invalid");
} else if (millis == -126) {
sprintf(strings[11], "Not Patched");
} }
aotagTempItem->setValue(strings[11]);
sprintf(strings[4], "%u.%u / %u mV", context->voltages[HocClkVoltage_EMCVDD2] / 1000U, (context->voltages[HocClkVoltage_EMCVDD2] % 1000U) / 100U, context->voltages[HocClkVoltage_EMCVDDQ] / 1000); sprintf(strings[4], "%u.%u / %u mV", context->voltages[HocClkVoltage_EMCVDD2] / 1000U, (context->voltages[HocClkVoltage_EMCVDD2] % 1000U) / 100U, context->voltages[HocClkVoltage_EMCVDDQ] / 1000);
ramVoltItem->setValue(strings[4]); ramVoltItem->setValue(strings[4]);
@@ -336,4 +414,37 @@ void AboutGui::refresh()
sprintf(strings[5], "%u.%u mV", context->voltages[HocClkVoltage_Display] / 1000U, (context->voltages[HocClkVoltage_Display] % 1000U) / 100U); sprintf(strings[5], "%u.%u mV", context->voltages[HocClkVoltage_Display] / 1000U, (context->voltages[HocClkVoltage_Display] % 1000U) / 100U);
dispVoltItem->setValue(strings[5]); dispVoltItem->setValue(strings[5]);
sprintf(strings[6], "%u MB/s", context->partLoad[HocClkPartLoad_RamBWAll]);
ramBWItemAll->setValue(strings[6]);
sprintf(strings[7], "%u MB/s", context->partLoad[HocClkPartLoad_RamBWCpu]);
ramBWItemCpu->setValue(strings[7]);
sprintf(strings[8], "%u MB/s", context->partLoad[HocClkPartLoad_RamBWGpu]);
ramBWItemGpu->setValue(strings[8]);
sprintf(strings[9], "%u MB/s", context->partLoad[HocClkPartLoad_RamBWPeak]);
ramBWItemMax->setValue(strings[9]);
switch(context->temps[HocClkThermalSensor_BQ24193]) {
case BQ24193Temp_Normal:
strcpy(strings[10], "Normal");
break;
case BQ24193Temp_Warm:
strcpy(strings[10], "Warm");
break;
case BQ24193Temp_Hot:
strcpy(strings[10], "Hot");
break;
case BQ24193Temp_Overheat:
strcpy(strings[10], "Overheat");
break;
default:
strcpy(strings[10], "Unknown");
}
bqtempitem->setValue(strings[10]);
cTypeItem->setValue(hocClkFormatConsoleType(this->context->consoleType, true));
} }

View File

@@ -59,9 +59,11 @@ void AppProfileGui::openFreqChoiceGui(tsl::elm::ListItem* listItem, HocClkProfil
} else if (module == HocClkModule_GPU) { } else if (module == HocClkModule_GPU) {
labels = IsMariko() ? *(marikoUV[configList.values[KipConfigValue_marikoGpuUV]]) : *(eristaUV[configList.values[KipConfigValue_eristaGpuUV]]); labels = IsMariko() ? *(marikoUV[configList.values[KipConfigValue_marikoGpuUV]]) : *(eristaUV[configList.values[KipConfigValue_eristaGpuUV]]);
} }
tsl::changeTo<FreqChoiceGui>(this->profileList->mhzMap[profile][module] * 1000000, hzList, hzCount, module, [this, listItem, profile, module](std::uint32_t hz) { RamDisplayUnit memUnit = (RamDisplayUnit)configList.values[HocClkConfigValue_RamDisplayUnit];
tsl::changeTo<FreqChoiceGui>(this->profileList->mhzMap[profile][module] * 1000000, hzList, hzCount, module, [this, listItem, profile, module, memUnit](std::uint32_t hz) {
this->profileList->mhzMap[profile][module] = hz / 1000000; this->profileList->mhzMap[profile][module] = hz / 1000000;
listItem->setValue(formatListFreqMHz(this->profileList->mhzMap[profile][module])); std::uint32_t mhz = this->profileList->mhzMap[profile][module];
listItem->setValue(module == HocClkModule_MEM ? formatListFreqMem(mhz, memUnit) : formatListFreqMHz(mhz));
Result rc = hocclkIpcSetProfiles(this->applicationId, this->profileList); Result rc = hocclkIpcSetProfiles(this->applicationId, this->profileList);
if(R_FAILED(rc)) if(R_FAILED(rc))
{ {
@@ -104,8 +106,10 @@ void AppProfileGui::openValueChoiceGui(
void AppProfileGui::addModuleListItem(HocClkProfile profile, HocClkModule module) void AppProfileGui::addModuleListItem(HocClkProfile profile, HocClkModule module)
{ {
tsl::elm::ListItem* listItem = new tsl::elm::ListItem(hocclkFormatModule(module, true)); tsl::elm::ListItem* listItem = new tsl::elm::ListItem(hocclkFormatModule(module, true));
listItem->setValue(formatListFreqMHz(this->profileList->mhzMap[profile][module])); RamDisplayUnit memUnit = (RamDisplayUnit)configList.values[HocClkConfigValue_RamDisplayUnit];
listItem->setClickListener([this, listItem, profile, module](u64 keys) { std::uint32_t mhz = this->profileList->mhzMap[profile][module];
listItem->setValue(module == HocClkModule_MEM ? formatListFreqMem(mhz, memUnit) : formatListFreqMHz(mhz));
listItem->setClickListener([this, listItem, profile, module, memUnit](u64 keys) {
if((keys & HidNpadButton_A) == HidNpadButton_A) if((keys & HidNpadButton_A) == HidNpadButton_A)
{ {
this->openFreqChoiceGui(listItem, profile, module); this->openFreqChoiceGui(listItem, profile, module);
@@ -115,7 +119,7 @@ void AppProfileGui::addModuleListItem(HocClkProfile profile, HocClkModule module
{ {
// Reset to "Default" (0 MHz) // Reset to "Default" (0 MHz)
this->profileList->mhzMap[profile][module] = 0; this->profileList->mhzMap[profile][module] = 0;
listItem->setValue(formatListFreqMHz(0)); listItem->setValue(module == HocClkModule_MEM ? formatListFreqMem(0, memUnit) : formatListFreqMHz(0));
Result rc = hocclkIpcSetProfiles(this->applicationId, this->profileList); Result rc = hocclkIpcSetProfiles(this->applicationId, this->profileList);
if(R_FAILED(rc)) if(R_FAILED(rc))
@@ -286,6 +290,9 @@ public:
: applicationId(appId), profileList(pList), profile(prof) {} : applicationId(appId), profileList(pList), profile(prof) {}
void listUI() override { void listUI() override {
BaseMenuGui::refresh(); // get latest context
if(!this->context)
return;
Result rc = hocclkIpcGetConfigValues(&configList); Result rc = hocclkIpcGetConfigValues(&configList);
if (R_FAILED(rc)) [[unlikely]] { if (R_FAILED(rc)) [[unlikely]] {
FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc);
@@ -296,7 +303,7 @@ public:
static constexpr struct { const char* label; int shift; } kAll[] = { static constexpr struct { const char* label; int shift; } kAll[] = {
{"CPU", 0}, {"GPU", 8}, {"VRR", 16} {"CPU", 0}, {"GPU", 8}, {"VRR", 16}
}; };
int count = configList.values[HocClkConfigValue_OverwriteRefreshRate] ? 3 : 2; int count = configList.values[HocClkConfigValue_OverwriteRefreshRate] || this->context->isUsingRetroSuper ? 3 : 2;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
u8 cur = (this->profileList->mhzMap[this->profile][HocClkModule_Governor] >> kAll[i].shift) & 0xFF; u8 cur = (this->profileList->mhzMap[this->profile][HocClkModule_Governor] >> kAll[i].shift) & 0xFF;

View File

@@ -28,7 +28,6 @@
#include "base_menu_gui.h" #include "base_menu_gui.h"
#include "freq_choice_gui.h" #include "freq_choice_gui.h"
#include "value_choice_gui.h" #include "value_choice_gui.h"
#define HOCCLK_GLOBAL_PROFILE_TID 0xA111111111111111
class AppProfileGui : public BaseMenuGui class AppProfileGui : public BaseMenuGui
{ {
protected: protected:

View File

@@ -48,10 +48,10 @@ std::string getVersionString() {
return std::string(buf); return std::string(buf);
} }
static constexpr tsl::Color dynamicLogoRGB1 = tsl::Color(0, 4, 8, 15); static constexpr tsl::Color dynamicLogoRGB1 = tsl::Color(0, 15, 3, 15);
static constexpr tsl::Color dynamicLogoRGB2 = tsl::Color(7, 15, 15, 15); static constexpr tsl::Color dynamicLogoRGB2 = tsl::Color(0, 8, 1, 15);
static constexpr tsl::Color STATIC_AQUA = tsl::Color(2, 10, 12, 15); static constexpr tsl::Color STATIC_GREEN = tsl::Color(0, 15, 0, 15);
const std::string name = "Horizon OC Zeus"; const std::string name = "Horizon OC Gaea";
static s32 drawDynamicUltraText( static s32 drawDynamicUltraText(
tsl::gfx::Renderer* renderer, tsl::gfx::Renderer* renderer,
@@ -100,12 +100,12 @@ static s32 drawDynamicUltraText(
g = std::clamp<u8>(g, 0, 15); g = std::clamp<u8>(g, 0, 15);
b = std::clamp<u8>(b, 0, 15); b = std::clamp<u8>(b, 0, 15);
bool lightning = (fmod(timeNow, 5.0) < 0.15); // bool lightning = (fmod(timeNow, 5.0) < 0.15);
if (lightning) { // if (lightning) {
r = std::min<u8>(r + 4, 15); // r = std::min<u8>(r + 4, 15);
g = std::min<u8>(g + 4, 15); // g = std::min<u8>(g + 4, 15);
b = std::min<u8>(b + 15, 15); // b = std::min<u8>(b + 15, 15);
} // }
tsl::Color color(r, g, b, 15); tsl::Color color(r, g, b, 15);
@@ -126,7 +126,7 @@ void BaseGui::preDraw(tsl::gfx::Renderer* renderer) {
LOGO_X, LOGO_X,
LOGO_Y, LOGO_Y,
LOGO_LABEL_FONT_SIZE, LOGO_LABEL_FONT_SIZE,
STATIC_AQUA, STATIC_GREEN,
false false
); );
} }

View File

@@ -27,6 +27,7 @@
#include "base_menu_gui.h" #include "base_menu_gui.h"
#include "fatal_gui.h" #include "fatal_gui.h"
#include "../format.h"
// Cache hardware model to avoid repeated syscalls // Cache hardware model to avoid repeated syscalls
@@ -57,8 +58,8 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
if(!this->context) [[unlikely]] return; if(!this->context) [[unlikely]] return;
// All constants pre-calculated and cached // All constants pre-calculated and cached
static constexpr const char* const labels[] = { const char* labels[] = {
"App ID", "Profile", "CPU", "GPU", "MEM", "SoC", "Board", "Skin", "Now", "Avg", "BAT", "PMIC", "FAN", "DISP", "FPS", "RES" "App ID", "Profile", "CPU", "GPU", "MEM", "SoC", "Board", "Skin", "Now", "Avg", "BAT", "PMIC", "Fan", IsAula() ? "OLED" : "LCD", "FPS", "RES"
}; };
static constexpr u32 dataPositions[6] = {63-3+3, 200-1, 344-1-3, 200-1, 342-1, 321-1}; static constexpr u32 dataPositions[6] = {63-3+3, 200-1, 344-1-3, 200-1, 342-1, 321-1};
@@ -121,7 +122,7 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
// === VOLTAGES === // === VOLTAGES ===
renderer->drawString(displayStrings[8], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU voltage renderer->drawString(displayStrings[8], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU voltage
renderer->drawString(displayStrings[9], false, dataPositions[1] + 9, y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU voltage renderer->drawString(displayStrings[9], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU voltage
renderer->drawStringWithColoredSections(displayStrings[10], false, {""}, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor, tsl::separatorColor); renderer->drawStringWithColoredSections(displayStrings[10], false, {""}, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor, tsl::separatorColor);
@@ -139,8 +140,8 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
// Temperatures with color - use pre-computed colors // Temperatures with color - use pre-computed colors
renderer->drawString(displayStrings[11], false, dataPositions[0] - 1, y, SMALL_TEXT_SIZE, tempColors[HocClkThermalSensor_SOC]); // SOC renderer->drawString(displayStrings[11], false, dataPositions[0] - 1, y, SMALL_TEXT_SIZE, tempColors[HocClkThermalSensor_SOC]); // SOC
renderer->drawString(displayStrings[12], false, dataPositions[1] + 5, y, SMALL_TEXT_SIZE, tempColors[HocClkThermalSensor_PCB]); // PCB renderer->drawString(displayStrings[12], false, dataPositions[1], y, SMALL_TEXT_SIZE, tempColors[HocClkThermalSensor_PCB]); // PCB
renderer->drawString(displayStrings[13], false, dataPositions[2] + 6, y, SMALL_TEXT_SIZE, tempColors[HocClkThermalSensor_Skin]); // Skin renderer->drawString(displayStrings[13], false, dataPositions[2], y, SMALL_TEXT_SIZE, tempColors[HocClkThermalSensor_Skin]); // Skin
y += 20; // Direct assignment (191 + 20) y += 20; // Direct assignment (191 + 20)
@@ -229,7 +230,20 @@ void BaseMenuGui::refresh()
sprintf(displayStrings[3], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U); sprintf(displayStrings[3], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
hz = context->freqs[HocClkModule_MEM]; // MEM hz = context->freqs[HocClkModule_MEM]; // MEM
sprintf(displayStrings[4], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U); std::uint32_t unit = configList.values[HocClkConfigValue_RamDisplayUnit];
std::uint32_t mhz = hz / 1000000U;
std::uint32_t mts = mhz * 2;
std::uint32_t tenth = (hz / 100000U) % 10U;
if(unit == RamDisplayUnit_MTs)
sprintf(displayStrings[4], "%u MT/s", mts);
else if(unit == RamDisplayUnit_MHz)
sprintf(displayStrings[4], "%u.%u MHz", mhz, tenth);
else if(unit == RamDisplayUnit_MHzMTs) {
hz = context->realFreqs[HocClkModule_MEM];
mhz = hz / 1000000U;
tenth = (hz / 100000U) % 10U;
sprintf(displayStrings[4], "%u.%u MHz", mhz, tenth);
}
// Real frequencies // Real frequencies
hz = context->realFreqs[HocClkModule_CPU]; // CPU hz = context->realFreqs[HocClkModule_CPU]; // CPU
@@ -239,7 +253,14 @@ void BaseMenuGui::refresh()
sprintf(displayStrings[6], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U); sprintf(displayStrings[6], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
hz = context->realFreqs[HocClkModule_MEM]; // MEM hz = context->realFreqs[HocClkModule_MEM]; // MEM
sprintf(displayStrings[7], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U); unit = configList.values[HocClkConfigValue_RamDisplayUnit];
mhz = hz / 1000000U;
mts = mhz * 2;
tenth = (hz / 100000U) % 10U;
if(unit == RamDisplayUnit_MTs || unit == RamDisplayUnit_MHzMTs)
sprintf(displayStrings[7], "%u MT/s", mts);
else
sprintf(displayStrings[7], "%u.%u MHz", mhz, tenth);
// Voltages // Voltages
sprintf(displayStrings[8], "%.1f mV", context->voltages[HocClkVoltage_CPU] / 1000.0); sprintf(displayStrings[8], "%.1f mV", context->voltages[HocClkVoltage_CPU] / 1000.0);

View File

@@ -0,0 +1,552 @@
/*
*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "config_info_strings.h"
std::vector<std::string> ConfigInfoStrings(HocClkConfigValue val, bool isMariko, bool isHoag)
{
switch (val)
{
case HocClkConfigValue_PollingIntervalMs:
return {
"The interval (in milliseconds) where clocks are applied, temperatures and voltages are polled and logs are written (if enabled).",
"Higher values may cause more delay between changing a setting and it taking effect, and lower values may increase sysmodule memory usage",
"Default: 300ms"
};
case HocClkConfigValue_RamDisplayUnit:
return {
"The unit used when displaying RAM frequency values.",
"Options:",
"- MHz: Megahertz (e.g. 1600 MHz)",
"- MT/s: MegaTransfers per second (e.g. 3200 MT/s)",
"- MHz and MT/s: Display in both MHz and MT/s",
"Default: MHz"
};
case HocClkConfigValue_RAMVoltDisplayMode:
return {
"The method used to display RAM voltage values.",
"Options:",
"- VDD2 - Display VDD2 voltage",
"- VDDQ - Display VDDQ voltage",
"Default: VDD2"
};
case HocClkConfigValue_EnableExperimentalSettings:
return {
"When enabled, shows settings that are still being tested and may be unstable or not work at all.",
"Use with caution and report any issues to the developers."
};
case HocClkConfigValue_MarikoMiddleFreqs:
return {
"Allows usage of frequencies stepped by 38.4MHz instead of 76.8MHz below 1228MHz GPU clock",
"Default: OFF"
};
case HocClkConfigValue_LiveCpuUv:
return {
"Allows changing CPU undervolt settings without a reboot",
"Default: OFF"
};
case HocClkConfigValue_GPUSchedulingMethod:
return {
"Method used for GPU scheduling override",
"Options:",
"- INI: override via system_settings.ini",
"- NV Service: override via nvservices sysmodule (experimental)",
"Default: INI"
};
case HocClkConfigValue_MemoryFrequencyMeasurementMode:
return {
"How the RAM real frequency is measured",
"Options:",
"- PLL: Measure from PLLMB and PLLM (more accurate)",
"- Actmon: Measure from Actmon (less accurate)",
"Default: PLL"
};
case HocClkConfigValue_BatteryChargeCurrent:
return {
"Overrides the charge current to the battery. Use with caution!",
isHoag ? "Default: 1664 mA" : "2048 mA"
};
case HocClkConfigValue_AulaDisplayColorPreset:
return {
"Current display color preset. Default is Basic",
"Options:",
"- Saturated: Based on Vivid but over-saturated.",
"- Washed: Washed out colors.",
"- Basic: Real natural profile.",
"- Natural: Not actually natural.. Extra saturation.",
"- Vivid: Saturated.",
"Default: Do not override"
};
case HocClkConfigValue_CpuGovernorMinimumFreq:
return {
"The minimum frequency that the CPU governor will allow.",
"Default: 612MHz"
};
case HocClkConfigValue_OverwriteRefreshRate:
return {
"Controls the availability of display refresh rate features.",
"When enabled, allows changing the display refresh rate and using display refresh rate related features.",
"This feature conflicts with FPSLocker's feature that does the same thing.",
"Default: OFF"
};
case HocClkConfigValue_MaxDisplayClockH:
return {
"The maximum display clock frequency in handheld mode (in Hz).",
"Warning: Changing this value may cause instability or display damage.",
"Default: 60 Hz"
};
case HocClkConfigValue_DisplayVoltage:
return {
"The voltage supplied to the display panel (in mV).",
"Warning: Changing this value may cause instability.",
"Default: 1200mV"
};
case HocClkConfigValue_UncappedClocks:
if(isMariko) {
return {
"When enabled, disables clock cappings",
"Warning: Enabling this may cause damage to your device without a proper undervolt. Use with caution!",
"Clock cappings:",
"- Handheld:",
" - GPU (HiOPT): 614 MHz",
" - GPU (HiOPT - 15mV): 691 MHz",
" - GPU (High UV): 768 MHz",
"- USB Charger",
" - GPU (HiOPT): 844 MHz",
" - GPU (HiOPT - 15mV): 921 MHz",
" - GPU (High UV): 998 MHz",
"- PD Charger / Docked:",
" - No capping applied",
"Default: OFF"
};
} else {
return {
"When enabled, disables clock cappings",
"Warning: Enabling this may cause damage to your device without a proper undervolt. Use with caution!",
"Clock cappings:",
"- Handheld:",
" - GPU: 460 MHz",
" - CPU: 1581 MHz",
"- USB Charger",
" - GPU: 768 MHz",
"- PD Charger / Docked:",
" - No capping applied",
"Default: OFF"
};
}
case HocClkConfigValue_ThermalThrottle:
return {
"If enabled, Resets to stock clocks after the threshold is applied",
"Default: ON",
};
case HocClkConfigValue_HandheldTDP:
return {
"If enabled, Resets to stock clocks when power consumption is above the threshold in handheld mode",
"Default: ON",
};
case HocClkConfigValue_HandheldTDPLimit:
case HocClkConfigValue_LiteTDPLimit:
return {
"The power consumption threshold (in mW) for resetting to stock clocks in handheld mode when Handheld TDP is enabled.",
isHoag ? "Default: 6400mW" : "Default: 9600mW"
};
case HocClkConfigValue_ThermalThrottleThreshold:
return {
"The temperature threshold (in °C) for resetting to stock clocks when Thermal Throttle is enabled.",
"Default: 70°C"
};
case KipConfigValue_emcDvbShift:
return {
"Each level adds/removes 25mV from the SOC Voltage table",
"Consoles are bracketed by SoC Speedo. The brackets are as follows:",
" - Speedo 1487-1598: Bracket 0",
" - Speedo 1598-1709: Bracket 1",
" - Speedo 1709-1820: Bracket 2",
"Default: 0"
};
case KipConfigValue_marikoSocVmax:
return {
"The maximum available SOC Voltage that the DVB-adjusted table can use",
"Default: Do not override"
};
case KipConfigValue_hpMode:
return {
"When enabled, disables RAM powerdown. Helps with latency significantly",
"Default: OFF"
};
case KipConfigValue_commonEmcMemVolt:
return {
"RAM VDD2 voltage",
"Increasing this WILL NOT increase your maximum frequency, but may help with timing reduction.",
"Undervolting RAM is pointless and may hurt performance and stability",
"Default: 1175 mV"
};
case KipConfigValue_marikoEmcVddqVolt:
return {
"RAM VDDQ voltage",
"Increasing this may help, but the default value is usually good enough.",
"Undervolting RAM is pointless and may hurt performance and stability",
"Default: 600 mV"
};
case KipConfigValue_stepMode:
return {
"The step that RAM clocks take.",
"Options (with examples):",
" - 66MHz - 66 MHz step (ex. 1600, 1666, 1733, etc.)",
" - 100MHz - 100 MHz step (ex. 1600, 1700, 1800, etc.)",
" - 133MHz - 66 MHz step (ex. 1600, 1733, 1866, etc.)",
" - JEDEC:",
" - 1600, 1866, 1996, 2133, 2400, 2666, 2933 and 3200 MHz are used",
"The RAM max clock will always be available regardless of the step mode, but the intermediate frequencies will be limited by the selected step mode.",
"This setting does not affect performance and the option you choose mostly is based on your personal taste",
"33 MHz step mode is not possible due to certain limitations of Horizon OS",
"Default: 66 MHz",
};
case KipConfigValue_marikoEmcMaxClock:
return {
"The maximum RAM frequency available.",
"Higher frequencies may cause instability, so increase this gradually and test for stability.",
"Default: 2133 MHz"
};
case KipConfigValue_eristaEmcMaxClock:
case KipConfigValue_eristaEmcMaxClock1:
case KipConfigValue_eristaEmcMaxClock2:
return {
"The RAM frequency used in the particular slot. Higher frequencies may cause instability, so increase this gradually and test for stability.",
"Default: Disabled (1600 MHz)"
};
case KipConfigValue_t1_tRCD:
return {
"RAS-to-CAS delay",
"Default: 0"
};
case KipConfigValue_t2_tRP:
return {
"Row precharge time",
"Default: 0"
};
case KipConfigValue_t3_tRAS:
return {
"Row active time",
"Default: 0"
};
case KipConfigValue_t4_tRRD:
return {
"Row refresh time",
"Default: 0"
};
case KipConfigValue_t5_tRFC:
return {
"Refresh Cycle Time",
"Default: 0"
};
case KipConfigValue_t6_tRTW:
return {
"Read To Write (High bracket)",
"Default: 0"
};
case KipConfigValue_t7_tWTR:
return {
"Write To Read (High bracket)",
"Default: 0"
};
case KipConfigValue_t8_tREFI:
return {
"Refresh command interval",
"Default: 0"
};
case KipConfigValue_timingEmcTbreak:
return {
"Frequency where t6 and t7 break between the low and high brackets",
"Example:",
"Tbreak is set to 1866 MHz, and t6Low is set to 4 and t6High is set to 2. At frequencies below 1866 MHz, t6 will be 4, and at frequencies above 1866 MHz, t6 will be 2.",
"Default: Disabled"
};
case KipConfigValue_low_t6_tRTW:
return {
"Read To Write (Low bracket)",
"Default: 0"
};
case KipConfigValue_low_t7_tWTR:
return {
"Write To Read (Low bracket)",
"Default: 0"
};
case KipConfigValue_t2_tRP_cap:
return {
"Cap for t2 when 1333WL is used.",
"The default value is sufficient for most RAMs but some may need a lower value",
"Default: 2"
};
case KipConfigValue_t6_tRTW_fine_tune:
return {
"Fine-tunes the raw calculation of t6",
"Default: 0"
};
case KipConfigValue_t7_tWTR_fine_tune:
return {
"Fine-tunes the raw calculation of t7",
"Default: 0"
};
case KipConfigValue_write_latency_1333:
case KipConfigValue_write_latency_1600:
case KipConfigValue_write_latency_1866:
case KipConfigValue_write_latency_2133:
case KipConfigValue_read_latency_1333:
case KipConfigValue_read_latency_1600:
case KipConfigValue_read_latency_1866:
case KipConfigValue_read_latency_2133:
return {
"Latency bracket settings",
"Example:",
"If 1333 is set to 2000 MHz, 1600 set to 2500 MHz, 1866 set to 2766 MHz and 2133 set to 2933 MHz:",
"Frequencies below 2000 MHz use 1333, 2033-2500 MHz use 1600, 2533-2766 MHz use 1866 and 2800-2933 MHz use 2133. ",
"Either of these can be omitted and it will work (say you set 1333 to -, then <2000 MHz will use 1600 latency)",
"If all of these parameters are omitted the latency will automatically be calculated as follows:",
"1633-1866 MHz - 1866 WRL",
"1900+ MHz - 2133 WRL",
"These properties apply for both write and read latencies, and you can mix-and-match the brackets if necessary",
"Default: -"
};
case KipConfigValue_mem_burst_read_latency:
return {
"The read latency for the ram",
"Default: 1600 RL"
};
case KipConfigValue_mem_burst_write_latency:
return {
"The write latency for the ram",
"Default: 1600 WL"
};
case KipConfigValue_marikoCpuUVLow:
return {
"The CPU UV level used before tBreak",
"Default: 0"
};
case KipConfigValue_marikoCpuUVHigh:
return {
"The CPU UV level used after tBreak",
"Default: 0"
};
case KipConfigValue_tableConf:
return {
"The current UV table used. The tbreaks are as follows:",
"1581 MHz tBreak and 1683 MHz tBreak use their respective tBreaks",
"The other tables use 1581 MHz as tBreak",
"The \"Default\" table does not contain frequencies past 1963 MHz and may not undervolt correctly"
};
case KipConfigValue_marikoCpuLowVmin:
return {
"The CPU vmin used before tBreak",
"Default: 620 mV"
};
case KipConfigValue_marikoCpuHighVmin:
return {
"The CPU vmin used after tBreak",
"Default: 750 mV"
};
case KipConfigValue_marikoCpuMaxVolt:
return {
"The maximum voltage that the CPU can use",
"Change this setting with caution!",
"Default: 1120 mV"
};
case KipConfigValue_marikoCpuMaxClock:
return {
"The maximum available CPU clock",
"Default: 1963 MHz"
};
case KipConfigValue_marikoCpuBoostClock:
return {
"The clock used for the CPU in \"boost mode\"",
"Default: 1963 MHz"
};
case KipConfigValue_eristaCpuUV:
return {
"CPU undervolt level",
"Default: 0"
};
case KipConfigValue_eristaCpuUnlock:
return {
"Unlock unsafe CPU clocks",
"Default: OFF"
};
case KipConfigValue_eristaCpuVmin:
return {
"Minimum CPU voltage",
"Default: 825 mV"
};
case KipConfigValue_eristaCpuMaxVolt:
return {
"Maximum CPU voltage",
"Default: 1235 mV"
};
case HocClkConfigValue_EristaMaxCpuClock:
return {
"The maximum available CPU clock",
"Default: 1785 MHz"
};
case KipConfigValue_eristaCpuBoostClock:
return {
"The clock used for the CPU in \"boost mode\"",
"Default: 1785 MHz"
};
case HocClkConfigValue_OverwriteBoostMode:
return {
"If enabled, profiles can override the boost mode setting",
"Default: OFF"
};
case KipConfigValue_marikoGpuUV:
return {
"GPU undervolt level",
"Options:",
" - HiOPT: L4T Custom HiOPT table",
" - HiOPT - 15mV: L4T Custom HiOPT table with a 15mV offset",
" - High UV: The highest undervolt table, recommended",
"Default: HiOPT"
};
case KipConfigValue_marikoGpuVmin:
return {
"Minimum GPU voltage",
"Note: DVFS may change this value when the RAM clock is changed if the DVFS mode is set to PCV Hijack",
"Default: 610 mV"
};
case KipConfigValue_marikoGpuVmax:
return {
"Maximum GPU voltage",
"Default: 800 mV"
};
case HocClkConfigValue_DVFSMode:
return {
"The mode used for GPU DVFS",
"Adjusts GPU vmin when RAM clock is changed due to a higher requirement",
"Options:",
"- Disabled: disabled...",
"- PCV Hijack: hijack PCV for override",
"Default: PCV Hijack"
};
case HocClkConfigValue_DVFSOffset:
return {
"The offset added/subtracted to the GPU vmin when the RAM clock is changed due to a higher requirement in PCV Hijack mode",
"Default: 0 mV (Disabled)"
};
case KipConfigValue_eristaGpuUV:
return {
"GPU undervolt level",
"Options:",
" - HiOPT: L4T Custom HiOPT table",
" - HiOPT - 15mV: L4T Custom HiOPT table with a 15mV offset",
" - High UV: The highest undervolt table, recommended",
"Default: HiOPT"
};
case KipConfigValue_eristaGpuVmin:
return {
"Minimum GPU voltage",
"Default: 810 mV (812mV as erista is stepped by 6.5mV instead of 5mV)"
};
case KipConfigValue_commonGpuVoltOffset:
return {
"The offset added/subtracted to all AUTO GPU voltages",
"Default: 0 mV (Disabled)"
};
case HocClkConfigValue_GPUScheduling:
return {
"The scheduling method used for GPU clocks",
"Options:",
"- Do Not Override: Do not override existing scheduling mode",
"- Disabled: Disables GPU scheduling, 99.7% GPU max load",
"- Enabled: Enables GPU scheduling, 96.5% GPU max load",
"Default: Do not override"
};
case KipConfigValue_marikoGpuBootVolt:
return {
"The voltage supplied to the GPU during boot and when the temperature is below 20°C (in mV).",
"Warning: Changing this value may cause instability.",
"Default: 800mV"
};
default:
return {};
}
}

View File

@@ -0,0 +1,23 @@
/*
*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "misc_gui.h"
#include <vector>
#include <string>
std::vector<std::string> ConfigInfoStrings(HocClkConfigValue val, bool isMariko, bool isHoag);

View File

@@ -55,7 +55,11 @@ FreqChoiceGui::~FreqChoiceGui()
tsl::elm::ListItem* FreqChoiceGui::createFreqListItem(std::uint32_t hz, bool selected, int safety) tsl::elm::ListItem* FreqChoiceGui::createFreqListItem(std::uint32_t hz, bool selected, int safety)
{ {
std::string text = formatListFreqHz(hz); std::string text;
if(module == HocClkModule_MEM)
text = formatListFreqHzMem(hz, (RamDisplayUnit)this->configList->values[HocClkConfigValue_RamDisplayUnit]);
else
text = formatListFreqHz(hz);
std::string rightText = ""; std::string rightText = "";
auto it = labels.find(hz); auto it = labels.find(hz);

View File

@@ -246,7 +246,8 @@ void GlobalOverrideGui::addModuleListItem(HocClkModule module)
{ {
tsl::elm::ListItem *listItem = tsl::elm::ListItem *listItem =
new tsl::elm::ListItem(hocclkFormatModule(module, true)); new tsl::elm::ListItem(hocclkFormatModule(module, true));
listItem->setValue(formatListFreqMHz(0)); RamDisplayUnit memUnit = (RamDisplayUnit)configList.values[HocClkConfigValue_RamDisplayUnit];
listItem->setValue(module == HocClkModule_MEM ? formatListFreqMem(0, memUnit) : formatListFreqMHz(0));
listItem->setClickListener([this, module](u64 keys) { listItem->setClickListener([this, module](u64 keys) {
if ((keys & HidNpadButton_A) == HidNpadButton_A) { if ((keys & HidNpadButton_A) == HidNpadButton_A) {
this->openFreqChoiceGui(module); this->openFreqChoiceGui(module);
@@ -262,7 +263,7 @@ void GlobalOverrideGui::addModuleListItem(HocClkModule module)
this->context->overrideFreqs[module] = 0; this->context->overrideFreqs[module] = 0;
this->listHz[module] = 0; this->listHz[module] = 0;
this->listItems[module]->setValue(formatListFreqHz(0)); this->listItems[module]->setValue(module == HocClkModule_MEM ? formatListFreqMem(0, (RamDisplayUnit)configList.values[HocClkConfigValue_RamDisplayUnit]) : formatListFreqHz(0));
return true; return true;
} }
@@ -300,6 +301,9 @@ public:
GovernorOverrideSubMenuGui(u32 initialPacked) : packed(initialPacked) {} GovernorOverrideSubMenuGui(u32 initialPacked) : packed(initialPacked) {}
void listUI() override { void listUI() override {
BaseMenuGui::refresh(); // get latest context
if(!this->context)
return;
Result rc = hocclkIpcGetConfigValues(&configList); // idk why this is needed, probably some refreshing issue Result rc = hocclkIpcGetConfigValues(&configList); // idk why this is needed, probably some refreshing issue
if (R_FAILED(rc)) [[unlikely]] { if (R_FAILED(rc)) [[unlikely]] {
FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc);
@@ -310,7 +314,7 @@ public:
static constexpr struct { const char* label; int shift; } kAll[] = { static constexpr struct { const char* label; int shift; } kAll[] = {
{"CPU", 0}, {"GPU", 8}, {"VRR", 16} {"CPU", 0}, {"GPU", 8}, {"VRR", 16}
}; };
int count = configList.values[HocClkConfigValue_OverwriteRefreshRate] ? 3 : 2; int count = configList.values[HocClkConfigValue_OverwriteRefreshRate] || this->context->isUsingRetroSuper ? 3 : 2;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
u8 cur = (this->packed >> kAll[i].shift) & 0xFF; u8 cur = (this->packed >> kAll[i].shift) & 0xFF;
@@ -409,7 +413,9 @@ void GlobalOverrideGui::refresh()
} }
} else { } else {
this->listItems[m]->setValue( this->listItems[m]->setValue(
formatListFreqHz(this->context->overrideFreqs[m])); m == HocClkModule_MEM
? formatListFreqHzMem(this->context->overrideFreqs[m], (RamDisplayUnit)configList.values[HocClkConfigValue_RamDisplayUnit])
: formatListFreqHz(this->context->overrideFreqs[m]));
} }
this->listHz[m] = this->context->overrideFreqs[m]; this->listHz[m] = this->context->overrideFreqs[m];

View File

@@ -0,0 +1,88 @@
/*
*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "info_gui.h"
#include "ult_ext.h"
#include <sstream>
InfoGui::InfoGui(std::string title, std::vector<std::string> strings)
: m_title(std::move(title)), m_strings(std::move(strings)) {}
static constexpr s32 TEXT_SIZE = 16;
static constexpr s32 LINE_H = 22;
static constexpr s32 PARA_GAP = 10;
static constexpr s32 MARGIN_L = 20;
static constexpr s32 MARGIN_R = 35;
static std::vector<std::string> wrapText(const std::string& text, s32 maxWidth)
{
constexpr float CHAR_W = 10.0f;
// Preserve leading whitespace as an indent prefix for wrapped continuation lines.
std::string indent;
for (char c : text) {
if (c == ' ') indent += ' ';
else break;
}
std::vector<std::string> lines;
std::istringstream ss(text);
std::string word, line = indent; // seed with indent so first word inherits it
bool first = true;
while (ss >> word) {
std::string candidate = (first && !indent.empty()) ? indent + word
: line.empty() ? word
: line + " " + word;
first = false;
if (static_cast<s32>(candidate.size() * CHAR_W) <= maxWidth)
line = std::move(candidate);
else {
if (!line.empty() && line != indent) lines.push_back(line);
line = indent + word;
}
}
if (!line.empty() && line != indent) lines.push_back(line);
if (lines.empty()) lines.emplace_back("");
return lines;
}
void InfoGui::listUI()
{
this->listElement->addItem(new tsl::elm::CategoryHeader(m_title));
const s32 maxWidth = tsl::cfg::FramebufferWidth - MARGIN_L - MARGIN_R;
for (const auto& para : m_strings) {
for (const auto& lineText : wrapText(para, maxWidth)) {
auto* d = new FocusableDrawer(
[lineText](tsl::gfx::Renderer* r, s32 x, s32 y, s32 w, s32 h) {
r->drawString((lineText + "\n").c_str(), false,
x + MARGIN_L, y + LINE_H - 5,
TEXT_SIZE, tsl::style::color::ColorText);
});
d->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, LINE_H);
this->listElement->addItem(d, LINE_H);
}
// paragraph gap
auto* gap = new tsl::elm::CustomDrawer(
[](tsl::gfx::Renderer*, s32, s32, s32, s32) {});
gap->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, PARA_GAP);
this->listElement->addItem(gap, PARA_GAP);
}
}

View File

@@ -0,0 +1,33 @@
/*
*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "base_menu_gui.h"
#include <string>
#include <vector>
class InfoGui : public BaseMenuGui
{
public:
InfoGui(std::string title, std::vector<std::string> strings);
~InfoGui() = default;
void listUI() override;
private:
std::string m_title;
std::vector<std::string> m_strings;
};

View File

@@ -87,7 +87,9 @@ std::map<uint32_t, std::string> gpu_freq_label_e_uv = {
std::map<uint32_t, std::string> gpu_freq_label_m = { std::map<uint32_t, std::string> gpu_freq_label_m = {
{76800000, "Boost Mode"}, {76800000, "Boost Mode"},
{307200000, "Handheld"}, {307200000, "Handheld"},
{345600000, "Handheld"},
{384000000, "Handheld"}, {384000000, "Handheld"},
{422400000, "Handheld"},
{460800000, "Handheld"}, {460800000, "Handheld"},
{614400000, "Handheld Safe Max"}, {614400000, "Handheld Safe Max"},
{768000000, "Docked"}, {768000000, "Docked"},

File diff suppressed because it is too large Load Diff

View File

@@ -18,12 +18,14 @@
#pragma once #pragma once
#include "../../ipc.h" #include "../../ipc.h"
#include "base_menu_gui.h" #include "base_menu_gui.h"
#include <initializer_list>
#include <set> #include <set>
#include <unordered_map> #include <unordered_map>
#include <string> #include <string>
#include <vector> #include <vector>
#include "freq_choice_gui.h" #include "freq_choice_gui.h"
#include "value_choice_gui.h" #include "value_choice_gui.h"
#include "info_gui.h"
class MiscGui : public BaseMenuGui class MiscGui : public BaseMenuGui
{ {
public: public:
@@ -41,8 +43,13 @@ protected:
std::map<HocClkConfigValue, std::tuple<tsl::elm::TrackBar*, tsl::elm::ListItem*, std::vector<uint64_t>>> configTrackbars; std::map<HocClkConfigValue, std::tuple<tsl::elm::TrackBar*, tsl::elm::ListItem*, std::vector<uint64_t>>> configTrackbars;
std::set<HocClkConfigValue> configButtonSKeys; std::set<HocClkConfigValue> configButtonSKeys;
std::map<HocClkConfigValue, std::string> configButtonSSubtext; std::map<HocClkConfigValue, std::string> configButtonSSubtext;
std::set<HocClkConfigValue> emcClockConfigs;
void addConfigToggle(HocClkConfigValue configVal, const char* altName); void addConfigToggle(HocClkConfigValue configVal, const char* altName, bool kip = false);
void addConfigTrackbar(HocClkConfigValue configVal, const char* altName, const ValueRange& range, bool kip = true);
void addMappedConfigTrackbar(HocClkConfigValue configVal, const char* altName,
std::vector<u32> vals,
std::initializer_list<std::string> names, bool kip = true);
void addConfigButton(HocClkConfigValue configVal, void addConfigButton(HocClkConfigValue configVal,
const char* altName, const char* altName,
const ValueRange& range, const ValueRange& range,
@@ -50,7 +57,8 @@ protected:
const ValueThresholds* thresholds, const ValueThresholds* thresholds,
const std::map<uint32_t, std::string>& labels = {}, const std::map<uint32_t, std::string>& labels = {},
const std::vector<NamedValue>& namedValues = {}, const std::vector<NamedValue>& namedValues = {},
bool showDefaultValue = true); bool showDefaultValue = true,
bool kip = false);
void addConfigButtonS(HocClkConfigValue configVal, void addConfigButtonS(HocClkConfigValue configVal,
const char* altName, const char* altName,
@@ -60,7 +68,8 @@ protected:
const std::map<uint32_t, std::string>& labels = {}, const std::map<uint32_t, std::string>& labels = {},
const std::vector<NamedValue>& namedValues = {}, const std::vector<NamedValue>& namedValues = {},
bool showDefaultValue = true, bool showDefaultValue = true,
const char* subText = nullptr); const char* subText = nullptr,
bool kip = false);
void addFreqButton(HocClkConfigValue configVal, void addFreqButton(HocClkConfigValue configVal,
const char* altName, const char* altName,
HocClkModule module, HocClkModule module,
@@ -69,4 +78,5 @@ protected:
tsl::elm::ToggleListItem* enabledToggle; tsl::elm::ToggleListItem* enabledToggle;
u8 frameCounter = 60; u8 frameCounter = 60;
bool shouldSaveKip = false;
}; };

View File

@@ -95,6 +95,18 @@ public:
} }
}; };
class FocusableDrawer : public tsl::elm::CustomDrawer {
public:
template<typename... Args>
FocusableDrawer(Args&&... args) : tsl::elm::CustomDrawer(std::forward<Args>(args)...) {
m_isItem = true;
}
Element* requestFocus(Element*, tsl::FocusDirection) override {
return this;
}
void drawHighlight(tsl::gfx::Renderer*) override {}
};
class HideableCustomDrawer : public tsl::elm::Element { class HideableCustomDrawer : public tsl::elm::Element {
private: private:
bool visible; bool visible;

View File

@@ -22,33 +22,33 @@ CONFIG_DIR := horizon-oc
BUILD := build BUILD := build
OUTDIR := out OUTDIR := out
RESOURCES := res RESOURCES := res
SOURCES := src src/nx/ipc ../common/src src/board SOURCES := src src/hos src/i2c src/ipc src/board src/display src/tsensor src/mgr src/file src/soc src/mapping src/pwr src/util
DATA := data DATA := data
INCLUDES := ../common/include INCLUDES := ../common/include src/hos src/soc src/i2c src/util src/pwr src/ipc
EXEFS_SRC := exefs_src EXEFS_SRC := exefs_src
LIBNAMES := minIni nxExt LIBNAMES := minIni
# major minor patch
#--------------------------------------------------------------------------------- TARGET_VERSION := 2.4.0
# version control constants KIP_VERSION := 240
#--------------------------------------------------------------------------------- CUST_REV := 4
TARGET_VERSION := $(shell git describe --dirty --always --tags)
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# options for code generation # options for code generation
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
DEFINES := -DDISABLE_IPC -DTARGET="\"$(TARGET)\"" -DTARGET_VERSION="\"$(TARGET_VERSION)\"" -DCONFIG_DIR="\"$(CONFIG_DIR)\"" DEFINES := -DDISABLE_IPC -DKIP_VERSION=$(KIP_VERSION) -DCUST_REV=$(CUST_REV) -DTARGET="\"$(TARGET)\"" -DTARGET_VERSION="\"$(TARGET_VERSION)\"" -DCONFIG_DIR="\"$(CONFIG_DIR)\""
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
CFLAGS := -g -Wall -Os -ffunction-sections \ CFLAGS := -g -Wall -Os \
$(ARCH) $(DEFINES) -ffast-math -ffast-math -ffunction-sections -fdata-sections -fno-asynchronous-unwind-tables -fno-unwind-tables \
$(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE) -D__SWITCH__ CFLAGS += $(INCLUDE) -D__SWITCH__
CXXFLAGS := $(CFLAGS) -fno-rtti -std=gnu++23 CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++23
ASFLAGS := -g $(ARCH) ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) -Wl,-wrap,__cxa_throw -Wl,-wrap,_Unwind_Resume -Wl,-wrap,__gxx_personality_v0
LIBS := $(foreach lib,$(LIBNAMES),-l$(lib)) -lnx LIBS := $(foreach lib,$(LIBNAMES),-l$(lib)) -lnx

View File

@@ -1,13 +0,0 @@
# Editor files
*.swp
*~
# Objects
*.o
*.a
*.so
# Lib
lib
release
debug

View File

@@ -1,132 +0,0 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
endif
include $(DEVKITPRO)/libnx/switch_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
SOURCES := src
DATA := data
INCLUDES := include
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIC -ftls-model=local-exec
CFLAGS := -g -Wall -Werror \
-ffunction-sections \
-fdata-sections \
$(ARCH) \
$(BUILD_CFLAGS)
CFLAGS += $(INCLUDE) -std=gnu11
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
ASFLAGS := -g $(ARCH)
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(PORTLIBS) $(LIBNX)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES)))
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
.PHONY: clean all lib/lib$(TARGET).a lib/lib$(TARGET)d.a
#---------------------------------------------------------------------------------
all: lib/lib$(TARGET).a lib/lib$(TARGET)d.a
lib:
@[ -d $@ ] || mkdir -p $@
release:
@[ -d $@ ] || mkdir -p $@
debug:
@[ -d $@ ] || mkdir -p $@
lib/lib$(TARGET).a : lib release $(SOURCES) $(INCLUDES)
@$(MAKE) BUILD=release OUTPUT=$(CURDIR)/$@ \
BUILD_CFLAGS="-DNDEBUG=1 -O2" \
DEPSDIR=$(CURDIR)/release \
--no-print-directory -C release \
-f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr release debug lib
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(OUTPUT) : $(OFILES)
$(OFILES_SRC) : $(HFILES)
#---------------------------------------------------------------------------------
%_bin.h %.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@@ -1,36 +0,0 @@
/*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* --------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
* wrote this file. As long as you retain this notice you can do whatever you
* want with this stuff. If you meet any of us some day, and you think this
* stuff is worth it, you can buy us a beer in return. - The sys-clk authors
* --------------------------------------------------------------------------
*/
#pragma once
#include "nxExt/apm_ext.h"
#include "nxExt/i2c.h"
#include "nxExt/t210.h"
#include "nxExt/max17050.h"
#include "nxExt/tmp451.h"
#include "nxExt/ipc_server.h"
#include "nxExt/cpp/lockable_mutex.h"

View File

@@ -3,7 +3,7 @@
"title_id": "0x00FF0000636C6BFF", "title_id": "0x00FF0000636C6BFF",
"title_id_range_min": "0x00FF0000636C6BFF", "title_id_range_min": "0x00FF0000636C6BFF",
"title_id_range_max": "0x00FF0000636C6BFF", "title_id_range_max": "0x00FF0000636C6BFF",
"main_thread_stack_size": "0x0000D000", "main_thread_stack_size": "0x0000C000",
"main_thread_priority": 16, "main_thread_priority": 16,
"default_cpu_id": 3, "default_cpu_id": 3,
"process_category": 1, "process_category": 1,
@@ -31,6 +31,14 @@
"highest_cpu_id": 3 "highest_cpu_id": 3
} }
}, { }, {
"type": "map",
"value": {
"address": "0x70000000",
"is_ro": false,
"size": "0x00001000",
"is_io": true
}
}, {
"type": "map", "type": "map",
"value": { "value": {
"address": "0x60006000", "address": "0x60006000",
@@ -86,7 +94,8 @@
"is_ro": false, "is_ro": false,
"is_io": true "is_io": true
} }
}, { },
{
"type": "syscalls", "type": "syscalls",
"value": { "value": {
"svcUnknown": "0x00", "svcUnknown": "0x00",

View File

@@ -24,14 +24,19 @@
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
#include <nxExt.h> #include "../hos/apm_ext.h"
#include <i2c.h>
#include <t210.h>
#include <max17050.h>
#include <tmp451.h>
#include <ipc_server.h>
#include <lockable_mutex.h>
#include <hocclk.h> #include <hocclk.h>
#include <switch.h> #include <switch.h>
#include <pwm.h> #include <pwm.h>
#include <registers.h> #include <registers.h>
#include <battery.h> #include <battery.h>
#include "display_refresh_rate.hpp" #include "../display/display_refresh_rate.hpp"
#include <rgltr.h>
#include <notification.h> #include <notification.h>
#include "board.hpp" #include "board.hpp"
@@ -39,49 +44,66 @@
#include "board_load.hpp" #include "board_load.hpp"
#include "board_volt.hpp" #include "board_volt.hpp"
#include "board_misc.hpp" #include "board_misc.hpp"
#include "../soctherm.hpp" #include "../tsensor/soctherm.hpp"
#include "../integrations.hpp" #include "../tsensor/aotag.hpp"
#include "../file_utils.hpp" #include "../hos/integrations.hpp"
#include "../file/file_utils.hpp"
#include "../hos/rgltr.h"
namespace board { namespace board {
u64 clkVirtAddr, dsiVirtAddr, apbVirtAddr, fuseVirtAddr;
HocClkSocType gSocType; HocClkSocType gSocType;
u8 gDramID; u8 gDramID;
HocClkConsoleType gConsoleType = HocClkConsoleType_Iowa; HocClkConsoleType gConsoleType = HocClkConsoleType_Icosa;
FuseData fuseData; FuseData fuseData;
u8 speedoBracket; u8 speedoBracket;
PwmChannelSession iCon; PwmChannelSession iCon;
u32 fd = 0, fd2 = 0; u32 fd = 0, fd2 = 0;
#define PMC_BASE 0x7000E400
#define APB_MISC_GP_HIDREV 0x804
#define GP_HIDREV_MAJOR_T210 0x1
#define GP_HIDREV_MAJOR_T210B01 0x2
#define APB_BASE 0x70000000
#define FUSE_RESERVED_ODMX(x) (0x1C8 + 4 * (x))
#define FUSE_OFFSET 0x800
void FetchHardwareInfos() { void FetchHardwareInfos() {
ReadFuses(fuseData); ReadFuses(fuseData, fuseVirtAddr);
SetGpuBracket(fuseData.gpuSpeedo, speedoBracket); SetGpuBracket(fuseData.gpuSpeedo, speedoBracket);
u64 sku = 0, dramID = 0; u32 hidrev = *(u32*)(apbVirtAddr + APB_MISC_GP_HIDREV);
Result rc = splInitialize(); if (((hidrev >> 4) & 0xF) >= GP_HIDREV_MAJOR_T210B01) {
ASSERT_RESULT_OK(rc, "splInitialize"); gSocType = HocClkSocType_Mariko;
CacheGpuVoltTable();
rc = splGetConfig(SplConfigItem_HardwareType, &sku); } else {
ASSERT_RESULT_OK(rc, "splGetConfig"); gSocType = HocClkSocType_Erista;
rc = splGetConfig(SplConfigItem_DramId, &dramID);
ASSERT_RESULT_OK(rc, "splGetConfig");
gDramID = dramID;
splExit();
switch(sku) {
case 2 ... 5:
gSocType = HocClkSocType_Mariko;
break;
default:
gSocType = HocClkSocType_Erista;
} }
u32 odm4 = *(u32*)(fuseVirtAddr + FUSE_OFFSET + FUSE_RESERVED_ODMX(4));
if (gSocType == HocClkSocType_Mariko) { if (gSocType == HocClkSocType_Mariko) {
CacheGpuVoltTable(); switch ((odm4 & 0xF0000) >> 16) {
case 2:
gConsoleType = HocClkConsoleType_Hoag;
break;
case 4:
gConsoleType = HocClkConsoleType_Aula;
break;
case 1:
default:
gConsoleType = HocClkConsoleType_Iowa;
}
} else {
gConsoleType = HocClkConsoleType_Icosa;
} }
gConsoleType = static_cast<HocClkConsoleType>(sku); gDramID = (odm4 & 0xF8) >> 3;
// Get extended dram id info.
if (gSocType == HocClkSocType_Mariko) {
gDramID |= (odm4 & 0x7000) >> 7;
}
} }
/* TODO: Check for config */ /* TODO: Check for config */
@@ -113,6 +135,26 @@ namespace board {
rc = tmp451Initialize(); rc = tmp451Initialize();
ASSERT_RESULT_OK(rc, "tmp451Initialize"); ASSERT_RESULT_OK(rc, "tmp451Initialize");
rc = pmdmntInitialize();
ASSERT_RESULT_OK(rc, "pmdmntInitialize");
rc = rgltrInitialize();
ASSERT_RESULT_OK(rc, "rgltrInitialize");
rc = QueryMemoryMapping(&clkVirtAddr, 0x60006000, 0x1000);
ASSERT_RESULT_OK(rc, "QueryMemoryMapping (clk)");
rc = QueryMemoryMapping(&dsiVirtAddr, 0x54300000, 0x40000);
ASSERT_RESULT_OK(rc, "QueryMemoryMapping (dsi)");
rc = QueryMemoryMapping(&apbVirtAddr, 0x70000000, 0x1000);
ASSERT_RESULT_OK(rc, "QueryMemoryMapping (apb)");
rc = QueryMemoryMapping(&fuseVirtAddr, 0x7000F000, 0x1000);
ASSERT_RESULT_OK(rc, "QueryMemoryMapping (fuse)");
FetchHardwareInfos();
Result nvCheck = 1; Result nvCheck = 1;
if (R_SUCCEEDED(nvInitialize())) { if (R_SUCCEEDED(nvInitialize())) {
nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu"); nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu");
@@ -125,18 +167,21 @@ namespace board {
} }
} }
rc = rgltrInitialize();
ASSERT_RESULT_OK(rc, "rgltrInitialize");
rc = pmdmntInitialize();
ASSERT_RESULT_OK(rc, "pmdmntInitialize");
StartLoad(nvCheck, fd); StartLoad(nvCheck, fd);
batteryInfoInitialize(); batteryInfoInitialize();
FetchHardwareInfos();
soctherm::Initialize(); tsensor::InitializeSoctherm(); // SOCTHERM must be init before AOTAG
// PMC exosphere check
SecmonArgs args = {};
args.X[0] = 0xF0000002;
args.X[1] = PMC_BASE;
svcCallSecureMonitor(&args);
if (args.X[1] != PMC_BASE) { // if param 1 is identical read failed
tsensor::InitializeAotag(GetSocType() == HocClkSocType_Mariko);
}
Result pwmCheck = 1; Result pwmCheck = 1;
if (hosversionAtLeast(6,0,0) && R_SUCCEEDED(pwmInitialize())) { if (hosversionAtLeast(6,0,0) && R_SUCCEEDED(pwmInitialize())) {
@@ -145,14 +190,6 @@ namespace board {
StartMiscThread(pwmCheck, &iCon); StartMiscThread(pwmCheck, &iCon);
u64 clkVirtAddr, dsiVirtAddr;
rc = QueryMemoryMapping(&clkVirtAddr, 0x60006000, 0x1000);
ASSERT_RESULT_OK(rc, "QueryMemoryMapping (clk)");
rc = QueryMemoryMapping(&dsiVirtAddr, 0x54300000, 0x40000);
ASSERT_RESULT_OK(rc, "QueryMemoryMapping (dsi)");
display::DisplayRefreshConfig cfg = {.clkVirtAddr = clkVirtAddr, .dsiVirtAddr = dsiVirtAddr, .isLite = (GetConsoleType() == HocClkConsoleType_Hoag), .isRetroSUPER = integrations::GetRETROSuperStatus()}; display::DisplayRefreshConfig cfg = {.clkVirtAddr = clkVirtAddr, .dsiVirtAddr = dsiVirtAddr, .isLite = (GetConsoleType() == HocClkConsoleType_Hoag), .isRetroSUPER = integrations::GetRETROSuperStatus()};
display::Initialize(&cfg); display::Initialize(&cfg);
@@ -168,13 +205,14 @@ namespace board {
apmExtExit(); apmExtExit();
psmExit(); psmExit();
rgltrExit();
if (HOSSVC_HAS_TC) { if (HOSSVC_HAS_TC) {
tcExit(); tcExit();
} }
max17050Exit(); max17050Exit();
tmp451Exit(); tmp451Exit();
display::Shutdown();
ExitLoad(); ExitLoad();
@@ -182,10 +220,8 @@ namespace board {
pwmChannelSessionClose(&iCon); pwmChannelSessionClose(&iCon);
pwmExit(); pwmExit();
rgltrExit();
batteryInfoExit(); batteryInfoExit();
pmdmntExit(); pmdmntExit();
display::Shutdown();
nvExit(); nvExit();
} }
@@ -208,7 +244,7 @@ namespace board {
svcCallSecureMonitor(&args); svcCallSecureMonitor(&args);
if (args.X[1] == (MC_REGISTER_BASE + MC_EMEM_CFG_0)) { // if param 1 is identical read failed if (args.X[1] == (MC_REGISTER_BASE + MC_EMEM_CFG_0)) { // if param 1 is identical read failed
notification::writeNotification("Horizon OC\nSecmon read failed!\n This may be a hardware issue!"); notification::writeNotification("Horizon OC\nSecmon-Lesen fehlgeschlagen!\nDies könnte ein Hardwareproblem sein!");
return false; return false;
} }

View File

@@ -35,11 +35,17 @@
#include "board_sensor.hpp" #include "board_sensor.hpp"
#include "board_volt.hpp" #include "board_volt.hpp"
#include "board_profile.hpp" #include "board_profile.hpp"
#include "../mem_map.hpp" #include "../mapping/mem_map.hpp"
#define HOSSVC_HAS_CLKRST (hosversionAtLeast(8,0,0)) #define HOSSVC_HAS_CLKRST (hosversionAtLeast(8,0,0))
#define HOSSVC_HAS_TC (hosversionAtLeast(5,0,0)) #define HOSSVC_HAS_TC (hosversionAtLeast(5,0,0))
namespace board { namespace board {
extern u64 clkVirtAddr, dsiVirtAddr, apbVirtAddr, fuseVirtAddr;
extern HocClkSocType gSocType;
extern u8 gDramID;
extern HocClkConsoleType gConsoleType;
extern FuseData fuseData;
extern u8 speedoBracket;
void Initialize(); void Initialize();
void Exit(); void Exit();

View File

@@ -26,14 +26,25 @@
#include <switch.h> #include <switch.h>
#include <hocclk.h> #include <hocclk.h>
#include <nxExt.h> #include "../hos/apm_ext.h"
#include "display_refresh_rate.hpp" #include <i2c.h>
#include "../i2c/i2cDrv.h"
#include <t210.h>
#include <max17050.h>
#include <tmp451.h>
#include <ipc_server.h>
#include <lockable_mutex.h>
#include "../display/display_refresh_rate.hpp"
#include "board.hpp" #include "board.hpp"
#include "board_name.hpp" #include "board_name.hpp"
#include "../errors.hpp" #include "../file/errors.hpp"
#include "../soc/pllmb.hpp"
#include "../file/config.hpp"
#include "../soc/gm20b.hpp"
#include "../file/config.hpp"
namespace board { namespace board {
#define MIDDLE_FREQ_TABLE_START_POINT 1228800000
static u32 currentInjectedHz = 0;
PcvModule GetPcvModule(HocClkModule hocclkModule) { PcvModule GetPcvModule(HocClkModule hocclkModule) {
switch (hocclkModule) { switch (hocclkModule) {
case HocClkModule_CPU: case HocClkModule_CPU:
@@ -65,11 +76,18 @@ namespace board {
ASSERT_RESULT_OK(pcvSetClockRate(moduleID, hz), "pcvSetClockRate"); ASSERT_RESULT_OK(pcvSetClockRate(moduleID, hz), "pcvSetClockRate");
} }
void HandleCpuUv()
{
if (board::GetSocType() == HocClkSocType_Erista)
board::SetDfllTunings(config::GetConfigValue(KipConfigValue_eristaCpuUV), 0, 1581000000); // Erista tbreak is always 1581MHz
else
board::SetDfllTunings(config::GetConfigValue(KipConfigValue_marikoCpuUVLow), config::GetConfigValue(KipConfigValue_marikoCpuUVHigh), board::CalculateTbreak(config::GetConfigValue(KipConfigValue_tableConf)));
}
void SetHz(HocClkModule module, u32 hz) { void SetHz(HocClkModule module, u32 hz) {
Result rc = 0; Result rc = 0;
bool usesGovenor = module > HocClkModule_MEM; bool usesGovenor = module > HocClkModule_MEM;
if (module == HocClkModule_Display) { if (module == HocClkModule_Display) {
display::SetRate(hz); display::SetRate(hz);
return; return;
@@ -79,27 +97,41 @@ namespace board {
return; return;
} }
bool useGm20b = (module == HocClkModule_GPU) && (GetSocType() == HocClkSocType_Mariko) && (hz % 38400000 == 0) && (hz % 76800000 != 0) && hz < MIDDLE_FREQ_TABLE_START_POINT;
u32 pcvHz = useGm20b ? ((hz + 76800000 - 1) / 76800000) * 76800000 : hz;
if (module == HocClkModule_GPU)
currentInjectedHz = 0;
if (HOSSVC_HAS_CLKRST) { if (HOSSVC_HAS_CLKRST) {
ClkrstSession session = {}; ClkrstSession session = {};
rc = clkrstOpenSession(&session, GetPcvModuleId(module), 3); rc = clkrstOpenSession(&session, GetPcvModuleId(module), 3);
ASSERT_RESULT_OK(rc, "clkrstOpenSession"); ASSERT_RESULT_OK(rc, "clkrstOpenSession");
ClkrstSetHz(session, hz); ClkrstSetHz(session, pcvHz);
/* Voltage bug workaround. */ /* Voltage bug workaround. */
if (module == HocClkModule_CPU) { if (module == HocClkModule_CPU) {
svcSleepThread(250'000); svcSleepThread(300'000);
ClkrstSetHz(session, hz); ClkrstSetHz(session, pcvHz);
} }
clkrstCloseSession(&session); clkrstCloseSession(&session);
} else { } else {
PcvSetHz(GetPcvModule(module), hz); PcvSetHz(GetPcvModule(module), pcvHz);
if (module == HocClkModule_CPU) { if (module == HocClkModule_CPU) {
svcSleepThread(250'000); svcSleepThread(300'000);
PcvSetHz(GetPcvModule(module), hz); PcvSetHz(GetPcvModule(module), pcvHz);
} }
} }
if(config::GetConfigValue(HocClkConfigValue_LiveCpuUv) && module == HocClkModule_CPU) {
HandleCpuUv();
}
if (useGm20b) {
gm20b::setClock(hz / 1000);
currentInjectedHz = hz;
}
} }
u32 GetDisplayRate(u32 hz) { u32 GetDisplayRate(u32 hz) {
@@ -115,6 +147,10 @@ namespace board {
return GetDisplayRate(hz); return GetDisplayRate(hz);
} }
if (module == HocClkModule_GPU && currentInjectedHz != 0) {
return currentInjectedHz;
}
if (HOSSVC_HAS_CLKRST) { if (HOSSVC_HAS_CLKRST) {
ClkrstSession session = {}; ClkrstSession session = {};
@@ -141,10 +177,9 @@ namespace board {
case HocClkModule_GPU: case HocClkModule_GPU:
return t210ClkGpuFreq(); return t210ClkGpuFreq();
case HocClkModule_MEM: case HocClkModule_MEM:
return t210ClkMemFreq(); return config::GetConfigValue(HocClkConfigValue_MemoryFrequencyMeasurementMode) == MemoryFrequencyMeasurementMode_PLL ? pllmb::getRamClockRatePLLMB() : t210ClkMemFreq();
case HocClkModule_Display: case HocClkModule_Display:
return GetDisplayRate(hz); return GetDisplayRate(hz);
return hz;
default: default:
ASSERT_ENUM_VALID(HocClkModule, module); ASSERT_ENUM_VALID(HocClkModule, module);
} }

View File

@@ -27,8 +27,14 @@
#pragma once #pragma once
#include <switch.h> #include <switch.h>
#include <hocclk.h> #include <hocclk.h>
#include <nxExt.h> #include "../hos/apm_ext.h"
#include "../errors.hpp" #include <i2c.h>
#include <t210.h>
#include <max17050.h>
#include <tmp451.h>
#include <ipc_server.h>
#include <lockable_mutex.h>
#include "../file/errors.hpp"
namespace board { namespace board {
@@ -38,6 +44,7 @@ namespace board {
u32 GetRealHz(HocClkModule module); u32 GetRealHz(HocClkModule module);
void GetFreqList(HocClkModule module, u32 *outList, u32 maxCount, u32 *outCount); void GetFreqList(HocClkModule module, u32 *outList, u32 maxCount, u32 *outCount);
u32 GetHighestDockedDisplayRate(); u32 GetHighestDockedDisplayRate();
void HandleCpuUv();
void ResetToStock(); void ResetToStock();
void ResetToStockDisplay(); void ResetToStockDisplay();

View File

@@ -42,61 +42,19 @@ namespace board {
gpuBracket = 3; gpuBracket = 3;
} }
void ReadFuses(FuseData &speedo) { void ReadFuses(FuseData &speedo, u64 fuseVa) {
u64 pid = 0; constexpr u32 FuseOffset = 0x800;
constexpr u64 UsbID = 0x0100000000000006; u8 *fusePtr = reinterpret_cast<u8 *>(fuseVa) + FuseOffset;
if (R_FAILED(pmdmntGetProcessId(&pid, UsbID))) {
return;
}
Handle debug; speedo.cpuSpeedo = *reinterpret_cast<u16 *>(fusePtr + FUSE_CPU_SPEEDO_0_CALIB);
if (R_FAILED(svcDebugActiveProcess(&debug, pid))) { speedo.gpuSpeedo = *reinterpret_cast<u16 *>(fusePtr + FUSE_CPU_SPEEDO_2_CALIB);
return; speedo.socSpeedo = *reinterpret_cast<u16 *>(fusePtr + FUSE_SOC_SPEEDO_0_CALIB);
} speedo.cpuIDDQ = *reinterpret_cast<u16 *>(fusePtr + FUSE_CPU_IDDQ_CALIB) * 4;
speedo.gpuIDDQ = *reinterpret_cast<u16 *>(fusePtr + FUSE_GPU_IDDQ_CALIB) * 5;
MemoryInfo mem_info = {}; speedo.socIDDQ = *reinterpret_cast<u16 *>(fusePtr + FUSE_SOC_IDDQ_CALIB) * 4;
u32 pageinfo = 0; speedo.waferX = *reinterpret_cast<s16 *>(fusePtr + FUSE_OPT_X_COORDINATE);
u64 addr = 0; speedo.waferY = *reinterpret_cast<s16 *>(fusePtr + FUSE_OPT_Y_COORDINATE);
speedo.waferX = (speedo.waferX & BIT(8)) ? (speedo.waferX - 512) : speedo.waferX;
u8 stack[0x10] = {};
const u8 compare[0x10] = {};
u8 dump[0x400] = {};
constexpr u64 PageSize = 0x1000;
while (true) {
if (R_FAILED(svcQueryDebugProcessMemory(&mem_info, &pageinfo, debug, addr)) || mem_info.addr < addr) {
break;
}
if (mem_info.type == MemType_Io && mem_info.size == PageSize) {
if (R_FAILED(svcReadDebugProcessMemory(stack, debug, mem_info.addr, sizeof(stack)))) {
break;
}
if (memcmp(stack, compare, sizeof(stack)) == 0) {
if (R_FAILED(svcReadDebugProcessMemory(dump, debug, mem_info.addr + 0x800, sizeof(dump)))) {
break;
}
speedo.cpuSpeedo = *reinterpret_cast<u16*>(dump + FUSE_CPU_SPEEDO_0_CALIB);
speedo.gpuSpeedo = *reinterpret_cast<u16*>(dump + FUSE_CPU_SPEEDO_2_CALIB);
speedo.socSpeedo = *reinterpret_cast<u16*>(dump + FUSE_SOC_SPEEDO_0_CALIB);
speedo.cpuIDDQ = *reinterpret_cast<u16*>(dump + FUSE_CPU_IDDQ_CALIB) * 4;
speedo.gpuIDDQ = *reinterpret_cast<u16*>(dump + FUSE_GPU_IDDQ_CALIB) * 5;
speedo.socIDDQ = *reinterpret_cast<u16*>(dump + FUSE_SOC_IDDQ_CALIB) * 4;
speedo.waferX = *reinterpret_cast<u16*>(dump + FUSE_OPT_X_COORDINATE);
speedo.waferY = *reinterpret_cast<u16*>(dump + FUSE_OPT_Y_COORDINATE);
svcCloseHandle(debug);
return;
}
}
addr = mem_info.addr + mem_info.size;
}
svcCloseHandle(debug);
} }
} }

View File

@@ -30,11 +30,11 @@ namespace board {
u16 gpuIDDQ; u16 gpuIDDQ;
u16 socIDDQ; u16 socIDDQ;
u16 waferX; s16 waferX;
u16 waferY; s16 waferY;
}; };
void ReadFuses(FuseData &speedo); void ReadFuses(FuseData &speedo, u64 fuseVa);
void SetGpuBracket(u16 gpuSpeedo, u8 &gpuBracket); void SetGpuBracket(u16 gpuSpeedo, u8 &gpuBracket);
} }

View File

@@ -26,7 +26,13 @@
#include <switch.h> #include <switch.h>
#include <hocclk.h> #include <hocclk.h>
#include <nxExt.h> #include "../hos/apm_ext.h"
#include <i2c.h>
#include <t210.h>
#include <max17050.h>
#include <tmp451.h>
#include <ipc_server.h>
#include <lockable_mutex.h>
#include <algorithm> #include <algorithm>
#include <math.h> #include <math.h>
#include <numeric> #include <numeric>
@@ -120,6 +126,14 @@ namespace board {
return info.RawBatteryCharge; return info.RawBatteryCharge;
case HocClkPartLoad_FAN: case HocClkPartLoad_FAN:
return GetFanLevel(); return GetFanLevel();
case HocClkPartLoad_RamBWAll:
return t210EmcBwAll();
case HocClkPartLoad_RamBWCpu:
return t210EmcBwCpu();
case HocClkPartLoad_RamBWGpu:
return t210EmcBwGpu();
case HocClkPartLoad_RamBWPeak:
return t210EmcBwPeak();
default: default:
ASSERT_ENUM_VALID(HocClkPartLoad, loadSource); ASSERT_ENUM_VALID(HocClkPartLoad, loadSource);
} }

View File

@@ -27,7 +27,6 @@
#include <switch.h> #include <switch.h>
#include <pwm.h> #include <pwm.h>
#include <cmath> #include <cmath>
#include <rgltr.h>
namespace board { namespace board {

View File

@@ -26,7 +26,13 @@
#include <switch.h> #include <switch.h>
#include <hocclk.h> #include <hocclk.h>
#include <nxExt.h> #include "../hos/apm_ext.h"
#include <i2c.h>
#include <t210.h>
#include <max17050.h>
#include <tmp451.h>
#include <ipc_server.h>
#include <lockable_mutex.h>
#include "board.hpp" #include "board.hpp"
namespace board { namespace board {

View File

@@ -26,12 +26,22 @@
#include <hocclk.h> #include <hocclk.h>
#include <switch.h> #include <switch.h>
#include <nxExt.h> #include "../hos/apm_ext.h"
#include <i2c.h>
#include "../i2c/i2cDrv.h"
#include <t210.h>
#include <max17050.h>
#include <tmp451.h>
#include <ipc_server.h>
#include <lockable_mutex.h>
#include <cmath> #include <cmath>
#include <battery.h> #include <battery.h>
#include <pwm.h> #include <pwm.h>
#include "board.hpp" #include "board.hpp"
#include "../soctherm.hpp" #include "../tsensor/soctherm.hpp"
#include "../tsensor/aotag.hpp"
#include "../tsensor/bq24193.hpp"
#include "../file/config.hpp"
namespace board { namespace board {
@@ -39,8 +49,8 @@ namespace board {
s32 millis = 0; s32 millis = 0;
BatteryChargeInfo info; BatteryChargeInfo info;
soctherm::TSensorTemps temps = {}; tsensor::TSensorTemps temps = {};
soctherm::ReadSensors(temps); tsensor::ReadTSensors(temps);
switch(sensor) { switch(sensor) {
case HocClkThermalSensor_SOC: { case HocClkThermalSensor_SOC: {
@@ -77,11 +87,24 @@ namespace board {
break; break;
} }
case HocClkThermalSensor_MEM: { case HocClkThermalSensor_MEM: {
millis = board::GetSocType() == HocClkSocType_Mariko ? temps.pllx : temps.mem; if (board::GetSocType() == HocClkSocType_Mariko && tsensor::IsInitialized() && tsensor::ReadAotag() > 0) {
millis = (temps.pllx * 0.10f) + (tsensor::ReadAotag() * 0.90f);
} else {
millis = board::GetSocType() == HocClkSocType_Mariko ? temps.pllx : temps.mem;
}
break; break;
} }
case HocClkThermalSensor_PLLX: { case HocClkThermalSensor_PLLX: {
millis = temps.pllx; millis = temps.pllx;
break;
}
case HocClkThermalSensor_BQ24193: {
millis = bq24193::getBQTemp();
break;
}
case HocClkThermalSensor_AO: {
millis = tsensor::ReadAotag();
break;
} }
default: { default: {
ASSERT_ENUM_VALID(HocClkThermalSensor, sensor); ASSERT_ENUM_VALID(HocClkThermalSensor, sensor);

View File

@@ -1,6 +1,8 @@
/* /*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
* *
* Copyright (c) B3711
*
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation. * version 2, as published by the Free Software Foundation.
@@ -20,16 +22,17 @@
#include <memmem.h> #include <memmem.h>
#include <registers.h> #include <registers.h>
#include <cstring> #include <cstring>
#include <rgltr.h>
#include <battery.h> #include <battery.h>
#include "board.hpp" #include "board.hpp"
#include "board_freq.hpp" #include "board_freq.hpp"
#include "board_volt.hpp" #include "board_volt.hpp"
#include "../file_utils.hpp" #include "../file/file_utils.hpp"
#include "../i2c/i2cDrv.h"
#include "../hos/rgltr.h"
namespace board { namespace board {
GpuVoltData voltData = {}; GpuVoltData voltData = {};
u32 cpuVoltTable[32] = {}; // 32LUT
u64 cldvfs; u64 cldvfs;
CpuDfllData cachedTune; CpuDfllData cachedTune;
@@ -47,7 +50,8 @@ namespace board {
u32 tune1_high; u32 tune1_high;
}; };
EristaCpuUvEntry eristaCpuUvTable[5] = { EristaCpuUvEntry eristaCpuUvTable[6] = {
{0xFFEAD0FF, 0x0},
{0xffff, 0x27007ff}, {0xffff, 0x27007ff},
{0xefff, 0x27407ff}, {0xefff, 0x27407ff},
{0xdfff, 0x27807ff}, {0xdfff, 0x27807ff},
@@ -132,19 +136,16 @@ namespace board {
return; return;
} }
} else { } else {
if (GetHz(HocClkModule_CPU) < tbreakPoint || (!levelLow)) { // account for tbreak // if (GetHz(HocClkModule_CPU) < tbreakPoint || (!levelLow)) { // account for tbreak
*tune0_ptr = cachedTune.tune0Low; // I think each erista has a different tune0/tune1? // *tune0_ptr = cachedTune.tune0Low; // I think each erista has a different tune0/tune1?
*tune1_ptr = cachedTune.tune1Low; // *tune1_ptr = cachedTune.tune1Low;
return; // return;
} else { // } else {
if (levelLow) { // if (levelLow) {
*tune0_ptr = eristaCpuUvTable[levelLow-1].tune0; *tune0_ptr = eristaCpuUvTable[levelLow].tune0;
*tune1_ptr = eristaCpuUvTable[levelLow-1].tune1; *tune1_ptr = eristaCpuUvTable[levelLow].tune1;
} else { // } else {
*tune0_ptr = 0x0; // }
*tune1_ptr = 0x0;
}
}
} }
} }
@@ -211,60 +212,47 @@ namespace board {
PcvPowerDomainId_Max77812_Dram = 0x3A000005, // vddq PcvPowerDomainId_Max77812_Dram = 0x3A000005, // vddq
} PowerDomainId; } PowerDomainId;
*/ */
/*
Note: I think Nintendo's I2C driver (or my driver, but it looks correct to me)
*/
u32 GetVoltage(HocClkVoltage voltage) { u32 GetVoltage(HocClkVoltage voltage) {
RgltrSession session;
Result rc = 0;
u32 out = 0; u32 out = 0;
BatteryChargeInfo info; BatteryChargeInfo info;
RgltrSession s;
switch (voltage) { switch (voltage) {
case HocClkVoltage_SOC: case HocClkVoltage_SOC:
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77620_Sd0); out = I2c_BuckConverter_GetUvOut(&I2c_SOC);
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
rgltrGetVoltage(&session, &out);
rgltrCloseSession(&session);
break; break;
case HocClkVoltage_EMCVDD2: case HocClkVoltage_EMCVDD2:
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77620_Sd1); out = I2c_BuckConverter_GetUvOut(&I2c_VDD2);
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
rgltrGetVoltage(&session, &out);
rgltrCloseSession(&session);
break; break;
case HocClkVoltage_CPU: case HocClkVoltage_CPU:
if (GetSocType() == HocClkSocType_Mariko) { if(GetSocType() == HocClkSocType_Mariko) {
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77621_Cpu); out = I2c_BuckConverter_GetUvOut(&I2c_Mariko_CPU);
} else { } else {
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77812_Cpu); rgltrOpenSession(&s, PcvPowerDomainId_Max77621_Cpu);
rgltrGetVoltage(&s, &out);
rgltrCloseSession(&s);
} }
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
rgltrGetVoltage(&session, &out);
rgltrCloseSession(&session);
break; break;
case HocClkVoltage_GPU: case HocClkVoltage_GPU:
if (GetSocType() == HocClkSocType_Mariko) { if(GetSocType() == HocClkSocType_Mariko) {
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77621_Gpu); out = I2c_BuckConverter_GetUvOut(&I2c_Mariko_GPU);
} else { } else {
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77812_Gpu); rgltrOpenSession(&s, PcvPowerDomainId_Max77621_Gpu);
rgltrGetVoltage(&s, &out);
rgltrCloseSession(&s);
} }
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
rgltrGetVoltage(&session, &out);
rgltrCloseSession(&session);
break; break;
case HocClkVoltage_EMCVDDQ: case HocClkVoltage_EMCVDDQ:
if (GetSocType() == HocClkSocType_Mariko) { if(GetSocType() == HocClkSocType_Mariko) {
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77812_Dram); out = I2c_BuckConverter_GetUvOut(&I2c_Mariko_DRAM_VDDQ);
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
rgltrGetVoltage(&session, &out);
rgltrCloseSession(&session);
} else { } else {
out = GetVoltage(HocClkVoltage_EMCVDD2); out = I2c_BuckConverter_GetUvOut(&I2c_VDD2);
} }
break; break;
case HocClkVoltage_Display: case HocClkVoltage_Display:
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77620_Ldo0); out = I2c_BuckConverter_GetUvOut(&I2c_Display);
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
rgltrGetVoltage(&session, &out);
rgltrCloseSession(&session);
break; break;
case HocClkVoltage_Battery: case HocClkVoltage_Battery:
batteryInfoGetChargeInfo(&info); batteryInfoGetChargeInfo(&info);
@@ -318,6 +306,7 @@ namespace board {
} }
void CacheGpuVoltTable() { void CacheGpuVoltTable() {
// Likely CPU regulator?
UnkRegulator reg = { UnkRegulator reg = {
.voltageMin = 600000, .voltageMin = 600000,
.voltageStep = 12500, .voltageStep = 12500,
@@ -371,14 +360,26 @@ namespace board {
/* Assuming mariko. */ /* Assuming mariko. */
const u32 vmax = 800; const u32 vmax = 800;
constexpr u32 VoltageTableOffset = 312; constexpr u32 GpuVoltageTableOffset = 312;
if (!std::memcmp(&buffer[index + VoltageTableOffset], &vmax, sizeof(vmax))) { if (!std::memcmp(&buffer[index + GpuVoltageTableOffset], &vmax, sizeof(vmax))) {
std::memcpy(voltData.voltTable, &buffer[index + VoltageTableOffset], sizeof(voltData.voltTable)); std::memcpy(voltData.voltTable, &buffer[index + GpuVoltageTableOffset], sizeof(voltData.voltTable));
voltData.voltTableAddress = base + memoryInfo.addr + VoltageTableOffset + index; voltData.voltTableAddress = base + memoryInfo.addr + GpuVoltageTableOffset + index;
} }
constexpr u32 CpuVoltageTableOffset = 0xB8;
std::memcpy(cpuVoltTable, &buffer[index + CpuVoltageTableOffset], sizeof(cpuVoltTable)); // TODO: verify the CPU table
svcCloseHandle(handle); svcCloseHandle(handle);
handle = INVALID_HANDLE; handle = INVALID_HANDLE;
// Print info AFTER we exit the handle to avoid hangs
for(int i = 0; i < (int)std::size(cpuVoltTable); ++i) {
fileUtils::LogLine("[dvfs] cpu volt %d: %u mV", i, cpuVoltTable[i]);
}
for(int i = 0; i < (int)std::size(voltData.voltTable); ++i) {
fileUtils::LogLine("[dvfs] gpu volt %d: %u mV", i, voltData.voltTable[i]);
}
return; return;
} }
} }
@@ -421,25 +422,41 @@ namespace board {
u32 GetMinimumGpuVmin(u32 freqMhz, u32 bracket) { u32 GetMinimumGpuVmin(u32 freqMhz, u32 bracket) {
static const u32 ramTable[][22] = { static const u32 ramTable[][22] = {
{ 2133, 2200, 2266, 2300, 2366, 2400, 2433, 2466, 2533, 2566, 2600, 2633, 2700, 2733, 2766, 2833, 2866, 2900, 2933, 3033, 3066, 3100, }, { 2133, 2200, 2266, 2300, 2366, 2400, 2433, 2466, 2533, 2566, 2600, 2633, 2700, 2733, 2766, 2833, 2866, 2900, 2933, 3033, 3066, 3100, }, // Bracket 0
{ 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, }, { 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, }, // Bracket 1
{ 2433, 2466, 2533, 2600, 2666, 2733, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, }, { 2433, 2466, 2533, 2566, 2600, 2666, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, }, // Bracket 2
{ 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, }, { 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, }, // Bracket 3
}; };
static const u32 gpuVoltArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800, }; static const u32 gpuVoltArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800, };
if (freqMhz <= 1600) { if (freqMhz <= 1600) return 0; // DVFS doesnt work below 1600MHz, it will just use vMin
return 0; if (bracket >= std::size(ramTable)) bracket = 0;
u32 bracketStart = ramTable[bracket][0];
u32 rampStartVolt = (bracket == 0) ? 535 : 525; // Do not touch!
u32 rampSpan = 590 - rampStartVolt;
if (freqMhz >= 1633 && freqMhz < bracketStart) {
u32 raw = rampStartVolt + ((freqMhz - 1633) * rampSpan) / (bracketStart - 1633);
u32 volt = ((raw + 2) / 5) * 5;
if (volt < rampStartVolt) volt = rampStartVolt;
if (volt > 590) volt = 590;
return volt;
} }
u32 baseVolt = gpuVoltArray[std::size(gpuVoltArray) - 1];
for (u32 i = 0; i < std::size(gpuVoltArray); ++i) { for (u32 i = 0; i < std::size(gpuVoltArray); ++i) {
if (freqMhz <= ramTable[bracket][i]) { if (freqMhz <= ramTable[bracket][i]) {
return gpuVoltArray[i]; baseVolt = gpuVoltArray[i];
break;
} }
} }
return gpuVoltArray[std::size(gpuVoltArray) - 1]; return baseVolt;
} }
} }

View File

@@ -26,8 +26,6 @@ namespace board {
u64 voltTableAddress; u64 voltTableAddress;
u32 ramVmin; u32 ramVmin;
}; };
/* TODO: Find out what component this actually targets. */
struct UnkRegulator { struct UnkRegulator {
u32 voltageMin; u32 voltageMin;
u32 voltageStep; u32 voltageStep;

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) Souldbminer
*
* Copyright (c) CtCaer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "aula.hpp"
#include "common.hpp"
// I *think* HOS changes this in some ways, so look into it more
namespace AulaDisplay {
#define MMIO_REG32(base, off) *(vu32 *)((base) + (off))
#define DSI(off) MMIO_REG32(board::dsiVirtAddr, (off) << 2u)
#define DSI_WR_DATA 0xA
#define DSI_TRIGGER 0x13
void _display_dsi_send_cmd(u8 cmd, u32 param, u32 wait) {
DSI(DSI_WR_DATA) = (param << 8) | cmd;
DSI(DSI_TRIGGER) = DSI_TRIGGER_HOST;
if (wait)
svcSleepThread(wait * 1000); // usleep-equivalant
}
void SetDisplayColorMode(AulaColorMode mode) {
if(mode == AulaDisplayColorMode_DoNotOverride)
return;
// send display command to change color mode.
_display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM,
MIPI_DCS_PRIV_SM_SET_COLOR_MODE | (mode << 8), 0);
}
}

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