@@ -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