248 Commits
1.2.1 ... main

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 $GITHUB_SHA >> dist/.commit
- name: Clone Libnx
run: git clone https://github.com/switchbrew/libnx.git
- name: Clone Atmosphere
run: git clone --depth=1 --single-branch https://github.com/Atmosphere-NX/Atmosphere.git atmosphere -b $(cat ams_ver.txt)
@@ -81,14 +84,23 @@ jobs:
ccache --set-config=max_size=10G
ccache --set-config=compiler_check=content
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
shell: bash
run: |
export CC="ccache aarch64-none-elf-gcc"
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"
mkdir -p "$DIST_DIR"
@@ -101,13 +113,14 @@ jobs:
echo "TITLE_ID: $TITLE_ID"
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"
popd
mkdir -p "$DIST_DIR/atmosphere/contents/$TITLE_ID/flags"
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/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
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!
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
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
9. Grab a copy of libultrahand (https://github.com/ppkantorski/libultrahand) and place it into Source/sys-clk/overlay/lib/libultrahand
10. Run ./build.sh in the root directory
9. 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)
![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)
![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
secmon=atmosphere/exosphere.bin
```
*(No changes needed if using fusee.)*
@@ -78,21 +79,64 @@ Refer to COMPILATION.md
---
## Clock table
### MEM clocks
### MEM clocks (mhz)
* 3200 → max on mariko, JEDEC.
* 3166
* 3133
* 3100
* 3066
* 3033
* 3000
* 2966
* 2933 → JEDEC.
* 2900
* 2866
* 2833
* 2800
* 2766
* 2733
* 2700
* 2666 → JEDEC.
* 2633
* 2600
* 2566
* 2533
* 2500
* 2466
* 2433
* 2400 → max on erista, JEDEC.
* 2133 → mariko safe max (4266 Modules), JEDEC.
* 1996 → JEDEC.
* 1866 → mariko safe max (3733 Modules), JEDEC.
* 1600 → official docked, boost mode, erista safe max, JEDEC.
* 2366
* 2333
* 2300
* 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.
* 1065
* 800
* 665
### CPU clocks
### CPU clocks (mhz)
* 2703 → mariko absolute max, dangerous
* 2601 → unsafe
* 2499
@@ -115,17 +159,17 @@ Refer to COMPILATION.md
* 714
* 612 → sleep mode
### GPU clocks
### GPU clocks (mhz)
* 1536 → absolute max clock on mariko. very dangerous
* 1459
* 1382
* 1305
* 1267 → NVIDIA T214 rating
* 1228 → mariko HiOPT safe clock
* 1152 → mariko SLT max clock
* 1075 → mariko no UV max clock. absolute max clock on erista. very dangerous
* 998 → NVIDIA T210 rating
* 960 (erista only) → erista slt/hiopt safe max clock
* 1267 → NVIDIA T214(mariko) rating
* 1228 → mariko High UV safe clock
* 1152 → mariko hiOpt-15mV max clock
* 1075 → mariko hiOpt max clock. absolute max clock on erista. very dangerous
* 998 → NVIDIA T210 (erista) rating
* 960 (erista only) → erista high uv/hiOpt-15mV safe max clock
* 921 → erista no UV max clock
* 844
* 768 → official docked
@@ -142,31 +186,31 @@ Refer to COMPILATION.md
**Notes:**
1. On Erista, CPU in handheld is capped to 1581MHz
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.
5. On Mariko, cap with No uv is 844MHz, with SLT it is 921MHz and with HiOPT it's 998MHz
---
## Credits
* **Lightos's Cat** - Cat
* **Souldbminer** - hoc-clk and loader development
* **Lightos** - Loader patches development, hoc-clk development, guides
* **TDRR** - HOC Logo Design
* **tetetete-ctrl** - Website design
* **SciresM** - Atmosphere CFW
* **CTCaer** - L4T, Hekate, proper RAM timings
* **KazushiMe** - Switch OC Suite
* **Hanai3bi (Meha)** - Switch OC Suite, EOS, sys-clk-eos
* **NaGaa95** - L4T-OC kernel, Status Monitor fork
* **B3711 (halop)** - EOS
* **B3711 (halop)** - EOS, contributions
* **sys-clk team (m4xw, p-sam, natinusala)** - sys-clk
* **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** - 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
* **angelblaster** - Korean 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

View File

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

View File

@@ -14,9 +14,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define __ACCESS_TABLE_NAME__ EmcAccessTable1
#define __ACCESS_TABLE_ADDRESS__ MemoryRegionPhysicalDeviceExternalMemoryController1.GetAddress()
#define __ACCESS_TABLE_INC__ "secmon_emc_access_table_data.inc"
#define __ACCESS_TABLE_NAME__ RtcPmcAccessTable
#define __ACCESS_TABLE_ADDRESS__ MemoryRegionPhysicalDeviceRtcPmc.GetAddress()
#define __ACCESS_TABLE_INC__ "secmon_rtc_pmc_access_table_data.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_mc_access_table.inc"
#include "secmon_define_emc_access_table.inc"
#include "secmon_define_emc1_access_table.inc"
#include "secmon_define_emc2_access_table.inc"
#include "secmon_define_rtc_pmc_access_table.inc"
#include "secmon_define_mc01_access_table.inc"
constexpr const AccessTableEntry AccessTables[] = {
{ PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, },
{ McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, },
{ EmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController.GetAddress(), EmcAccessTable::Address, EmcAccessTable::Size, },
{ EmcAccessTable1::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController1.GetAddress(), EmcAccessTable1::Address, EmcAccessTable1::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 + MemoryRegionVirtualDeviceMemoryController1.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController1.GetAddress(), Mc01AccessTable::Size, },
{ PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, },
{ McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, },
{ EmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController.GetAddress(), EmcAccessTable::Address, EmcAccessTable::Size, },
{ RtcPmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceRtcPmc.GetAddress(), RtcPmcAccessTable::Address, RtcPmcAccessTable::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, },
};
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 {
volatile CustomizeTable C = {
/* Disables RAM powerdown */
.hpMode = DISABLED,
.commonEmcMemVolt = 1175000, /* LPDDR4(X) JEDEC Specification */
.eristaEmcMaxClock = 1600000, /* Maximum HB-MGCH ram rating */
.commonEmcMemVolt = 1175000, /* LPDDR4(X) JEDEC Specification */
.eristaEmcMaxClock = 1600000, /* Maximum HB-MGCH ram rating */
.eristaEmcMaxClock1 = 1600000,
.eristaEmcMaxClock2 = 1600000,
.marikoEmcMaxClock = 1866000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */
.marikoEmcVddqVolt = 600000, /* Micron: 600mV, other manafacturers: 640mV */
.emcDvbShift = 0,
/* Available: 66MHz step rate, 100MHz step rate, 133MHz step rate and jedec. */
/* Jedec freqs are 1333MHz, 1600MHz, 1866MHz, 2133MHz, 2400MHz, 2666MHz, 2933MHz, 3200MHz. */
.stepMode = StepMode_66MHz,
// Primary
.t1_tRCD = 0,
.t2_tRP = 0,
.t3_tRAS = 0,
// Secondary
.t4_tRRD = 0,
.t5_tRFC = 0,
.t6_tRTW = 0,
.t7_tWTR = 0,
.t8_tREFI = 0,
.marikoEmcMaxClock = 2133000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */
.marikoEmcVddqVolt = 600000,
.emcDvbShift = 0,
.marikoSocVmax = 0, /* 0 = stock limits (1450 - 1597 is 1050mV, 1598-1708 is 1025mV, 1709+ is 1000mV). */
/* Primary. */
.t1_tRCD = 0,
.t2_tRP = 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 */
/*
* Read:
* 2133RL = 40
* 1866RL = 36
* 1600RL = 32
* 1331RL = 28
* Write:
* 2133WL = 18
* 1866WL = 16
* 1600WL = 14
* 1331WL = 12
* Read:
* 2133RL = 40
* 1866RL = 36
* 1600RL = 32
* 1331RL = 28
* Write:
* 2133WL = 18
* 1866WL = 16
* 1600WL = 14
* 1331WL = 12
*/
.mem_burst_read_latency = RL_1866,
.mem_burst_write_latency = WL_1866,
/* Erista only. */
.mem_burst_read_latency = RL_1600,
.mem_burst_write_latency = WL_1600,
.eristaCpuUV = 0,
.eristaCpuVmin = 800,
.eristaCpuUV = 0,
.eristaCpuVmin = 800,
.eristaCpuMaxVolt = 1200,
/* Unlocks up to 2295 Mhz CPU, usage is not recommended. */
.eristaCpuUnlock = DISABLED,
/* Unlocks up to 2397 Mhz CPU, usage is not recommended. */
.eristaCpuUnlock = DISABLED,
.marikoCpuUVLow = 0, // No undervolt
.marikoCpuUVLow = 0, // No undervolt
.marikoCpuUVHigh = 0, // No undervolt
.tableConf = TBREAK_1683,
.marikoCpuLowVmin = 620,
.tableConf = TBREAK_1683,
.marikoCpuLowVmin = 620,
.marikoCpuHighVmin = 750,
/* 1120mV is NVIDIA rating */
.marikoCpuMaxVolt = 1120,
.marikoCpuMaxVolt = 1120,
/* Supported values: 1963500, 2091000, 2193000, 2295000, 2397000, 2499000, 2601000, 2703000. */
/* 1963500 is official rating of T214/Mariko, fully safe. */
@@ -95,17 +127,16 @@ volatile CustomizeTable C = {
/* 2703000 is potentially dangerous and not advised. */
.marikoCpuMaxClock = 1963500,
.eristaCpuBoostClock = 1785000, // Default boost clock
.marikoCpuBoostClock = 1963500, // Default boost clock
.eristaCpuBoostClock = 1785000, /* Default boost clock */
.marikoCpuBoostClock = 1963500, /* Default boost clock */
.eristaGpuUV = 0,
.eristaGpuUV = 0,
.eristaGpuVmin = 810,
.marikoGpuUV = 0,
/* Vmin past 795mV won't work due boot voltage being 800mV. */
/* Vmin past 795mV won't work due boot voltage being 800mV (can be adjusted though). */
.marikoGpuVmin = 610,
.marikoGpuBootVolt = 800, /* Used during boot and when temp is <20°C */
.marikoGpuVmax = 800,
.commonGpuVoltOffset = 0,
@@ -117,7 +148,6 @@ volatile CustomizeTable C = {
/* 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) */
/* You can overwrite auto with any voltage (in mv) of your choice - offset will not be applied. */
.eristaGpuVoltArray = {
AUTO /* 76 */,
AUTO /* 115 */,

View File

@@ -20,34 +20,27 @@
#pragma once
#define CUST_REV 1
#define CUST_REV 4
#define KIP_VERSION 240
#include "oc_common.hpp"
#include "pcv/pcv_common.hpp"
namespace ams::ldr::hoc {
#include "mtc_timing_table.hpp"
enum TableConfig: u32 {
DEFAULT_TABLE = 1,
TBREAK_1581 = 2,
TBREAK_1683 = 3,
TBREAK_1581 = 2,
TBREAK_1683 = 3,
EXTREME_TABLE = 4,
};
/*
* Read:
* 2133RL = 40
* 1866RL = 36
* 1600RL = 32
* 1331RL = 28
* Write:
* 2133WL = 18
* 1866WL = 16
* 1600WL = 14
* 1331WL = 12
*/
enum StepMode: u32 {
StepMode_66MHz = 0,
StepMode_100MHz = 1,
StepMode_Jedec = 2,
StepMode_133MHz = 3,
};
enum ReadLatency: u32 {
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(pcv::cvb_entry_t) * pcv::DvfsTableEntryLimit);
constexpr uint32_t ERISTA_MTC_MAGIC = 0x43544D45; // EMTC
constexpr uint32_t MARIKO_MTC_MAGIC = 0x43544D4D; // MMTC
struct CustomizeTable {
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 commonEmcMemVolt;
u32 eristaEmcMaxClock;
u32 eristaEmcMaxClock1;
u32 eristaEmcMaxClock2;
StepMode stepMode;
u32 marikoEmcMaxClock;
u32 marikoEmcVddqVolt;
u32 emcDvbShift;
s32 emcDvbShift;
u32 marikoSocVmax;
// advanced config
u32 t1_tRCD;
u32 t2_tRP;
@@ -95,6 +88,15 @@ typedef struct CustomizeTable {
u32 t7_tWTR;
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_write_latency;
@@ -119,6 +121,7 @@ typedef struct CustomizeTable {
u32 marikoGpuUV;
u32 marikoGpuVmin;
u32 marikoGpuBootVolt;
u32 marikoGpuVmax;
u32 commonGpuVoltOffset;
@@ -150,7 +153,7 @@ typedef struct CustomizeTable {
CustomizeGpuDvfsTable marikoGpuDvfsTableSLT;
CustomizeGpuDvfsTable marikoGpuDvfsTableHiOPT;
} CustomizeTable;
};
extern volatile CustomizeTable C;

View File

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

View File

@@ -14,7 +14,7 @@
* 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 "timing_tables.hpp"
@@ -26,8 +26,72 @@ namespace ams::ldr::hoc::pcv::mariko {
return;
}
/* Fallback. */
rext = 0x1A;
/* > 3200 */
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() {
@@ -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)));
}
void CalculateTimings() {
void CalculateTimings(double tCK_avg, u32 freq) {
RL = RL_1331;
WL = WL_1331;
HandleLatency(freq);
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();
}

View File

@@ -18,7 +18,7 @@
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/>.
*/
#include "../mtc_timing_value.hpp"
#include "../oc_common.hpp"
#include "timing_tables.hpp"
namespace ams::ldr::hoc::pcv::mariko {

View File

@@ -15,7 +15,7 @@
*/
#pragma once
#include "../mtc_timing_value.hpp"
#include <stratosphere.hpp>
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, 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];
const u32 tRPpb = tRP_values[C.t2_tRP];
const u32 tRAS = tRAS_values[C.t3_tRAS];
const double tRRD = tRRD_values[C.t4_tRRD];
const u32 tRFCpb = tRFC_values[C.t5_tRFC];
const u32 tWTR = 10 - tWTR_values[C.t7_tWTR];
const s32 finetRTW = C.fineTune_t6_tRTW;
const s32 finetWTR = C.fineTune_t7_tWTR;
inline u32 tRC;
inline u32 tRFCab;
inline double tXSR;
inline u32 tFAW;
inline double tRPab;
const u32 tRC = tRAS + tRPpb;
const u32 tRFCab = tRFCpb * 2;
const double tXSR = static_cast<double>(tRFCab + 7.5);
const u32 tFAW = static_cast<u32>(tRRD * 4.0);
const double tRPab = tRPpb + 3;
inline u32 RL;
inline u32 WL;
const u32 tR2P = CEIL((RL * 0.426) - 2.0);
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;
const u32 tRTM = FLOOR((10.0 + RL) + (3.502 / tCK_avg)) + FLOOR(7.489 / tCK_avg);
const u32 tRATM = CEIL((tRTM - 10.0) + (RL * 0.426));
inline u32 tR2P;
inline u32 tR2W;
inline u32 tRTM;
inline u32 tRATM;
inline u32 rext;
const u32 rdv = RL + FLOOR((5.105 / tCK_avg) + 17.017);
const u32 qpop = rdv - 14;
const u32 quse_width = CEIL(((4.897 / tCK_avg) - FLOOR(2.538 / tCK_avg)) + 3.782);
const u32 quse = FLOOR(RL + ((5.082 / tCK_avg) + FLOOR(2.560 / tCK_avg))) - CEIL(4.820 / tCK_avg);
const u32 einput_duration = FLOOR(9.936 / tCK_avg) + 5.0 + quse_width;
const u32 einput = quse - CEIL(9.928 / tCK_avg);
const u32 qrst_duration = FLOOR(8.399 - tCK_avg);
const u32 qrstLow = MAX(static_cast<s32>(einput - qrst_duration - 2), static_cast<s32>(0));
const u32 qrst = PACK_U32(qrst_duration, qrstLow);
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;
inline u32 rdv;
inline u32 qpop;
inline u32 quse_width;
inline u32 quse;
inline u32 einput_duration;
inline u32 einput;
inline u32 qrst;
inline u32 ibdly;
inline u32 qsafe;
const u32 wdv = WL;
const u32 wsv = WL - 2;
const u32 wev = 0xA + (WL - 14);
inline u32 tW2P;
inline u32 tWTPDEN;
inline u32 tW2R;
inline u32 tWTM;
inline u32 tWATM;
const u32 obdlyHigh = 3 / FLOOR(MIN(static_cast<double>(2), tCK_avg * (WL - 7)));
const u32 obdlyLow = MAX(WL - FLOOR((126.0 / CEIL(tCK_avg + 8.601))), 0.0);
const u32 obdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(obdlyHigh, obdlyLow);
inline u32 wdv;
inline u32 wsv;
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);
const double pdex2mrr = tMMRI + 10; /* Do this properly? */
inline u32 tCLKSTOP;
inline u32 pdex2mrr;
inline u8 mrw2;
}

View File

@@ -18,17 +18,17 @@
#pragma once
#ifdef ATMOSPHERE_IS_STRATOSPHERE
#include <stratosphere.hpp>
#include <vapours/results/results_common.hpp>
#define LOGGING(fmt, ...) ((void)0)
#define CRASH(msg, ...) { ams::diag::AbortImpl(msg, __PRETTY_FUNCTION__, "", 0); __builtin_unreachable(); }
#else
#include "oc_test.hpp"
#endif
#include <stratosphere.hpp>
#include <vapours/results/results_common.hpp>
#define LOGGING(fmt, ...) ((void)0)
#define CRASH(msg, ...) { ams::diag::AbortImpl(msg, __PRETTY_FUNCTION__, "", 0); __builtin_unreachable(); }
#include "customize.hpp"
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING)
#include "oc_log.hpp"
#endif
#define PATCH_OFFSET(offset, value) \
static_assert(sizeof(__typeof__(offset)) <= sizeof(u64)); \
*(offset) = value;
@@ -50,6 +50,9 @@ namespace ams::ldr {
R_DEFINE_ERROR_RESULT(UninitializedPatcher, 1013);
R_DEFINE_ERROR_RESULT(UnsuccessfulPatcher, 1014);
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 {
@@ -63,38 +66,42 @@ namespace ams::ldr::hoc {
size_t maximum_patched_count = 0;
patternFn pattern_search_fn = nullptr;
Pointer value_search;
size_t patched_count = 0;
Result Apply(Pointer* ptr) {
Result Apply(Pointer *ptr) {
Result res = patcher_fn(ptr);
if (R_SUCCEEDED(res))
if (R_SUCCEEDED(res)) {
patched_count++;
}
return res;
}
Result SearchAndApply(Pointer* ptr) {
Result SearchAndApply(Pointer *ptr) {
bool searchOk = false;
if (pattern_search_fn) {
if (pattern_search_fn(ptr)) searchOk = true;
if (pattern_search_fn(ptr)) {
searchOk = true;
}
} else {
if (value_search == *(ptr)) searchOk = true;
if (value_search == *(ptr)) {
searchOk = true;
}
}
if (searchOk)
if (searchOk) {
return Apply(ptr);
}
R_THROW(ldr::ResultUnsuccessfulPatcher());
}
Result CheckResult() {
#ifndef ATMOSPHERE_IS_STRATOSPHERE
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_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
* 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/>.
*/
#define __ACCESS_TABLE_NAME__ EmcAccessTable2
#define __ACCESS_TABLE_ADDRESS__ MemoryRegionPhysicalDeviceExternalMemoryController2.GetAddress()
#define __ACCESS_TABLE_INC__ "secmon_emc_access_table_data.inc"
/* See https://github.com/lulle2007200/emuMMC/blob/internal-emummc/source/ */
#include "secmon_define_access_table.inc"
#pragma once
#undef __ACCESS_TABLE_INC__
#undef __ACCESS_TABLE_ADDRESS__
#undef __ACCESS_TABLE_NAME__
namespace ams::ldr::hoc {
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 {
Result MemFreqPllmLimit(u32* ptr) {
clk_pll_param* entry = reinterpret_cast<clk_pll_param *>(ptr);
Result MemFreqPllmLimit(u32 *ptr) {
clk_pll_param *entry = reinterpret_cast<clk_pll_param *>(ptr);
R_UNLESS(entry->freq == entry->vco_max, ldr::ResultInvalidMemPllmEntry());
// Double the max clk simply
u32 max_clk = entry->freq * 2;
entry->freq = max_clk;
u32 max_clk = entry->freq * 2;
entry->freq = max_clk;
entry->vco_max = max_clk;
R_SUCCEED();
}
Result MemVoltHandler(u32* ptr) {
Result MemVoltHandler(u32 *ptr) {
// 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.max_uv)),
};
@@ -44,16 +44,16 @@ namespace ams::ldr::hoc::pcv {
constexpr u32 uv_min = 600'000;
auto validator = [](regulator* entry) {
R_UNLESS(entry->id == 1, ldr::ResultInvalidRegulatorEntry());
R_UNLESS(entry->type == 1, ldr::ResultInvalidRegulatorEntry());
R_UNLESS(entry->id == 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.step_uv == uv_step, ldr::ResultInvalidRegulatorEntry());
R_UNLESS(entry->type_1.min_uv == uv_min, 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_SUCCEED();
};
regulator* entry = nullptr;
for (auto& i : entries) {
regulator *entry = nullptr;
for (auto &i : entries) {
if (R_SUCCEEDED(validator(i))) {
entry = i;
}
@@ -76,24 +76,25 @@ namespace ams::ldr::hoc::pcv {
}
void SafetyCheck() {
// if (C.custRev != CUST_REV)
// CRASH("Triggered");
struct sValidator {
volatile u32 value;
u32 min;
u32 max;
bool value_required = false;
u32 panic;
bool value_required = false;
Result check() {
if (!value_required && !value)
if (!value_required && !value) {
R_SUCCEED();
}
if (min && value < min)
if (min && value < min) {
R_THROW(ldr::ResultSafetyCheckFailure());
if (max && value > max)
}
if (max && value > max) {
R_THROW(ldr::ResultSafetyCheckFailure());
}
R_SUCCEED();
}
@@ -102,28 +103,24 @@ namespace ams::ldr::hoc::pcv {
u32 eristaCpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaCpuDvfsTable)->freq);
u32 marikoCpuDvfsMaxFreq;
if (C.marikoCpuUVHigh) {
marikoCpuDvfsMaxFreq = static_cast<u32>(
GetDvfsTableLastEntry(C.marikoCpuDvfsTableSLT)->freq
);
marikoCpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.marikoCpuDvfsTableSLT)->freq);
} else {
marikoCpuDvfsMaxFreq = static_cast<u32>(
GetDvfsTableLastEntry(C.marikoCpuDvfsTable)->freq
);
marikoCpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.marikoCpuDvfsTable)->freq);
}
u32 eristaGpuDvfsMaxFreq;
switch (C.eristaGpuUV) {
case 0:
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq);
break;
case 1:
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTableSLT)->freq);
break;
case 2:
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTableHiOPT)->freq);
break;
default:
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq);
break;
case 0:
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq);
break;
case 1:
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTableSLT)->freq);
break;
case 2:
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTableHiOPT)->freq);
break;
default:
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq);
break;
}
u32 marikoGpuDvfsMaxFreq;
@@ -142,43 +139,40 @@ namespace ams::ldr::hoc::pcv {
break;
}
using namespace ams::ldr::hoc::pcv;
sValidator validators[] = {
{ C.eristaCpuBoostClock, 1020'000, 2397'000, true, panic::Cpu },
{ C.marikoCpuBoostClock, 1020'000, 2703'000, true, panic::Cpu },
{ C.eristaCpuMaxVolt, 1000, 1260, false, panic::Cpu },
{ C.marikoCpuMaxVolt, 1000, 1200, false, panic::Cpu },
{ eristaCpuDvfsMaxFreq, 1785'000, 2397'000, false, panic::Cpu },
{ marikoCpuDvfsMaxFreq, 1785'000, 2703'000, false, panic::Cpu },
{ C.commonEmcMemVolt, 912'500, 1350'000, false, panic::Emc }, // Official burst vmax for the RAMs is 1500mV
{ GET_MAX_OF_ARR(erista::maxEmcClocks), 1600'000, 2600'000, false, panic::Emc },
{ C.marikoEmcMaxClock, 1600'000, 3500'000, false, panic::Emc },
{ C.marikoEmcVddqVolt, 250'000, 700'000, false, panic::Emc },
{ eristaGpuDvfsMaxFreq, 768'000, 1152'000, false, panic::Gpu },
{ marikoGpuDvfsMaxFreq, 768'000, 1536'000, false, panic::Gpu },
{ C.marikoGpuVmax, 800, 960, false, panic::Gpu },
{ C.eristaCpuBoostClock, 1020'000, 2397'000, panic::Cpu, true },
{ C.marikoCpuBoostClock, 1020'000, 2703'000, panic::Cpu, true },
{ C.eristaCpuMaxVolt, 1000, 1260, panic::Cpu, },
{ C.marikoCpuMaxVolt, 1000, 1200, panic::Cpu, },
{ eristaCpuDvfsMaxFreq, 1785'000, 2397'000, panic::Cpu, },
{ marikoCpuDvfsMaxFreq, 1785'000, 2703'000, panic::Cpu, },
{ 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, panic::Emc, },
{ C.marikoEmcMaxClock, 1600'000, 3500'000, panic::Emc, },
{ C.marikoEmcVddqVolt, 400'000, 750'000, panic::Emc, },
{ C.marikoSocVmax, 1000, 1200, panic::Emc, },
{ eristaGpuDvfsMaxFreq, 768'000, 1152'000, panic::Gpu, },
{ marikoGpuDvfsMaxFreq, 768'000, 1536'000, panic::Gpu, },
{ C.marikoGpuVmax, 800, 960, panic::Gpu, },
};
for (auto &v : validators) {
if (R_FAILED(v.check())) {
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING)
panic::SmcError(v.panic);
#endif
panic::SmcError(v.panic);
CRASH("Validation FAIL");
}
}
}
void Patch(uintptr_t mapped_nso, size_t nso_size) {
#ifdef ATMOSPHERE_IS_STRATOSPHERE
SafetyCheck();
bool isMariko = (spl::GetSocType() == spl::SocType_Mariko);
if (isMariko)
if (isMariko) {
mariko::Patch(mapped_nso, nso_size);
else
} else {
erista::Patch(mapped_nso, nso_size);
#endif
}
}
}

View File

@@ -22,244 +22,11 @@
#include "../oc_common.hpp"
#include "pcv_common.hpp"
#include "pcv_erista.hpp"
#include "pcv_mariko.hpp"
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) {
for (size_t i = 0; i < std::size(values); ++i) {
if (*(base + offsets[i]) != values[i]) {
@@ -351,34 +118,34 @@ namespace ams::ldr::hoc::pcv {
cvb_entry_t *customize_table;
if (isMariko) {
switch (C.marikoGpuUV) {
case 0:
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTable);
break;
case 1:
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTableSLT);
break;
case 2:
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTableHiOPT);
break;
default:
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTable);
break;
}
case 0:
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTable);
break;
case 1:
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTableSLT);
break;
case 2:
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTableHiOPT);
break;
default:
customize_table = const_cast<cvb_entry_t *>(C.marikoGpuDvfsTable);
break;
}
} else {
switch (C.eristaGpuUV) {
case 0:
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTable);
break;
case 1:
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTableSLT);
break;
case 2:
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTableHiOPT);
break;
default:
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTable);
break;
}
case 0:
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTable);
break;
case 1:
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTableSLT);
break;
case 2:
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTableHiOPT);
break;
default:
customize_table = const_cast<cvb_entry_t *>(C.eristaGpuDvfsTable);
break;
}
}
size_t default_entry_count = GetDvfsTableEntryCount(default_table);
@@ -428,26 +195,6 @@ namespace ams::ldr::hoc::pcv {
Result MemFreqPllmLimit(u32 *ptr);
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 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
#include "../mtc_timing_table.hpp"
namespace ams::ldr::hoc::pcv {
typedef struct cvb_coefficients {
struct cvb_coefficients {
s32 c0 = 0;
s32 c1 = 0;
s32 c2 = 0;
s32 c3 = 0;
s32 c4 = 0;
s32 c5 = 0;
} cvb_coefficients;
};
typedef struct cvb_entry_t {
struct cvb_entry_t {
u64 freq;
cvb_coefficients cvb_dfll_param;
cvb_coefficients cvb_pll_param;
} cvb_entry_t;
};
static_assert(sizeof(cvb_entry_t) == 0x38);
typedef struct cvb_cpu_dfll_data {
struct CvbCpuDfllData {
u32 tune0_low;
u32 tune0_high;
u32 tune1_low;
u32 tune1_high;
unsigned int tune_high_min_millivolts;
unsigned int tune_high_margin_millivolts;
unsigned long dvco_calibration_max;
} cvb_cpu_dfll_data;
u32 tune_high_min_millivolts;
u32 tune_high_margin_millivolts;
u64 dvco_calibration_max;
};
typedef struct emc_dvb_dvfs_table_t {
u64 freq;
s32 volt[4] = {0};
} emc_dvb_dvfs_table_t;
typedef struct __attribute__((packed)) div_nmp {
struct __attribute__((packed)) div_nmp {
u8 divn_shift;
u8 divn_width;
u8 divm_shift;
@@ -61,9 +58,9 @@ namespace ams::ldr::hoc::pcv {
u8 override_divn_shift;
u8 override_divm_shift;
u8 override_divp_shift;
} div_nmp;
};
typedef struct __attribute__((packed)) clk_pll_param {
struct __attribute__((packed)) clk_pll_param {
u32 freq;
u32 input_min;
u32 input_max;
@@ -77,9 +74,9 @@ namespace ams::ldr::hoc::pcv {
struct div_nmp *div_nmp;
u32 unk_1[4];
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 unk_0[5];
u32 freq;
@@ -89,9 +86,9 @@ namespace ams::ldr::hoc::pcv {
u32 step_mv;
u32 max_mv;
u32 unk_2[11];
} dvfs_rail;
};
typedef struct __attribute__((packed)) regulator {
struct __attribute__((packed)) regulator {
u64 id;
const char* name;
u32 type;
@@ -115,11 +112,30 @@ namespace ams::ldr::hoc::pcv {
} type_2_3;
};
u32 unk_x[60];
} regulator;
};
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;
#define R_SKIP() R_SUCCEED()
@@ -129,11 +145,11 @@ namespace ams::ldr::hoc::pcv {
constexpr size_t DvfsTableEntryLimit = DvfsTableEntryCount - 1;
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>>;
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++) {
if (*(m + i)) {
return false;
@@ -142,7 +158,7 @@ namespace ams::ldr::hoc::pcv {
return true;
};
NT* table = const_cast<NT *>(table_head);
NT *table = const_cast<NT *>(table_head);
size_t count = 0;
while (count < DvfsTableEntryLimit) {
if (is_empty(table++)) {
@@ -154,10 +170,10 @@ namespace ams::ldr::hoc::pcv {
}
template<typename T>
T* GetDvfsTableLastEntry(T* table_head) {
T *GetDvfsTableLastEntry(T *table_head) {
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);
if (!count) {
return nullptr;

View File

@@ -66,11 +66,12 @@ namespace ams::ldr::hoc::pcv::erista {
}
Result CpuVoltDfll(u32* ptr) {
cvb_cpu_dfll_data *entry = reinterpret_cast<cvb_cpu_dfll_data *>(ptr);
R_UNLESS(entry->tune0_low == 0xFFEAD0FF, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune0_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune1_low == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune1_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
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->tune1_low == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
R_UNLESS(entry->tune1_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
if (!C.eristaCpuUV) {
R_SKIP();
@@ -100,6 +101,7 @@ namespace ams::ldr::hoc::pcv::erista {
default:
break;
}
R_SUCCEED();
}
@@ -121,10 +123,10 @@ namespace ams::ldr::hoc::pcv::erista {
}
if (C.eristaGpuVmin) {
PATCH_OFFSET(ptr , C.eristaGpuVmin);
PATCH_OFFSET(ptr + 3, C.eristaGpuVmin);
PATCH_OFFSET(ptr + 6, C.eristaGpuVmin);
PATCH_OFFSET(ptr + 9, C.eristaGpuVmin);
PATCH_OFFSET(ptr, C.eristaGpuVmin);
PATCH_OFFSET(ptr + 3, C.eristaGpuVmin);
PATCH_OFFSET(ptr + 6, C.eristaGpuVmin);
PATCH_OFFSET(ptr + 9, C.eristaGpuVmin);
PATCH_OFFSET(ptr + 12, C.eristaGpuVmin);
}
@@ -134,13 +136,15 @@ namespace ams::ldr::hoc::pcv::erista {
Result GpuFreqMaxAsm(u32 *ptr32) {
// Check if both two instructions match the pattern
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());
}
// Both instructions should operate on the same register
u8 rd = asm_get_rd(ins1);
if (rd != asm_get_rd(ins2))
if (rd != asm_get_rd(ins2)) {
R_THROW(ldr::ResultInvalidGpuFreqMaxPattern());
}
u32 max_clock;
switch (C.eristaGpuUV) {
@@ -157,10 +161,13 @@ namespace ams::ldr::hoc::pcv::erista {
max_clock = GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq;
break;
}
u32 asm_patch[2] = {
asm_set_rd(asm_set_imm16(asm_pattern[0], max_clock), rd),
asm_set_rd(asm_set_imm16(asm_pattern[1], max_clock >> 16), rd)};
PATCH_OFFSET(ptr32, asm_patch[0]);
asm_set_rd(asm_set_imm16(GpuAsmPattern[0], max_clock), rd),
asm_set_rd(asm_set_imm16(GpuAsmPattern[1], max_clock >> 16), rd)
};
PATCH_OFFSET(ptr32, asm_patch[0]);
PATCH_OFFSET(ptr32 + 1, asm_patch[1]);
R_SUCCEED();
@@ -204,13 +211,15 @@ namespace ams::ldr::hoc::pcv::erista {
}
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);
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_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_rrd, GET_CYCLE_CEIL(tRRD));
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_pre_refresh_req_cnt, refresh_raw / 4);
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_pdex2wr, 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_mask, rdv + 2);
// 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->dram_timings.rl = RL;
/* This needs some clean up. */
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_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_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_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_rfcpb = CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV) - 1;
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_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_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_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_rap2pre = CEIL(tR2P / MC_ARB_DIV);
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;
constexpr u32 MaskHigh = 0xFF00FFFF;
constexpr u32 Mask2 = 0xFFFFFF00;
constexpr u32 Mask3 = 0xFF00FF00;
constexpr u32 Mask2 = 0xFFFFFF00;
constexpr u32 Mask3 = 0xFF00FF00;
const u32 allowance1 = static_cast<u32>(0x32000 / (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_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->emc_cfg_2 = 0x11083D;
table->min_volt = std::min(static_cast<u32>(1050), 900 + C.emcDvbShift * 25);
table->emc_cfg_2 = 0x11083D;
table->min_volt = std::clamp(900 + (C.emcDvbShift * 25), 900, 1050);
}
/* Probably more intuitive to point to 40800 rather than 1600000, but oh well. */
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 };
std::sort(maxEmcClocks, maxEmcClocks + std::size(maxEmcClocks));
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());
}
if (GET_MAX_OF_ARR(maxEmcClocks) <= EmcClkOSLimit) {
R_SKIP();
}
/* If we oc ram at all, tables are always shifted by at least 1. */
u32 tableShifts = 1;
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) {
u32 CpuCvbDefaultMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(CpuCvbTableDefault)->freq);
u32 GpuCvbDefaultMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(GpuCvbTableDefault)->freq);
PatcherEntry<u32> patches[] = {
{"CPU Freq Table", CpuFreqCvbTable<false>, 1, nullptr, static_cast<u32>(GetDvfsTableLastEntry(CpuCvbTableDefault)->freq)},
{"CPU Volt DVFS", &CpuVoltDvfs, 1, nullptr, CpuVminOfficial},
{"CPU Volt Thermals", &CpuVoltThermals, 1, nullptr, CpuVminOfficial},
{"CPU Volt Dfll", &CpuVoltDfll, 1, nullptr, 0xFFEAD0FF},
{"GPU Volt DVFS", &GpuVoltDVFS, 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 Asm", &GpuFreqMaxAsm, 2, &GpuMaxClockPatternFn},
{"GPU PLL Max", &GpuFreqPllMax, 1, nullptr, GpuClkPllMax},
// {"GPU PLL Limit", &GpuFreqPllLimit, 4, nullptr, GpuClkPllLimit},
{"MEM Freq Mtc", &MemFreqMtcTable, 0, nullptr, EmcClkOSLimit},
{"MEM Freq Max", &MemFreqMax, 0, nullptr, EmcClkOSLimit},
{"MEM Freq PLLM", &MemFreqPllmLimit, 2, nullptr, EmcClkPllmLimit},
{"MEM Volt", &MemVoltHandler, 2, nullptr, MemVoltHOS},
{"CPU Freq Table", CpuFreqCvbTable<false>, 1, nullptr, CpuCvbDefaultMaxFreq },
{"CPU Volt DVFS", &CpuVoltDvfs, 1, nullptr, CpuVminOfficial },
{"CPU Volt Thermals", &CpuVoltThermals, 1, nullptr, CpuVminOfficial },
{"CPU Volt Dfll", &CpuVoltDfll, 1, nullptr, CpuTune0Low },
{"GPU Volt DVFS", &GpuVoltDVFS, 1, nullptr, GpuVminOfficial },
{"GPU Volt Thermals", &GpuVoltThermals, 1, nullptr, GpuVminOfficial },
{"GPU Freq Table", GpuFreqCvbTable<false>, 1, nullptr, GpuCvbDefaultMaxFreq },
{"GPU Freq Asm", &GpuFreqMaxAsm, 2, &GpuMaxClockPatternFn },
{"GPU PLL Max", & GpuFreqPllMax, 1, nullptr, GpuClkPllMax },
// {"GPU PLL Limit", &GpuFreqPllLimit, 4, nullptr, GpuClkPllLimit },
{"MEM Freq Mtc", &MemFreqMtcTable, 0, nullptr, EmcClkOSLimit },
{"MEM Freq Max", &MemFreqMax, 0, nullptr, EmcClkOSLimit },
{"MEM Freq PLLM", &MemFreqPllmLimit, 2, nullptr, EmcClkPllmLimit },
{"MEM Volt", &MemVoltHandler, 2, nullptr, MemVoltHOS },
};
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) {
LOGGING("%s Count: %zu", entry.description, entry.patched_count);
if (R_FAILED(entry.CheckResult())) {
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING)
panic::SmcError(panic::Patch);
#endif
panic::SmcError(panic::Patch);
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 {
Result CpuPtmBoost(perf_conf_entry* entry) {
#ifdef ATMOSPHERE_IS_STRATOSPHERE
bool isMariko = (spl::GetSocType() == spl::SocType_Mariko);
#else
bool isMariko = true;
#endif
if (!C.eristaCpuBoostClock || !C.marikoCpuBoostClock) {
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> memPtmPatch = { "MEM Ptm", &MemPtm, 16, };
#ifdef ATMOSPHERE_IS_STRATOSPHERE
bool isMariko = (spl::GetSocType() == spl::SocType_Mariko);
#else
bool isMariko = true;
#endif
for (u32 i = 0; i < entryCnt; i++) {
perf_conf_entry *entry = confTable + i;

View File

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

View File

@@ -69,9 +69,7 @@ MmuRequest nvencRequest;
MmuRequest nvjpgRequest;
//Checks
Result clkrstCheck = 1;
Result nvCheck = 1;
Result pcvCheck = 1;
Result i2cCheck = 1;
Result pwmCheck = 1;
Result tcCheck = 1;
@@ -554,28 +552,6 @@ void Misc(void*) {
do {
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
if (R_SUCCEEDED(hocclkCheck)) {
HocClkContext hocclkCTX;
@@ -583,8 +559,12 @@ void Misc(void*) {
realCPU_Hz = hocclkCTX.realFreqs[HocClkModule_CPU];
realGPU_Hz = hocclkCTX.realFreqs[HocClkModule_GPU];
realRAM_Hz = hocclkCTX.realFreqs[HocClkModule_MEM];
partLoad[HocClkPartLoad_EMC] = hocclkCTX.partLoad[HocClkPartLoad_EMC];
partLoad[HocClkPartLoad_EMCCpu] = hocclkCTX.partLoad[HocClkPartLoad_EMCCpu];
partLoad[HocClkPartLoad_EMC] = hocclkCTX.partLoad[HocClkPartLoad_EMC];
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];
realGPU_Temp = hocclkCTX.temps[HocClkThermalSensor_GPU];
realPLLX_Temp = hocclkCTX.temps[HocClkThermalSensor_PLLX];
@@ -595,6 +575,9 @@ void Misc(void*) {
realSOC_mV = hocclkCTX.voltages[HocClkVoltage_SOC];
realVDD2_mV = hocclkCTX.voltages[HocClkVoltage_EMCVDD2];
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)) {
HocClkContext hocclkCTX;
if (R_SUCCEEDED(hocclkIpcGetCurrentContext(&hocclkCTX))) {
partLoad[HocClkPartLoad_EMC] = hocclkCTX.partLoad[HocClkPartLoad_EMC];
partLoad[HocClkPartLoad_EMCCpu] = hocclkCTX.partLoad[HocClkPartLoad_EMCCpu];
partLoad[HocClkPartLoad_EMC] = hocclkCTX.partLoad[HocClkPartLoad_EMC];
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];
realGPU_Temp = hocclkCTX.temps[HocClkThermalSensor_GPU];
@@ -1274,6 +1261,7 @@ struct FullSettings {
bool showFPS;
bool showRES;
bool showRDSD;
std::string ramInfoMode;
bool useDynamicColors;
bool disableScreenshots;
uint16_t separatorColor;
@@ -1309,6 +1297,7 @@ struct MiniSettings {
std::string show;
bool showpartLoad;
bool showpartLoadCPUGPU;
std::string ramInfoMode;
bool invertBatteryDisplay;
bool disableScreenshots;
bool sleepExit;
@@ -1343,6 +1332,7 @@ struct MicroSettings {
uint16_t textColor;
std::string show;
bool showpartLoad;
std::string ramInfoMode;
bool setPosBottom;
bool disableScreenshots;
bool sleepExit;
@@ -1430,6 +1420,7 @@ ALWAYS_INLINE void GetConfigSettings(MiniSettings* settings) {
settings->show = "DTC+BAT+CPU+GPU+RAM+TMP+FPS+RES";
settings->showpartLoad = true;
settings->showpartLoadCPUGPU = false;
settings->ramInfoMode = "LOAD";
settings->invertBatteryDisplay = true;
settings->refreshRate = 1;
settings->disableScreenshots = false;
@@ -1639,6 +1630,12 @@ ALWAYS_INLINE void GetConfigSettings(MiniSettings* settings) {
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
it = section.find("invert_battery_display");
if (it != section.end()) {
@@ -1727,6 +1724,7 @@ ALWAYS_INLINE void GetConfigSettings(MicroSettings* settings) {
convertStrToRGBA4444("#FFFF", &(settings->textColor));
settings->show = "FPS+CPU+GPU+RAM+SOC+BAT+DTC";
settings->showpartLoad = true;
settings->ramInfoMode = "LOAD";
settings->setPosBottom = false;
settings->disableScreenshots = false;
settings->sleepExit = false;
@@ -1926,6 +1924,12 @@ ALWAYS_INLINE void GetConfigSettings(MicroSettings* settings) {
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
it = section.find("show");
if (it != section.end()) {
@@ -2257,6 +2261,7 @@ ALWAYS_INLINE void GetConfigSettings(FullSettings* settings) {
settings->showFPS = true;
settings->showRES = true;
settings->showRDSD = true;
settings->ramInfoMode = "LOAD";
settings->useDynamicColors = true;
settings->disableScreenshots = false;
convertStrToRGBA4444("#888F", &(settings->separatorColor));
@@ -2352,6 +2357,11 @@ ALWAYS_INLINE void GetConfigSettings(FullSettings* settings) {
settings->showRDSD = !(key == "FALSE");
}
it = section.find("ram_info_mode");
if (it != section.end()) {
settings->ramInfoMode = it->second;
}
it = section.find("use_dynamic_colors");
if (it != section.end()) {
key = it->second;

View File

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

View File

@@ -142,7 +142,7 @@ public:
});
// 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);
return rootFrame;

View File

@@ -377,6 +377,21 @@ public:
});
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());
dynamicColors->setStateChangedListener([this](bool state) {
ult::setIniFileValue(configIniPath, "fps-graph", "use_dynamic_colors", state ? "true" : "false");
@@ -417,13 +432,13 @@ public:
});
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) {
ult::setIniFileValue(configIniPath, section, "show_vddq", state ? "true" : "false");
});
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) {
ult::setIniFileValue(configIniPath, section, "show_vdd2", state ? "true" : "false");
});
@@ -449,6 +464,21 @@ public:
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) {
auto* invertBatteryDisplay = new tsl::elm::ToggleListItem("Invert Battery Display", getCurrentInvertBatteryDisplay());
invertBatteryDisplay->setStateChangedListener([this, section](bool state) {
@@ -616,6 +646,11 @@ private:
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() {
const std::string section = isMiniMode ? "mini" : "micro";
std::string value = ult::parseValueFromIniSection(configIniPath, section, "invert_battery_display");

View File

@@ -26,6 +26,11 @@ private:
char BatteryDraw_c[64] = "";
char FPS_var_compressed_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 readSpeed_c[32] = "";
@@ -120,7 +125,7 @@ public:
//Print strings
///CPU
if (R_SUCCEEDED(clkrstCheck) || R_SUCCEEDED(pcvCheck)) {
if (1) {
uint32_t height_offset = 155;
if (realCPU_Hz && settings.showRealFreqs) {
@@ -168,7 +173,7 @@ public:
}
///GPU
if (R_SUCCEEDED(clkrstCheck) || R_SUCCEEDED(pcvCheck) || R_SUCCEEDED(nvCheck)) {
if (R_SUCCEEDED(nvCheck)) {
uint32_t height_offset = 320-8;
if (realGPU_Hz && settings.showRealFreqs) {
@@ -176,7 +181,7 @@ public:
}
renderer->drawString("GPU Usage", false, COMMON_MARGIN, 285-8, 20, (settings.catColor1));
if (R_SUCCEEDED(clkrstCheck) || R_SUCCEEDED(pcvCheck)) {
if (1) {
if (settings.showTargetFreqs) {
//static auto targetFreqWidth = renderer->getTextDimensions("Target Frequency: ", false, 15).first;
renderer->drawString("Target Frequency", false, COMMON_MARGIN, height_offset, 15, (settings.catColor2));
@@ -208,7 +213,7 @@ public:
static std::vector<std::string> specialChars = {""};
///RAM
if (R_SUCCEEDED(clkrstCheck) || R_SUCCEEDED(pcvCheck) || R_SUCCEEDED(Hinted)) {
if (R_SUCCEEDED(Hinted)) {
uint32_t height_offset = 410;
if (realRAM_Hz && settings.showRealFreqs) {
@@ -216,7 +221,7 @@ public:
}
renderer->drawString("RAM Usage", false, COMMON_MARGIN, 375, 20, (settings.catColor1));
if (R_SUCCEEDED(clkrstCheck) || R_SUCCEEDED(pcvCheck)) {
if (1) {
if (settings.showTargetFreqs) {
//static auto targetFreqWidth = renderer->getTextDimensions("Target Frequency: ", false, 15).first;
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));
}
if (R_SUCCEEDED(hocclkCheck)) {
static std::vector<std::string> partLoadColoredChars = {"CPU", "GPU"};
//static auto loadLabelWidth = renderer->getTextDimensions("Load: ", false, 15).first;
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 (settings.ramInfoMode == "Bandwidth") {
// Fixed column layout: labels at fixed x, values at fixed x after max label width
// Col1: Peak/GPU labels, Col2: Total/CPU labels
// 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)) {
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;
renderer->drawString("Total\nApplication\nApplet\nSystem\nSystem Unsafe", false, COMMON_MARGIN, height_offset + 40, 15, (settings.catColor2));
renderer->drawString(RAM_var_compressed_c, false, COMMON_MARGIN + valueOffset, height_offset + 40, 15, (settings.textColor));
renderer->drawString(RAM_percentage_var_compressed_c, false, ramPercentageOffset, height_offset + 40, 15, (settings.textColor));
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, ramUsageOffset, 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)) {
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);
if (settings.ramInfoMode == "Bandwidth") {
const unsigned bwAll = partLoad[HocClkPartLoad_RamBWAll] / 1000;
const unsigned bwAllD = (partLoad[HocClkPartLoad_RamBWAll] % 1000) / 100;
const unsigned bwPeak = partLoad[HocClkPartLoad_RamBWPeak] / 1000;
const unsigned bwPeakD= (partLoad[HocClkPartLoad_RamBWPeak]% 1000) / 100;
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
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_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);
} 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 {
// User wants percentage display
if (R_SUCCEEDED(hocclkCheck)) {

View File

@@ -362,8 +362,32 @@ public:
width = renderer->getTextDimensions("100%@4444.4444 mV", false, fontsize).first;
}
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))) {
//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;
}
}
if (key == "GPU" && settings.realTemps) {
width += renderer->getTextDimensions(" 88.8°C", false, fontsize).first;
}
if (settings.realTemps) {
width += renderer->getTextDimensions(" 88.8°C ", false, fontsize).first;
}
} else if (key == "RAM" && (!settings.showpartLoad || R_FAILED(hocclkCheck))) {
//dimensions = renderer->drawString("44444444MB@4444.4", false, 0, 0, fontsize, renderer->a(0x0000));
if (!settings.realVolts) {
width = renderer->getTextDimensions("100%@4444.4", false, fontsize).first;
if (settings.realTemps) {
width += renderer->getTextDimensions(" 88.8°C", false, fontsize).first;
width += renderer->getTextDimensions(" 88.8°C ", false, fontsize).first;
}
} else {
if (isMariko) {
@@ -1142,53 +1166,64 @@ public:
RAM_Hz / 1000000, (RAM_Hz / 100000) % 10);
}
} else {
unsigned partLoadInt;
if (R_SUCCEEDED(hocclkCheck)) {
partLoadInt = partLoad[HocClkPartLoad_EMC] / 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);
}
}
if (settings.ramInfoMode == "Bandwidth" && R_SUCCEEDED(hocclkCheck)) {
// Bandwidth mode: show GB/s from context (partLoad values are in MB/s)
const uint32_t ramFreq = settings.realFrequencies && realRAM_Hz ? realRAM_Hz : RAM_Hz;
const unsigned bwAll = partLoad[HocClkPartLoad_RamBWAll] / 1000;
const unsigned bwAllD = (partLoad[HocClkPartLoad_RamBWAll] % 1000) / 100;
snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c),
"%u.%uGB/s@%hu.%hhu",
bwAll, bwAllD,
ramFreq / 1000000, (ramFreq / 100000) % 10);
} else {
const uint64_t RAM_Total_all = RAM_Total_application_u + RAM_Total_applet_u +
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;
unsigned partLoadInt;
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);
if (R_SUCCEEDED(hocclkCheck)) {
partLoadInt = partLoad[HocClkPartLoad_EMC] / 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 {
snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c),
"%u%%@%hu.%hhu", partLoadInt,
RAM_Hz / 1000000, (RAM_Hz / 100000) % 10);
const uint64_t RAM_Total_all = RAM_Total_application_u + RAM_Total_applet_u +
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) {
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::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);
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
Switch sysmodule allowing you to set cpu/gpu/mem clocks according to the running application and docked state.
Modified for Horizon OC
Overclocking suite for Nintendo Switch.
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"
fi
echo "DIST_DIR: $DIST_DIR"
echo "CORES: $CORES"
echo "*** sysmodule ***"
TITLE_ID="$(grep -oP '"title_id":\s*"0x\K(\w+)' "$ROOT_DIR/sysmodule/perms.json")"
echo
echo "*** Compiling hoc-clk ***"
TITLE_ID="$(sed -n 's/.*"title_id"[[:space:]]*:[[:space:]]*"0x\([^"]*\)".*/\1/p' "$ROOT_DIR/sysmodule/perms.json")"
pushd "$ROOT_DIR/sysmodule"
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"
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"
make -j$CORES
popd > /dev/null
mkdir -p "$DIST_DIR/switch/.overlays"
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"
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 ***"
cp -r "$ROOT_DIR/overlay/lang/" "$DIST_DIR/config/horizon-oc/lang/"
echo
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/config.h"
#include "hocclk/errors.h"
#include "hocclk/psm_ext.h"
#include "hocclk/result.hpp"
#ifdef __cplusplus
}

View File

@@ -33,46 +33,45 @@
#include <switch/types.h>
typedef enum
{
HocClkSocType_Erista = 0,
HocClkSocType_Mariko,
HocClkSocType_Erista = 0, // T210, found in Icosa and Copper
HocClkSocType_Mariko, // T214/T210B01, found in Hoag, Iowa, Calcio and Aula
// HocClkSocType_Drake, // T239, found in Switch 2. Maybe someday...
HocClkSocType_EnumMax
} HocClkSocType;
typedef enum
{
HocClkConsoleType_Icosa = 0,
HocClkConsoleType_Copper,
HocClkConsoleType_Hoag,
HocClkConsoleType_Iowa,
HocClkConsoleType_Calcio,
HocClkConsoleType_Aula,
HocClkConsoleType_Icosa = 0, // V1
HocClkConsoleType_Iowa, // V2
HocClkConsoleType_Hoag, // Lite
HocClkConsoleType_Aula, // OLED
HocClkConsoleType_EnumMax,
} HocClkConsoleType;
typedef enum {
HocClkVoltage_SOC = 0,
HocClkVoltage_EMCVDD2,
HocClkVoltage_CPU,
HocClkVoltage_GPU,
HocClkVoltage_EMCVDDQ,
HocClkVoltage_Display,
HocClkVoltage_Battery,
HocClkVoltage_SOC = 0, // VDD_SOC rail.
HocClkVoltage_EMCVDD2, // DRAM VDD2 rail
HocClkVoltage_CPU, // CPU rail
HocClkVoltage_GPU, // GPU rail
HocClkVoltage_EMCVDDQ, // DRAM VDDQ rail
HocClkVoltage_Display, // Display rail
HocClkVoltage_Battery, // Battery voltage
HocClkVoltage_EnumMax,
} HocClkVoltage;
typedef enum
{
HocClkProfile_Handheld = 0,
HocClkProfile_HandheldCharging,
HocClkProfile_HandheldCharging, // Not a real profile, just a marker
HocClkProfile_HandheldChargingUSB,
HocClkProfile_HandheldChargingOfficial,
HocClkProfile_Docked,
HocClkProfile_Docked, // Not shown on Lites
HocClkProfile_EnumMax
} HocClkProfile;
typedef enum
{
HocClkModule_CPU = 0,
HocClkModule_CPU = 0,
HocClkModule_GPU,
HocClkModule_MEM,
HocClkModule_Governor,
@@ -82,15 +81,17 @@ typedef enum
typedef enum
{
HocClkThermalSensor_SOC = 0,
HocClkThermalSensor_PCB,
HocClkThermalSensor_Skin,
HocClkThermalSensor_Battery,
HocClkThermalSensor_PMIC,
HocClkThermalSensor_CPU,
HocClkThermalSensor_GPU,
HocClkThermalSensor_MEM,
HocClkThermalSensor_PLLX,
HocClkThermalSensor_SOC = 0, // SoC temperature in millicelcius
HocClkThermalSensor_PCB, // PCB temperature in millicelcius
HocClkThermalSensor_Skin, // "Skin" temperature in millicelcius
HocClkThermalSensor_Battery, // Battery temperature in millicelcius
HocClkThermalSensor_PMIC, // Always return 50.0C, as thats the only reasonable value the PMIC sensor can generate
HocClkThermalSensor_CPU, // CPU temperature in millicelcius
HocClkThermalSensor_GPU, // GPU temperature in millicelcius
HocClkThermalSensor_MEM, // MEM temperature in millicelcius. Returns the PLLX sensor value on Mariko
HocClkThermalSensor_PLLX, // PLLX temperature in millicelcius
HocClkThermalSensor_AO, // AOTAG
HocClkThermalSensor_BQ24193, // BQ24193 temperature. Refer to BQ24193Temp for returned values
HocClkThermalSensor_EnumMax
} HocClkThermalSensor;
@@ -107,8 +108,12 @@ typedef enum
HocClkPartLoad_EMCCpu,
HocClkPartLoad_GPU,
HocClkPartLoad_CPUMax,
HocClkPartLoad_BAT,
HocClkPartLoad_BAT, // Battery raw charge percentage
HocClkPartLoad_FAN,
HocClkPartLoad_RamBWAll,
HocClkPartLoad_RamBWCpu,
HocClkPartLoad_RamBWGpu,
HocClkPartLoad_RamBWPeak, // Maximum possible RAM bandwidth
HocClkPartLoad_EnumMax
} HocClkPartLoad;
@@ -120,15 +125,15 @@ typedef enum {
} HocClkSpeedo;
typedef enum {
GPUUVLevel_NoUV = 0,
GPUUVLevel_SLT,
GPUUVLevel_HiOPT,
GPUUVLevel_HiOPT = 0,
GPUUVLevel_HiOPT15,
GPUUVLevel_HighUV,
GPUUVLevel_EnumMax,
} GPUUndervoltLevel;
enum {
DVFSMode_Disabled = 0,
DVFSMode_Hijack,
DVFSMode_Hijack, // PCV hijack dvfs
// DVFSMode_OfficialService,
// DVFSMode_Hack,
DVFSMode_EnumMax,
@@ -158,6 +163,64 @@ typedef enum {
RamDisplayMode_EnumMax,
} 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)
// Packed u32
@@ -219,8 +282,12 @@ static inline const char* hocclkFormatThermalSensor(HocClkThermalSensor thermSen
return pretty ? "MEM" : "mem";
case HocClkThermalSensor_PLLX:
return pretty ? "PLLX" : "pllx";
case HocClkThermalSensor_AO:
return pretty ? "AO" : "ao";
case HocClkThermalSensor_BQ24193:
return pretty ? "BQ24193" : "bq24193";
default:
return NULL;
return "unknown";
}
}
@@ -233,7 +300,7 @@ static inline const char* hocclkFormatPowerSensor(HocClkPowerSensor powSensor, b
case HocClkPowerSensor_Avg:
return pretty ? "Avg" : "avg";
default:
return NULL;
return "unknown";
}
}
@@ -252,7 +319,7 @@ static inline const char* hocclkFormatProfile(HocClkProfile profile, bool pretty
case HocClkProfile_HandheldChargingOfficial:
return pretty ? "PD Charger" : "handheld_charging_official";
default:
return NULL;
return "unknown";
}
}
@@ -266,7 +333,7 @@ static inline const char* hocClkFormatVoltage(HocClkVoltage voltage, bool pretty
case HocClkVoltage_GPU:
return pretty ? "GPU" : "gpu";
case HocClkVoltage_EMCVDD2:
return pretty ? "VDD2" : "emcvdd2";
return pretty ? "VDD2" : "vdd2";
case HocClkVoltage_EMCVDDQ:
return pretty ? "VDDQ" : "vddq";
case HocClkVoltage_SOC:
@@ -274,6 +341,64 @@ static inline const char* hocClkFormatVoltage(HocClkVoltage voltage, bool pretty
case HocClkVoltage_Display:
return pretty ? "Display" : "display";
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

@@ -12,9 +12,9 @@
*
* 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>
@@ -30,21 +30,41 @@
#include <stdint.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;
HocClkProfile profile;
uint32_t freqs[HocClkModule_EnumMax];
uint32_t realFreqs[HocClkModule_EnumMax];
uint32_t overrideFreqs[HocClkModule_EnumMax];
uint32_t temps[HocClkThermalSensor_EnumMax];
int32_t temps[HocClkThermalSensor_EnumMax];
int32_t power[HocClkPowerSensor_EnumMax];
uint32_t partLoad[HocClkPartLoad_EnumMax];
uint32_t voltages[HocClkVoltage_EnumMax];
u16 speedos[HocClkSpeedo_EnumMax];
u16 iddq[HocClkSpeedo_EnumMax];
u16 waferX;
u16 waferY;
s16 waferX;
s16 waferY;
// Misc stuff
GpuSchedulingMode gpuSchedulingMode;
@@ -54,10 +74,16 @@ typedef struct
u8 maxDisplayFreq;
u8 dramID;
bool isDram8GB;
HocClkConsoleType consoleType;
// FPS / Resolution
u8 fps;
u16 resolutionHeight;
u8 custRev;
u16 kipVersion;
// Reserved for future use
u8 reserved[0x35B];
} HocClkContext;
typedef struct
@@ -68,6 +94,8 @@ typedef struct
};
} 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 <stddef.h>
#include "board.h"
typedef enum {
HocClkConfigValue_PollingIntervalMs = 0,
HocClkConfigValue_TempLogIntervalMs,
@@ -68,7 +68,15 @@ typedef enum {
HocClkConfigValue_CpuGovernorMinimumFreq,
HocClkConfigValue_DisplayVoltage,
HocClkConfigValue_MemoryFrequencyMeasurementMode,
HocClkConfigValue_RamDisplayUnit,
HocClkConfigValue_IsFirstLoad,
HocClkConfigValue_AulaDisplayColorPreset,
HocClkConfigValue_MarikoMiddleFreqs,
KipConfigValue_custRev,
KipConfigValue_KipVersion,
// KipConfigValue_mtcConf,
KipConfigValue_hpMode,
@@ -76,9 +84,12 @@ typedef enum {
KipConfigValue_eristaEmcMaxClock,
KipConfigValue_eristaEmcMaxClock1,
KipConfigValue_eristaEmcMaxClock2,
KipConfigValue_stepMode,
KipConfigValue_marikoEmcMaxClock,
KipConfigValue_marikoEmcVddqVolt,
KipConfigValue_emcDvbShift,
KipConfigValue_marikoSocVmax,
KipConfigValue_t1_tRCD,
KipConfigValue_t2_tRP,
@@ -88,6 +99,23 @@ typedef enum {
KipConfigValue_t6_tRTW,
KipConfigValue_t7_tWTR,
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_write_latency,
@@ -111,6 +139,7 @@ typedef enum {
KipConfigValue_marikoGpuUV,
KipConfigValue_marikoGpuVmin,
KipConfigValue_marikoGpuBootVolt,
KipConfigValue_marikoGpuVmax,
KipConfigValue_commonGpuVoltOffset,
@@ -173,7 +202,6 @@ typedef enum {
KipConfigValue_t7_tWTR_fine_tune,
KipCrc32,
HocClkConfigValue_IsFirstLoad,
HocClkConfigValue_EnumMax,
} HocClkConfigValue;
@@ -257,9 +285,20 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr
case HocClkConfigValue_DisplayVoltage:
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
case KipConfigValue_custRev:
return pretty ? "Custom Revision" : "kip_cust_rev";
case KipConfigValue_KipVersion:
return pretty ? "KIP Version" : "kip_version";
// case KipConfigValue_mtcConf:
// return pretty ? "MTC Config" : "kip_mtc_conf";
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";
case KipConfigValue_eristaEmcMaxClock2:
return pretty ? "Erista EMC Max Clock 3" : "erista_emc_max_clock2";
case KipConfigValue_stepMode:
return pretty ? "Step Mode:" : "step_mode";
case KipConfigValue_marikoEmcMaxClock:
return pretty ? "Mariko EMC Max Clock" : "mariko_emc_max_clock";
case KipConfigValue_marikoEmcVddqVolt:
return pretty ? "Mariko EMC VDDQ Voltage" : "mariko_emc_vddq_volt";
case KipConfigValue_emcDvbShift:
return pretty ? "EMC DVB Shift" : "emc_dvb_shift";
case KipConfigValue_marikoSocVmax:
return pretty ? "SOC Vmax" : "soc_vmax";
// Memory timings
case KipConfigValue_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";
case KipConfigValue_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:
return pretty ? "Memory Burst Read Latency" : "mem_burst_read_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";
case KipConfigValue_marikoGpuVmin:
return pretty ? "Mariko GPU Vmin" : "mariko_gpu_vmin";
case KipConfigValue_marikoGpuBootVolt:
return pretty ? "Mariko GPU Boot Voltage" : "mariko_gpu_boot_volt";
case KipConfigValue_marikoGpuVmax:
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_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_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 KipCrc32:
return pretty ? "CRC32" : "crc32";
@@ -436,7 +509,11 @@ static inline uint64_t hocclkDefaultConfigValue(HocClkConfigValue val)
case HocClkConfigValue_GPUScheduling:
case HocClkConfigValue_LiveCpuUv:
case HocClkConfigValue_GPUSchedulingMethod:
case HocClkConfigValue_MemoryFrequencyMeasurementMode:
case HocClkConfigValue_MarikoMiddleFreqs:
return 0ULL;
case HocClkConfigValue_RamDisplayUnit:
return (uint64_t)RamDisplayUnit_MHz;
case HocClkConfigValue_EristaMaxCpuClock:
return 1785ULL;
@@ -460,6 +537,8 @@ static inline uint64_t hocclkDefaultConfigValue(HocClkConfigValue val)
return 60ULL;
case HocClkConfigValue_DisplayVoltage:
return 1200ULL; // Auto
case HocClkConfigValue_AulaDisplayColorPreset:
return AulaDisplayColorMode_DoNotOverride;
default:
return 0ULL;
}
@@ -491,8 +570,9 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in
case HocClkConfigValue_EnableExperimentalSettings:
case HocClkConfigValue_LiveCpuUv:
case HocClkConfigValue_GPUSchedulingMethod:
case HocClkConfigValue_MarikoMiddleFreqs:
return (input & 0x1) == input;
case KipConfigValue_KipVersion:
case KipConfigValue_custRev:
// case KipConfigValue_mtcConf:
case KipConfigValue_hpMode:
@@ -500,9 +580,11 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in
case KipConfigValue_eristaEmcMaxClock:
case KipConfigValue_eristaEmcMaxClock1:
case KipConfigValue_eristaEmcMaxClock2:
case KipConfigValue_stepMode:
case KipConfigValue_marikoEmcMaxClock:
case KipConfigValue_marikoEmcVddqVolt:
case KipConfigValue_emcDvbShift:
case KipConfigValue_marikoSocVmax:
case KipConfigValue_t1_tRCD:
case KipConfigValue_t2_tRP:
case KipConfigValue_t3_tRAS:
@@ -511,6 +593,18 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in
case KipConfigValue_t6_tRTW:
case KipConfigValue_t7_tWTR:
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_write_latency:
case KipConfigValue_eristaCpuUV:
@@ -528,6 +622,7 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in
case KipConfigValue_eristaGpuVmin:
case KipConfigValue_marikoGpuUV:
case KipConfigValue_marikoGpuVmin:
case KipConfigValue_marikoGpuBootVolt:
case KipConfigValue_marikoGpuVmax:
case KipConfigValue_commonGpuVoltOffset:
case KipConfigValue_gpuSpeedo:
@@ -592,13 +687,16 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in
case HocClkConfigValue_GPUScheduling:
case HocClkConfigValue_RAMVoltDisplayMode:
case HocClkConfigValue_CpuGovernorMinimumFreq:
case HocClkConfigValue_MemoryFrequencyMeasurementMode:
case HocClkConfigValue_RamDisplayUnit:
case HocClkConfigValue_AulaDisplayColorPreset:
return true;
case HocClkConfigValue_BatteryChargeCurrent:
return ((input >= 1024) && (input <= 3072)) || !input;
case HocClkConfigValue_DisplayVoltage:
return ((input >= 900) && (input <= 1325));
return ((input >= 800) && (input <= 1325));
default:
return false;
return true;
}
}

View File

@@ -31,7 +31,7 @@
#include "board.h"
#include "clock_manager.h"
#define HOCCLK_IPC_API_VERSION 1
#define HOCCLK_IPC_API_VERSION 2
#define HOCCLK_IPC_SERVICE_NAME "hoc:clk"
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
IS_MINIMAL := 0
APP_TITLE := Horizon OC Zeus
APP_TITLE := Horizon OC Gaea
NO_ICON := 1
@@ -39,7 +39,7 @@ include ${TOPDIR}/lib/libultrahand/ultrahand.mk
# version control constants
#---------------------------------------------------------------------------------
#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)
#---------------------------------------------------------------------------------

View File

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

View File

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

View File

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

View File

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

View File

@@ -30,6 +30,7 @@
#include <cstdio>
#include <string>
#include <cstdint>
#include <hocclk/board.h>
#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));
}
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 "ult_ext.h"
// tsl::elm::ListItem* custRevItem = NULL;
tsl::elm::ListItem* kipVersionItem = NULL;
tsl::elm::ListItem* SpeedoItem = NULL;
tsl::elm::ListItem* IddqItem = NULL;
tsl::elm::ListItem* DramModule = NULL;
@@ -32,6 +34,13 @@ tsl::elm::ListItem* waferCordsItem = NULL;
tsl::elm::ListItem* ramVoltItem = NULL;
tsl::elm::ListItem* eristaPLLXItem = 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;
HideableCategoryHeader* CatHeader = NULL;
@@ -49,24 +58,71 @@ AboutGui::~AboutGui()
void AboutGui::listUI()
{
BaseMenuGui::refresh();
if (!this->context)
return;
this->listElement->addItem(
new tsl::elm::CategoryHeader("Information")
new tsl::elm::CategoryHeader("Voltages")
);
ramVoltItem =
new tsl::elm::ListItem("RAM Voltage:");
this->listElement->addItem(ramVoltItem);
if(IsMariko()) {
this->listElement->addItem(ramVoltItem);
}
dispVoltItem =
new tsl::elm::ListItem("Display Voltage:");
this->listElement->addItem(dispVoltItem);
this->listElement->addItem(
new tsl::elm::CategoryHeader("Temperatures")
);
eristaPLLXItem =
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);
}
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 =
new tsl::elm::ListItem("Speedo:");
this->listElement->addItem(SpeedoItem);
@@ -76,9 +132,29 @@ void AboutGui::listUI()
this->listElement->addItem(IddqItem);
DramModule =
new tsl::elm::ListItem("Module: ");
new tsl::elm::ListItem("DRAM Module: ");
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()) {
sysdockStatusItem =
new tsl::elm::ListItem("sys-dock status:");
@@ -88,16 +164,6 @@ void AboutGui::listUI()
saltyNXStatusItem =
new tsl::elm::ListItem("SaltyNX status:");
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(
new tsl::elm::CategoryHeader("Credits")
@@ -140,13 +206,25 @@ void AboutGui::listUI()
new tsl::elm::ListItem("Blaise25")
);
// ---- Testers ----
this->listElement->addItem(
new tsl::elm::CategoryHeader("Testers")
new tsl::elm::ListItem("tetetete-ctrl")
);
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(
@@ -154,7 +232,7 @@ void AboutGui::listUI()
);
this->listElement->addItem(
new tsl::elm::ListItem("Delta")
new tsl::elm::ListItem("arcdelta")
);
this->listElement->addItem(
@@ -165,10 +243,6 @@ void AboutGui::listUI()
new tsl::elm::ListItem("Happy")
);
this->listElement->addItem(
new tsl::elm::ListItem("Flopsider")
);
this->listElement->addItem(
new tsl::elm::ListItem("Winnerboi77")
);
@@ -185,10 +259,6 @@ void AboutGui::listUI()
new tsl::elm::ListItem("Alvise")
);
this->listElement->addItem(
new tsl::elm::ListItem("TDRR")
);
this->listElement->addItem(
new tsl::elm::ListItem("agjeococh")
);
@@ -207,7 +277,7 @@ void AboutGui::listUI()
);
this->listElement->addItem(
new tsl::elm::ListItem("ScriesM - Atmosphere CFW")
new tsl::elm::ListItem("SciresM - Atmosphere CFW")
);
this->listElement->addItem(
@@ -215,27 +285,23 @@ void AboutGui::listUI()
);
this->listElement->addItem(
new tsl::elm::ListItem("hanai3bi - Switch OC Suite & EOS")
new tsl::elm::ListItem("hanai3Bi - Switch OC Suite & EOS")
);
this->listElement->addItem(
new tsl::elm::ListItem("NaGaa95 - L4T-OC-Kernel")
);
this->listElement->addItem(
new tsl::elm::ListItem("B3711 - EOS")
);
this->listElement->addItem(
new tsl::elm::ListItem("RetroNX - sys-clk")
);
this->listElement->addItem(
new tsl::elm::ListItem("b0rd2death - Ultrahand")
new tsl::elm::ListItem("ppkantorski - Ultrahand")
);
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
@@ -313,27 +379,72 @@ void AboutGui::refresh()
SpeedoItem->setValue(strings[0]);
IddqItem->setValue(strings[1]);
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())
sysdockStatusItem->setValue(this->context->isSysDockInstalled ? "Installed" : "Not Installed");
saltyNXStatusItem->setValue(this->context->isSaltyNXInstalled ? "Installed" : "Not Installed");
if(IsHoag())
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]);
if(IsErista()) {
u32 millis = context->temps[HocClkThermalSensor_PLLX];
sprintf(strings[3], "%u.%u", millis / 1000U, (millis % 1000U) / 100U);
eristaPLLXItem->setValue(strings[3]);
s32 millis = context->temps[HocClkThermalSensor_PLLX];
sprintf(strings[3], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
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);
ramVoltItem->setValue(strings[4]);
sprintf(strings[5], "%u.%u mV", context->voltages[HocClkVoltage_Display] / 1000U, (context->voltages[HocClkVoltage_Display] % 1000U) / 100U);
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) {
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;
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);
if(R_FAILED(rc))
{
@@ -104,8 +106,10 @@ void AppProfileGui::openValueChoiceGui(
void AppProfileGui::addModuleListItem(HocClkProfile profile, HocClkModule module)
{
tsl::elm::ListItem* listItem = new tsl::elm::ListItem(hocclkFormatModule(module, true));
listItem->setValue(formatListFreqMHz(this->profileList->mhzMap[profile][module]));
listItem->setClickListener([this, listItem, profile, module](u64 keys) {
RamDisplayUnit memUnit = (RamDisplayUnit)configList.values[HocClkConfigValue_RamDisplayUnit];
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)
{
this->openFreqChoiceGui(listItem, profile, module);
@@ -115,7 +119,7 @@ void AppProfileGui::addModuleListItem(HocClkProfile profile, HocClkModule module
{
// Reset to "Default" (0 MHz)
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);
if(R_FAILED(rc))
@@ -286,6 +290,9 @@ public:
: applicationId(appId), profileList(pList), profile(prof) {}
void listUI() override {
BaseMenuGui::refresh(); // get latest context
if(!this->context)
return;
Result rc = hocclkIpcGetConfigValues(&configList);
if (R_FAILED(rc)) [[unlikely]] {
FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc);
@@ -296,7 +303,7 @@ public:
static constexpr struct { const char* label; int shift; } kAll[] = {
{"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++) {
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 "freq_choice_gui.h"
#include "value_choice_gui.h"
#define HOCCLK_GLOBAL_PROFILE_TID 0xA111111111111111
class AppProfileGui : public BaseMenuGui
{
protected:

View File

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

View File

@@ -27,6 +27,7 @@
#include "base_menu_gui.h"
#include "fatal_gui.h"
#include "../format.h"
// Cache hardware model to avoid repeated syscalls
@@ -57,8 +58,8 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
if(!this->context) [[unlikely]] return;
// All constants pre-calculated and cached
static constexpr const char* const labels[] = {
"App ID", "Profile", "CPU", "GPU", "MEM", "SoC", "Board", "Skin", "Now", "Avg", "BAT", "PMIC", "FAN", "DISP", "FPS", "RES"
const char* labels[] = {
"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};
@@ -121,7 +122,7 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
// === VOLTAGES ===
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);
@@ -139,8 +140,8 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
// 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[12], false, dataPositions[1] + 5, 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[12], false, dataPositions[1], y, SMALL_TEXT_SIZE, tempColors[HocClkThermalSensor_PCB]); // PCB
renderer->drawString(displayStrings[13], false, dataPositions[2], y, SMALL_TEXT_SIZE, tempColors[HocClkThermalSensor_Skin]); // Skin
y += 20; // Direct assignment (191 + 20)
@@ -229,7 +230,20 @@ void BaseMenuGui::refresh()
sprintf(displayStrings[3], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
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
hz = context->realFreqs[HocClkModule_CPU]; // CPU
@@ -239,7 +253,14 @@ void BaseMenuGui::refresh()
sprintf(displayStrings[6], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
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
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)
{
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 = "";
auto it = labels.find(hz);

View File

@@ -246,7 +246,8 @@ void GlobalOverrideGui::addModuleListItem(HocClkModule module)
{
tsl::elm::ListItem *listItem =
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) {
if ((keys & HidNpadButton_A) == HidNpadButton_A) {
this->openFreqChoiceGui(module);
@@ -262,7 +263,7 @@ void GlobalOverrideGui::addModuleListItem(HocClkModule module)
this->context->overrideFreqs[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;
}
@@ -300,6 +301,9 @@ public:
GovernorOverrideSubMenuGui(u32 initialPacked) : packed(initialPacked) {}
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
if (R_FAILED(rc)) [[unlikely]] {
FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc);
@@ -310,7 +314,7 @@ public:
static constexpr struct { const char* label; int shift; } kAll[] = {
{"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++) {
u8 cur = (this->packed >> kAll[i].shift) & 0xFF;
@@ -409,7 +413,9 @@ void GlobalOverrideGui::refresh()
}
} else {
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];

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 = {
{76800000, "Boost Mode"},
{307200000, "Handheld"},
{345600000, "Handheld"},
{384000000, "Handheld"},
{422400000, "Handheld"},
{460800000, "Handheld"},
{614400000, "Handheld Safe Max"},
{768000000, "Docked"},

File diff suppressed because it is too large Load Diff

View File

@@ -18,12 +18,14 @@
#pragma once
#include "../../ipc.h"
#include "base_menu_gui.h"
#include <initializer_list>
#include <set>
#include <unordered_map>
#include <string>
#include <vector>
#include "freq_choice_gui.h"
#include "value_choice_gui.h"
#include "info_gui.h"
class MiscGui : public BaseMenuGui
{
public:
@@ -31,7 +33,7 @@ public:
~MiscGui();
void listUI() override;
void refresh() override;
protected:
HocClkConfigValueList* configList;
std::map<HocClkConfigValue, tsl::elm::ListItem*> configButtons;
@@ -41,32 +43,40 @@ protected:
std::map<HocClkConfigValue, std::tuple<tsl::elm::TrackBar*, tsl::elm::ListItem*, std::vector<uint64_t>>> configTrackbars;
std::set<HocClkConfigValue> configButtonSKeys;
std::map<HocClkConfigValue, std::string> configButtonSSubtext;
void addConfigToggle(HocClkConfigValue configVal, const char* altName);
void addConfigButton(HocClkConfigValue configVal,
const char* altName,
const ValueRange& range,
const std::string& categoryName,
const ValueThresholds* thresholds,
const std::map<uint32_t, std::string>& labels = {},
const std::vector<NamedValue>& namedValues = {},
bool showDefaultValue = true);
void addConfigButtonS(HocClkConfigValue configVal,
const char* altName,
std::set<HocClkConfigValue> emcClockConfigs;
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,
const char* altName,
const ValueRange& range,
const std::string& categoryName,
const ValueThresholds* thresholds,
const std::map<uint32_t, std::string>& labels = {},
const std::vector<NamedValue>& namedValues = {},
bool showDefaultValue = true,
const char* subText = nullptr);
bool kip = false);
void addConfigButtonS(HocClkConfigValue configVal,
const char* altName,
const ValueRange& range,
const std::string& categoryName,
const ValueThresholds* thresholds,
const std::map<uint32_t, std::string>& labels = {},
const std::vector<NamedValue>& namedValues = {},
bool showDefaultValue = true,
const char* subText = nullptr,
bool kip = false);
void addFreqButton(HocClkConfigValue configVal,
const char* altName,
HocClkModule module,
const std::map<uint32_t, std::string>& labels = {});
void updateConfigToggles();
tsl::elm::ToggleListItem* enabledToggle;
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 {
private:
bool visible;

View File

@@ -22,33 +22,33 @@ CONFIG_DIR := horizon-oc
BUILD := build
OUTDIR := out
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
INCLUDES := ../common/include
INCLUDES := ../common/include src/hos src/soc src/i2c src/util src/pwr src/ipc
EXEFS_SRC := exefs_src
LIBNAMES := minIni nxExt
#---------------------------------------------------------------------------------
# version control constants
#---------------------------------------------------------------------------------
TARGET_VERSION := $(shell git describe --dirty --always --tags)
LIBNAMES := minIni
# major minor patch
TARGET_VERSION := 2.4.0
KIP_VERSION := 240
CUST_REV := 4
#---------------------------------------------------------------------------------
# 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
CFLAGS := -g -Wall -Os -ffunction-sections \
$(ARCH) $(DEFINES) -ffast-math
CFLAGS := -g -Wall -Os \
-ffast-math -ffunction-sections -fdata-sections -fno-asynchronous-unwind-tables -fno-unwind-tables \
$(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE) -D__SWITCH__
CXXFLAGS := $(CFLAGS) -fno-rtti -std=gnu++23
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++23
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

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_range_min": "0x00FF0000636C6BFF",
"title_id_range_max": "0x00FF0000636C6BFF",
"main_thread_stack_size": "0x0000D000",
"main_thread_stack_size": "0x0000C000",
"main_thread_priority": 16,
"default_cpu_id": 3,
"process_category": 1,
@@ -31,6 +31,14 @@
"highest_cpu_id": 3
}
}, {
"type": "map",
"value": {
"address": "0x70000000",
"is_ro": false,
"size": "0x00001000",
"is_io": true
}
}, {
"type": "map",
"value": {
"address": "0x60006000",
@@ -86,7 +94,8 @@
"is_ro": false,
"is_io": true
}
}, {
},
{
"type": "syscalls",
"value": {
"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 <switch.h>
#include <pwm.h>
#include <registers.h>
#include <battery.h>
#include "display_refresh_rate.hpp"
#include <rgltr.h>
#include "../display/display_refresh_rate.hpp"
#include <notification.h>
#include "board.hpp"
@@ -39,49 +44,66 @@
#include "board_load.hpp"
#include "board_volt.hpp"
#include "board_misc.hpp"
#include "../soctherm.hpp"
#include "../integrations.hpp"
#include "../file_utils.hpp"
#include "../tsensor/soctherm.hpp"
#include "../tsensor/aotag.hpp"
#include "../hos/integrations.hpp"
#include "../file/file_utils.hpp"
#include "../hos/rgltr.h"
namespace board {
u64 clkVirtAddr, dsiVirtAddr, apbVirtAddr, fuseVirtAddr;
HocClkSocType gSocType;
u8 gDramID;
HocClkConsoleType gConsoleType = HocClkConsoleType_Iowa;
HocClkConsoleType gConsoleType = HocClkConsoleType_Icosa;
FuseData fuseData;
u8 speedoBracket;
PwmChannelSession iCon;
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() {
ReadFuses(fuseData);
ReadFuses(fuseData, fuseVirtAddr);
SetGpuBracket(fuseData.gpuSpeedo, speedoBracket);
u64 sku = 0, dramID = 0;
Result rc = splInitialize();
ASSERT_RESULT_OK(rc, "splInitialize");
rc = splGetConfig(SplConfigItem_HardwareType, &sku);
ASSERT_RESULT_OK(rc, "splGetConfig");
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 hidrev = *(u32*)(apbVirtAddr + APB_MISC_GP_HIDREV);
if (((hidrev >> 4) & 0xF) >= GP_HIDREV_MAJOR_T210B01) {
gSocType = HocClkSocType_Mariko;
CacheGpuVoltTable();
} else {
gSocType = HocClkSocType_Erista;
}
u32 odm4 = *(u32*)(fuseVirtAddr + FUSE_OFFSET + FUSE_RESERVED_ODMX(4));
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 */
@@ -113,6 +135,26 @@ namespace board {
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;
if (R_SUCCEEDED(nvInitialize())) {
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);
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;
if (hosversionAtLeast(6,0,0) && R_SUCCEEDED(pwmInitialize())) {
@@ -145,14 +190,6 @@ namespace board {
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::Initialize(&cfg);
@@ -168,13 +205,14 @@ namespace board {
apmExtExit();
psmExit();
rgltrExit();
if (HOSSVC_HAS_TC) {
tcExit();
}
max17050Exit();
tmp451Exit();
display::Shutdown();
ExitLoad();
@@ -182,10 +220,8 @@ namespace board {
pwmChannelSessionClose(&iCon);
pwmExit();
rgltrExit();
batteryInfoExit();
pmdmntExit();
display::Shutdown();
nvExit();
}
@@ -208,7 +244,7 @@ namespace board {
svcCallSecureMonitor(&args);
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;
}

View File

@@ -35,12 +35,18 @@
#include "board_sensor.hpp"
#include "board_volt.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_TC (hosversionAtLeast(5,0,0))
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 Exit();
HocClkSocType GetSocType();

View File

@@ -26,14 +26,25 @@
#include <switch.h>
#include <hocclk.h>
#include <nxExt.h>
#include "display_refresh_rate.hpp"
#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 "../display/display_refresh_rate.hpp"
#include "board.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 {
#define MIDDLE_FREQ_TABLE_START_POINT 1228800000
static u32 currentInjectedHz = 0;
PcvModule GetPcvModule(HocClkModule hocclkModule) {
switch (hocclkModule) {
case HocClkModule_CPU:
@@ -65,11 +76,18 @@ namespace board {
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) {
Result rc = 0;
bool usesGovenor = module > HocClkModule_MEM;
if (module == HocClkModule_Display) {
display::SetRate(hz);
return;
@@ -79,27 +97,41 @@ namespace board {
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) {
ClkrstSession session = {};
rc = clkrstOpenSession(&session, GetPcvModuleId(module), 3);
ASSERT_RESULT_OK(rc, "clkrstOpenSession");
ClkrstSetHz(session, hz);
ClkrstSetHz(session, pcvHz);
/* Voltage bug workaround. */
if (module == HocClkModule_CPU) {
svcSleepThread(250'000);
ClkrstSetHz(session, hz);
svcSleepThread(300'000);
ClkrstSetHz(session, pcvHz);
}
clkrstCloseSession(&session);
} else {
PcvSetHz(GetPcvModule(module), hz);
PcvSetHz(GetPcvModule(module), pcvHz);
if (module == HocClkModule_CPU) {
svcSleepThread(250'000);
PcvSetHz(GetPcvModule(module), hz);
svcSleepThread(300'000);
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) {
@@ -115,6 +147,10 @@ namespace board {
return GetDisplayRate(hz);
}
if (module == HocClkModule_GPU && currentInjectedHz != 0) {
return currentInjectedHz;
}
if (HOSSVC_HAS_CLKRST) {
ClkrstSession session = {};
@@ -141,10 +177,9 @@ namespace board {
case HocClkModule_GPU:
return t210ClkGpuFreq();
case HocClkModule_MEM:
return t210ClkMemFreq();
return config::GetConfigValue(HocClkConfigValue_MemoryFrequencyMeasurementMode) == MemoryFrequencyMeasurementMode_PLL ? pllmb::getRamClockRatePLLMB() : t210ClkMemFreq();
case HocClkModule_Display:
return GetDisplayRate(hz);
return hz;
default:
ASSERT_ENUM_VALID(HocClkModule, module);
}

View File

@@ -27,8 +27,14 @@
#pragma once
#include <switch.h>
#include <hocclk.h>
#include <nxExt.h>
#include "../errors.hpp"
#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 "../file/errors.hpp"
namespace board {
@@ -38,7 +44,8 @@ namespace board {
u32 GetRealHz(HocClkModule module);
void GetFreqList(HocClkModule module, u32 *outList, u32 maxCount, u32 *outCount);
u32 GetHighestDockedDisplayRate();
void HandleCpuUv();
void ResetToStock();
void ResetToStockDisplay();

View File

@@ -42,61 +42,19 @@ namespace board {
gpuBracket = 3;
}
void ReadFuses(FuseData &speedo) {
u64 pid = 0;
constexpr u64 UsbID = 0x0100000000000006;
if (R_FAILED(pmdmntGetProcessId(&pid, UsbID))) {
return;
}
void ReadFuses(FuseData &speedo, u64 fuseVa) {
constexpr u32 FuseOffset = 0x800;
u8 *fusePtr = reinterpret_cast<u8 *>(fuseVa) + FuseOffset;
Handle debug;
if (R_FAILED(svcDebugActiveProcess(&debug, pid))) {
return;
}
MemoryInfo mem_info = {};
u32 pageinfo = 0;
u64 addr = 0;
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);
speedo.cpuSpeedo = *reinterpret_cast<u16 *>(fusePtr + FUSE_CPU_SPEEDO_0_CALIB);
speedo.gpuSpeedo = *reinterpret_cast<u16 *>(fusePtr + FUSE_CPU_SPEEDO_2_CALIB);
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;
speedo.socIDDQ = *reinterpret_cast<u16 *>(fusePtr + FUSE_SOC_IDDQ_CALIB) * 4;
speedo.waferX = *reinterpret_cast<s16 *>(fusePtr + FUSE_OPT_X_COORDINATE);
speedo.waferY = *reinterpret_cast<s16 *>(fusePtr + FUSE_OPT_Y_COORDINATE);
speedo.waferX = (speedo.waferX & BIT(8)) ? (speedo.waferX - 512) : speedo.waferX;
}
}

View File

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

View File

@@ -26,7 +26,13 @@
#include <switch.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 <math.h>
#include <numeric>
@@ -120,6 +126,14 @@ namespace board {
return info.RawBatteryCharge;
case HocClkPartLoad_FAN:
return GetFanLevel();
case HocClkPartLoad_RamBWAll:
return t210EmcBwAll();
case HocClkPartLoad_RamBWCpu:
return t210EmcBwCpu();
case HocClkPartLoad_RamBWGpu:
return t210EmcBwGpu();
case HocClkPartLoad_RamBWPeak:
return t210EmcBwPeak();
default:
ASSERT_ENUM_VALID(HocClkPartLoad, loadSource);
}

View File

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

View File

@@ -26,7 +26,13 @@
#include <switch.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"
namespace board {

View File

@@ -26,12 +26,22 @@
#include <hocclk.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 <battery.h>
#include <pwm.h>
#include "board.hpp"
#include "../soctherm.hpp"
#include "../tsensor/soctherm.hpp"
#include "../tsensor/aotag.hpp"
#include "../tsensor/bq24193.hpp"
#include "../file/config.hpp"
namespace board {
@@ -39,8 +49,8 @@ namespace board {
s32 millis = 0;
BatteryChargeInfo info;
soctherm::TSensorTemps temps = {};
soctherm::ReadSensors(temps);
tsensor::TSensorTemps temps = {};
tsensor::ReadTSensors(temps);
switch(sensor) {
case HocClkThermalSensor_SOC: {
@@ -77,11 +87,24 @@ namespace board {
break;
}
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;
}
case HocClkThermalSensor_PLLX: {
millis = temps.pllx;
break;
}
case HocClkThermalSensor_BQ24193: {
millis = bq24193::getBQTemp();
break;
}
case HocClkThermalSensor_AO: {
millis = tsensor::ReadAotag();
break;
}
default: {
ASSERT_ENUM_VALID(HocClkThermalSensor, sensor);

View File

@@ -1,6 +1,8 @@
/*
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
*
*
* Copyright (c) B3711
*
* 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.
@@ -20,16 +22,17 @@
#include <memmem.h>
#include <registers.h>
#include <cstring>
#include <rgltr.h>
#include <battery.h>
#include "board.hpp"
#include "board_freq.hpp"
#include "board_volt.hpp"
#include "../file_utils.hpp"
#include "../file/file_utils.hpp"
#include "../i2c/i2cDrv.h"
#include "../hos/rgltr.h"
namespace board {
GpuVoltData voltData = {};
u32 cpuVoltTable[32] = {}; // 32LUT
u64 cldvfs;
CpuDfllData cachedTune;
@@ -47,7 +50,8 @@ namespace board {
u32 tune1_high;
};
EristaCpuUvEntry eristaCpuUvTable[5] = {
EristaCpuUvEntry eristaCpuUvTable[6] = {
{0xFFEAD0FF, 0x0},
{0xffff, 0x27007ff},
{0xefff, 0x27407ff},
{0xdfff, 0x27807ff},
@@ -132,19 +136,16 @@ namespace board {
return;
}
} else {
if (GetHz(HocClkModule_CPU) < tbreakPoint || (!levelLow)) { // account for tbreak
*tune0_ptr = cachedTune.tune0Low; // I think each erista has a different tune0/tune1?
*tune1_ptr = cachedTune.tune1Low;
return;
} else {
if (levelLow) {
*tune0_ptr = eristaCpuUvTable[levelLow-1].tune0;
*tune1_ptr = eristaCpuUvTable[levelLow-1].tune1;
} else {
*tune0_ptr = 0x0;
*tune1_ptr = 0x0;
}
}
// if (GetHz(HocClkModule_CPU) < tbreakPoint || (!levelLow)) { // account for tbreak
// *tune0_ptr = cachedTune.tune0Low; // I think each erista has a different tune0/tune1?
// *tune1_ptr = cachedTune.tune1Low;
// return;
// } else {
// if (levelLow) {
*tune0_ptr = eristaCpuUvTable[levelLow].tune0;
*tune1_ptr = eristaCpuUvTable[levelLow].tune1;
// } else {
// }
}
}
@@ -211,60 +212,47 @@ namespace board {
PcvPowerDomainId_Max77812_Dram = 0x3A000005, // vddq
} PowerDomainId;
*/
/*
Note: I think Nintendo's I2C driver (or my driver, but it looks correct to me)
*/
u32 GetVoltage(HocClkVoltage voltage) {
RgltrSession session;
Result rc = 0;
u32 out = 0;
BatteryChargeInfo info;
RgltrSession s;
switch (voltage) {
case HocClkVoltage_SOC:
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77620_Sd0);
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
rgltrGetVoltage(&session, &out);
rgltrCloseSession(&session);
out = I2c_BuckConverter_GetUvOut(&I2c_SOC);
break;
case HocClkVoltage_EMCVDD2:
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77620_Sd1);
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
rgltrGetVoltage(&session, &out);
rgltrCloseSession(&session);
out = I2c_BuckConverter_GetUvOut(&I2c_VDD2);
break;
case HocClkVoltage_CPU:
if (GetSocType() == HocClkSocType_Mariko) {
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77621_Cpu);
if(GetSocType() == HocClkSocType_Mariko) {
out = I2c_BuckConverter_GetUvOut(&I2c_Mariko_CPU);
} 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;
case HocClkVoltage_GPU:
if (GetSocType() == HocClkSocType_Mariko) {
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77621_Gpu);
if(GetSocType() == HocClkSocType_Mariko) {
out = I2c_BuckConverter_GetUvOut(&I2c_Mariko_GPU);
} else {
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77812_Gpu);
}
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
rgltrGetVoltage(&session, &out);
rgltrCloseSession(&session);
rgltrOpenSession(&s, PcvPowerDomainId_Max77621_Gpu);
rgltrGetVoltage(&s, &out);
rgltrCloseSession(&s);
}
break;
case HocClkVoltage_EMCVDDQ:
if (GetSocType() == HocClkSocType_Mariko) {
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77812_Dram);
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
rgltrGetVoltage(&session, &out);
rgltrCloseSession(&session);
if(GetSocType() == HocClkSocType_Mariko) {
out = I2c_BuckConverter_GetUvOut(&I2c_Mariko_DRAM_VDDQ);
} else {
out = GetVoltage(HocClkVoltage_EMCVDD2);
out = I2c_BuckConverter_GetUvOut(&I2c_VDD2);
}
break;
case HocClkVoltage_Display:
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77620_Ldo0);
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
rgltrGetVoltage(&session, &out);
rgltrCloseSession(&session);
out = I2c_BuckConverter_GetUvOut(&I2c_Display);
break;
case HocClkVoltage_Battery:
batteryInfoGetChargeInfo(&info);
@@ -318,6 +306,7 @@ namespace board {
}
void CacheGpuVoltTable() {
// Likely CPU regulator?
UnkRegulator reg = {
.voltageMin = 600000,
.voltageStep = 12500,
@@ -371,14 +360,26 @@ namespace board {
/* Assuming mariko. */
const u32 vmax = 800;
constexpr u32 VoltageTableOffset = 312;
if (!std::memcmp(&buffer[index + VoltageTableOffset], &vmax, sizeof(vmax))) {
std::memcpy(voltData.voltTable, &buffer[index + VoltageTableOffset], sizeof(voltData.voltTable));
voltData.voltTableAddress = base + memoryInfo.addr + VoltageTableOffset + index;
constexpr u32 GpuVoltageTableOffset = 312;
if (!std::memcmp(&buffer[index + GpuVoltageTableOffset], &vmax, sizeof(vmax))) {
std::memcpy(voltData.voltTable, &buffer[index + GpuVoltageTableOffset], sizeof(voltData.voltTable));
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);
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;
}
}
@@ -421,25 +422,41 @@ namespace board {
u32 GetMinimumGpuVmin(u32 freqMhz, u32 bracket) {
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, },
{ 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, },
{ 2433, 2466, 2533, 2600, 2666, 2733, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, },
{ 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, },
{ 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, }, // Bracket 1
{ 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, }, // 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, };
if (freqMhz <= 1600) {
return 0;
if (freqMhz <= 1600) return 0; // DVFS doesnt work below 1600MHz, it will just use vMin
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) {
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;
u32 ramVmin;
};
/* TODO: Find out what component this actually targets. */
struct UnkRegulator {
u32 voltageMin;
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