Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TurboVcoreSDK

Decode and encode ASUS Turbo VCore .OC overclock profile files

TurboVcoreSDK is a pure-Python toolkit that turns ASUS Turbo VCore save files into human-readable voltage and ratio reports (text + JSON), and can rebuild valid .OC XML from edited settings. It is intended for documentation, logging, archival, and careful offline editing of Turbo VCore profiles—not for live hardware control.

Language Python 3.11+
Dependencies Standard library only
Input ASUS Turbo VCore .OC (XML)
Output Text reports, JSON settings, re-encoded .OC
Entry points turbo_decode.py, turbo_encode.py, python -m src

Table of contents

  1. Motivation
  2. Important disclaimers
  3. How Turbo VCore stores values
  4. Requirements
  5. Repository layout
  6. Quick start
  7. CLI reference
  8. Decode workflow
  9. Encode workflow
  10. Output formats
  11. Conversion model
  12. Known voltage and ratio profiles
  13. Key registry and unknown settings
  14. Using the library in Python
  15. Extending profiles and key maps
  16. Testing
  17. Design principles
  18. Current limitations
  19. Roadmap
  20. Sample files
  21. Contributing / review checklist
  22. License
  23. Credits

1. Motivation

ASUS Turbo VCore (and related motherboard utilities) can export overclock profiles as .OC files. Those files are XML documents filled with opaque integer fields, for example:

<item key="0x03020031">174</item>

The integer 174 is not a voltage in volts, millivolts, or “1.74 V”. It is a raw step count: how many adjustment increments have been applied from a rail’s minimum. The real engineering value depends on:

  • the rail’s minimum voltage (value at raw 0)
  • the rail’s step size (volts per raw increment)
  • and, for ratios, a fixed offset from raw to multiplier

Without those formulas, .OC files are effectively opaque. This project exists so you can:

  • Export BIOS / Turbo VCore settings into documentation and logs
  • Inspect voltages and ratios in plain language
  • Edit settings in JSON and write a new .OC
  • Round-trip known values with deterministic encode/decode math

2. Important disclaimers

Overclocking and voltage changes can damage hardware, void warranties, cause instability, data loss, or failure to boot.

Please read carefully:

  1. This software does not talk to your BIOS, firmware, or hardware. It only reads and writes files on disk.
  2. Formulas and key maps are incomplete and partially experimental. Only a subset of item keys are mapped to named rails. Unmapped keys are preserved as raw integers only.
  3. PLL Termination Voltage uses a non-standard step size confirmed against experimental BIOS arrow-press data. Other rails use anchors documented in the project design notes; they may differ across CPU generations, motherboards, or Turbo VCore versions.
  4. BCLK Frequency conversion is provisional and marked as needing verification. Do not trust BCLK decode/encode for production profiles until validated on your hardware.
  5. Loading a hand-edited .OC into Turbo VCore or a motherboard utility is entirely at your own risk. Always keep backups of original profiles and know how to clear CMOS / restore defaults.
  6. This project is not affiliated with ASUS or any motherboard vendor.

3. How Turbo VCore stores values

3.1 File type

Original ASUS Turbo VCore saves are XML, often with a .OC extension. A minimal shape looks like:

<?xml version="1.0" encoding="utf-8"?>
<root>
    <minor>
        <item key="0x03020031">174</item>
    </minor>
</root>

Real profiles typically contain many more sections and items. The parser:

  • Walks the entire tree
  • Collects every <item key="...">...</item>
  • Keeps the ElementTree so re-export can preserve structure

3.2 What “raw” means

For a linear voltage rail:

voltage = minimum + raw × step
raw     = round((voltage − minimum) / step)

Example (CPU Core Voltage in this project):

Raw Voltage
0 1.00000 V
80 1.25000 V (1.0 + 80 × 0.003125)

Example (PLL Termination Voltage):

Raw Voltage
20 0.33204 V
40 0.46408 V
60 0.59612 V
174 1.34875 V

For core ratios:

multiplier = raw + 12
raw 28  →  40×

3.3 Separation of concerns

Parsing never hardcodes voltage math. All conversions live in configurable profiles (src/profiles.py). The parser only preserves:

  • XML structure
  • Element / section tags
  • Item keys
  • Raw integer values

4. Requirements

Requirement Detail
Python 3.11 or newer (type hints use modern syntax; tested with 3.12)
OS Windows, Linux, or macOS
Third-party packages None
Standard library modules used argparse, xml.etree.ElementTree, dataclasses, json, pathlib, unittest

On some Windows setups the python command is not on PATH. If so, use the launcher or full shim name available on your machine, for example:

python3.12 turbo_decode.py examples/sample_profile.OC
# or
py -3.12 turbo_decode.py examples/sample_profile.OC

No pip install step is required to run from a clone of this repository.


5. Repository layout

TurboVcoreSDK/
├── README.md                 # This document
├── grok.md                   # Original design / mission notes
├── turbo_decode.py           # CLI wrapper: decode .OC → reports
├── turbo_encode.py           # CLI wrapper: JSON → .OC
├── src/
│   ├── __init__.py           # Package version
│   ├── __main__.py           # python -m src → CLI
│   ├── cli.py                # argparse subcommands: decode | encode
│   ├── parser.py             # OC XML parse, write, structure updates
│   ├── profiles.py           # VoltageProfile, RatioProfile, key registry
│   ├── converter.py          # decode_document / encode_settings_dict
│   └── reporter.py           # Text + JSON report generation
├── tests/
│   ├── test_profiles.py      # All known voltage/ratio anchors
│   ├── test_parser.py        # XML parse / write / set_item_raw
│   ├── test_converter.py     # End-to-end decode/encode
│   └── test_reporter.py      # Report output shape
└── examples/
    ├── sample_profile.OC     # Minimal sample input
    ├── profile_report.txt    # Example decode text (generated)
    └── profile.json          # Example decode JSON (generated)

Module responsibilities

Module Responsibility
parser.py Load/save XML; OcDocument / OcItem; update raw values without losing sibling keys
profiles.py VoltageProfile, RatioProfile, BclkProfile; named constants; KNOWN_KEY_PROFILES
converter.py Map items through profiles; build JSON-friendly structures; encode settings dicts
reporter.py Human text layout; JSON dump; load settings JSON for encode
cli.py User-facing commands and output path selection

6. Quick start

Clone or copy the repository, then from the repo root:

Decode a profile

python turbo_decode.py examples/sample_profile.OC

This writes next to the input file (legacy names used by the wrapper):

File Description
examples/profile_report.txt Human-readable report
examples/profile.json Machine-readable settings

Encode settings back to .OC

python turbo_encode.py examples/profile.json examples/rebuilt.OC

Prefer updating an existing profile (recommended)

When you already have a full .OC from Turbo VCore, use it as a base so unmapped keys and XML structure are preserved:

python turbo_encode.py edited_settings.json output.OC --base-oc original.OC

Run the unit tests

python -m unittest discover -s tests -v

7. CLI reference

There are two layers of entry points. Both ultimately call src.cli.main.

7.1 Convenience scripts

turbo_decode.py

python turbo_decode.py <profile.OC> [options...]
python turbo_decode.py --help

Behavior notes:

  • Inserts the decode subcommand for you.
  • If you do not pass custom output paths (-t / --text-out), it adds --legacy-names, so outputs are:
    • profile_report.txt
    • profile.json in the same directory as the input file.

turbo_encode.py

python turbo_encode.py <settings.json> <output.OC> [--base-oc base.OC]
python turbo_encode.py --help

Inserts the encode subcommand for you.

7.2 Module / package CLI

python -m src decode <oc_file> [options]
python -m src encode <settings_json> <output_oc> [options]
python -m src.cli decode ...

Program name in help text: turbo_vcore.

7.3 decode options

Argument Description
oc_file Path to the ASUS Turbo VCore .OC file (required)
-t, --text-out Explicit path for the text report
-j, --json-out Explicit path for the JSON report
-o, --output-dir Write {stem}_report.txt and {stem}.json into this directory
--legacy-names Write profile_report.txt and profile.json beside the input
--title Title line for the text report (default: ASUS Turbo VCore Profile)
--stdout Also print the text report to standard output

Output path priority:

  1. If both --text-out and --json-out are set → use those paths.
  2. Else if --output-dir is set → {output_dir}/{stem}_report.txt and {stem}.json.
  3. Else default → {parent}/{stem}_report.txt and {parent}/{stem}.json.
  4. If --legacy-names is set in the default branch → profile_report.txt / profile.json in the input’s parent directory.

turbo_decode.py always enables legacy names unless you override with -t/--text-out.

7.4 encode options

Argument Description
settings_json Path to JSON object of settings (required)
output_oc Path for the written .OC file (required)
-b, --base-oc Optional existing .OC to update in place (structure-preserving)

Without --base-oc, the encoder builds a minimal document:

<root>
    <minor>
        <item key="...">...</item>
        ...
    </minor>
</root>

That is enough for round-trips of known keys, but a full Turbo VCore profile may expect many more nodes. Prefer --base-oc when feeding files back into the utility.


8. Decode workflow

  profile.OC
      │
      ▼
  parser.parse_oc_file()
      │  OcDocument (ElementTree + list[OcItem])
      ▼
  converter.decode_document()
      │  For each item:
      │    look up KNOWN_KEY_PROFILES[key]
      │    if found → profile.decode(raw)
      │    else     → raw only (known=False)
      ▼
  reporter.write_reports()
      │
      ├── profile_report.txt   (or custom name)
      └── profile.json

Console summary after a successful decode:

Wrote examples\profile_report.txt
Wrote examples\profile.json
Decoded 1/1 settings with known profiles

The Decoded N/M line tells you how many item keys had conversion profiles. On a real multi-key profile you will often see something like Decoded 1/87 until more keys are registered.


9. Encode workflow

  settings.json
      │
      ▼
  reporter.load_settings_json()
      │
      ▼
  converter.encode_settings_dict(settings, base_document?)
      │  For each named setting:
      │    resolve profile by name (or key)
      │    encode voltage/multiplier/value → raw
      │    or pass through explicit "raw"
      │  If base_document: set_item_raw() on matching keys
      │  Else: create_minimal_document()
      ▼
  parser.write_oc_file()
      │
      ▼
  output.OC

Accepted JSON value shapes

Each top-level key is normally a human-readable setting name (or a hex key). Values may be:

{
  "PLL Termination Voltage": { "voltage": 1.34875 },
  "PLL Termination Voltage (raw form)": { "raw": 174, "key": "0x03020031" },
  "Some Rail": { "value": 1.25 },
  "Core 1": { "multiplier": 40 },
  "Bare number means engineering value when name is known": 1.34875
}

Field priority when encoding from an object:

Field Meaning
voltage Engineering volts (for unit == "V" profiles)
multiplier Core ratio multiplier (for ratio profiles)
frequency_mhz BCLK-style frequency
value Generic engineering value
raw Skip conversion; write this integer (optionally with key)
key Override which XML item key is written/updated

Keys starting with _ are treated as metadata and skipped.

Round-trip example

# 1. Decode
python turbo_decode.py myboard.OC

# 2. Edit profile.json voltages carefully

# 3. Encode back onto the original structure
python turbo_encode.py profile.json myboard_edited.OC --base-oc myboard.OC

Encoding uses rounding to the nearest raw step:

raw = round((voltage − minimum) / step)

Slight floating-point drift is expected to snap back to the nearest discrete BIOS step.


10. Output formats

10.1 Text report

Example (examples/profile_report.txt after decoding the sample):

ASUS Turbo VCore Profile

CPU Voltages
============

PLL Termination Voltage
Raw Value: 174
Voltage: 1.34875V


Source: examples\sample_profile.OC

Sections produced when present:

Section Contents
CPU Voltages Settings with unit V (or names containing Voltage)
CPU Ratios Settings with unit x / core names
Other Settings Everything else (including unknown keys with raw only)

Unknown items appear under “Other Settings” with key, raw value, and a note that no conversion profile exists.

10.2 JSON report

Example:

{
  "PLL Termination Voltage": {
    "raw": 174,
    "voltage": 1.34875,
    "key": "0x03020031"
  }
}

Per-setting fields that may appear:

Field When
raw Always
voltage Decoded voltage rail
multiplier Decoded core ratio
frequency_mhz Decoded BCLK-style profile
value Other decoded engineering units
key XML item key when known
unit Present in some intermediate dict helpers

The top-level object is keyed by setting name (or raw hex key if the setting is unknown).


11. Conversion model

11.1 Voltage profiles

Implemented as VoltageProfile in src/profiles.py:

class VoltageProfile:
    def decode(self, raw: int) -> float:
        return round(self.minimum + raw * self.step, self.decimals)

    def encode(self, voltage: float) -> int:
        return int(round((voltage - self.minimum) / self.step))

Attributes:

Attribute Role
name Human-readable label
minimum Voltage at raw 0
step ΔV per raw step
unit Default "V"
decimals Rounding for display / decode

11.2 Ratio profiles

class RatioProfile:
    def decode(self, raw: int) -> float:
        return float(raw + self.offset)   # default offset = 12

    def encode(self, multiplier: float) -> int:
        return int(round(multiplier - self.offset))

Confirmed anchor: raw 2840×.

11.3 BCLK profile (provisional)

frequency_mhz ≈ base_mhz + (raw − raw_base) × scale

Defaults currently:

Parameter Value
base_mhz 100.0
raw_base 1000
scale 0.1

This formula is a placeholder. Do not rely on it until validated against real Turbo VCore / BIOS exports for your platform.


12. Known voltage and ratio profiles

These constants are defined in src/profiles.py and covered by unit tests.

12.1 Voltage rails

Profile constant Display name Formula Anchor (raw → value)
CPU_CORE_VOLTAGE CPU Core Voltage 1.00000 + raw × 0.003125 80 → 1.25000 V
DRAM_VOLTAGE DRAM Voltage 0.800 + raw × 0.005 110 → 1.350 V
CPU_CACHE_VOLTAGE CPU Cache Voltage 1.000 + raw × 0.003125 64 → 1.20000 V
CPU_SYSTEM_AGENT_VOLTAGE CPU System Agent Voltage 0.80000 + raw × 0.003125 48 → 0.95000 V
PLL_TERMINATION_VOLTAGE PLL Termination Voltage 0.20000 + raw × 0.006602 174 → 1.34875 V
CPU_INPUT_VOLTAGE CPU Input Voltage (VCCIN) 0.80 + raw × 0.01 111 → 1.91 V

12.2 PLL Termination details

PLL Termination is not a normal decimal step (not 0.005 / 0.00625). Experimental notes:

  • Raw step count matches BIOS arrow presses
  • Minimum: 0.20000 V
  • Implementation step: 0.006602 (chosen so verification points hit cleanly)

Verification points:

Raw Expected voltage
20 0.33204 V
40 0.46408 V
60 0.59612 V
174 1.34875 V

Note on the original design doc: grok.md listed step ≈ 0.00660143678. That value is very close but does not land exactly on the same verification table (especially raw 174 → 1.34875). This codebase uses 0.006602, which satisfies the tabulated checkpoints and still round-trips correctly.

12.3 Core ratios

Name keys Formula Anchor
Core 1Core 6 / core01core06 multiplier = raw + 12 raw 28 → 40×

12.4 BCLK

Profile Status
BCLK_FREQUENCY Provisional; needs experimental verification

13. Key registry and unknown settings

13.1 Why keys matter

XML items are identified by hexadecimal keys, not by English names:

<item key="0x03020031">174</item>

Decoding to a named voltage requires a key → profile map.

13.2 Currently registered keys

XML key Profile
0x03020031 PLL Termination Voltage

Defined in KNOWN_KEY_PROFILES inside src/profiles.py.

13.3 Behavior for unknown keys

If a key is not in the registry:

  • It still appears in reports
  • Only the raw integer is shown
  • known is false in converter structures
  • Encode with --base-oc preserves those values unless you overwrite them

This is intentional: a partial map must never drop settings from a full profile.

13.4 Name registry for encode

PROFILES_BY_NAME maps human-readable names (and some short ids like core01) to profiles so JSON like:

{ "PLL Termination Voltage": { "voltage": 1.35 } }

can be encoded without the user knowing the hex key—when that name is known and a key is registered for it. For PLL, encode resolves name → key 0x03020031.


14. Using the library in Python

Run from the repository root (or ensure the repo root is on PYTHONPATH).

Decode

from src.parser import parse_oc_file
from src.converter import decode_document
from src.reporter import format_text_report, format_json_report, write_reports

doc = parse_oc_file("examples/sample_profile.OC")
profile = decode_document(doc)

print(format_text_report(profile))
print(format_json_report(profile))

write_reports(profile, "out_report.txt", "out.json")

Encode

from src.converter import encode_settings_dict
from src.parser import parse_oc_file, write_oc_file

settings = {
    "PLL Termination Voltage": {"voltage": 1.34875},
}

# Minimal new document
doc = encode_settings_dict(settings)
write_oc_file(doc, "minimal.OC")

# Or patch an existing full profile
base = parse_oc_file("original.OC")
doc = encode_settings_dict(settings, base_document=base)
write_oc_file(doc, "patched.OC")

Direct profile math

from src.profiles import (
    CPU_CORE_VOLTAGE,
    PLL_TERMINATION_VOLTAGE,
    RatioProfile,
)

assert CPU_CORE_VOLTAGE.decode(80) == 1.25
assert PLL_TERMINATION_VOLTAGE.encode(1.34875) == 174

ratio = RatioProfile(name="Core 1")
assert ratio.decode(28) == 40.0
assert ratio.encode(40) == 28

Register a new key at runtime

from src.profiles import CPU_CORE_VOLTAGE, register_key

register_key("0xYOURKEYHERE", CPU_CORE_VOLTAGE)

For permanent maps, edit KNOWN_KEY_PROFILES in src/profiles.py and add tests.


15. Extending profiles and key maps

Add a new voltage rail

  1. Define a VoltageProfile constant in src/profiles.py with measured minimum and step.
  2. Add it to PROFILES_BY_NAME.
  3. If you know the XML key, add it to KNOWN_KEY_PROFILES.
  4. Add unit tests in tests/test_profiles.py for the known anchor(s).
  5. Optionally add converter/parser tests with a tiny sample XML fragment.

Discover keys (future)

Planned approach (not automated yet):

  • Compare IFR / BIOS setup dumps with Turbo VCore exports
  • Diff .OC files after changing one BIOS option at a time
  • Map keys experimentally the same way PLL was mapped

Keep the parser clean

Do not put voltage formulas in parser.py. New rails always go through profiles so decode and encode stay symmetric.


16. Testing

Run all tests

python -m unittest discover -s tests -v

What is covered

Test module Focus
test_profiles.py CPU core, DRAM, cache, SA, PLL verification points, VCCIN, core ratio 28→40×, encode/decode round-trips
test_parser.py Item collection, section paths, find, write/reread, set_item_raw, minimal document creation
test_converter.py Known PLL key decode, unknown raw-only keys, JSON shape, encode by voltage/raw, base document patching
test_reporter.py Text content, JSON validity, write_reports file creation

As of the current tree, the suite is 35 tests, all expected to pass on Python 3.12.

Manual smoke test

python turbo_decode.py examples/sample_profile.OC
# Inspect examples/profile_report.txt and examples/profile.json

python turbo_encode.py examples/profile.json examples/roundtrip.OC
# Inspect examples/roundtrip.OC for key 0x03020031 / raw 174

17. Design principles

  1. Profiles are data, not parser logic — conversion formulas are swappable and testable in isolation.
  2. Structure preservation — encode-with-base updates raw values without discarding unknown siblings.
  3. Loss-aware partial knowledge — unknown keys remain visible as raw, never silently dropped.
  4. Standard library only — easy to run on air-gapped lab machines.
  5. Type hints everywhere — clearer public surfaces for future GUI or comparison tools.
  6. Round-trip honesty — encode uses rounding to discrete steps; floats that are not on a step boundary snap to the nearest raw.

18. Current limitations

Be aware of these before publishing or relying on the tool for full profiles:

Limitation Detail
Sparse key map Only 0x03020031 (PLL Termination) is registered by default
Named profiles without keys Core/DRAM/VCCIN math exists for encode-by-name and tests, but automatic decode from real OC keys needs those keys registered
BCLK formula Provisional / unverified
Turbo VCore versions No multi-version schema handling yet
Minimal encode documents Without --base-oc, output is a tiny <root><minor>… skeleton, not a full utility-compatible dump
No GUI CLI and library only
No profile diff Comparison / Markdown export are roadmap items
Platform variance Steps and mins may differ by board / CPU / BIOS; validate anchors on your system

19. Roadmap

The original design (grok.md) calls for future work that the architecture is meant to accommodate without a rewrite:

  • GUI front-end
  • BIOS / profile comparison and difference reports
  • Markdown report export
  • Automatic BIOS variable mapping from IFR dumps
  • Support multiple ASUS Turbo VCore versions
  • Expand KNOWN_KEY_PROFILES for core, DRAM, cache, SA, VCCIN, and ratios
  • Validate and lock BCLK formula experimentally
  • Optional packaging (pyproject.toml) and console script entry points

20. Sample files

Path Purpose
examples/sample_profile.OC Minimal valid OC with PLL key 0x03020031 = 174
examples/profile_report.txt Generated text report from the sample
examples/profile.json Generated JSON from the sample
grok.md Mission brief, original formulas, and product requirements

Regenerate sample outputs anytime:

python turbo_decode.py examples/sample_profile.OC

21. Contributing / review checklist

Before opening a PR or tagging a release, please verify:

  • python -m unittest discover -s tests -v is green
  • New voltage rails include encode and decode tests with at least one known anchor
  • New XML keys are documented in this README’s key table
  • Changes to PLL or other experimental steps include a short rationale (anchors used)
  • No third-party dependencies added without discussion
  • Encode paths that touch real profiles prefer documenting --base-oc usage
  • README formulas match src/profiles.py constants

Pre-GitHub hygiene (recommended before first push)

You may want to add (not required by the code itself):

  • .gitignore for __pycache__/, *.pyc, local .OC dumps you do not want public, IDE folders
  • A clear license file (MIT/Apache-2.0/etc.) if the project is public
  • Redact any personal BIOS dumps that contain machine-identifying data

This README was written for local review; the repository is not automatically published.


22. License

Use and modify freely for personal overclock documentation and tooling unless a separate license file is added to the repository. If you publish a fork, please keep the safety disclaimers.

No warranty. See Important disclaimers.


23. Credits

  • Mission and conversion anchors documented in grok.md (experimental BIOS / Turbo VCore observations).
  • Implementation as a stdlib Python package under src/, with CLI wrappers turbo_decode.py and turbo_encode.py.

One-liner summary

TurboVcoreSDK turns ASUS Turbo VCore raw step counts into real voltages and ratios—and can write them back—using explicit, testable conversion profiles and structure-preserving XML handling.

About

Decode and encode ASUS Turbo VCore .OC overclock profiles to human-readable voltage/ratio reports

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages