Skip to content

Commit 0dd8ee1

Browse files
vupleaclaude
andcommitted
Keep the README non-technical; document the curve files in CURVE-FILES.md
The JSON export/import options and the document format are power-user material, so the README keeps only a pointer. CURVE-FILES.md carries the commands, annotated examples of both document kinds, the minimal hand-written forms, and the app's own store files (the saved reference and the persisted tuning) - which also lets the README's persistence and disclaimer paragraphs stay at their simpler wording. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01USJLMsRerGrWg8h6Fwtear
1 parent ce21a9b commit 0dd8ee1

2 files changed

Lines changed: 131 additions & 42 deletions

File tree

‎CURVE-FILES.md‎

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# Curve data files
2+
3+
Curve data travels as JSON documents, so you can plot it, archive it, or move it between installs.
4+
There are two kinds:
5+
6+
- a **reference curve** — the card's full stock V/F table, as `set-reference-curve` saves it;
7+
- a **tuning** — the offsets a tuning run applies: the tuned curve anchors and the memory offset.
8+
9+
## Exporting and importing
10+
11+
```powershell
12+
# Save the reference and also export it:
13+
simple-nvidia-undervolt set-reference-curve --out-curve-file stock.json
14+
# Restore that reference later (validated against the card - same GPU, same curve anchors):
15+
simple-nvidia-undervolt set-reference-curve --in-curve-file stock.json
16+
# Tune and also export the resulting tuning:
17+
simple-nvidia-undervolt --mv 900 --out-tuning-file tuning.json
18+
# Export whatever tuning is currently applied (works for a foreign one, e.g. Afterburner's):
19+
simple-nvidia-undervolt status --out-tuning-file tuning.json
20+
# Re-apply an exported tuning exactly, offsets as data - no planning:
21+
simple-nvidia-undervolt --in-tuning-file tuning.json
22+
```
23+
24+
With `--dry-run`, `--out-tuning-file` exports the planned tuning without applying anything.
25+
26+
## Reference curve
27+
28+
The full stock table, one `{ mv, mhz }` entry per anchor, plus where it came from:
29+
30+
```json
31+
{
32+
"type": "referenceCurve",
33+
"formatVersion": 1,
34+
"appVersion": "1.0.4",
35+
"savedAt": "2026-07-25 09:14",
36+
"gpuName": "NVIDIA GeForce RTX 5090",
37+
"gpuPciIds": "2B8510DE-89EE1043-000000A1-00002B85",
38+
"tempC": 30,
39+
"curve": [
40+
{ "mv": 900, "mhz": 2392 },
41+
{ "mv": 910, "mhz": 2415 },
42+
… one entry per anchor, the whole stock table …
43+
{ "mv": 1235, "mhz": 3187 },
44+
{ "mv": 1240, "mhz": 3195 }
45+
]
46+
}
47+
```
48+
49+
Capture it stock, idle and cool: the reference exists to make tuning reproducible, and a curve
50+
captured tuned or hot bakes those conditions into every plan made from it. Importing checks the
51+
identity fields and the anchor voltages against the live card.
52+
53+
## Tuning
54+
55+
The tuned range of anchors — `offset` (MHz from stock) is what a re-apply writes, `mhz` (the
56+
anchor's clock at the moment of tuning) is informative — plus `memoryOffset` (MHz from the factory
57+
base clock):
58+
59+
```json
60+
{
61+
"type": "tuning",
62+
"formatVersion": 1,
63+
"appVersion": "1.0.4",
64+
"savedAt": "2026-07-25 09:14",
65+
"gpuName": "NVIDIA GeForce RTX 5090",
66+
"gpuPciIds": "2B8510DE-89EE1043-000000A1-00002B85",
67+
"memoryOffset": 1400,
68+
"curve": [
69+
{ "mv": 890, "offset": 480, "mhz": 2820 },
70+
{ "mv": 895, "offset": 480, "mhz": 2842 },
71+
{ "mv": 900, "offset": 480, "mhz": 2872 },
72+
{ "mv": 910, "offset": 457, "mhz": 2872 },
73+
… the flattened anchors above the cap …
74+
{ "mv": 1240, "offset": -323, "mhz": 2872 }
75+
]
76+
}
77+
```
78+
79+
Re-applying matches each entry to the card's table by voltage and writes the offsets exactly as
80+
validated — no re-planning. Anchors the document doesn't name stay stock. Identity is model-level
81+
on purpose: chips of the same model bin differently, but offsets land on the target card's own
82+
stock curve, so sharing a tuning between cards of the same model is part of what the format is
83+
for — a structurally different curve table is refused by the anchor matching.
84+
85+
## Hand-written documents
86+
87+
Only `curve` is required; every other field may be omitted. The minimal tuning — raise the 900 mV
88+
anchor by 100 MHz, leave everything else stock:
89+
90+
```json
91+
{
92+
"curve": [
93+
{ "mv": 900, "offset": 100 }
94+
]
95+
}
96+
```
97+
98+
Each tuned anchor needs `mv` and `offset` and/or `mhz` — given only `mhz`, the offset resolves as
99+
`mhz - stock` against the saved reference (or a live stock read). The minimal reference curve is
100+
the same document as above with the metadata dropped — but its `curve` must still be the complete
101+
stock table, so in practice start from an `--out-curve-file` export.
102+
103+
The optional fields degrade predictably: a document naming no GPU applies with a warning instead
104+
of an identity check, and an absent `type`/`formatVersion` is accepted (the flag a file is handed
105+
to already says which kind it holds). What must match, must match exactly: a named identity field,
106+
a present `type`, the anchor voltages. Unknown fields are refused like unknown CLI flags — a
107+
typo'd `memoryOffest` must fail, not silently change the tuning — and every offset is held to the
108+
same plausibility bounds a planned tuning gets. Anything only a foreign tool sets — a voltage
109+
boost, say — is outside the format, so it is neither exported nor re-applied.
110+
111+
## The app's own store files
112+
113+
The same documents are how the app stores its own state, under `data\` in the install directory
114+
(`%ProgramFiles%\simple-nvidia-undervolt`):
115+
116+
- `data\reference-curve.json` — the saved reference curve (the same document `--out-curve-file`
117+
exports).
118+
- `data\persisted-tuning.json` — the tuning the logon task re-applies (the same document
119+
`--out-tuning-file` exports). It lives under Program Files deliberately: the file is admin-only
120+
writable, and the elevated logon task must not consume user-writable data. `clear` removes it
121+
along with the task.

‎README.md‎

Lines changed: 10 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,6 @@ Memory clock (optional):
7878
Other:
7979
--cap-points <n> Curve anchors holding the cap's offset, counting down from the cap.
8080
1 = only the cap point.
81-
--in-tuning-file <f>
82-
Re-apply an exported tuning file exactly (excludes the other tuning options).
83-
--out-tuning-file <f>
84-
Also export the run's tuning as JSON; with --dry-run, export without applying.
8581
--no-persist Don't persist; by default a real run re-applies at logon.
8682
--save-shortcut [name]
8783
Drop a .lnk (specify name/path, otherwise auto-generated).
@@ -96,46 +92,18 @@ By default, tuning resolves against the live curve, which shifts slightly with t
9692
same command applied hot vs. cold bakes in a slightly different tuning. `set-reference-curve` fixes
9793
that: run it once with the GPU idle and cool to save the stock V/F curve. Tuning then plans from the
9894
saved curve instead of a live read, so the same command always produces the same result — this
99-
enables tuning during load. The reference is stored as `data\reference-curve.json` in the install
100-
directory (the same document `--out-curve-file` exports).
95+
enables tuning during load.
10196

10297
### Exporting and importing curve data
10398

104-
The curve data travels as JSON files, so you can plot it, archive it, or move it between installs:
105-
106-
```powershell
107-
# Save the reference and also export it:
108-
simple-nvidia-undervolt set-reference-curve --out-curve-file stock.json
109-
# Restore that reference later (validated against the card - same GPU, same curve anchors):
110-
simple-nvidia-undervolt set-reference-curve --in-curve-file stock.json
111-
# Tune and also export the resulting tuning:
112-
simple-nvidia-undervolt --mv 900 --out-tuning-file tuning.json
113-
# Export whatever tuning is currently applied (works for a foreign one, e.g. Afterburner's):
114-
simple-nvidia-undervolt status --out-tuning-file tuning.json
115-
# Re-apply an exported tuning exactly, offsets as data - no planning:
116-
simple-nvidia-undervolt --in-tuning-file tuning.json
117-
```
118-
119-
Both files hold a `curve` of `{mv, ...}` anchors — the stock table (`{mv, mhz}`) in a reference
120-
curve, the tuned range of anchors in a tuning, whose `offset` (MHz from stock) is what a re-apply writes and
121-
`mhz` (the clock at the moment of tuning) is informative — plus `memoryOffset` (MHz) in a tuning.
122-
Anchors are matched to the card's table by voltage, and the identity fields (`gpuName`,
123-
`gpuPciIds`) are checked against the live card. Only `curve` is required: in a hand-written
124-
document every other field may be omitted — an unnamed identity just warns, and an anchor without
125-
`offset` resolves it from its `mhz` against the reference curve (or a live stock read). Anything
126-
only a foreign tool sets — a voltage boost, say — is outside the format, so it is neither exported
127-
nor re-applied.
99+
The reference curve and applied tunings can travel as JSON files — plot them, archive them, or
100+
move them between installs. The commands and the file format: [CURVE-FILES.md](CURVE-FILES.md).
128101

129102
### Persisting at startup
130103

131-
A tuning run **persists by default**: it copies the app to Program Files, stores the resolved
132-
tuning as `data\persisted-tuning.json` in the install directory (the same document
133-
`--out-tuning-file` exports — admin-only writable there, since the elevated logon task must not
134-
consume user-writable data), and registers a Task Scheduler task that re-applies it at logon
135-
(`tune --apply-persisted`). The offsets re-apply exactly as validated — they are
136-
temperature-independent, so nothing is re-planned from a boot-time curve read. If the re-apply ever
137-
fails you get a message box so you are aware. Pass `--no-persist` to skip persistence; `clear`
138-
removes the file along with the task.
104+
A tuning run **persists by default**: it copies the app to Program Files, and registers a Task Scheduler
105+
task that re-applies the same undervolt at logon, elevated. If apply ever fails you get a message box
106+
so you are aware. Pass `--no-persist` to skip persistence.
139107

140108
### Saving a shortcut
141109

@@ -164,10 +132,10 @@ saved shortcuts keep working.
164132

165133
The app writes GPU tuning via `ClkVfPointsSetControl`, and the memory clock offset via
166134
`SetPstates20`. The worst case is believed to be an unstable configuration causing application,
167-
driver, or system crashes. It never raises voltage or power limits: the direct voltage knobs — the
168-
core voltage-boost percentage and the pstate voltage-offset field, separate APIs from the V/F curve
169-
— are only ever written as zero, and power-limit APIs are not used. The tuning itself does not
170-
survive a reboot, but by default it is re-applied at logon — run `clear` to revert to stock.
135+
driver, or system crashes. It never raises voltage or power limits: the voltage-boost and
136+
voltage-offset fields are only written as zero, and power-limit APIs are not used. The tuning
137+
itself does not survive a reboot, but by default it is re-applied at logon — run `clear` to revert
138+
to stock.
171139

172140
Importantly, this is still an experimental tool and you use it entirely at your own risk — we are not
173141
responsible for any consequences of using it, whether to hardware or software.

0 commit comments

Comments
 (0)