Update pawn parsing

I get some exceptions when running lgpe stuff in linqpad, but this is
getting cleaner
This commit is contained in:
Kurt 2019-01-01 12:23:06 -08:00
parent a94d63e615
commit 86018c52aa
3 changed files with 53 additions and 260 deletions

View File

@ -1,4 +1,5 @@
using System.Runtime.InteropServices;
using System;
using System.Runtime.InteropServices;
namespace pkNX.Structures
{
@ -63,6 +64,21 @@ public class AmxHeader
/// <summary> Offset to the overlay table </summary>
public int Overlays; // 0x3C
public int CellSize
{
get
{
switch (Magic)
{
case MAGIC_16: return 16;
case MAGIC_32: return 32;
case MAGIC_64: return 64;
default:
throw new ArgumentException("Invalid Magic identifier.");
}
}
}
}
/* File format version

View File

@ -547,223 +547,6 @@ internal static string EF(uint c, params uint[] arr)
return $"{cmd}({parameters})";
}
internal static readonly Dictionary<uint, string> Commands = new Dictionary<uint, string>
{// { 0x00, "$00" }, // Invalid Code
{ 0x01, "$01" },
{ 0x02, "$02" },
{ 0x03, "$03" },
{ 0x04, "$04" },
{ 0x05, "$05" },
{ 0x06, "$06" },
{ 0x07, "$07" },
{ 0x08, "$08" },
{ 0x09, "$09" },
{ 0x0A, "$0A" },
{ 0x0B, "$0B" },
{ 0x0C, "$0C" },
{ 0x0D, "$0D" },
{ 0x0E, "$0E" },
{ 0x0F, "$0F" },
{ 0x10, "$10" },
{ 0x11, "$11" },
{ 0x12, "$12" },
{ 0x13, "$13" },
{ 0x14, "$14" },
{ 0x15, "$15" },
{ 0x16, "$16" },
{ 0x17, "$17" },
{ 0x18, "$18" },
{ 0x19, "$19" },
{ 0x1A, "$1A" },
{ 0x1B, "$1B" },
{ 0x1C, "$1C" },
{ 0x1D, "$1D" },
{ 0x1E, "$1E" },
{ 0x1F, "$1F" },
{ 0x20, "$20" },
{ 0x21, "$21" },
{ 0x22, "$22" },
{ 0x23, "$23" },
{ 0x24, "$24" },
{ 0x25, "$25" },
{ 0x26, "$26" },
{ 0x27, "PushConst" },
{ 0x28, "$28" },
{ 0x29, "$29" },
{ 0x2A, "$2A" },
{ 0x2B, "$2B" },
{ 0x2C, "$2C" },
{ 0x2D, "$2D" },
{ 0x2E, "Begin" },
{ 0x2F, "$2F" },
{ 0x30, "Return" },
{ 0x31, "CallFunc" },
{ 0x32, "$32" },
{ 0x33, "$33" },
{ 0x34, "$34" },
{ 0x35, "BNE" },
{ 0x36, "BEQ" },
{ 0x37, "$37" },
{ 0x38, "$38" },
{ 0x39, "$39" },
{ 0x3A, "$3A" },
{ 0x3B, "$3B" },
{ 0x3C, "$3C" },
{ 0x3D, "$3D" },
{ 0x3E, "$3E" },
{ 0x3F, "$3F" },
{ 0x40, "$40" },
{ 0x41, "$41" },
{ 0x42, "$42" },
{ 0x43, "$43" },
{ 0x44, "$44" },
{ 0x45, "$45" },
{ 0x46, "$46" },
{ 0x47, "$47" },
{ 0x48, "$48" },
{ 0x49, "$49" },
{ 0x4A, "$4A" },
{ 0x4B, "$4B" },
{ 0x4C, "$4C" },
{ 0x4D, "$4D" },
{ 0x4E, "Add?" },
{ 0x4F, "$4F" },
{ 0x50, "$50" },
{ 0x51, "Cmp?" },
{ 0x52, "$52" },
{ 0x53, "$53" },
{ 0x54, "$54" },
{ 0x55, "$55" },
{ 0x56, "$56" },
{ 0x57, "$57" },
{ 0x58, "$58" },
{ 0x59, "ClearAll" },
{ 0x5A, "$5A" },
{ 0x5B, "$5B" },
{ 0x5C, "$5C" },
{ 0x5D, "$5D" },
{ 0x5E, "$5E" },
{ 0x5F, "$5F" },
{ 0x60, "$60" },
{ 0x61, "$61" },
{ 0x62, "$62" },
{ 0x63, "$63" },
{ 0x64, "$64" },
{ 0x65, "$65" },
{ 0x66, "$66" },
{ 0x67, "$67" },
{ 0x68, "$68" },
{ 0x69, "$69" },
{ 0x6A, "$6A" },
{ 0x6B, "$6B" },
{ 0x6C, "$6C" },
{ 0x6D, "$6D" },
{ 0x6E, "$6E" },
{ 0x6F, "$6F" },
{ 0x70, "$70" },
{ 0x71, "$71" },
{ 0x72, "$72" },
{ 0x73, "$73" },
{ 0x74, "$74" },
{ 0x75, "$75" },
{ 0x76, "$76" },
{ 0x77, "$77" },
{ 0x78, "$78" },
{ 0x79, "$79" },
{ 0x7A, "$7A" },
{ 0x7B, "$7B" },
// { 0x7C, "$7C" }, // Invalid Code
// { 0x7D, "$7D" }, // Invalid Code
// { 0x7E, "$7E" }, // Invalid Code
// { 0x7F, "$7F" }, // Invalid Code
// { 0x80, "$80" }, // Invalid Code
{ 0x81, "JMP" },
{ 0x82, "switch" },
{ 0x83, "$83" },
{ 0x84, "$84" },
{ 0x85, "$85" },
{ 0x86, "$86" },
{ 0x87, "DoCommand?" },
// { 0x88, "$88" }, // Invalid Code
{ 0x89, "LineNo?" },
{ 0x8A, "$8A" },
{ 0x8B, "$8B" },
{ 0x8C, "$8C" },
{ 0x8D, "$8D" },
{ 0x8E, "$8E" },
{ 0x8F, "$8F" },
{ 0x90, "$90" },
{ 0x91, "$91" },
{ 0x92, "$92" },
{ 0x93, "$93" },
{ 0x94, "$94" },
{ 0x95, "$95" },
{ 0x96, "$96" },
{ 0x97, "$97" },
{ 0x98, "$98" },
{ 0x99, "$99" },
{ 0x9A, "$9A" },
{ 0x9B, "Copy" },
{ 0x9C, "$9C" },
{ 0x9D, "$9D" },
{ 0x9E, "$9E" },
{ 0x9F, "$9F" },
{ 0xA0, "$A0" },
{ 0xA1, "$A1" },
{ 0xA2, "GetGlobal2" },
{ 0xA3, "GetGlobal" },
{ 0xA4, "GetGlobal4" },
{ 0xA5, "$A5" },
{ 0xA6, "$A6" },
{ 0xA7, "$A7" },
{ 0xA8, "$A8" },
{ 0xA9, "$A9" },
{ 0xAA, "$AA" },
{ 0xAB, "PushConst2" },
{ 0xAC, "CmpConst2" },
{ 0xAD, "$AD" },
{ 0xAE, "$AE" },
{ 0xAF, "SetGlobal" },
{ 0xB0, "$B0" },
{ 0xB1, "SetLocal" },
{ 0xB2, "$B2" },
{ 0xB3, "$B3" },
{ 0xB4, "$B4" },
{ 0xB5, "$B5" },
{ 0xB6, "$B6" },
{ 0xB7, "$B7" },
{ 0xB8, "$B8" },
{ 0xB9, "$B9" },
{ 0xBA, "$BA" },
{ 0xBB, "$BB" },
{ 0xBC, "PushConst" },
{ 0xBD, "GetGlobal3" },
{ 0xBE, "GetArg" },
{ 0xBF, "AdjustStack" },
{ 0xC0, "$C0" },
{ 0xC1, "$C1" },
{ 0xC2, "$C2" },
{ 0xC3, "$C3" },
{ 0xC4, "$C4" },
{ 0xC5, "$C5" },
{ 0xC6, "$C6" },
{ 0xC7, "$C7" },
{ 0xC8, "CmpLocal" },
{ 0xC9, "CmpConst" },
{ 0xCA, "$CA" },
{ 0xCB, "$CB" },
{ 0xCC, "$CC" },
{ 0xCD, "$CD" },
{ 0xCE, "$CE" },
{ 0xCF, "$CF" },
{ 0xD0, "$D0" },
{ 0xD1, "$D1" },
{ 0xD2, "$D2" },
{ 0xD3, "$D3" },
{ 0xD4, "$D4" },
{ 0xD5, "Mode1" },
{ 0xD6, "Mode2" },
};
private static readonly string[] Commands = Enum.GetNames(typeof(AmxOpCode));
}
}

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace pkNX.Structures
@ -9,56 +10,49 @@ namespace pkNX.Structures
/// <remarks>https://github.com/compuphase/pawn</remarks>
public class Script
{
public AmxHeader Header;
public int Length => Header.Size;
public uint Magic => Header.Magic;
// case 0x0A0AF1E0: code = read_code_block(f); break;
// case 0x0A0AF1EF: debug = read_debug_block(f); break;
public bool Debug => Header.Flags.HasFlagFast(AmxFlags.DEBUG);
public readonly byte[] Data;
public readonly AmxHeader Header;
public readonly int CellSize;
public ushort PtrOffset => BitConverter.ToUInt16(Raw, 0x08);
public ushort PtrCount => BitConverter.ToUInt16(Raw, 0x0A);
public int ScriptInstructionStart => BitConverter.ToInt32(Raw, 0x0C);
public int ScriptMovementStart => BitConverter.ToInt32(Raw, 0x10);
public int FinalOffset => BitConverter.ToInt32(Raw, 0x14);
public int AllocatedMemory => BitConverter.ToInt32(Raw, 0x18);
// Generated Attributes
public int CompressedLength => Length - ScriptInstructionStart;
public byte[] CompressedBytes => Raw.Skip(ScriptInstructionStart).ToArray();
public int DecompressedLength => FinalOffset - ScriptInstructionStart;
public uint[] DecompressedInstructions => PawnUtil.QuickDecompress(CompressedBytes, DecompressedLength / 4);
public uint[] ScriptCommands => DecompressedInstructions.Take((ScriptMovementStart - ScriptInstructionStart) / 4).ToArray();
public uint[] MoveCommands => DecompressedInstructions.Skip((ScriptMovementStart - ScriptInstructionStart) / 4).ToArray();
public string[] ParseScript => PawnUtil.ParseScript(ScriptCommands);
public string[] ParseMoves => PawnUtil.ParseMovement(MoveCommands);
public string Info => "Data Start: 0x" + ScriptInstructionStart.ToString("X4")
+ Environment.NewLine + "Movement Offset: 0x" + ScriptMovementStart.ToString("X4")
+ Environment.NewLine + "Total Used Size: 0x" + FinalOffset.ToString("X4")
+ Environment.NewLine + "Reserved Size: 0x" + AllocatedMemory.ToString("X4")
+ Environment.NewLine + "Compressed Len: 0x" + CompressedLength.ToString("X4")
+ Environment.NewLine + "Decompressed Len: 0x" + DecompressedLength.ToString("X4")
+ Environment.NewLine + "Compression Ratio: " +
((DecompressedLength - CompressedLength) / (decimal)DecompressedLength).ToString("p1");
public byte[] Raw;
public Script(byte[] data = null)
public Script(byte[] data)
{
Raw = data ?? Array.Empty<byte>();
Data = data;
Header = data.ToClass<AmxHeader>();
CellSize = Header.CellSize;
// sub_51AAFC
if (Header.Flags.HasFlagFast(AmxFlags.OVERLAY))
throw new ArgumentException("Multi-environment script!?");
}
public byte[] Write()
public byte[] Write() => Data;
public bool Debug => Header.Flags.HasFlagFast(AmxFlags.DEBUG);
// Generated Attributes
public int CodeLength => Header.Data - Header.COD;
public int CompressedLength => Header.Size - Header.COD;
public byte[] CompressedBytes => Data.Skip(Header.COD).ToArray();
public int DecompressedLength => Header.Heap - Header.COD;
public uint[] DecompressedInstructions => PawnUtil.QuickDecompress(CompressedBytes, DecompressedLength / sizeof(uint));
public uint[] ScriptCommands => DecompressedInstructions.Take(CodeLength / sizeof(uint)).ToArray(); // Code
public uint[] DataPayload => DecompressedInstructions.Skip(CodeLength / sizeof(uint)).ToArray(); // Data
public string[] ParseScript => PawnUtil.ParseScript(ScriptCommands);
public string[] DataChunk => PawnUtil.ParseMovement(DataPayload);
public string Info => string.Join(Environment.NewLine, SummaryLines);
public IEnumerable<string> SummaryLines
{
return Raw;
get
{
yield return $"Code Start: 0x{Header.COD:X4}";
yield return $"Data Start: 0x{Header.Data:X4}";
yield return $"Total Used Size: 0x{Header.Heap:X4}";
yield return $"Reserved Size: 0x{Header.StackTop:X4}";
yield return $"Compressed Len: 0x{CompressedLength:X4}";
yield return $"Decompressed Len: 0x{DecompressedLength:X4}";
yield return $"Compression Ratio: {(DecompressedLength - CompressedLength) / (decimal) DecompressedLength:p1}";
}
}
}
}