|
| 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. |
0 commit comments