/// <summary> /// Loads exports from a Black Ops II Script /// </summary> public override void LoadExports() { Reader.BaseStream.Position = Header.ExportTableOffset; Exports = new List <ScriptExport>(Header.ExportsCount); for (int i = 0; i < Header.ExportsCount; i++) { var export = new ScriptExport() { Checksum = Reader.ReadUInt32(), ByteCodeOffset = Reader.ReadInt32(), Name = Reader.PeekNullTerminatedString(Reader.ReadUInt16()), // Use the file name as namespace like Bo3 does if none is present Namespace = Path.GetFileNameWithoutExtension(FilePath.Replace("/", "\\")), ParameterCount = Reader.ReadByte(), Flags = (ScriptExportFlags)Reader.ReadByte() }; var crc32 = new CRC32(); // Store our current position as we'll need to return back here var offset = Reader.BaseStream.Position; Reader.BaseStream.Position = export.ByteCodeOffset; var byteCodeSize = 0; // From kokole/Nukem's, brute force via CRC32 // This will only work on files dumped from a fast file while (true) { crc32.Update(Reader.ReadByte()); // If we hit, we're done if (crc32.Value == export.Checksum) { break; } byteCodeSize += 1; } // We can now use this - the start as our size export.ByteCodeSize = byteCodeSize; LoadFunction(export); // Go back to the table Reader.BaseStream.Position = offset; Exports.Add(export); } }
public void LoadFunction(ScriptExport function) { var offset = function.ByteCodeOffset; var endOffset = function.ByteCodeOffset + function.ByteCodeSize; while (offset <= endOffset) { var operation = LoadOperation(offset); if (operation == null) { //function.Operations.Add(new ScriptOp() //{ // Metadata = new ScriptOpMetadata(ScriptOpCode.Invalid, ScriptOpType.None, ScriptOperandType.None), // OpCodeOffset = offset //}); break; } offset += operation.OpCodeSize; function.Operations.Add(operation); } }
/// <summary> /// Loads exports from a Black Ops III Script /// </summary> public override void LoadExports() { Reader.BaseStream.Position = Header.ExportTableOffset; Exports = new List <ScriptExport>(Header.ExportsCount); var byteCodeEnd = Header.ByteCodeOffset + Header.ByteCodeSize; for (int i = 0; i < Header.ExportsCount; i++) { var export = new ScriptExport() { Checksum = Reader.ReadUInt32(), ByteCodeOffset = Reader.ReadInt32(), Name = GetHashValue(Reader.ReadUInt32(), "function_"), Namespace = GetHashValue(Reader.ReadUInt32(), "namespace_"), ParameterCount = Reader.ReadByte(), Flags = (ScriptExportFlags)Reader.ReadByte() }; Reader.BaseStream.Position += 2; var crc32 = new CRC32(); // Store our current position as we'll need to return back here // (+ 2 to skip padding) var offset = Reader.BaseStream.Position + 2; Reader.BaseStream.Position = export.ByteCodeOffset; var byteCodeSize = 0; // From kokole/Nukem's, brute force via CRC32 // This will only work on files dumped from a fast file while (true) { crc32.Update(Reader.ReadByte()); // If we hit, we're done if (crc32.Value == export.Checksum) { break; } byteCodeSize += 1; } // We can now use this - the start as our size export.ByteCodeSize = byteCodeSize; LoadFunction(export); // Go back to the table Reader.BaseStream.Position = offset; Exports.Add(export); } for (int i = 0; i < Header.ExportsCount; i++) { Exports[i].ByteCodeSize = (i == Header.ExportsCount - 1) ? byteCodeEnd - Exports[i].ByteCodeOffset : Exports[i + 1].ByteCodeOffset - Exports[i].ByteCodeOffset; Reader.BaseStream.Position = Exports[i].ByteCodeOffset; LoadFunction(Exports[i]); } }