<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Gift: A Open-source Udon Decompiler]]></title><description><![CDATA[<h2>A Open-source Udon Decompiler</h2>
<p dir="auto">This is a opensource decompiler for Udon bytecode that attempts to reconstruct readable C#-like pseudocode, along with parsing public variables.</p>
<p dir="auto">Repo: <a href="https://github.com/ParaN3xus/udon-decompiler" rel="nofollow ugc">https://github.com/ParaN3xus/udon-decompiler</a><br />
Docs: <a href="https://udon-decompiler.paran3x.us/" rel="nofollow ugc">https://udon-decompiler.paran3x.us/</a></p>
<h3>Features</h3>
<ul>
<li>Core functionialities
<ul>
<li>Decompile Udon bytecode into readable C#-like pseudocode</li>
<li>Parse and reconstruct public variables</li>
</ul>
</li>
<li>Unity-free decompilation workflow<br />
After a one-time setup step (extracting Udon module information using Unity), the rest of the process no longer depends on Unity or the VRChat SDK<br />
Everything can be done with two executables (&lt;10MB total)</li>
<li>Some less documented features that are already usable:
<ul>
<li>Udon disassembly output</li>
<li>Modifying assembly and patching it back into the original program</li>
</ul>
</li>
</ul>
<h3>Comparison with existing tools</h3>
<p dir="auto">There are a few existing open-source attempts at Udon decompilation:</p>
<ul>
<li><a href="https://gitlab.com/lox9973/UdonFlat" rel="nofollow ugc">https://gitlab.com/lox9973/UdonFlat</a></li>
<li><a href="https://github.com/UdonSharpRE/" rel="nofollow ugc">https://github.com/UdonSharpRE/</a></li>
</ul>
<p dir="auto">However, both of these projects appear to have been inactive for quite some time.</p>
<p dir="auto">I haven’t thoroughly evaluated UdonFlat’s output quality, but judging from its scope and codebase size, it likely does not aim for deeper reconstruction.</p>
<p dir="auto">With UdonSharpRE, I’ve personally run into cases where it would completely hang on certain scripts, which might be related to less robust control flow handling. Even in cases where it does produce output, the structure and readability are generally not as strong as what this project is trying to achieve.</p>
<p dir="auto">I’ve also had some discussions with authors of other (unreleased) decompilers, and while I can’t make definitive claims, from comparing output fragments it seems this decompiler performs better in certain scenarios.</p>
<h3>Example 1 (Decompiling the FISH! world)</h3>
<p dir="auto">I will demonstrate the full workflow using the FISH! world:</p>
<ol>
<li>Assume the decompiler is already installed</li>
<li>Obtain &amp; decrypt world cache (or acquire <code>.vrcw</code>), dump serialized programs &amp; public variables<br />
<img src="/assets/uploads/files/1774154867651-68549b16-f319-4bc7-96ff-458a4d39f8ef-image.jpeg" alt="68549b16-f319-4bc7-96ff-458a4d39f8ef-image.jpeg" class=" img-fluid img-markdown" width="1204" height="285" /></li>
<li>Decompile programs and parse variables<br />
<img src="/assets/uploads/files/1774155037415-e5f3c77b-abc1-4a20-8ad1-218f672dd547-image.jpeg" alt="e5f3c77b-abc1-4a20-8ad1-218f672dd547-image.jpeg" class=" img-fluid img-markdown" width="1200" height="623" /></li>
</ol>
<p dir="auto">Output (the <code>__data-dumped</code> directory): <a href="/login" class="hide-to-guest">[register or login to view this hidden content]</a></p>
<h3>Example 2 (selected functions from <code>DataServerManager.cs</code> in the Massive Medal Pusher world)</h3>
<p dir="auto">Comparison of the original asset, disassembly, and decompiled output of selected functions from <code>DataServerManager.cs</code> in the Massive Medal Pusher world</p>
<p dir="auto">Original asset</p>
<pre><code class="language-yaml">It’s just a regular Unity asset YAML that contains serializedProgramCompressedBytes. It’s quite uninteresting, so it’s omitted here.
</code></pre>
<p dir="auto">Disassembly</p>
<pre><code class="language-cs">entry__start: ; @ 0x00000000
  PUSH __const_SystemUInt32_0
  PUSH __gintnl_SystemUInt32_0
  JUMP addr_0x00000138 ; call function_0();
addr_0x00000018: ; @ 0x00000018
  PUSH __0__MedalTex__ret
  PUSH __lcl_t_SystemString_0
  COPY ; __lcl_t_SystemString_0 = __0__MedalTex__ret;
  PUSH __const_SystemString_0
  PUSH __const_SystemString_1
  PUSH __lcl_t_SystemString_0
  PUSH __const_SystemString_2
  PUSH __lcl_s_SystemString_0
  EXTERN heap_0x0000033F ; __lcl_s_SystemString_0 = System.String.Format(__const_SystemString_0, __const_SystemString_1, __lcl_t_SystemString_0, __const_SystemString_2);
  PUSH __gintnl_SystemUInt32_1
  PUSH __const_SystemString_3
  PUSH __1__intnlparam
  COPY ; __1__intnlparam = __const_SystemString_3;
  JUMP addr_0x00004838 ; call function_11();
addr_0x00000080: ; @ 0x00000080
  PUSH __0__intnlparam
  PUSH userSecretL
  COPY ; userSecretL = __0__intnlparam;
  PUSH __gintnl_SystemUInt32_2
  PUSH __intnl_VRCSDKBaseVRCPlayerApi_0
  EXTERN heap_0x00000340 ; __intnl_VRCSDKBaseVRCPlayerApi_0 = VRC.SDKBase.Networking.LocalPlayer;
  PUSH __intnl_VRCSDKBaseVRCPlayerApi_0
  PUSH __intnl_SystemString_0
  EXTERN heap_0x00000341 ; __intnl_SystemString_0 = __intnl_VRCSDKBaseVRCPlayerApi_0.displayName;
  PUSH __lcl_s_SystemString_0
  PUSH __0_s__param
  COPY ; __0_s__param = __lcl_s_SystemString_0;
  PUSH __intnl_SystemString_0
  PUSH __0_userId__param
  COPY ; __0_userId__param = __intnl_SystemString_0;
  PUSH userSecretA
  PUSH __0_userSecretA__param
  COPY ; __0_userSecretA__param = userSecretA;
  JUMP addr_0x0000390C ; call function_9();
addr_0x00000108: ; @ 0x00000108
  PUSH __0_userSecretA__param
  PUSH userSecretA
  COPY ; userSecretA = __0_userSecretA__param;
  PUSH __intnl_returnJump_SystemUInt32_0
  COPY ; __intnl_returnJump_SystemUInt32_0 = __const_SystemUInt32_0;
  JUMP_INDIRECT __intnl_returnJump_SystemUInt32_0
  PUSH __const_SystemUInt32_0
addr_0x00000138: ; @ 0x00000138
  PUSH medalTex9999
  PUSH __intnl_UnityEngineTransform_0
  EXTERN heap_0x00000342 ; __intnl_UnityEngineTransform_0 = medalTex9999.transform;
  PUSH __intnl_UnityEngineTransform_0
  PUSH __const_SystemType_0
  PUSH __lcl_rend_UnityEngineRenderer_0
  EXTERN heap_0x00000343 ; __lcl_rend_UnityEngineRenderer_0 = __intnl_UnityEngineTransform_0.GetComponent(__const_SystemType_0);
  PUSH __lcl_rend_UnityEngineRenderer_0
  PUSH __intnl_UnityEngineMaterial_0
  EXTERN heap_0x00000344 ; __intnl_UnityEngineMaterial_0 = __lcl_rend_UnityEngineRenderer_0.material;
  PUSH __intnl_UnityEngineMaterial_0
  PUSH __lcl_col_UnityEngineColor_0
  EXTERN heap_0x00000345 ; __lcl_col_UnityEngineColor_0 = __intnl_UnityEngineMaterial_0.color;
  PUSH __lcl_col_UnityEngineColor_0
  PUSH __intnl_SystemSingle_0
  EXTERN heap_0x00000346 ; __intnl_SystemSingle_0 = __lcl_col_UnityEngineColor_0.r;
  PUSH __intnl_SystemSingle_0
  PUSH __const_SystemSingle_0
  PUSH __intnl_SystemSingle_1
  EXTERN heap_0x00000347 ; __intnl_SystemSingle_1 = __intnl_SystemSingle_0 * __const_SystemSingle_0;
  PUSH __intnl_SystemSingle_1
  PUSH __intnl_SystemInt32_0
  EXTERN heap_0x00000348 ; __intnl_SystemInt32_0 = UnityEngine.Mathf.RoundToInt(__intnl_SystemSingle_1);
  PUSH __intnl_SystemInt32_0
  PUSH __const_SystemInt32_0
  PUSH __const_SystemInt32_1
  PUSH __lcl_r_SystemInt32_0
  EXTERN heap_0x00000349 ; __lcl_r_SystemInt32_0 = UnityEngine.Mathf.Clamp(__intnl_SystemInt32_0, __const_SystemInt32_0, __const_SystemInt32_1);
  PUSH __lcl_col_UnityEngineColor_0
  PUSH __intnl_SystemSingle_2
  EXTERN heap_0x0000034A ; __intnl_SystemSingle_2 = __lcl_col_UnityEngineColor_0.g;
  PUSH __intnl_SystemSingle_2
  PUSH __const_SystemSingle_0
  PUSH __intnl_SystemSingle_3
  EXTERN heap_0x00000347 ; __intnl_SystemSingle_3 = __intnl_SystemSingle_2 * __const_SystemSingle_0;
  PUSH __intnl_SystemSingle_3
  PUSH __intnl_SystemInt32_1
  EXTERN heap_0x00000348 ; __intnl_SystemInt32_1 = UnityEngine.Mathf.RoundToInt(__intnl_SystemSingle_3);
  PUSH __intnl_SystemInt32_1
  PUSH __const_SystemInt32_0
  PUSH __const_SystemInt32_1
  PUSH __lcl_g_SystemInt32_0
  EXTERN heap_0x00000349 ; __lcl_g_SystemInt32_0 = UnityEngine.Mathf.Clamp(__intnl_SystemInt32_1, __const_SystemInt32_0, __const_SystemInt32_1);
  PUSH __lcl_col_UnityEngineColor_0
  PUSH __intnl_SystemSingle_4
  EXTERN heap_0x0000034B ; __intnl_SystemSingle_4 = __lcl_col_UnityEngineColor_0.b;
  PUSH __intnl_SystemSingle_4
  PUSH __const_SystemSingle_0
  PUSH __intnl_SystemSingle_5
  EXTERN heap_0x00000347 ; __intnl_SystemSingle_5 = __intnl_SystemSingle_4 * __const_SystemSingle_0;
  PUSH __intnl_SystemSingle_5
  PUSH __intnl_SystemInt32_2
  EXTERN heap_0x00000348 ; __intnl_SystemInt32_2 = UnityEngine.Mathf.RoundToInt(__intnl_SystemSingle_5);
  PUSH __intnl_SystemInt32_2
  PUSH __const_SystemInt32_0
  PUSH __const_SystemInt32_1
  PUSH __lcl_b_SystemInt32_0
  EXTERN heap_0x00000349 ; __lcl_b_SystemInt32_0 = UnityEngine.Mathf.Clamp(__intnl_SystemInt32_2, __const_SystemInt32_0, __const_SystemInt32_1);
  PUSH __const_SystemString_4
  PUSH __lcl_r_SystemInt32_0
  PUSH __lcl_g_SystemInt32_0
  PUSH __lcl_b_SystemInt32_0
  PUSH __0__MedalTex__ret
  EXTERN heap_0x0000033F ; __0__MedalTex__ret = System.String.Format(__const_SystemString_4, __lcl_r_SystemInt32_0, __lcl_g_SystemInt32_0, __lcl_b_SystemInt32_0);
  PUSH __intnl_returnJump_SystemUInt32_0
  COPY
  JUMP_INDIRECT __intnl_returnJump_SystemUInt32_0
  PUSH __intnl_returnJump_SystemUInt32_0
  COPY
  JUMP_INDIRECT __intnl_returnJump_SystemUInt32_0
</code></pre>
<p dir="auto">Decompiled C#-like output (class definition and member variable declarations have been manually omitted)</p>
<pre><code class="language-cs">public void _start()
{
    System.String __lcl_t_SystemString_0 = null;
    System.String __lcl_s_SystemString_0 = null;
    System.String __intnl_SystemString_0 = null;

    function_0();
    __lcl_t_SystemString_0 = __0__MedalTex__ret;
    __lcl_s_SystemString_0 = System.String.Format("{0}{1}{2}", "GodSh1lbe",
                                                  __lcl_t_SystemString_0, "Shirbe334zako");
    __1__intnlparam = "qWRuTqiyLYJUwwG44DdF537cPEyDPf";
    function_11();
    userSecretL = __0__intnlparam;
    __intnl_SystemString_0 = VRC.SDKBase.Networking.LocalPlayer.displayName;
    __0_s__param = __lcl_s_SystemString_0;
    __0_userId__param = __intnl_SystemString_0;
    __0_userSecretA__param = userSecretA;
    function_9();
    userSecretA = __0_userSecretA__param;
    return;
}

void function_0()
{
    UnityEngine.Renderer __lcl_rend_UnityEngineRenderer_0 = null;
    UnityEngine.Color __lcl_col_UnityEngineColor_0 =
        new UnityEngine.Color(0.0f, 0.0f, 0.0f, 0.0f);
    System.Int32 __lcl_r_SystemInt32_0 = 0;
    System.Int32 __lcl_g_SystemInt32_0 = 0;
    System.Int32 __lcl_b_SystemInt32_0 = 0;

    __lcl_rend_UnityEngineRenderer_0 = medalTex9999.transform.GetComponent(
        typeof(UnityEngine.Renderer) /* UnityEngine.CoreModule */);
    __lcl_col_UnityEngineColor_0 = __lcl_rend_UnityEngineRenderer_0.material.color;
    __lcl_r_SystemInt32_0 = UnityEngine.Mathf.Clamp(
        UnityEngine.Mathf.RoundToInt(__lcl_col_UnityEngineColor_0.r * 255.0f), 0, 255);
    __lcl_g_SystemInt32_0 = UnityEngine.Mathf.Clamp(
        UnityEngine.Mathf.RoundToInt(__lcl_col_UnityEngineColor_0.g * 255.0f), 0, 255);
    __lcl_b_SystemInt32_0 = UnityEngine.Mathf.Clamp(
        UnityEngine.Mathf.RoundToInt(__lcl_col_UnityEngineColor_0.b * 255.0f), 0, 255);
    __0__MedalTex__ret = System.String.Format("{0:D2}{1:D2}{2:D2}", __lcl_r_SystemInt32_0,
                                              __lcl_g_SystemInt32_0, __lcl_b_SystemInt32_0);
    return;
}
</code></pre>
<h3>Disclaimer / Intended Use</h3>
<p dir="auto">This project is intended for learning and research, please respect original creators’ rights and follow VRChat's Terms of Service and applicable laws.</p>
<h3>Project status</h3>
<p dir="auto">This project is still under active development, but it is already usable:</p>
<ul>
<li>Only nightly builds are currently available</li>
<li>There are many unfinished todos</li>
</ul>
<h3>Reporting issues &amp; contributing</h3>
<p dir="auto">If you encounter bugs or incorrect output, please report them following <a href="https://udon-decompiler.paran3x.us/user-en/reporting-issues" rel="nofollow ugc">docs/user-en/reporting-issues</a></p>
<p dir="auto">Contributions are very welcome:</p>
<ul>
<li>bug reports</li>
<li>PRs / improvements</li>
</ul>
<p dir="auto">If you want to contribute to this project, check: <a href="https://udon-decompiler.paran3x.us/dev/status" rel="nofollow ugc">docs/dev/status</a> and <a href="https://udon-decompiler.paran3x.us/dev/contributing" rel="nofollow ugc">docs/dev/contributing</a></p>
]]></description><link>https://forum.ripper.store/topic/100445/gift-a-open-source-udon-decompiler</link><generator>RSS for Node</generator><lastBuildDate>Thu, 17 Sep 2026 05:58:59 GMT</lastBuildDate><atom:link href="https://forum.ripper.store/topic/100445.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 22 Mar 2026 05:57:35 GMT</pubDate><ttl>60</ttl></channel></rss>