Skip to content

Commit 57d9b76

Browse files
committed
[Minor] adds some asm abstraction helper (for later)
1 parent 1759d93 commit 57d9b76

1 file changed

Lines changed: 67 additions & 21 deletions

File tree

ModUtils/AsmUtils.cs

Lines changed: 67 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,22 @@ public static partial class Msl
1818
/// <param name="instructions"></param>
1919
public static void CheckInstructionsVariables(UndertaleCode originalCode, string instructions)
2020
{
21-
Regex variableRegex = new (@"\bpop\.v\.\w\s(?<var>\w+)\.(?<name>\w+)");
21+
Regex variableRegex = new(@"\bpop\.v\.\w\s(?<var>\w+)\.(?<name>\w+)");
2222
foreach (string instruction in instructions.Split('\n').Where(x => x.Contains("pop.v")))
2323
{
2424
System.Text.RegularExpressions.Match matches = variableRegex.Match(instruction);
25-
if (matches.Success)
25+
if (matches.Success)
2626
{
2727
string instanceValue = matches.Groups["var"].Value;
28-
if(instanceValue == "self")
28+
if (instanceValue == "self")
2929
{
3030
AssemblyWrapper.CheckRefVariableOrCreate(matches.Groups["name"].Value, UndertaleInstruction.InstanceType.Self);
3131
}
32-
else if(instanceValue == "global")
32+
else if (instanceValue == "global")
3333
{
3434
AssemblyWrapper.CheckRefVariableOrCreate(matches.Groups["name"].Value, UndertaleInstruction.InstanceType.Global);
3535
}
36-
else if(instanceValue == "local")
36+
else if (instanceValue == "local")
3737
{
3838
AssemblyWrapper.CheckRefLocalVariableOrCreate(originalCode, matches.Groups["name"].Value);
3939
}
@@ -46,33 +46,33 @@ public static void CheckInstructionsVariables(UndertaleCode originalCode, string
4646
}
4747
public static string GetAssemblyString(string fileName)
4848
{
49-
try
49+
try
5050
{
5151
UndertaleCode originalCode = GetUMTCodeFromFile(fileName);
5252
return originalCode.Disassemble(ModLoader.Data.Variables, ModLoader.Data.CodeLocals.For(originalCode));
5353
}
54-
catch(Exception ex)
54+
catch (Exception ex)
5555
{
5656
Log.Error(ex, "Something went wrong");
5757
throw;
5858
}
5959
}
6060
public static void SetAssemblyString(string codeAsString, string fileName)
6161
{
62-
try
62+
try
6363
{
6464
UndertaleCode originalCode = GetUMTCodeFromFile(fileName);
6565
originalCode.Replace(Assembler.Assemble(codeAsString, ModLoader.Data));
6666
}
67-
catch(Exception ex)
67+
catch (Exception ex)
6868
{
6969
Log.Error(ex, "Something went wrong");
7070
throw;
7171
}
7272
}
7373
public static void InsertAssemblyString(string codeAsString, string fileName, int position)
7474
{
75-
try
75+
try
7676
{
7777
Log.Information(string.Format("Trying insert assembly in: {0}", fileName.ToString()));
7878

@@ -82,15 +82,15 @@ public static void InsertAssemblyString(string codeAsString, string fileName, in
8282

8383
Log.Information(string.Format("Patched function with InsertAssemblyString: {0}", fileName.ToString()));
8484
}
85-
catch(Exception ex)
85+
catch (Exception ex)
8686
{
8787
Log.Error(ex, "Something went wrong");
8888
throw;
8989
}
9090
}
9191
public static void ReplaceAssemblyString(string codeAsString, string fileName, int position)
9292
{
93-
try
93+
try
9494
{
9595
Log.Information(string.Format("Trying replace assembly in: {0}", fileName.ToString()));
9696

@@ -100,37 +100,38 @@ public static void ReplaceAssemblyString(string codeAsString, string fileName, i
100100

101101
Log.Information(string.Format("Patched function with ReplaceAssemblyString: {0}", fileName.ToString()));
102102
}
103-
catch(Exception ex)
103+
catch (Exception ex)
104104
{
105105
Log.Error(ex, "Something went wrong");
106106
throw;
107107
}
108108
}
109109
public static void ReplaceAssemblyString(string codeAsString, string fileName, int start, int len)
110110
{
111-
try
111+
try
112112
{
113113
Log.Information(string.Format("Trying replace assembly in: {0}", fileName.ToString()));
114114

115115
List<string>? originalCode = GetAssemblyString(fileName).Split("\n").ToList();
116116
originalCode[start] = codeAsString;
117-
for (int i = 1; i < Math.Min(len, originalCode.Count - start); i++) {
117+
for (int i = 1; i < Math.Min(len, originalCode.Count - start); i++)
118+
{
118119
originalCode[start + i] = "";
119120
}
120121

121122
SetAssemblyString(string.Join("\n", originalCode), fileName);
122123

123124
Log.Information(string.Format("Patched function with ReplaceAssemblyString: {0}", fileName.ToString()));
124125
}
125-
catch(Exception ex)
126+
catch (Exception ex)
126127
{
127128
Log.Error(ex, "Something went wrong");
128129
throw;
129130
}
130131
}
131132
public static void InjectAssemblyInstruction(string name, Func<IEnumerable<UndertaleInstruction>, IEnumerable<UndertaleInstruction>> patch)
132133
{
133-
try
134+
try
134135
{
135136
Log.Information(string.Format("Trying inject assembly in: {0}", name.ToString()));
136137

@@ -139,12 +140,43 @@ public static void InjectAssemblyInstruction(string name, Func<IEnumerable<Under
139140

140141
Log.Information(string.Format("Patched function with InjectAssemblyInstruction: {0}", name.ToString()));
141142
}
142-
catch(Exception ex)
143+
catch (Exception ex)
143144
{
144145
Log.Error(ex, "Something went wrong");
145146
throw;
146147
}
147148
}
149+
public static IEnumerable<UndertaleInstruction> ReplaceTable(this IEnumerable<UndertaleInstruction> original, IEnumerable<UndertaleInstruction> injected)
150+
{
151+
bool pushFound = false;
152+
bool callFound = false;
153+
foreach ((int index, UndertaleInstruction instruction) in original.Enumerate())
154+
{
155+
if (!pushFound && AssemblyWrapper.IsPushString(instruction))
156+
{
157+
pushFound = true;
158+
foreach (UndertaleInstruction replacement in injected) yield return replacement;
159+
}
160+
else if (pushFound
161+
&& instruction.Kind == UndertaleInstruction.Opcode.Call
162+
&& instruction.Type1 == UndertaleInstruction.DataType.Int32
163+
)
164+
{
165+
callFound = true;
166+
yield return instruction;
167+
}
168+
else if (!pushFound || callFound)
169+
{
170+
Log.Information(string.Format("yield line {0}: {1}", index, instruction));
171+
yield return instruction;
172+
}
173+
}
174+
175+
if (!pushFound)
176+
throw new InvalidOperationException("Didnt find any string in that file, is that a legitimate table ?");
177+
if (!callFound)
178+
throw new InvalidOperationException("Didnt find any final call in that file, the function is maybe ill-formed.");
179+
}
148180
}
149181
public static class AssemblyWrapper
150182
{
@@ -308,12 +340,13 @@ public static UndertaleResourceById<UndertaleString, UndertaleChunkSTRG> GetStri
308340
(int ind, UndertaleString str) = ModLoader.Data.Strings.Enumerate().FirstOrDefault(x => x.Item2.Content == name);
309341

310342
if (str == null)
343+
{
311344
stringById = CreateString(name);
345+
Log.Information(string.Format("Created string: {0}", stringById.ToString()));
346+
}
312347
else
313348
stringById = new UndertaleResourceById<UndertaleString, UndertaleChunkSTRG>(str, ind);
314349

315-
Log.Information(string.Format("Find string: {0}", stringById.ToString()));
316-
317350
return stringById;
318351
}
319352
catch (Exception ex)
@@ -397,7 +430,20 @@ public static UndertaleInstruction PopIntSelf(string val)
397430
TypeInst = UndertaleInstruction.InstanceType.Self,
398431
};
399432
}
400-
433+
public static UndertaleInstruction ConvString()
434+
{
435+
return new()
436+
{
437+
Kind = UndertaleInstruction.Opcode.Conv,
438+
Type1 = UndertaleInstruction.DataType.String,
439+
Type2 = UndertaleInstruction.DataType.Variable,
440+
};
441+
}
442+
public static IEnumerable<UndertaleInstruction> CreateStringLine(string s)
443+
{
444+
yield return PushString(s);
445+
yield return ConvString();
446+
}
401447
public static bool IsPushString(UndertaleInstruction instruction)
402448
{
403449
return instruction.Kind == UndertaleInstruction.Opcode.Push && instruction.Value is UndertaleResourceById<UndertaleString, UndertaleChunkSTRG> stringRef;

0 commit comments

Comments
 (0)