Skip to content

How to Contribute

xAstroBoy edited this page Jul 11, 2026 · 3 revisions

How to Contribute — start helping in an afternoon

This tool is a one-person reverse-engineering of Meta's libshell.so, shared as-is. Help is very welcome and you do not need to understand the whole thing to be useful. This page is the on-ramp: pick a lane, build once, ship a small PR.

TL;DR: git clone, build with CMake+Ninja, change one thing, open a PR. No CLA, no ceremony. The repo is Quest-Home-Editor; the tool source lives in the QuestHomeEditor/ folder.

Pick a lane (easiest → deepest)

Lane You need What you'd do
🌍 Translations just a text editor + your language fill in / fix UI strings in QuestHomeEditor/lang/strings.py
📝 Docs / wiki Markdown fix a confusing step, add a screenshot, write a how-to
🐛 Bug reports a Quest + the tool reproduce, attach the Logcat Export report + _crash.txt
🎛️ Editor features C++ (any level) a new UI toggle, a tooltip, a quality-of-life fix
🏗️ Cook / format work C++ + patience a new component, a format edge case (see the RE guide)
🔬 Reverse engineering IDA/Ghidra or capstone crack an unknown field; document it

Start at the top of the table. A translation or a docs fix is a real contribution and the fastest way to get your first PR merged.

Build it once

git clone https://github.com/xAstroBoy/Quest-Home-Editor
cd Quest-Home-Editor
cmake -S QuestHomeEditor -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DHSR_HAVE_PHYSX=ON
cmake --build build --target hsr_renderer
  • CMake target is hsr_renderer; the output is Quest Home Editor(.exe).
  • PhysX is optional-DHSR_HAVE_PHYSX=OFF builds fine on Linux/macOS (the cooker falls back to the device-compatible ColliderBox grid). QuestHomeEditor/build_linux.sh is the one-command Linux build.
  • Default build is SSE4.1 (runs on any 64-bit CPU). -DHSR_AVX2=ON is the faster opt-in.
  • A Vulkan-capable GPU is required to run it (macOS uses MoltenVK).

Prebuilt binaries for every OS are on Releases.

🌍 Translations — the easiest first PR

The UI is localized into 16 languages and every translation lives in source — there is no runtime dependency, no .json/.po fetched at startup. One file is the single source of truth:

QuestHomeEditor/lang/strings.py

LANGS = [ ("EN","English","latin"), ("ZH","中文","cjk"), ... ]   # add a language here
T = {
  "Cook APK": {"ZH":"烘焙 APK","ES":"Compilar APK", ... },       # English key -> per-language cell
  ...
}

To fix or add a translation, edit the cell(s), then regenerate the baked header:

python QuestHomeEditor/cooker/gen_i18n.py

That command does two things:

  1. bakes lang/strings.py into QuestHomeEditor/src/ui/i18n.h (as \xNN escapes, pure-ASCII, compiled into the binary), and
  2. scans the source for every UI string and writes any that are missing from the table to QuestHomeEditor/lang/_untranslated.txt. That file is your to-do list — if it lists a string, add it to T in strings.py.

To add a whole new language: append ("XX","NativeName","script") to LANGS (script tag drives font-glyph baking: latin / cyrillic / cjk / hangul / kana / arabic), then fill its column in each T entry (missing cells simply fall back to English, so partial is fine to start). Re-run the generator and rebuild — your language appears in the in-app language dropdown.

You don't even need a working C++ build to propose a translation PR: edit strings.py and open the PR; a maintainer can regenerate. (But building once is nice so you can see it live.)

🎛️ Adding an editor feature

  • Cook features are UI toggles, not global flags: add a member + a checkbox in the Cook panel (QuestHomeEditor/src/ui/editor.h) and have runCook set an env var the cooker reads. Keep the device-limit mitigations opt-in.
  • Render/preview changes are proven on the desktop first (the preview is the ground truth), then cooked to the device. Don't guess a device format — read libshell's logic (see below) and match it.
  • New UI text? Wrap nothing special — any string you pass to a ui::Context widget (button/tab/label/tip/textAligned) auto-translates. After adding strings, run gen_i18n.py and add them to lang/strings.py (the scanner will remind you).
  • Add a tooltip to any button/tab/pill with cx.tip(x, y, w, h, "explanation…") right after it.

Project layout (inside QuestHomeEditor/)

  • src/render/ — the Vulkan libshell replica (SPIR-V, materials, IBL, skinning).
  • src/loaders/ — V79 .gltf.ovrscene, .opa official homes, the SceneLoader.
  • src/io/ — the Blender/glTF round-trip (import + export).
  • src/cook/hsl_cooker.h — the whole V203/HSL cook (RENDMESH/MATL/…/ASMH + PhysX SEBD + APK bake).
  • src/ui/editor.h — the editor, the device install, and the Logcat diagnostics.
  • lang/strings.py — all UI translations (baked by cooker/gen_i18n.py).

🐛 Filing a good bug report

The tool is built to hand you the evidence — please attach it:

  • A cooked home fell back to Haven/nuxd? Open the Logcat tab, hit Reload home, then Export, and attach the quest_env_diag_*.txt. It pinpoints the exact reject reason. See Diagnosing a Rejected Home.
  • A crash? Attach the _crash.txt written next to the exe (symbolized on Windows, backtrace on Linux/macOS) + what env you loaded and what you clicked.
  • Include your headset model, whether it's rooted, and the tool version.

🔬 Reverse-engineering libshell

When you need to crack a device format or an unknown field, don't guess — read libshell's exact logic. The full workflow (offline capstone or IDA-via-MCP, string→xref→function, the verified env-load gate map) is on Reverse Engineering & Contributing.

Sending the PR

  • Branch off master, keep the change focused, match the surrounding code style.
  • Say what changed and why; if it's device-facing, note what you tested it on.
  • Translations, docs, and tooltips are merged fastest — they can't regress the cook.

Thanks for helping port the old homes back. 🛖🥽

Clone this wiki locally