Skip to content
This repository was archived by the owner on Jul 27, 2022. It is now read-only.

Commit 0b21dfe

Browse files
committed
lots of changes
1 parent a9e4bcb commit 0b21dfe

File tree

4 files changed

+96
-94
lines changed

4 files changed

+96
-94
lines changed

AstralUdonViewer.cs

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
using MelonLoader;
22
using System;
33
using System.IO;
4-
using System.Linq;
54
using UnityEngine.SceneManagement;
65
using VRC.Udon;
7-
using VRC.Udon.UAssembly.Disassembler;
86

9-
[assembly: MelonInfo(typeof(Astrum.AstralUdonDecompiler), nameof(Astrum.AstralUdonDecompiler), "0.1.0", downloadLink: "github.com/Astrum-Project/" + nameof(Astrum.AstralUdonDecompiler))]
7+
[assembly: MelonInfo(typeof(Astrum.AstralUdonViewer), nameof(Astrum.AstralUdonViewer), "0.2.0", downloadLink: "github.com/Astrum-Project/" + nameof(Astrum.AstralUdonViewer))]
108
[assembly: MelonColor(ConsoleColor.DarkMagenta)]
119

1210
namespace Astrum
1311
{
14-
public class AstralUdonDecompiler : MelonMod
12+
public partial class AstralUdonViewer : MelonMod
1513
{
1614
private const string basePath = "UserData/AstralUdonDecompiler";
1715

@@ -23,44 +21,37 @@ public override void OnApplicationStart()
2321

2422
public override void OnSceneWasLoaded(int index, string name)
2523
{
26-
if (index != -1) return;
27-
MelonCoroutines.Start(WaitForLocalLoad(name));
24+
if (index == -1)
25+
MelonCoroutines.Start(DissassembleAll());
2826
}
2927

30-
public System.Collections.IEnumerator WaitForLocalLoad(string name)
31-
{
32-
Scene scene = SceneManager.GetSceneByName(name);
33-
while (!scene.GetRootGameObjects().Any(f => f.name.StartsWith("VRCPlayer[Local]")))
34-
yield return null;
35-
36-
DissassembleAll();
37-
}
38-
39-
public static void DissassembleAll()
28+
public static System.Collections.IEnumerator DissassembleAll()
4029
{
4130
string path = $"{basePath}/{RemoveInvalid(SceneManager.GetActiveScene().name)}";
4231

43-
if (Directory.Exists(path)) return;
44-
32+
if (Directory.Exists(path)) yield break;
4533
else Directory.CreateDirectory(path);
4634

35+
while (VRC.SDKBase.Networking.LocalPlayer is null)
36+
yield return null;
37+
38+
// todo: change this to All
39+
// todo: dedup
4740
UdonBehaviour[] behaviours = UnityEngine.Object.FindObjectsOfType<UdonBehaviour>();
4841

49-
AstralCore.Logger.Debug($"{behaviours.Length} UdonBehaviours");
42+
AstralCore.Logger.Notif($"[UdonViewer] Disassembling {behaviours.Length} UdonBehaviours");
5043

51-
for (int i = 0; i < behaviours.Length - 1; i++)
44+
foreach (UdonBehaviour behaviour in behaviours)
5245
{
53-
if (behaviours[i]._program is null) continue;
46+
if (behaviour._program is null) continue;
47+
48+
AstralCore.Logger.Trace($"Disassembling {behaviour.name}");
49+
Disassembler.DisassembleProgram($"{path}/{RemoveInvalid(behaviour.name)}.uasm", behaviour._program);
5450

55-
File.WriteAllLines($"{path}/{RemoveInvalid(behaviours[i].name)}.uasm", DisassembleProgram(behaviours[i]));
51+
yield return null;
5652
}
57-
}
5853

59-
public static string[] DisassembleProgram(UdonBehaviour udonBehaviour)
60-
{
61-
AstralCore.Logger.Trace($"Disassembling {udonBehaviour.name}");
62-
Console.Beep(800, 10);
63-
return UAssemblyDisassembler.DisassembleProgram(udonBehaviour._program);
54+
AstralCore.Logger.Notif("[UdonViewer] Finished!");
6455
}
6556

6657
private static string RemoveInvalid(string str)

AstralUdonViewer.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
</ItemGroup>
7979
<ItemGroup>
8080
<Compile Include="AstralUdonViewer.cs" />
81-
<Compile Include="UAssemblyDisassembler.cs" />
81+
<Compile Include="Disassembler.cs" />
8282
</ItemGroup>
8383
<ItemGroup>
8484
<Folder Include="Properties\" />

Disassembler.cs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// This is a modified version of `VRC.Udon.Compiler.dll`
2+
3+
using System;
4+
using System.IO;
5+
using VRC.Udon.Common.Interfaces;
6+
using VRC.Udon.VM.Common;
7+
8+
namespace Astrum
9+
{
10+
partial class AstralUdonViewer
11+
{
12+
public static class Disassembler
13+
{
14+
public static System.Collections.IEnumerator DisassembleProgram(string path, IUdonProgram program)
15+
{
16+
string[] lines = new string[program.ByteCode.Length];
17+
for (uint i = 0; i < program.ByteCode.Length;)
18+
{
19+
lines[i] = DisassembleInstruction(program, ref i);
20+
yield return null;
21+
}
22+
File.WriteAllLines(path, lines);
23+
}
24+
25+
public static string DisassembleInstruction(IUdonProgram program, ref uint offset)
26+
{
27+
OpCode opCode = (OpCode)UIntFromBytes(program.ByteCode, offset);
28+
if (opCode == OpCode.NOP)
29+
return SimpleInstruction(ref offset, "NOP");
30+
else if (opCode == OpCode.PUSH)
31+
return DirectInstruction(ref offset, "PUSH", program);
32+
else if (opCode == OpCode.POP)
33+
return SimpleInstruction(ref offset, "POP");
34+
else if (opCode == OpCode.JUMP_IF_FALSE)
35+
return DirectInstruction(ref offset, "JUMP_IF_FALSE", program);
36+
else if (opCode == OpCode.JUMP)
37+
return DirectInstruction(ref offset, "JUMP", program);
38+
else if (opCode == OpCode.EXTERN)
39+
return ExternInstruction(ref offset, "EXTERN", program);
40+
else if (opCode == OpCode.ANNOTATION)
41+
return AnnotationInstruction(ref offset, "ANNOTATION", program);
42+
else if (opCode == OpCode.JUMP_INDIRECT)
43+
return JumpIndirectInstruction(ref offset, "JUMP_INDIRECT", program);
44+
else if (opCode == OpCode.COPY)
45+
return SimpleInstruction(ref offset, "COPY");
46+
else return $"0x{(offset += 4) - 4:X}: INVALID (0x{opCode:X})";
47+
}
48+
49+
private static string SimpleInstruction(ref uint offset, string name)
50+
=> string.Format("0x{0:X8}: {1}", (offset += 4) - 4, name);
51+
private static string DirectInstruction(ref uint offset, string name, IUdonProgram program)
52+
=> string.Format("0x{0:X8}: {1}, 0x{2}", (offset += 8) - 8, name, Convert.ToString((long)(ulong)UIntFromBytes(program.ByteCode, offset - 4), 16).PadLeft(8, '0').ToUpper());
53+
private static string AnnotationInstruction(ref uint offset, string name, IUdonProgram program)
54+
=> ExternInstruction(ref offset, name, program);
55+
private static string ExternInstruction(ref uint offset, string name, IUdonProgram program)
56+
{
57+
string str = (offset + 4).ToString();
58+
try { str = program.Heap.GetHeapVariable<string>(UIntFromBytes(program.ByteCode, offset + 4)); }
59+
catch { }
60+
return string.Format("0x{0:X8}: {1}, <{2}>", (offset += 8) - 8, name, str);
61+
}
62+
63+
private static string JumpIndirectInstruction(ref uint offset, string name, IUdonProgram program)
64+
{
65+
uint addr = UIntFromBytes(program.ByteCode, (offset += 8) - 4);
66+
if (program.SymbolTable.HasSymbolForAddress(addr))
67+
return string.Format("0x{0:X8}: {1}, {2}", offset - 8, name, program.SymbolTable.GetSymbolFromAddress(addr));
68+
else return string.Format("0x{0:X8}: {1}, 0x{2}", offset - 8, name, Convert.ToString((long)(ulong)addr, 16).PadLeft(8, '0').ToUpper());
69+
}
70+
71+
private unsafe static uint UIntFromBytes(byte[] bytes, uint startIndex)
72+
=> (uint)((bytes[(int)startIndex] << 24) + (bytes[(int)(startIndex + 1)] << 16) + (bytes[(int)(startIndex + 2)] << 8) + bytes[(int)(startIndex + 3)]);
73+
}
74+
}
75+
}
76+

UAssemblyDisassembler.cs

Lines changed: 0 additions & 65 deletions
This file was deleted.

0 commit comments

Comments
 (0)