diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Environment/Scenes/scripting/Engines/LSLEngine/LSLHandler/LSO_Parser.cs | 608 |
1 files changed, 608 insertions, 0 deletions
diff --git a/OpenSim/Region/Environment/Scenes/scripting/Engines/LSLEngine/LSLHandler/LSO_Parser.cs b/OpenSim/Region/Environment/Scenes/scripting/Engines/LSLEngine/LSLHandler/LSO_Parser.cs new file mode 100644 index 0000000..5f2e3c1 --- /dev/null +++ b/OpenSim/Region/Environment/Scenes/scripting/Engines/LSLEngine/LSLHandler/LSO_Parser.cs | |||
@@ -0,0 +1,608 @@ | |||
1 | using System; | ||
2 | using System.Collections.Generic; | ||
3 | using System.Text; | ||
4 | using System.IO; | ||
5 | using System.Reflection; | ||
6 | using System.Reflection.Emit; | ||
7 | using OpenSim.Region.Environment.Scripting; | ||
8 | |||
9 | namespace OpenSim.ScriptEngines.LSL | ||
10 | { | ||
11 | class LSO_Parser | ||
12 | { | ||
13 | private bool Debug = true; | ||
14 | private FileStream fs; | ||
15 | private BinaryReader br; | ||
16 | private LSO_Struct.Header myHeader; | ||
17 | |||
18 | private TypeBuilder typeBuilder; | ||
19 | private ScriptInfo WorldAPI; | ||
20 | |||
21 | /// <summary> | ||
22 | /// Parse LSO file. | ||
23 | /// Reads LSO ByteCode into memory structures. | ||
24 | /// TODO: What else does it do? | ||
25 | /// </summary> | ||
26 | /// <param name="FileName">FileName of LSO ByteCode file</param> | ||
27 | public void ParseFile(string FileName, ScriptInfo _WorldAPI, ref TypeBuilder _typeBuilder) | ||
28 | { | ||
29 | typeBuilder = _typeBuilder; | ||
30 | WorldAPI = _WorldAPI; | ||
31 | // Open | ||
32 | SendToDebug("Opening filename: " + FileName); | ||
33 | fs = File.Open(FileName, FileMode.Open, FileAccess.Read, FileShare.Read); | ||
34 | br = new BinaryReader(fs, Encoding.BigEndianUnicode); | ||
35 | |||
36 | |||
37 | // The LSO Format consist of 6 major blocks: header, statics, functions, states, heap, and stack. | ||
38 | |||
39 | |||
40 | // HEADER BLOCK | ||
41 | SendToDebug("Reading HEADER BLOCK at: 0"); | ||
42 | fs.Seek(0, SeekOrigin.Begin); | ||
43 | myHeader = new LSO_Struct.Header(); | ||
44 | myHeader.TM = BitConverter.ToUInt32(br_read(4), 0); | ||
45 | myHeader.IP = BitConverter.ToUInt32(br_read(4), 0); | ||
46 | myHeader.VN = BitConverter.ToUInt32(br_read(4), 0); | ||
47 | myHeader.BP = BitConverter.ToUInt32(br_read(4), 0); | ||
48 | myHeader.SP = BitConverter.ToUInt32(br_read(4), 0); | ||
49 | myHeader.HR = BitConverter.ToUInt32(br_read(4), 0); | ||
50 | myHeader.HP = BitConverter.ToUInt32(br_read(4), 0); | ||
51 | myHeader.CS = BitConverter.ToUInt32(br_read(4), 0); | ||
52 | myHeader.NS = BitConverter.ToUInt32(br_read(4), 0); | ||
53 | myHeader.CE = BitConverter.ToUInt32(br_read(4), 0); | ||
54 | myHeader.IE = BitConverter.ToUInt32(br_read(4), 0); | ||
55 | myHeader.ER = BitConverter.ToUInt32(br_read(4), 0); | ||
56 | myHeader.FR = BitConverter.ToUInt32(br_read(4), 0); | ||
57 | myHeader.SLR = BitConverter.ToUInt32(br_read(4), 0); | ||
58 | myHeader.GVR = BitConverter.ToUInt32(br_read(4), 0); | ||
59 | myHeader.GFR = BitConverter.ToUInt32(br_read(4), 0); | ||
60 | myHeader.PR = BitConverter.ToUInt32(br_read(4), 0); | ||
61 | myHeader.ESR = BitConverter.ToUInt32(br_read(4), 0); | ||
62 | myHeader.SR = BitConverter.ToUInt32(br_read(4), 0); | ||
63 | myHeader.NCE = BitConverter.ToUInt64(br_read(8), 0); | ||
64 | myHeader.NIE = BitConverter.ToUInt64(br_read(8), 0); | ||
65 | myHeader.NER = BitConverter.ToUInt64(br_read(8), 0); | ||
66 | |||
67 | // Print Header Block to debug | ||
68 | SendToDebug("TM - Top of memory (size): " + myHeader.TM); | ||
69 | SendToDebug("IP - Instruction Pointer (0=not running): " + myHeader.IP); | ||
70 | SendToDebug("VN - Version number: " + myHeader.VN); | ||
71 | SendToDebug("BP - Local Frame Pointer: " + myHeader.BP); | ||
72 | SendToDebug("SP - Stack Pointer: " + myHeader.SP); | ||
73 | SendToDebug("HR - Heap Register: " + myHeader.HR); | ||
74 | SendToDebug("HP - Heap Pointer: " + myHeader.HP); | ||
75 | SendToDebug("CS - Current State: " + myHeader.CS); | ||
76 | SendToDebug("NS - Next State: " + myHeader.NS); | ||
77 | SendToDebug("CE - Current Events: " + myHeader.CE); | ||
78 | SendToDebug("IE - In Event: " + myHeader.IE); | ||
79 | SendToDebug("ER - Event Register: " + myHeader.ER); | ||
80 | SendToDebug("FR - Fault Register: " + myHeader.FR); | ||
81 | SendToDebug("SLR - Sleep Register: " + myHeader.SLR); | ||
82 | SendToDebug("GVR - Global Variable Register: " + myHeader.GVR); | ||
83 | SendToDebug("GFR - Global Function Register: " + myHeader.GFR); | ||
84 | SendToDebug("PR - Parameter Register: " + myHeader.PR); | ||
85 | SendToDebug("ESR - Energy Supply Register: " + myHeader.ESR); | ||
86 | SendToDebug("SR - State Register: " + myHeader.SR); | ||
87 | SendToDebug("NCE - 64-bit Current Events: " + myHeader.NCE); | ||
88 | SendToDebug("NIE - 64-bit In Events: " + myHeader.NIE); | ||
89 | SendToDebug("NER - 64-bit Event Register: " + myHeader.NER); | ||
90 | SendToDebug("Read position when exiting HEADER BLOCK: " + fs.Position); | ||
91 | |||
92 | // STATIC BLOCK | ||
93 | SendToDebug("Reading STATIC BLOCK at: " + myHeader.GVR); | ||
94 | fs.Seek(myHeader.GVR, SeekOrigin.Begin); | ||
95 | int StaticBlockCount = 0; | ||
96 | // Read function blocks until we hit GFR | ||
97 | while (fs.Position < myHeader.GFR) | ||
98 | { | ||
99 | StaticBlockCount++; | ||
100 | SendToDebug("Reading Static Block " + StaticBlockCount + " at: " + fs.Position); | ||
101 | //fs.Seek(myHeader.GVR, SeekOrigin.Begin); | ||
102 | LSO_Struct.StaticBlock myStaticBlock = new LSO_Struct.StaticBlock(); | ||
103 | myStaticBlock.Static_Chunk_Header_Size = BitConverter.ToUInt32(br_read(4), 0); | ||
104 | myStaticBlock.ObjectType = br_read(1)[0]; | ||
105 | SendToDebug("Static Block ObjectType: " + ((LSO_Enums.Variable_Type_Codes)myStaticBlock.ObjectType).ToString()); | ||
106 | myStaticBlock.Unknown = br_read(1)[0]; | ||
107 | // Size of datatype varies | ||
108 | if (myStaticBlock.ObjectType != 0) | ||
109 | myStaticBlock.BlockVariable = br_read(getObjectSize(myStaticBlock.ObjectType)); | ||
110 | } | ||
111 | SendToDebug("Number of Static Blocks read: " + StaticBlockCount); | ||
112 | |||
113 | |||
114 | // FUNCTION BLOCK | ||
115 | // Always right after STATIC BLOCK | ||
116 | LSO_Struct.FunctionBlock myFunctionBlock = new LSO_Struct.FunctionBlock(); | ||
117 | if (myHeader.GFR == myHeader.SR) | ||
118 | { | ||
119 | // If GFR and SR are at same position then there is no fuction block | ||
120 | SendToDebug("No FUNCTION BLOCK found"); | ||
121 | } else { | ||
122 | SendToDebug("Reading FUNCTION BLOCK at: " + myHeader.GFR); | ||
123 | fs.Seek(myHeader.GFR, SeekOrigin.Begin); | ||
124 | myFunctionBlock.FunctionCount = BitConverter.ToUInt32(br_read(4), 0); | ||
125 | SendToDebug("Number of functions in Fuction Block: " + myFunctionBlock.FunctionCount); | ||
126 | if (myFunctionBlock.FunctionCount > 0) | ||
127 | { | ||
128 | myFunctionBlock.CodeChunkPointer = new UInt32[myFunctionBlock.FunctionCount]; | ||
129 | for (int i = 0; i < myFunctionBlock.FunctionCount; i++) | ||
130 | { | ||
131 | SendToDebug("Reading function " + i + " at: " + fs.Position); | ||
132 | // TODO: ADD TO FUNCTION LIST (How do we identify it later?) | ||
133 | // Note! Absolute position | ||
134 | myFunctionBlock.CodeChunkPointer[i] = BitConverter.ToUInt32(br_read(4), 0) + myHeader.GFR; | ||
135 | SendToDebug("Fuction " + i + " code chunk position: " + myFunctionBlock.CodeChunkPointer[i]); | ||
136 | } | ||
137 | } | ||
138 | } | ||
139 | |||
140 | |||
141 | // STATE FRAME BLOCK | ||
142 | // Always right after FUNCTION BLOCK | ||
143 | SendToDebug("Reading STATE BLOCK at: " + myHeader.SR); | ||
144 | fs.Seek(myHeader.SR, SeekOrigin.Begin); | ||
145 | LSO_Struct.StateFrameBlock myStateFrameBlock = new LSO_Struct.StateFrameBlock(); | ||
146 | myStateFrameBlock.StateCount = BitConverter.ToUInt32(br_read(4), 0); | ||
147 | if (myStateFrameBlock.StateCount > 0) | ||
148 | { | ||
149 | // Initialize array | ||
150 | myStateFrameBlock.StatePointer = new LSO_Struct.StatePointerBlock[myStateFrameBlock.StateCount]; | ||
151 | for (int i = 0; i < myStateFrameBlock.StateCount; i++) | ||
152 | { | ||
153 | SendToDebug("Reading STATE POINTER BLOCK " + (i+1) + " at: " + fs.Position); | ||
154 | // Position is relative to state frame | ||
155 | myStateFrameBlock.StatePointer[i].Location = myHeader.SR + BitConverter.ToUInt32(br_read(4), 0); | ||
156 | myStateFrameBlock.StatePointer[i].EventMask = new System.Collections.BitArray(br_read(8)); | ||
157 | SendToDebug("Pointer: " + myStateFrameBlock.StatePointer[i].Location); | ||
158 | SendToDebug("Total potential EventMask bits: " + myStateFrameBlock.StatePointer[i].EventMask.Count); | ||
159 | |||
160 | //// Read STATE BLOCK | ||
161 | //long CurPos = fs.Position; | ||
162 | //fs.Seek(CurPos, SeekOrigin.Begin); | ||
163 | |||
164 | } | ||
165 | } | ||
166 | |||
167 | |||
168 | // STATE BLOCK | ||
169 | // For each StateFrameBlock there is one StateBlock with multiple event handlers | ||
170 | |||
171 | if (myStateFrameBlock.StateCount > 0) | ||
172 | { | ||
173 | // Go through all State Frame Pointers found | ||
174 | for (int i = 0; i < myStateFrameBlock.StateCount; i++) | ||
175 | { | ||
176 | |||
177 | fs.Seek(myStateFrameBlock.StatePointer[i].Location, SeekOrigin.Begin); | ||
178 | SendToDebug("Reading STATE BLOCK " + (i + 1) + " at: " + fs.Position); | ||
179 | |||
180 | // READ: STATE BLOCK HEADER | ||
181 | myStateFrameBlock.StatePointer[i].StateBlock = new LSO_Struct.StateBlock(); | ||
182 | myStateFrameBlock.StatePointer[i].StateBlock.StartPos = (UInt32)fs.Position; // Note | ||
183 | myStateFrameBlock.StatePointer[i].StateBlock.HeaderSize = BitConverter.ToUInt32(br_read(4), 0); | ||
184 | myStateFrameBlock.StatePointer[i].StateBlock.Unknown = br_read(1)[0]; | ||
185 | myStateFrameBlock.StatePointer[i].StateBlock.EndPos = (UInt32)fs.Position; // Note | ||
186 | SendToDebug("State block Start Pos: " + myStateFrameBlock.StatePointer[i].StateBlock.StartPos); | ||
187 | SendToDebug("State block Header Size: " + myStateFrameBlock.StatePointer[i].StateBlock.HeaderSize); | ||
188 | SendToDebug("State block Header End Pos: " + myStateFrameBlock.StatePointer[i].StateBlock.EndPos); | ||
189 | |||
190 | // We need to count number of bits flagged in EventMask? | ||
191 | |||
192 | |||
193 | // for each bit in myStateFrameBlock.StatePointer[i].EventMask | ||
194 | |||
195 | // ADDING TO ALL RIGHT NOW, SHOULD LIMIT TO ONLY THE ONES IN USE | ||
196 | //TODO: Create event hooks | ||
197 | myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers = new LSO_Struct.StateBlockHandler[myStateFrameBlock.StatePointer[i].EventMask.Count - 1]; | ||
198 | for (int ii = 0; ii < myStateFrameBlock.StatePointer[i].EventMask.Count - 1; ii++) | ||
199 | { | ||
200 | |||
201 | if (myStateFrameBlock.StatePointer[i].EventMask.Get(ii) == true) | ||
202 | { | ||
203 | // We got an event | ||
204 | // READ: STATE BLOCK HANDLER | ||
205 | SendToDebug("Reading STATE BLOCK " + (i + 1) + " HANDLER matching EVENT MASK " + ii + " (" + ((LSO_Enums.Event_Mask_Values)ii).ToString() + ") at: " + fs.Position); | ||
206 | myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer = myStateFrameBlock.StatePointer[i].StateBlock.EndPos + BitConverter.ToUInt32(br_read(4), 0); | ||
207 | myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CallFrameSize = BitConverter.ToUInt32(br_read(4), 0); | ||
208 | SendToDebug("Reading STATE BLOCK " + (i + 1) + " HANDLER EVENT MASK " + ii + " (" + ((LSO_Enums.Event_Mask_Values)ii).ToString() + ") Code Chunk Pointer: " + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer); | ||
209 | SendToDebug("Reading STATE BLOCK " + (i + 1) + " HANDLER EVENT MASK " + ii + " (" + ((LSO_Enums.Event_Mask_Values)ii).ToString() + ") Call Frame Size: " + myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CallFrameSize ); | ||
210 | } | ||
211 | } | ||
212 | } | ||
213 | } | ||
214 | |||
215 | |||
216 | |||
217 | |||
218 | //// READ FUNCTION CODE CHUNKS | ||
219 | //// Functions + Function start pos (GFR) | ||
220 | //// TODO: Somehow be able to identify and reference this | ||
221 | //LSO_Struct.CodeChunk[] myFunctionCodeChunk; | ||
222 | //if (myFunctionBlock.FunctionCount > 0) | ||
223 | //{ | ||
224 | // myFunctionCodeChunk = new LSO_Struct.CodeChunk[myFunctionBlock.FunctionCount]; | ||
225 | // for (int i = 0; i < myFunctionBlock.FunctionCount; i++) | ||
226 | // { | ||
227 | // SendToDebug("Reading Function Code Chunk " + i); | ||
228 | // myFunctionCodeChunk[i] = GetCodeChunk((UInt32)myFunctionBlock.CodeChunkPointer[i]); | ||
229 | // } | ||
230 | |||
231 | //} | ||
232 | // READ EVENT CODE CHUNKS | ||
233 | LSO_Struct.CodeChunk[] myEventCodeChunk; | ||
234 | if (myStateFrameBlock.StateCount > 0) | ||
235 | { | ||
236 | myEventCodeChunk = new LSO_Struct.CodeChunk[myStateFrameBlock.StateCount]; | ||
237 | for (int i = 0; i < myStateFrameBlock.StateCount; i++) | ||
238 | { | ||
239 | // TODO: Somehow organize events and functions so they can be found again, | ||
240 | // two level search ain't no good | ||
241 | for (int ii = 0; ii < myStateFrameBlock.StatePointer[i].EventMask.Count - 1; ii++) | ||
242 | { | ||
243 | |||
244 | |||
245 | if (myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer > 0) | ||
246 | { | ||
247 | SendToDebug("Reading Event Code Chunk state " + i + ", event " + (LSO_Enums.Event_Mask_Values)ii); | ||
248 | |||
249 | |||
250 | // Override a Method / Function | ||
251 | string eventname = "event_" + (LSO_Enums.Event_Mask_Values)ii; | ||
252 | SendToDebug("CLR:" + eventname + ":MethodBuilder methodBuilder = typeBuilder.DefineMethod..."); | ||
253 | MethodBuilder methodBuilder = typeBuilder.DefineMethod(eventname, | ||
254 | MethodAttributes.Private | MethodAttributes.Virtual, | ||
255 | typeof(void), | ||
256 | new Type[] { typeof(object) }); | ||
257 | |||
258 | SendToDebug("CLR:" + eventname + ":typeBuilder.DefineMethodOverride(methodBuilder..."); | ||
259 | typeBuilder.DefineMethodOverride(methodBuilder, | ||
260 | typeof(LSL_CLRInterface.LSLScript).GetMethod(eventname)); | ||
261 | |||
262 | // Create the IL generator | ||
263 | |||
264 | SendToDebug("CLR:" + eventname + ":ILGenerator il = methodBuilder.GetILGenerator();"); | ||
265 | ILGenerator il = methodBuilder.GetILGenerator(); | ||
266 | |||
267 | |||
268 | LSO_Struct.CodeChunk myECC = | ||
269 | GetCodeChunk(myStateFrameBlock.StatePointer[i].StateBlock.StateBlockHandlers[ii].CodeChunkPointer, il, eventname); | ||
270 | } | ||
271 | |||
272 | } | ||
273 | } | ||
274 | |||
275 | } | ||
276 | |||
277 | |||
278 | // Close | ||
279 | br.Close(); | ||
280 | fs.Close(); | ||
281 | |||
282 | } | ||
283 | |||
284 | private LSO_Struct.HeapBlock GetHeap(UInt32 pos) | ||
285 | { | ||
286 | // HEAP BLOCK | ||
287 | // TODO:? Special read for strings/keys (null terminated) and lists (pointers to other HEAP entries) | ||
288 | SendToDebug("Reading HEAP BLOCK at: " + pos); | ||
289 | fs.Seek(pos, SeekOrigin.Begin); | ||
290 | |||
291 | LSO_Struct.HeapBlock myHeapBlock = new LSO_Struct.HeapBlock(); | ||
292 | myHeapBlock.DataBlockSize = BitConverter.ToUInt32(br_read(4), 0); | ||
293 | myHeapBlock.ObjectType = br_read(1)[0]; | ||
294 | myHeapBlock.ReferenceCount = BitConverter.ToUInt16(br_read(2), 0); | ||
295 | myHeapBlock.Data = br_read(getObjectSize(myHeapBlock.ObjectType)); | ||
296 | |||
297 | SendToDebug("Heap Block Data Block Size: " + myHeapBlock.DataBlockSize); | ||
298 | SendToDebug("Heap Block ObjectType: " + ((LSO_Enums.Variable_Type_Codes)myHeapBlock.ObjectType).ToString()); | ||
299 | SendToDebug("Heap Block Reference Count: " + myHeapBlock.ReferenceCount); | ||
300 | |||
301 | return myHeapBlock; | ||
302 | } | ||
303 | |||
304 | |||
305 | |||
306 | private byte[] br_read(int len) | ||
307 | { | ||
308 | if (len <= 0) | ||
309 | return null; | ||
310 | |||
311 | try | ||
312 | { | ||
313 | byte[] bytes = new byte[len]; | ||
314 | for (int i = len - 1; i > -1; i--) | ||
315 | bytes[i] = br.ReadByte(); | ||
316 | return bytes; | ||
317 | } | ||
318 | catch (Exception e) | ||
319 | { | ||
320 | SendToDebug("Exception: " + e.ToString()); | ||
321 | throw (e); | ||
322 | } | ||
323 | } | ||
324 | //private byte[] br_read_smallendian(int len) | ||
325 | //{ | ||
326 | // byte[] bytes = new byte[len]; | ||
327 | // br.Read(bytes,0, len); | ||
328 | // return bytes; | ||
329 | //} | ||
330 | |||
331 | private int getObjectSize(byte ObjectType) | ||
332 | { | ||
333 | switch (ObjectType) | ||
334 | { | ||
335 | case 1: | ||
336 | case 2: | ||
337 | case 3: | ||
338 | case 4: | ||
339 | case 7: | ||
340 | return 4; | ||
341 | case 5: | ||
342 | return 12; | ||
343 | case 6: | ||
344 | return 16; | ||
345 | default: | ||
346 | return 0; | ||
347 | } | ||
348 | } | ||
349 | private void SendToDebug(string Message) | ||
350 | { | ||
351 | if (Debug == true) | ||
352 | Console.WriteLine("Debug: " + Message); | ||
353 | } | ||
354 | |||
355 | |||
356 | private string Read_String() | ||
357 | { | ||
358 | string ret = ""; | ||
359 | byte reader = br_read(1)[0]; | ||
360 | while (reader != 0x000) | ||
361 | { | ||
362 | ret += (char)reader; | ||
363 | reader = br_read(1)[0]; | ||
364 | } | ||
365 | return ret; | ||
366 | } | ||
367 | |||
368 | /// <summary> | ||
369 | /// Reads a code chunk into structure and returns it. | ||
370 | /// </summary> | ||
371 | /// <param name="pos">Absolute position in file. REMEMBER TO ADD myHeader.GFR!</param> | ||
372 | /// <returns></returns> | ||
373 | private LSO_Struct.CodeChunk GetCodeChunk(UInt32 pos, ILGenerator il, string eventname) | ||
374 | { | ||
375 | |||
376 | /* | ||
377 | * CLR TRY | ||
378 | */ | ||
379 | //SendToDebug("CLR:" + eventname + ":il.BeginExceptionBlock()"); | ||
380 | il.BeginExceptionBlock(); | ||
381 | |||
382 | // Push "Hello World!" string to stack | ||
383 | //SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Ldstr..."); | ||
384 | il.Emit(OpCodes.Ldstr, "Starting CLR dynamic execution of: " + eventname); | ||
385 | |||
386 | // Push Console.WriteLine command to stack ... Console.WriteLine("Hello World!"); | ||
387 | //SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Call..."); | ||
388 | il.Emit(OpCodes.Call, typeof(Console).GetMethod | ||
389 | ("WriteLine", new Type[] { typeof(string) })); | ||
390 | |||
391 | |||
392 | LSO_Struct.CodeChunk myCodeChunk = new LSO_Struct.CodeChunk(); | ||
393 | |||
394 | SendToDebug("Reading Function Code Chunk at: " + pos); | ||
395 | fs.Seek(pos, SeekOrigin.Begin); | ||
396 | myCodeChunk.CodeChunkHeaderSize = BitConverter.ToUInt32(br_read(4), 0); | ||
397 | SendToDebug("CodeChunk Header Size: " + myCodeChunk.CodeChunkHeaderSize ); | ||
398 | // Read until null | ||
399 | myCodeChunk.Comment = Read_String(); | ||
400 | SendToDebug("Function comment: " + myCodeChunk.Comment); | ||
401 | myCodeChunk.ReturnType = br_read(1)[0]; | ||
402 | SendToDebug("Return type: " + (LSO_Enums.Variable_Type_Codes)myCodeChunk.ReturnType); | ||
403 | // TODO: How to determine number of codechunks -- does this method work? | ||
404 | myCodeChunk.CodeChunkArguments = new System.Collections.Generic.List<LSO_Struct.CodeChunkArgument>(); | ||
405 | byte reader = br_read(1)[0]; | ||
406 | reader = br_read(1)[0]; | ||
407 | int ccount = 0; | ||
408 | while (reader != 0x000) | ||
409 | { | ||
410 | ccount++; | ||
411 | SendToDebug("Reading Code Chunk Argument " + ccount); | ||
412 | LSO_Struct.CodeChunkArgument CCA = new LSO_Struct.CodeChunkArgument(); | ||
413 | CCA.FunctionReturnType = reader; | ||
414 | reader = br_read(1)[0]; | ||
415 | CCA.NullString = reader; | ||
416 | myCodeChunk.CodeChunkArguments.Add(CCA); | ||
417 | SendToDebug("Code Chunk Argument " + ccount + " return type: " + (LSO_Enums.Variable_Type_Codes)CCA.FunctionReturnType); | ||
418 | } | ||
419 | // End marker is 0x000 | ||
420 | myCodeChunk.EndMarker = reader; | ||
421 | // TODO: How to read and identify following code | ||
422 | // TODO: Code is read until a return of some sort is found | ||
423 | bool FoundRet = false; | ||
424 | while (FoundRet == false) | ||
425 | { | ||
426 | //reader = br_read(1)[0]; | ||
427 | //UInt16 opcode = BitConverter.ToUInt16(br_read(1),0); | ||
428 | UInt16 opcode = br_read(1)[0]; | ||
429 | //long rPos = fs.Position; | ||
430 | SendToDebug("OPCODE: " + ((LSO_Enums.Operation_Table)opcode).ToString()); | ||
431 | switch (opcode) | ||
432 | { | ||
433 | // LONG | ||
434 | case (UInt16)LSO_Enums.Operation_Table.POPARG: | ||
435 | case (UInt16)LSO_Enums.Operation_Table.STORE: | ||
436 | case (UInt16)LSO_Enums.Operation_Table.STORES: | ||
437 | case (UInt16)LSO_Enums.Operation_Table.STOREL: | ||
438 | case (UInt16)LSO_Enums.Operation_Table.STOREV: | ||
439 | case (UInt16)LSO_Enums.Operation_Table.STOREQ: | ||
440 | case (UInt16)LSO_Enums.Operation_Table.STOREG: | ||
441 | case (UInt16)LSO_Enums.Operation_Table.STOREGS: | ||
442 | case (UInt16)LSO_Enums.Operation_Table.STOREGL: | ||
443 | case (UInt16)LSO_Enums.Operation_Table.STOREGV: | ||
444 | case (UInt16)LSO_Enums.Operation_Table.STOREGQ: | ||
445 | case (UInt16)LSO_Enums.Operation_Table.LOADP: | ||
446 | case (UInt16)LSO_Enums.Operation_Table.LOADSP: | ||
447 | case (UInt16)LSO_Enums.Operation_Table.LOADLP: | ||
448 | case (UInt16)LSO_Enums.Operation_Table.LOADVP: | ||
449 | case (UInt16)LSO_Enums.Operation_Table.LOADQP: | ||
450 | case (UInt16)LSO_Enums.Operation_Table.PUSH: | ||
451 | case (UInt16)LSO_Enums.Operation_Table.PUSHS: | ||
452 | case (UInt16)LSO_Enums.Operation_Table.PUSHL: | ||
453 | case (UInt16)LSO_Enums.Operation_Table.PUSHV: | ||
454 | case (UInt16)LSO_Enums.Operation_Table.PUSHQ: | ||
455 | case (UInt16)LSO_Enums.Operation_Table.PUSHG: | ||
456 | case (UInt16)LSO_Enums.Operation_Table.PUSHGS: | ||
457 | case (UInt16)LSO_Enums.Operation_Table.PUSHGL: | ||
458 | case (UInt16)LSO_Enums.Operation_Table.PUSHGV: | ||
459 | case (UInt16)LSO_Enums.Operation_Table.PUSHGQ: | ||
460 | SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4),0)); | ||
461 | break; | ||
462 | // BYTE | ||
463 | case (UInt16)LSO_Enums.Operation_Table.PUSHARGB: | ||
464 | SendToDebug("Param1: " + br_read(1)[0]); | ||
465 | break; | ||
466 | // INTEGER | ||
467 | case (UInt16)LSO_Enums.Operation_Table.PUSHARGI: | ||
468 | // TODO: What is size of integer? | ||
469 | SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4),0)); | ||
470 | break; | ||
471 | // FLOAT | ||
472 | case (UInt16)LSO_Enums.Operation_Table.PUSHARGF: | ||
473 | // TODO: What is size of float? | ||
474 | SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4),0)); | ||
475 | break; | ||
476 | // STRING | ||
477 | case (UInt16)LSO_Enums.Operation_Table.PUSHARGS: | ||
478 | string s = Read_String(); | ||
479 | SendToDebug("Param1: " + s); | ||
480 | il.Emit(OpCodes.Ldstr, s); | ||
481 | break; | ||
482 | // VECTOR z,y,x | ||
483 | case (UInt16)LSO_Enums.Operation_Table.PUSHARGV: | ||
484 | SendToDebug("Param1 Z: " + BitConverter.ToUInt32(br_read(4),0)); | ||
485 | SendToDebug("Param1 Y: " + BitConverter.ToUInt32(br_read(4),0)); | ||
486 | SendToDebug("Param1 X: " + BitConverter.ToUInt32(br_read(4),0)); | ||
487 | break; | ||
488 | // ROTATION s,z,y,x | ||
489 | case (UInt16)LSO_Enums.Operation_Table.PUSHARGQ: | ||
490 | SendToDebug("Param1 S: " + BitConverter.ToUInt32(br_read(4),0)); | ||
491 | SendToDebug("Param1 Z: " + BitConverter.ToUInt32(br_read(4),0)); | ||
492 | SendToDebug("Param1 Y: " + BitConverter.ToUInt32(br_read(4),0)); | ||
493 | SendToDebug("Param1 X: " + BitConverter.ToUInt32(br_read(4),0)); | ||
494 | break; | ||
495 | // LONG | ||
496 | case (UInt16)LSO_Enums.Operation_Table.PUSHARGE: | ||
497 | SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4),0)); | ||
498 | break; | ||
499 | // BYTE | ||
500 | case (UInt16)LSO_Enums.Operation_Table.ADD: | ||
501 | case (UInt16)LSO_Enums.Operation_Table.SUB: | ||
502 | case (UInt16)LSO_Enums.Operation_Table.MUL: | ||
503 | case (UInt16)LSO_Enums.Operation_Table.DIV: | ||
504 | case (UInt16)LSO_Enums.Operation_Table.MOD: | ||
505 | case (UInt16)LSO_Enums.Operation_Table.EQ: | ||
506 | case (UInt16)LSO_Enums.Operation_Table.NEQ: | ||
507 | case (UInt16)LSO_Enums.Operation_Table.LEQ: | ||
508 | case (UInt16)LSO_Enums.Operation_Table.GEQ: | ||
509 | case (UInt16)LSO_Enums.Operation_Table.LESS: | ||
510 | case (UInt16)LSO_Enums.Operation_Table.GREATER: | ||
511 | case (UInt16)LSO_Enums.Operation_Table.BOOLOR: | ||
512 | SendToDebug("Param1: " + br_read(1)[0]); | ||
513 | break; | ||
514 | // LONG | ||
515 | case (UInt16)LSO_Enums.Operation_Table.JUMP: | ||
516 | SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4),0)); | ||
517 | break; | ||
518 | // BYTE, LONG | ||
519 | case (UInt16)LSO_Enums.Operation_Table.JUMPIF: | ||
520 | case (UInt16)LSO_Enums.Operation_Table.JUMPNIF: | ||
521 | SendToDebug("Param1: " + br_read(1)[0]); | ||
522 | SendToDebug("Param2: " + BitConverter.ToUInt32(br_read(4),0)); | ||
523 | break; | ||
524 | // LONG | ||
525 | case (UInt16)LSO_Enums.Operation_Table.STATE: | ||
526 | case (UInt16)LSO_Enums.Operation_Table.CALL: | ||
527 | SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4),0)); | ||
528 | break; | ||
529 | // BYTE | ||
530 | case (UInt16)LSO_Enums.Operation_Table.CAST: | ||
531 | SendToDebug("Param1: " + br_read(1)[0]); | ||
532 | break; | ||
533 | // LONG | ||
534 | case (UInt16)LSO_Enums.Operation_Table.STACKTOS: | ||
535 | case (UInt16)LSO_Enums.Operation_Table.STACKTOL: | ||
536 | SendToDebug("Param1: " + BitConverter.ToUInt32(br_read(4),0)); | ||
537 | break; | ||
538 | // BYTE | ||
539 | case (UInt16)LSO_Enums.Operation_Table.PRINT: | ||
540 | case (UInt16)LSO_Enums.Operation_Table.CALLLIB: | ||
541 | SendToDebug("Param1: " + br_read(1)[0]); | ||
542 | break; | ||
543 | // SHORT | ||
544 | case (UInt16)LSO_Enums.Operation_Table.CALLLIB_TWO_BYTE: | ||
545 | // TODO: What is size of short? | ||
546 | UInt16 _i = BitConverter.ToUInt16(br_read(2), 0); | ||
547 | SendToDebug("Param1: " + _i); | ||
548 | switch (_i) | ||
549 | { | ||
550 | case (UInt16)LSO_Enums.BuiltIn_Functions.llSay: | ||
551 | il.Emit(OpCodes.Call, typeof(Console).GetMethod | ||
552 | ("WriteLine", new Type[] { typeof(string) })); | ||
553 | break; | ||
554 | } | ||
555 | break; | ||
556 | |||
557 | |||
558 | // RETURN | ||
559 | case (UInt16)LSO_Enums.Operation_Table.RETURN: | ||
560 | SendToDebug("Last OPCODE was return command. Code chunk execution complete."); | ||
561 | FoundRet = true; | ||
562 | break; | ||
563 | } | ||
564 | //fs.Seek(rPos, SeekOrigin.Begin); | ||
565 | |||
566 | } | ||
567 | |||
568 | |||
569 | /* | ||
570 | * CATCH | ||
571 | */ | ||
572 | SendToDebug("CLR:" + eventname + ":il.BeginCatchBlock(typeof(Exception));"); | ||
573 | il.BeginCatchBlock(typeof(Exception)); | ||
574 | |||
575 | // Push "Hello World!" string to stack | ||
576 | SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Ldstr..."); | ||
577 | il.Emit(OpCodes.Ldstr, "Execption executing dynamic CLR function " + eventname + ": "); | ||
578 | |||
579 | //call void [mscorlib]System.Console::WriteLine(string) | ||
580 | SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Call..."); | ||
581 | il.Emit(OpCodes.Call, typeof(Console).GetMethod | ||
582 | ("Write", new Type[] { typeof(string) })); | ||
583 | |||
584 | //callvirt instance string [mscorlib]System.Exception::get_Message() | ||
585 | SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Callvirt..."); | ||
586 | il.Emit(OpCodes.Callvirt, typeof(Exception).GetMethod | ||
587 | ("get_Message")); | ||
588 | |||
589 | //call void [mscorlib]System.Console::WriteLine(string) | ||
590 | SendToDebug("CLR:" + eventname + ":il.Emit(OpCodes.Call..."); | ||
591 | il.Emit(OpCodes.Call, typeof(Console).GetMethod | ||
592 | ("WriteLine", new Type[] { typeof(string) })); | ||
593 | |||
594 | /* | ||
595 | * CLR END TRY | ||
596 | */ | ||
597 | //SendToDebug("CLR:" + eventname + ":il.EndExceptionBlock();"); | ||
598 | il.EndExceptionBlock(); | ||
599 | // Push "Return from current method, with return value if present" to stack | ||
600 | il.Emit(OpCodes.Ret); | ||
601 | |||
602 | |||
603 | |||
604 | return myCodeChunk; | ||
605 | |||
606 | } | ||
607 | } | ||
608 | } | ||