mirror of
https://github.com/kwsch/pkNX.git
synced 2026-04-25 15:26:55 -05:00
Initial c#8 update
pkNX.Sprites to be replaced with a pkhex.drawing dll once that is updated with swsh stuff (when the time comes)
This commit is contained in:
parent
0a6146b47d
commit
537ce93efa
|
|
@ -12,17 +12,16 @@ public static class Container
|
|||
/// <param name="t">File type</param>
|
||||
public static IFileContainer GetContainer(string path, ContainerType t)
|
||||
{
|
||||
switch (t)
|
||||
return t switch
|
||||
{
|
||||
case ContainerType.GARC: return new GARC(path);
|
||||
case ContainerType.Mini: return MiniUtil.GetMini(path);
|
||||
case ContainerType.SARC: return new SARC(path);
|
||||
case ContainerType.Folder: return new FolderContainer(path);
|
||||
case ContainerType.SingleFile: return new SingleFileContainer(path);
|
||||
case ContainerType.GFPack: return new GFPack(path);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(t), t, null);
|
||||
}
|
||||
ContainerType.GARC => (IFileContainer) new GARC(path),
|
||||
ContainerType.Mini => MiniUtil.GetMini(path),
|
||||
ContainerType.SARC => new SARC(path),
|
||||
ContainerType.Folder => new FolderContainer(path),
|
||||
ContainerType.SingleFile => new SingleFileContainer(path),
|
||||
ContainerType.GFPack => new GFPack(path),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(t), t, null)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -48,7 +47,9 @@ public static IFileContainer GetContainer(string path)
|
|||
/// <param name="stream">Stream for the binary data</param>
|
||||
public static IFileContainer GetContainer(Stream stream)
|
||||
{
|
||||
#pragma warning disable IDE0068 // Use recommended dispose pattern
|
||||
var br = new BinaryReader(stream);
|
||||
#pragma warning restore IDE0068 // Use recommended dispose pattern
|
||||
var container = GetContainer(br);
|
||||
if (!(container is LargeContainer)) // not kept
|
||||
br.Dispose();
|
||||
|
|
|
|||
|
|
@ -142,6 +142,11 @@ public async Task SaveAs(string path, ContainerHandler handler, CancellationToke
|
|||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
Stream.Dispose();
|
||||
Reader.Dispose();
|
||||
|
|
|
|||
|
|
@ -67,8 +67,8 @@ public void Dump(Stream parent, string path, int DataOffset)
|
|||
if (File is string)
|
||||
return;
|
||||
|
||||
using (var file = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
Write(parent, file, DataOffset);
|
||||
using var file = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
Write(parent, file, DataOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,38 +30,34 @@ public static byte[] PackMini(byte[][] fileData, string identifier)
|
|||
int dataOffset = 4 + 4 + (count * 4);
|
||||
|
||||
// Start the data filling.
|
||||
using (MemoryStream dataout = new MemoryStream())
|
||||
using (MemoryStream offsetMap = new MemoryStream())
|
||||
using (BinaryWriter bd = new BinaryWriter(dataout))
|
||||
using (BinaryWriter bo = new BinaryWriter(offsetMap))
|
||||
using MemoryStream dataout = new MemoryStream();
|
||||
using MemoryStream offsetMap = new MemoryStream();
|
||||
using BinaryWriter bd = new BinaryWriter(dataout);
|
||||
using BinaryWriter bo = new BinaryWriter(offsetMap);
|
||||
// For each file...
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
// For each file...
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
// Write File Offset
|
||||
uint fileOffset = (uint)(dataout.Position + dataOffset);
|
||||
bo.Write(fileOffset);
|
||||
// Write File Offset
|
||||
uint fileOffset = (uint)(dataout.Position + dataOffset);
|
||||
bo.Write(fileOffset);
|
||||
|
||||
// Write File to Stream
|
||||
bd.Write(fileData[i]);
|
||||
// Write File to Stream
|
||||
bd.Write(fileData[i]);
|
||||
|
||||
// Pad the Data MemoryStream with Zeroes until len%4=0;
|
||||
while (dataout.Length % 4 != 0)
|
||||
bd.Write((byte)0);
|
||||
// File Offset will be updated as the offset is based off of the Data length.
|
||||
}
|
||||
// Cap the File
|
||||
bo.Write((uint)(dataout.Position + dataOffset));
|
||||
|
||||
using (var newPack = new MemoryStream())
|
||||
using (var header = new MemoryStream(data))
|
||||
{
|
||||
header.WriteTo(newPack);
|
||||
offsetMap.WriteTo(newPack);
|
||||
dataout.WriteTo(newPack);
|
||||
return newPack.ToArray();
|
||||
}
|
||||
// Pad the Data MemoryStream with Zeroes until len%4=0;
|
||||
while (dataout.Length % 4 != 0)
|
||||
bd.Write((byte)0);
|
||||
// File Offset will be updated as the offset is based off of the Data length.
|
||||
}
|
||||
// Cap the File
|
||||
bo.Write((uint)(dataout.Position + dataOffset));
|
||||
|
||||
using var newPack = new MemoryStream();
|
||||
using var header = new MemoryStream(data);
|
||||
header.WriteTo(newPack);
|
||||
offsetMap.WriteTo(newPack);
|
||||
dataout.WriteTo(newPack);
|
||||
return newPack.ToArray();
|
||||
}
|
||||
|
||||
public static byte[][] UnpackMini(string file, string identifier = null)
|
||||
|
|
@ -99,9 +95,9 @@ public static byte[][] UnpackMini(byte[] fileData, string identifier = null)
|
|||
public static Mini GetMini(string path)
|
||||
{
|
||||
path = FileMitm.GetRedirectedReadPath(path);
|
||||
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
|
||||
using (var br = new BinaryReader(fs))
|
||||
return GetMini(br);
|
||||
using var fs = new FileStream(path, FileMode.Open, FileAccess.Read);
|
||||
using var br = new BinaryReader(fs);
|
||||
return GetMini(br);
|
||||
}
|
||||
|
||||
public static Mini GetMini(BinaryReader br)
|
||||
|
|
@ -139,9 +135,9 @@ public static string GetIsMini(string path)
|
|||
try
|
||||
{
|
||||
path = FileMitm.GetRedirectedWritePath(path);
|
||||
using (var fs = new FileStream(path, FileMode.Open))
|
||||
using (var br = new BinaryReader(fs))
|
||||
return GetIsMini(br);
|
||||
using var fs = new FileStream(path, FileMode.Open);
|
||||
using var br = new BinaryReader(fs);
|
||||
return GetIsMini(br);
|
||||
}
|
||||
catch { return null; }
|
||||
}
|
||||
|
|
@ -150,9 +146,9 @@ public static string GetIsMini(byte[] data)
|
|||
{
|
||||
try
|
||||
{
|
||||
using (var ms = new MemoryStream(data))
|
||||
using (var br = new BinaryReader(ms))
|
||||
return GetIsMini(br);
|
||||
using var ms = new MemoryStream(data);
|
||||
using var br = new BinaryReader(ms);
|
||||
return GetIsMini(br);
|
||||
}
|
||||
catch { return null; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace pkNX.Containers
|
|||
{
|
||||
public class GFPack : IEnumerable<byte[]>, IFileContainer
|
||||
{
|
||||
private const ulong Magic = 0x4B434150_584C4647; // GFLXPACK
|
||||
public const ulong Magic = 0x4B434150_584C4647; // GFLXPACK
|
||||
|
||||
// Overall structure: Header, metadata, and the raw compressed files
|
||||
public GFPackHeader Header { get; set; }
|
||||
|
|
@ -33,9 +33,9 @@ public class GFPack : IEnumerable<byte[]>, IFileContainer
|
|||
/// <param name="data">Packed file</param>
|
||||
public GFPack(byte[] data)
|
||||
{
|
||||
using (var ms = new MemoryStream(data))
|
||||
using (var br = new BinaryReader(ms))
|
||||
ReadPack(br);
|
||||
using var ms = new MemoryStream(data);
|
||||
using var br = new BinaryReader(ms);
|
||||
ReadPack(br);
|
||||
}
|
||||
|
||||
public GFPack(BinaryReader br) => ReadPack(br);
|
||||
|
|
@ -81,137 +81,6 @@ private void ReadPack(BinaryReader br)
|
|||
DecompressedFiles[i] = Decompress(CompressedFiles[i], FileTable[i].SizeDecompressed, FileTable[i].Type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Intro bytes to the packed binary.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class GFPackHeader
|
||||
{
|
||||
public const int SIZE = 0x18;
|
||||
public ulong MAGIC = Magic;
|
||||
public uint Version = 0x1000;
|
||||
public uint IsRelocated; // bit0
|
||||
|
||||
/// <summary>
|
||||
/// Count of Files packed into the binary.
|
||||
/// </summary>
|
||||
public int CountFiles;
|
||||
|
||||
/// <summary>
|
||||
/// Count of Folders packed into the binary.
|
||||
/// </summary>
|
||||
public int CountFolders;
|
||||
}
|
||||
|
||||
public class GFPackPointers
|
||||
{
|
||||
/// <summary>
|
||||
/// Data offset for the <see cref="FileData"/> table.
|
||||
/// </summary>
|
||||
public long PtrFileTable; // array stored at end
|
||||
|
||||
/// <summary>
|
||||
/// Data offset for the <see cref="FileHashAbsolute"/> table.
|
||||
/// </summary>
|
||||
public long PtrHashPaths; // array stored first
|
||||
|
||||
/// <summary>
|
||||
/// Data offset for the <see cref="FileHashFolder"/> table, which has a leading <see cref="FileHashFolderInfo"/>.
|
||||
/// </summary>
|
||||
public long[] PtrHashFolders; // array stored in middle
|
||||
|
||||
// immediately after the pointers are the arrays
|
||||
|
||||
public GFPackPointers(BinaryReader br, int folderCount)
|
||||
{
|
||||
PtrFileTable = br.ReadInt64();
|
||||
PtrHashPaths = br.ReadInt64();
|
||||
PtrHashFolders = new long[folderCount];
|
||||
for (int i = 0; i < PtrHashFolders.Length; i++)
|
||||
PtrHashFolders[i] = br.ReadInt64();
|
||||
}
|
||||
|
||||
public void Write(BinaryWriter bw)
|
||||
{
|
||||
bw.Write(PtrFileTable);
|
||||
bw.Write(PtrHashPaths);
|
||||
foreach (var table in PtrHashFolders)
|
||||
bw.Write(table);
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class FileHashAbsolute
|
||||
{
|
||||
public const int SIZE = 0x08;
|
||||
|
||||
/// <summary>
|
||||
/// Filename (with directory details) hash.
|
||||
/// </summary>
|
||||
public ulong HashFnv1aPathFull;
|
||||
|
||||
public bool IsMatch(string fileName) => FnvHash.HashFnv1a_64(fileName) == HashFnv1aPathFull;
|
||||
}
|
||||
|
||||
public class FileHashFolder
|
||||
{
|
||||
public FileHashFolderInfo Folder;
|
||||
public FileHashIndex[] Files;
|
||||
public int GetIndexFileName(ulong hash) => Array.FindIndex(Files, z => z.HashFnv1aPathFileName == hash);
|
||||
public int GetIndexFileName(string name) => Array.FindIndex(Files, z => z.IsMatch(name));
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class FileHashFolderInfo
|
||||
{
|
||||
public const int SIZE = 0x10;
|
||||
|
||||
/// <summary>
|
||||
/// Filename (without directory details) hash.
|
||||
/// </summary>
|
||||
public ulong HashFnv1aPathFolderName;
|
||||
public int FileCount;
|
||||
public uint Padding = 0xCC;
|
||||
|
||||
public bool IsMatch(string fileName) => FnvHash.HashFnv1a_64(fileName) == HashFnv1aPathFolderName;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class FileHashIndex
|
||||
{
|
||||
public const int SIZE = 0x10;
|
||||
|
||||
/// <summary>
|
||||
/// Filename (without directory details) hash.
|
||||
/// </summary>
|
||||
public ulong HashFnv1aPathFileName;
|
||||
public int Index;
|
||||
public uint Padding = 0xCC;
|
||||
|
||||
public bool IsMatch(string fileName) => FnvHash.HashFnv1a_64(fileName) == HashFnv1aPathFileName;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class FileData
|
||||
{
|
||||
public const int SIZE = 0x18;
|
||||
|
||||
public ushort Level = 9; // quality?
|
||||
public CompressionType Type;
|
||||
public int SizeDecompressed;
|
||||
public int SizeCompressed;
|
||||
public int Padding = 0xCC;
|
||||
public int OffsetPacked;
|
||||
public uint unused;
|
||||
}
|
||||
|
||||
public enum CompressionType : ushort
|
||||
{
|
||||
None = 0,
|
||||
Zlib = 1,
|
||||
Lz4 = 2,
|
||||
}
|
||||
|
||||
public IEnumerator<byte[]> GetEnumerator() => (IEnumerator<byte[]>)DecompressedFiles.GetEnumerator();
|
||||
IEnumerator IEnumerable.GetEnumerator() => DecompressedFiles.GetEnumerator();
|
||||
public int Count => Header.CountFiles;
|
||||
|
|
@ -298,56 +167,50 @@ public void LoadFiles(string[] directories, string parent, CompressionType type
|
|||
|
||||
public byte[] Write()
|
||||
{
|
||||
using (var ms = new MemoryStream())
|
||||
using (var bw = new BinaryWriter(ms))
|
||||
using var ms = new MemoryStream();
|
||||
using var bw = new BinaryWriter(ms);
|
||||
WriteHeaderTableList(bw);
|
||||
for (var i = 0; i < DecompressedFiles.Length; i++)
|
||||
{
|
||||
WriteHeaderTableList(bw);
|
||||
for (var i = 0; i < DecompressedFiles.Length; i++)
|
||||
{
|
||||
var entry = FileTable[i];
|
||||
var f = DecompressedFiles[i];
|
||||
var c = Compress(f, entry.Type);
|
||||
CompressedFiles[i] = c;
|
||||
var entry = FileTable[i];
|
||||
var f = DecompressedFiles[i];
|
||||
var c = Compress(f, entry.Type);
|
||||
CompressedFiles[i] = c;
|
||||
|
||||
// update entry details
|
||||
entry.SizeDecompressed = f.Length;
|
||||
entry.SizeCompressed = c.Length;
|
||||
entry.OffsetPacked = (int)bw.BaseStream.Position;
|
||||
// update entry details
|
||||
entry.SizeDecompressed = f.Length;
|
||||
entry.SizeCompressed = c.Length;
|
||||
entry.OffsetPacked = (int)bw.BaseStream.Position;
|
||||
|
||||
bw.Write(c);
|
||||
while (bw.BaseStream.Position % 0x10 != 0) // pad to nearest 0x10 alignment
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
bw.BaseStream.Position = 0;
|
||||
WriteHeaderTableList(bw);
|
||||
return ms.ToArray();
|
||||
bw.Write(c);
|
||||
while (bw.BaseStream.Position % 0x10 != 0) // pad to nearest 0x10 alignment
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
bw.BaseStream.Position = 0;
|
||||
WriteHeaderTableList(bw);
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
private static byte[] Decompress(byte[] encryptedData, int decryptedLength, CompressionType type)
|
||||
{
|
||||
switch (type)
|
||||
return type switch
|
||||
{
|
||||
case CompressionType.None:
|
||||
return encryptedData;
|
||||
case CompressionType.Zlib:
|
||||
return null; // not implemented
|
||||
default:
|
||||
return LZ4.Decode(encryptedData, decryptedLength);
|
||||
}
|
||||
CompressionType.None => encryptedData,
|
||||
CompressionType.Zlib => null // not implemented
|
||||
,
|
||||
_ => LZ4.Decode(encryptedData, decryptedLength)
|
||||
};
|
||||
}
|
||||
|
||||
private static byte[] Compress(byte[] decryptedData, CompressionType type)
|
||||
{
|
||||
switch (type)
|
||||
return type switch
|
||||
{
|
||||
case CompressionType.None:
|
||||
return decryptedData;
|
||||
case CompressionType.Zlib:
|
||||
return null; // not implemented
|
||||
default:
|
||||
return LZ4.Encode(decryptedData);
|
||||
}
|
||||
CompressionType.None => decryptedData,
|
||||
CompressionType.Zlib => null // not implemented
|
||||
,
|
||||
_ => LZ4.Encode(decryptedData)
|
||||
};
|
||||
}
|
||||
|
||||
public void CancelEdits()
|
||||
|
|
@ -411,4 +274,135 @@ public void Dump(string path, ContainerHandler handler)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Intro bytes to the packed binary.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class GFPackHeader
|
||||
{
|
||||
public const int SIZE = 0x18;
|
||||
public ulong MAGIC = GFPack.Magic;
|
||||
public uint Version = 0x1000;
|
||||
public uint IsRelocated; // bit0
|
||||
|
||||
/// <summary>
|
||||
/// Count of Files packed into the binary.
|
||||
/// </summary>
|
||||
public int CountFiles;
|
||||
|
||||
/// <summary>
|
||||
/// Count of Folders packed into the binary.
|
||||
/// </summary>
|
||||
public int CountFolders;
|
||||
}
|
||||
|
||||
public class GFPackPointers
|
||||
{
|
||||
/// <summary>
|
||||
/// Data offset for the <see cref="FileData"/> table.
|
||||
/// </summary>
|
||||
public long PtrFileTable; // array stored at end
|
||||
|
||||
/// <summary>
|
||||
/// Data offset for the <see cref="FileHashAbsolute"/> table.
|
||||
/// </summary>
|
||||
public long PtrHashPaths; // array stored first
|
||||
|
||||
/// <summary>
|
||||
/// Data offset for the <see cref="FileHashFolder"/> table, which has a leading <see cref="FileHashFolderInfo"/>.
|
||||
/// </summary>
|
||||
public long[] PtrHashFolders; // array stored in middle
|
||||
|
||||
// immediately after the pointers are the arrays
|
||||
|
||||
public GFPackPointers(BinaryReader br, int folderCount)
|
||||
{
|
||||
PtrFileTable = br.ReadInt64();
|
||||
PtrHashPaths = br.ReadInt64();
|
||||
PtrHashFolders = new long[folderCount];
|
||||
for (int i = 0; i < PtrHashFolders.Length; i++)
|
||||
PtrHashFolders[i] = br.ReadInt64();
|
||||
}
|
||||
|
||||
public void Write(BinaryWriter bw)
|
||||
{
|
||||
bw.Write(PtrFileTable);
|
||||
bw.Write(PtrHashPaths);
|
||||
foreach (var table in PtrHashFolders)
|
||||
bw.Write(table);
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class FileHashAbsolute
|
||||
{
|
||||
public const int SIZE = 0x08;
|
||||
|
||||
/// <summary>
|
||||
/// Filename (with directory details) hash.
|
||||
/// </summary>
|
||||
public ulong HashFnv1aPathFull;
|
||||
|
||||
public bool IsMatch(string fileName) => FnvHash.HashFnv1a_64(fileName) == HashFnv1aPathFull;
|
||||
}
|
||||
|
||||
public class FileHashFolder
|
||||
{
|
||||
public FileHashFolderInfo Folder;
|
||||
public FileHashIndex[] Files;
|
||||
public int GetIndexFileName(ulong hash) => Array.FindIndex(Files, z => z.HashFnv1aPathFileName == hash);
|
||||
public int GetIndexFileName(string name) => Array.FindIndex(Files, z => z.IsMatch(name));
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class FileHashFolderInfo
|
||||
{
|
||||
public const int SIZE = 0x10;
|
||||
|
||||
/// <summary>
|
||||
/// Filename (without directory details) hash.
|
||||
/// </summary>
|
||||
public ulong HashFnv1aPathFolderName;
|
||||
public int FileCount;
|
||||
public uint Padding = 0xCC;
|
||||
|
||||
public bool IsMatch(string fileName) => FnvHash.HashFnv1a_64(fileName) == HashFnv1aPathFolderName;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class FileHashIndex
|
||||
{
|
||||
public const int SIZE = 0x10;
|
||||
|
||||
/// <summary>
|
||||
/// Filename (without directory details) hash.
|
||||
/// </summary>
|
||||
public ulong HashFnv1aPathFileName;
|
||||
public int Index;
|
||||
public uint Padding = 0xCC;
|
||||
|
||||
public bool IsMatch(string fileName) => FnvHash.HashFnv1a_64(fileName) == HashFnv1aPathFileName;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class FileData
|
||||
{
|
||||
public const int SIZE = 0x18;
|
||||
|
||||
public ushort Level = 9; // quality?
|
||||
public CompressionType Type;
|
||||
public int SizeDecompressed;
|
||||
public int SizeCompressed;
|
||||
public int Padding = 0xCC;
|
||||
public int OffsetPacked;
|
||||
public uint unused;
|
||||
}
|
||||
|
||||
public enum CompressionType : ushort
|
||||
{
|
||||
None = 0,
|
||||
Zlib = 1,
|
||||
Lz4 = 2,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,9 +28,9 @@ public class NSO
|
|||
|
||||
public NSO(byte[] data)
|
||||
{
|
||||
using (var ms = new MemoryStream(data))
|
||||
using (var br = new BinaryReader(ms))
|
||||
ReadHeader(br);
|
||||
using var ms = new MemoryStream(data);
|
||||
using var br = new BinaryReader(ms);
|
||||
ReadHeader(br);
|
||||
}
|
||||
|
||||
private void ReadHeader(BinaryReader br)
|
||||
|
|
@ -53,7 +53,7 @@ public static byte[] GetCompressedSegment(BinaryReader br, SegmentHeader h, int
|
|||
return br.ReadBytes(sizeCompressed);
|
||||
}
|
||||
|
||||
public byte[] GetDecompressedSegment(BinaryReader br, SegmentHeader h, int sizeCompressed)
|
||||
public static byte[] GetDecompressedSegment(BinaryReader br, SegmentHeader h, int sizeCompressed)
|
||||
{
|
||||
byte[] data = GetCompressedSegment(br, h, sizeCompressed);
|
||||
return LZ4.Decode(data, h.DecompressedSize);
|
||||
|
|
@ -61,8 +61,8 @@ public byte[] GetDecompressedSegment(BinaryReader br, SegmentHeader h, int sizeC
|
|||
|
||||
public static byte[] Hash(byte[] data)
|
||||
{
|
||||
using (var method = SHA256.Create())
|
||||
return method.ComputeHash(data);
|
||||
using var method = SHA256.Create();
|
||||
return method.ComputeHash(data);
|
||||
}
|
||||
|
||||
private void Decompress()
|
||||
|
|
@ -105,30 +105,28 @@ private void Compress()
|
|||
public byte[] Write()
|
||||
{
|
||||
Compress();
|
||||
using (var ms = new MemoryStream())
|
||||
using (var bw = new BinaryWriter(ms))
|
||||
{
|
||||
bw.Write(Header.ToBytesClass());
|
||||
while (bw.BaseStream.Position != Header.HeaderText.FileOffset)
|
||||
bw.Write((byte)0); // match layout for previous example
|
||||
using var ms = new MemoryStream();
|
||||
using var bw = new BinaryWriter(ms);
|
||||
bw.Write(Header.ToBytesClass());
|
||||
while (bw.BaseStream.Position != Header.HeaderText.FileOffset)
|
||||
bw.Write((byte)0); // match layout for previous example
|
||||
|
||||
// text
|
||||
Header.HeaderText.FileOffset = (int)bw.BaseStream.Position;
|
||||
bw.Write(CompressedText);
|
||||
// text
|
||||
Header.HeaderText.FileOffset = (int)bw.BaseStream.Position;
|
||||
bw.Write(CompressedText);
|
||||
|
||||
// ro
|
||||
Header.HeaderRO.FileOffset = (int)bw.BaseStream.Position;
|
||||
bw.Write(CompressedRO);
|
||||
// ro
|
||||
Header.HeaderRO.FileOffset = (int)bw.BaseStream.Position;
|
||||
bw.Write(CompressedRO);
|
||||
|
||||
// data
|
||||
Header.HeaderData.FileOffset = (int)bw.BaseStream.Position;
|
||||
bw.Write(CompressedData);
|
||||
// data
|
||||
Header.HeaderData.FileOffset = (int)bw.BaseStream.Position;
|
||||
bw.Write(CompressedData);
|
||||
|
||||
bw.BaseStream.Position = 0;
|
||||
bw.Write(Header.ToBytesClass());
|
||||
bw.BaseStream.Position = 0;
|
||||
bw.Write(Header.ToBytesClass());
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ public override byte[] GetEntry(int index, int subFile)
|
|||
|
||||
public override void Dump(string path, ContainerHandler handler)
|
||||
{
|
||||
path = path ?? FilePath;
|
||||
path ??= FilePath;
|
||||
if (path == null)
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
if (File.Exists(path))
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net46</TargetFrameworks>
|
||||
<Description>Packing & Unpacking</Description>
|
||||
<LangVersion>8</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ public class DataCache<T> : IDataEditor where T : class
|
|||
public void CancelEdits()
|
||||
{
|
||||
for (int i = 0; i < Cache.Length; i++)
|
||||
Cache[i] = default(T);
|
||||
Cache[i] = default;
|
||||
}
|
||||
|
||||
public void Initialize() { }
|
||||
|
|
|
|||
|
|
@ -2,6 +2,5 @@
|
|||
{
|
||||
public class EditorBase
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
namespace pkNX.Game
|
||||
{
|
||||
class EditorFactory
|
||||
public class EditorFactory
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ public abstract class ShinyRateInfo
|
|||
public abstract void SetFixedRate(int rerollCount);
|
||||
public abstract void SetAlwaysShiny();
|
||||
|
||||
protected bool IsPresent(byte[] source, byte[] pattern, int offset)
|
||||
protected static bool IsPresent(byte[] source, byte[] pattern, int offset)
|
||||
{
|
||||
for (int i = 0; i < pattern.Length; i++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -66,8 +66,11 @@ public void Save()
|
|||
public VsTrainer[] LoadAll()
|
||||
{
|
||||
for (int i = 0; i < Length; i++)
|
||||
{
|
||||
// ReSharper disable once AssignmentIsFullyDiscarded
|
||||
_ = this[i]; // force load cache
|
||||
}
|
||||
|
||||
return Cache;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,19 +54,19 @@ internal void SaveAll()
|
|||
|
||||
public static IReadOnlyCollection<GameFileReference> GetMapping(GameVersion game)
|
||||
{
|
||||
switch (game)
|
||||
return game switch
|
||||
{
|
||||
case GameVersion.SN: return SN;
|
||||
case GameVersion.MN: return MN;
|
||||
case GameVersion.US: return US;
|
||||
case GameVersion.UM: return UM;
|
||||
case GameVersion.XY: return XY;
|
||||
case GameVersion.GG: return GG;
|
||||
case GameVersion.ORASDEMO:
|
||||
case GameVersion.ORAS: return AO;
|
||||
case GameVersion.SMDEMO: return SMDEMO;
|
||||
}
|
||||
return null;
|
||||
GameVersion.SN => SN,
|
||||
GameVersion.MN => MN,
|
||||
GameVersion.US => US,
|
||||
GameVersion.UM => UM,
|
||||
GameVersion.XY => XY,
|
||||
GameVersion.GG => GG,
|
||||
GameVersion.ORASDEMO => AO,
|
||||
GameVersion.ORAS => AO,
|
||||
GameVersion.SMDEMO => SMDEMO,
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
#region Games
|
||||
|
|
|
|||
|
|
@ -100,13 +100,11 @@ public FolderContainer GetFilteredFolder(GameFile type, Func<string, bool> filte
|
|||
|
||||
public static GameManager GetManager(GameLocation loc, int language)
|
||||
{
|
||||
switch (loc.Game)
|
||||
return loc.Game switch
|
||||
{
|
||||
case GameVersion.GG:
|
||||
return new GameManagerGG(loc, language);
|
||||
default:
|
||||
throw new ArgumentException(nameof(loc.Game));
|
||||
}
|
||||
GameVersion.GG => new GameManagerGG(loc, language),
|
||||
_ => throw new ArgumentException(nameof(loc.Game))
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,19 +7,19 @@ public static class TextMapping
|
|||
{
|
||||
public static IReadOnlyCollection<TextReference> GetMapping(GameVersion game)
|
||||
{
|
||||
switch (game)
|
||||
return game switch
|
||||
{
|
||||
case GameVersion.XY: return XY;
|
||||
case GameVersion.ORASDEMO:
|
||||
case GameVersion.ORAS: return AO;
|
||||
case GameVersion.SMDEMO: return SMDEMO;
|
||||
case GameVersion.SN:
|
||||
case GameVersion.MN: return SM;
|
||||
case GameVersion.US:
|
||||
case GameVersion.UM: return USUM;
|
||||
case GameVersion.GG: return GG;
|
||||
}
|
||||
return null;
|
||||
GameVersion.XY => XY,
|
||||
GameVersion.ORASDEMO => AO,
|
||||
GameVersion.ORAS => AO,
|
||||
GameVersion.SMDEMO => SMDEMO,
|
||||
GameVersion.SN => SM,
|
||||
GameVersion.MN => SM,
|
||||
GameVersion.US => USUM,
|
||||
GameVersion.UM => USUM,
|
||||
GameVersion.GG => GG,
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
private static readonly TextReference[] XY =
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net46</TargetFrameworks>
|
||||
<Description>Game Data Manager</Description>
|
||||
<LangVersion>8</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using pkNX.Structures;
|
||||
|
||||
|
|
@ -41,17 +42,17 @@ public class PersonalRandSettings : RandSettings
|
|||
/// <summary>Percent chance to learn a TMHM move (0-100).</summary>
|
||||
/// <remarks>Average Learnable TMs is 35.260.</remarks>
|
||||
[Category(Moves), Description("Percentage chance to learn a given TM move.")]
|
||||
public decimal LearnTMPercent { get; set; } = 35;
|
||||
public float LearnTMPercent { get; set; } = 35;
|
||||
|
||||
/// <summary>Percent chance to learn a type tutor move (0-100).</summary>
|
||||
/// <remarks>136 special tutor moves learnable by species in Untouched ORAS.</remarks>
|
||||
[Category(Moves), Description("Percentage chance to learn a given special Type Tutor move.")]
|
||||
public decimal LearnTypeTutorPercent { get; set; } = 2;
|
||||
public float LearnTypeTutorPercent { get; set; } = 2;
|
||||
|
||||
/// <summary>Percent chance to learn a tutor move (0-100).</summary>
|
||||
/// <remarks>10001 tutor moves learnable by 826 species in Untouched ORAS.</remarks>
|
||||
[Category(Moves), Description("Percentage chance to learn a given Move Tutor move.")]
|
||||
public decimal LearnMoveTutorPercent { get; set; } = 30;
|
||||
public float LearnMoveTutorPercent { get; set; } = 30;
|
||||
#endregion
|
||||
|
||||
#region Types
|
||||
|
|
@ -65,7 +66,7 @@ public class PersonalRandSettings : RandSettings
|
|||
|
||||
/// <summary>Chance that both types are the same.</summary>
|
||||
[Category(Types), Description("Chance that both types are the same.")]
|
||||
public decimal SameTypeChance { get; set; } = 50;
|
||||
public float SameTypeChance { get; set; } = 50;
|
||||
#endregion
|
||||
|
||||
#region Ability
|
||||
|
|
@ -83,7 +84,7 @@ public class PersonalRandSettings : RandSettings
|
|||
|
||||
/// <summary>Chance that both abilities are the same.</summary>
|
||||
[Category(Abilities), Description("Chance that both abilities are the same.")]
|
||||
public decimal SameAbilityChance { get; set; } = 100;
|
||||
public float SameAbilityChance { get; set; } = 100;
|
||||
#endregion
|
||||
|
||||
#region Stats
|
||||
|
|
@ -130,7 +131,7 @@ public class PersonalRandSettings : RandSettings
|
|||
/// <summary>
|
||||
/// Flags to edit the stats when randomizing.
|
||||
/// </summary>
|
||||
public bool[] StatsToRandomize => new[] {HP, ATK, DEF, SPE, SPA, SPD};
|
||||
public IReadOnlyList<bool> StatsToRandomize => new[] {HP, ATK, DEF, SPE, SPA, SPD};
|
||||
#endregion
|
||||
|
||||
#region Misc
|
||||
|
|
@ -138,13 +139,13 @@ public class PersonalRandSettings : RandSettings
|
|||
[Category(Misc), Description("Enables a PKM's catch rate to be modified. Can inversely scale off BST.")]
|
||||
public CatchRate CatchRate { get; set; } = CatchRate.Unchanged;
|
||||
|
||||
/// <summary>Permits modification of <see cref="PersonalInfo.HeldItems"/>.</summary>
|
||||
[Category(Misc), Description("Enables a PKM's base stats to be modified.")]
|
||||
/// <summary>Permits modification of Held Items.</summary>
|
||||
[Category(Misc), Description("Enables a PKM's held items to be modified.")]
|
||||
public bool ModifyHeldItems { get; set; } = true;
|
||||
|
||||
/// <summary>Chance all held items are the same.</summary>
|
||||
[Category(Misc), Description("Percentage chance that all Held Items are the same, resulting in a 100% chance of having the held item.")]
|
||||
public decimal AlwaysHeldItemChance { get; set; } = 20;
|
||||
public float AlwaysHeldItemChance { get; set; } = 20;
|
||||
|
||||
/// <summary>Permits modification of <see cref="PersonalInfo.EggGroups"/>.</summary>
|
||||
[Category(Misc), Description("Enables a PKM's egg groups to be modified.")]
|
||||
|
|
@ -152,7 +153,7 @@ public class PersonalRandSettings : RandSettings
|
|||
|
||||
/// <summary>Chance both egg groups are the same.</summary>
|
||||
[Category(Misc), Description("Percentage chance that both egg groups will be the same.")]
|
||||
public decimal SameEggGroupChance { get; set; } = 50;
|
||||
public float SameEggGroupChance { get; set; } = 50;
|
||||
#endregion
|
||||
|
||||
#region Evolutions
|
||||
|
|
@ -166,11 +167,11 @@ public class PersonalRandSettings : RandSettings
|
|||
|
||||
/// <summary>Percentage chance that only one type will be inherited, and a new random one will replace the other.</summary>
|
||||
[Category(Evolutions), Description("Percentage chance that only one type will be inherited, and a new random one will replace the other.")]
|
||||
public decimal InheritTypeOnlyOneChance { get; set; } = 65;
|
||||
public float InheritTypeOnlyOneChance { get; set; } = 65;
|
||||
|
||||
/// <summary>Percentage chance that neither one type will be inherited, and new random ones will replace the others.</summary>
|
||||
[Category(Evolutions), Description("Percentage chance that neither type will be inherited, and new random ones will replace the others.")]
|
||||
public decimal InheritTypeNeitherChance { get; set; } = 30;
|
||||
public float InheritTypeNeitherChance { get; set; } = 30;
|
||||
|
||||
/// <summary>Toggles chance that neither one type will be inherited, and new random ones will replace the others.</summary>
|
||||
[Category(Evolutions), Description("Amount of abilities that will be inherited, and new random ones will replace the others.")]
|
||||
|
|
@ -182,11 +183,11 @@ public class PersonalRandSettings : RandSettings
|
|||
|
||||
/// <summary>Percentage chance that only one ability will be inherited, and a new random one will replace the other.</summary>
|
||||
[Category(Evolutions), Description("Percentage chance that only one ability will be inherited, and a new random one will replace the other.")]
|
||||
public decimal InheritAbilityOnlyOneChance { get; set; } = 45;
|
||||
public float InheritAbilityOnlyOneChance { get; set; } = 45;
|
||||
|
||||
/// <summary>Percentage chance that neither one ability will be inherited, and new random ones will replace the others.</summary>
|
||||
[Category(Evolutions), Description("Percentage chance that neither ability will be inherited, and new random ones will replace the others.")]
|
||||
public decimal InheritAbilityNeitherChance { get; set; } = 20;
|
||||
public float InheritAbilityNeitherChance { get; set; } = 20;
|
||||
|
||||
/// <summary>Inherit the held item values from the pre-evolution.</summary>
|
||||
[Category(Evolutions), Description("Inherit the held item values from the pre-evolution.")]
|
||||
|
|
|
|||
|
|
@ -395,7 +395,7 @@ private void RandomizeStats(PersonalInfo z)
|
|||
z.Stats = stats;
|
||||
}
|
||||
|
||||
private void RandomShuffledStats(PersonalInfo z)
|
||||
private static void RandomShuffledStats(PersonalInfo z)
|
||||
{
|
||||
// Fiddle with Base Stats, don't muck with Shedinja.
|
||||
var stats = z.Stats;
|
||||
|
|
|
|||
|
|
@ -23,8 +23,9 @@ public class LearnSettings
|
|||
|
||||
[Category(General), Description("Requires a certain percent of moves to have STAB.")]
|
||||
public bool STAB { get; set; }
|
||||
|
||||
[Category(General), Description("Required percent of moves having STAB.")]
|
||||
public decimal STABPercent { get; set; }
|
||||
public float STABPercent { get; set; }
|
||||
|
||||
[Category(Misc), Description("Reorders moves so that moves are learned with increasing power.")]
|
||||
public bool OrderByPower { get; set; } = true;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ public class MovesetRandSettings
|
|||
public int STABCount { get; set; } = 2;
|
||||
|
||||
[Category(SameType), Description("Minimum percent of STAB moves in generated learnsets.")]
|
||||
public decimal STABPercent { get; set; } = 100;
|
||||
public float STABPercent { get; set; } = 100;
|
||||
|
||||
[Category(Misc), Description("Banned move IDs.")]
|
||||
internal IList<int> BannedMoves { get; set; } = Array.Empty<int>();
|
||||
|
|
|
|||
|
|
@ -2,6 +2,5 @@ namespace pkNX.Randomization
|
|||
{
|
||||
public class RandSettings
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -90,7 +90,7 @@ public int[] GetSpecies(int maxSpecies, int generation)
|
|||
return list.Count == 0 ? GetSpeciesAll(maxSpecies) : list.ToArray();
|
||||
}
|
||||
|
||||
private int[] GetSpeciesAll(int maxSpecies) => Enumerable.Range(1, maxSpecies).ToArray();
|
||||
private static int[] GetSpeciesAll(int maxSpecies) => Enumerable.Range(1, maxSpecies).ToArray();
|
||||
|
||||
private void AddGen1Species(List<int> list, int maxSpecies)
|
||||
{
|
||||
|
|
@ -186,7 +186,7 @@ private void AddGen7Species(List<int> list, int maxSpecies)
|
|||
}
|
||||
}
|
||||
|
||||
private void AddGGEvents(List<int> list)
|
||||
private static void AddGGEvents(List<int> list)
|
||||
{
|
||||
list.AddRange(Enumerable.Range(808, Legal.MaxSpeciesID_7_GG - Legal.MaxSpeciesID_7_USUM)); // *
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ public class TrainerRandSettings
|
|||
public bool BoostLevel { get; set; } = true;
|
||||
|
||||
[Category(PKM), Description("Boosts levels of all PKM by this ratio if the " + nameof(BoostLevel) + " setting is set.")]
|
||||
public decimal LevelBoostRatio { get; set; } = 1.1m;
|
||||
public float LevelBoostRatio { get; set; } = 1.1f;
|
||||
#endregion
|
||||
|
||||
#region Stats
|
||||
|
|
@ -68,7 +68,7 @@ public class TrainerRandSettings
|
|||
public bool RandomShinies { get; set; } = true;
|
||||
|
||||
[Category(Stats), Description("Makes random Trainer PKM shiny at this rate (percent).")]
|
||||
public decimal ShinyChance { get; set; } = 2.5m;
|
||||
public float ShinyChance { get; set; } = 2.5f;
|
||||
|
||||
[Category(Stats), Description("Maximizes all IVs.")]
|
||||
public bool MaxIVs { get; set; } = true;
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ private void UpdatePKMFromSettings(TrainerPoke pk)
|
|||
RandomizeEntryMoves(pk);
|
||||
}
|
||||
|
||||
public static void BoostLevel(IPokeData pk, decimal ratio)
|
||||
public static void BoostLevel(IPokeData pk, double ratio)
|
||||
{
|
||||
pk.Level = Legal.GetModifiedLevel(pk.Level, ratio);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net46</TargetFrameworks>
|
||||
<Description>Randomizer Utility</Description>
|
||||
<LangVersion>8</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -9,27 +9,24 @@ public EggMoves6(byte[] data)
|
|||
{
|
||||
if (data.Length < 2 || data.Length % 2 != 0)
|
||||
{ Count = 0; Moves = Array.Empty<int>(); return; }
|
||||
using (BinaryReader br = new BinaryReader(new MemoryStream(data)))
|
||||
{
|
||||
Moves = new int[Count = br.ReadUInt16()];
|
||||
for (int i = 0; i < Count; i++)
|
||||
Moves[i] = br.ReadUInt16();
|
||||
}
|
||||
|
||||
using BinaryReader br = new BinaryReader(new MemoryStream(data));
|
||||
Moves = new int[Count = br.ReadUInt16()];
|
||||
for (int i = 0; i < Count; i++)
|
||||
Moves[i] = br.ReadUInt16();
|
||||
}
|
||||
|
||||
public override byte[] Write()
|
||||
{
|
||||
Count = Moves.Length;
|
||||
if (Count == 0) return Array.Empty<byte>();
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
using (BinaryWriter bw = new BinaryWriter(ms))
|
||||
{
|
||||
bw.Write((ushort)Count);
|
||||
for (int i = 0; i < Count; i++)
|
||||
bw.Write((ushort)Moves[i]);
|
||||
using MemoryStream ms = new MemoryStream();
|
||||
using BinaryWriter bw = new BinaryWriter(ms);
|
||||
bw.Write((ushort)Count);
|
||||
for (int i = 0; i < Count; i++)
|
||||
bw.Write((ushort)Moves[i]);
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,29 +9,26 @@ public EggMoves7(byte[] data)
|
|||
{
|
||||
if (data.Length < 2 || data.Length % 2 != 0)
|
||||
{ Count = 0; Moves = Array.Empty<int>(); return; }
|
||||
using (BinaryReader br = new BinaryReader(new MemoryStream(data)))
|
||||
{
|
||||
FormTableIndex = br.ReadUInt16();
|
||||
Count = br.ReadUInt16();
|
||||
Moves = new int[Count];
|
||||
for (int i = 0; i < Count; i++)
|
||||
Moves[i] = br.ReadUInt16();
|
||||
}
|
||||
|
||||
using BinaryReader br = new BinaryReader(new MemoryStream(data));
|
||||
FormTableIndex = br.ReadUInt16();
|
||||
Count = br.ReadUInt16();
|
||||
Moves = new int[Count];
|
||||
for (int i = 0; i < Count; i++)
|
||||
Moves[i] = br.ReadUInt16();
|
||||
}
|
||||
|
||||
public override byte[] Write()
|
||||
{
|
||||
Count = Moves.Length;
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
using (BinaryWriter bw = new BinaryWriter(ms))
|
||||
{
|
||||
bw.Write((ushort)FormTableIndex);
|
||||
bw.Write((ushort)Count);
|
||||
for (int i = 0; i < Count; i++)
|
||||
bw.Write((ushort)Moves[i]);
|
||||
using MemoryStream ms = new MemoryStream();
|
||||
using BinaryWriter bw = new BinaryWriter(ms);
|
||||
bw.Write((ushort)FormTableIndex);
|
||||
bw.Write((ushort)Count);
|
||||
for (int i = 0; i < Count; i++)
|
||||
bw.Write((ushort)Moves[i]);
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
using System.IO;
|
||||
using Newtonsoft.Json;
|
||||
// ReSharper disable UnusedMember.Global
|
||||
|
||||
namespace pkNX.Structures
|
||||
{
|
||||
|
|
@ -12,18 +13,16 @@ public class EncounterArchive
|
|||
public string WriteJson()
|
||||
{
|
||||
var serializer = new JsonSerializer();
|
||||
using (var stringWriter = new StringWriter())
|
||||
using var stringWriter = new StringWriter();
|
||||
using var writer = new JsonTextWriter(stringWriter)
|
||||
{
|
||||
using (var writer = new JsonTextWriter(stringWriter))
|
||||
{
|
||||
writer.QuoteName = false;
|
||||
writer.Formatting = Formatting.Indented;
|
||||
writer.IndentChar = ' ';
|
||||
writer.Indentation = 2;
|
||||
serializer.Serialize(writer, this);
|
||||
}
|
||||
return stringWriter.ToString();
|
||||
}
|
||||
QuoteName = false,
|
||||
Formatting = Formatting.Indented,
|
||||
IndentChar = ' ',
|
||||
Indentation = 2
|
||||
};
|
||||
serializer.Serialize(writer, this);
|
||||
return stringWriter.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,17 +40,15 @@ private static EvolutionMethod GetEvo(byte[] data, int offset)
|
|||
|
||||
public override byte[] Write()
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
using (BinaryWriter bw = new BinaryWriter(ms))
|
||||
using MemoryStream ms = new MemoryStream();
|
||||
using BinaryWriter bw = new BinaryWriter(ms);
|
||||
foreach (EvolutionMethod evo in PossibleEvolutions)
|
||||
{
|
||||
foreach (EvolutionMethod evo in PossibleEvolutions)
|
||||
{
|
||||
bw.Write((ushort)evo.Method);
|
||||
bw.Write((ushort)evo.Argument);
|
||||
bw.Write((ushort)evo.Species);
|
||||
}
|
||||
return ms.ToArray();
|
||||
bw.Write((ushort)evo.Method);
|
||||
bw.Write((ushort)evo.Argument);
|
||||
bw.Write((ushort)evo.Species);
|
||||
}
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -30,19 +30,17 @@ private static EvolutionMethod GetEvo(byte[] data, int offset)
|
|||
|
||||
public override byte[] Write()
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
using (BinaryWriter bw = new BinaryWriter(ms))
|
||||
using MemoryStream ms = new MemoryStream();
|
||||
using BinaryWriter bw = new BinaryWriter(ms);
|
||||
foreach (EvolutionMethod evo in PossibleEvolutions)
|
||||
{
|
||||
foreach (EvolutionMethod evo in PossibleEvolutions)
|
||||
{
|
||||
bw.Write((ushort)evo.Method);
|
||||
bw.Write((ushort)evo.Argument);
|
||||
bw.Write((ushort)evo.Species);
|
||||
bw.Write((sbyte)evo.Form);
|
||||
bw.Write((byte)evo.Level);
|
||||
}
|
||||
return ms.ToArray();
|
||||
bw.Write((ushort)evo.Method);
|
||||
bw.Write((ushort)evo.Argument);
|
||||
bw.Write((ushort)evo.Species);
|
||||
bw.Write((sbyte)evo.Form);
|
||||
bw.Write((byte)evo.Level);
|
||||
}
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,13 +20,11 @@ public SeedPokeTable(byte[] data)
|
|||
|
||||
public byte[] Write()
|
||||
{
|
||||
using (var ms = new MemoryStream())
|
||||
using (var bw = new BinaryWriter(ms))
|
||||
{
|
||||
foreach (var seed in Table)
|
||||
bw.Write(seed);
|
||||
return ms.ToArray();
|
||||
}
|
||||
using var ms = new MemoryStream();
|
||||
using var bw = new BinaryWriter(ms);
|
||||
foreach (var seed in Table)
|
||||
bw.Write(seed);
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
public IEnumerable<string> Dump(string[] specNames)
|
||||
|
|
|
|||
|
|
@ -25,17 +25,15 @@ public ZukanEvolutionTable(byte[] data)
|
|||
|
||||
public byte[] Write()
|
||||
{
|
||||
using (var ms = new MemoryStream())
|
||||
using (var bw = new BinaryWriter(ms))
|
||||
using var ms = new MemoryStream();
|
||||
using var bw = new BinaryWriter(ms);
|
||||
foreach (var t in Table)
|
||||
{
|
||||
foreach (var t in Table)
|
||||
{
|
||||
foreach (var e in t)
|
||||
bw.Write(e);
|
||||
bw.Write(t.Count(x => x != 0));
|
||||
}
|
||||
return ms.ToArray();
|
||||
foreach (var e in t)
|
||||
bw.Write(e);
|
||||
bw.Write(t.Count(x => x != 0));
|
||||
}
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,79 +26,53 @@ public static class GameUtil
|
|||
/// <returns>Version Group Identifier or Invalid if type cannot be determined.</returns>
|
||||
public static GameVersion GetMetLocationVersionGroup(GameVersion Version)
|
||||
{
|
||||
switch (Version)
|
||||
return Version switch
|
||||
{
|
||||
// Sidegame
|
||||
case CXD:
|
||||
return CXD;
|
||||
case GO:
|
||||
return GO;
|
||||
|
||||
CXD => CXD,
|
||||
GO => GO,
|
||||
// Gen1
|
||||
case RBY:
|
||||
case RD:
|
||||
case BU:
|
||||
case YW:
|
||||
case GN:
|
||||
return RBY;
|
||||
|
||||
RBY => RBY,
|
||||
RD => RBY,
|
||||
BU => RBY,
|
||||
YW => RBY,
|
||||
GN => RBY,
|
||||
// Gen2
|
||||
case GS:
|
||||
case GD:
|
||||
case SV:
|
||||
case C:
|
||||
return GSC;
|
||||
|
||||
GS => GSC,
|
||||
GD => GSC,
|
||||
SV => GSC,
|
||||
C => GSC,
|
||||
// Gen3
|
||||
case R:
|
||||
case S:
|
||||
return RS;
|
||||
case E:
|
||||
return E;
|
||||
case FR:
|
||||
case LG:
|
||||
return FR;
|
||||
|
||||
R => RS,
|
||||
S => RS,
|
||||
E => E,
|
||||
FR => FR,
|
||||
LG => FR,
|
||||
// Gen4
|
||||
case D:
|
||||
case P:
|
||||
return DP;
|
||||
case Pt:
|
||||
return Pt;
|
||||
case HG:
|
||||
case SS:
|
||||
return HGSS;
|
||||
|
||||
D => DP,
|
||||
P => DP,
|
||||
Pt => Pt,
|
||||
HG => HGSS,
|
||||
SS => HGSS,
|
||||
// Gen5
|
||||
case B:
|
||||
case W:
|
||||
return BW;
|
||||
case B2:
|
||||
case W2:
|
||||
return B2W2;
|
||||
|
||||
B => BW,
|
||||
W => BW,
|
||||
B2 => B2W2,
|
||||
W2 => B2W2,
|
||||
// Gen6
|
||||
case X:
|
||||
case Y:
|
||||
return XY;
|
||||
case OR:
|
||||
case AS:
|
||||
return ORAS;
|
||||
|
||||
X => XY,
|
||||
Y => XY,
|
||||
OR => ORAS,
|
||||
AS => ORAS,
|
||||
// Gen7
|
||||
case SN:
|
||||
case MN:
|
||||
return SM;
|
||||
case US:
|
||||
case UM:
|
||||
return USUM;
|
||||
case GP:
|
||||
case GE:
|
||||
return GG;
|
||||
|
||||
default:
|
||||
return Invalid;
|
||||
}
|
||||
SN => SM,
|
||||
MN => SM,
|
||||
US => USUM,
|
||||
UM => USUM,
|
||||
GP => GG,
|
||||
GE => GG,
|
||||
_ => Invalid
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -108,18 +82,17 @@ public static GameVersion GetMetLocationVersionGroup(GameVersion Version)
|
|||
/// <returns>Version ID from requested generation. If none, return <see cref="Invalid"/>.</returns>
|
||||
public static GameVersion GetVersion(int generation)
|
||||
{
|
||||
switch (generation)
|
||||
return generation switch
|
||||
{
|
||||
case 1: return RBY;
|
||||
case 2: return C;
|
||||
case 3: return E;
|
||||
case 4: return SS;
|
||||
case 5: return W2;
|
||||
case 6: return AS;
|
||||
case 7: return UM;
|
||||
default:
|
||||
return Invalid;
|
||||
}
|
||||
1 => RBY,
|
||||
2 => C,
|
||||
3 => E,
|
||||
4 => SS,
|
||||
5 => W2,
|
||||
6 => AS,
|
||||
7 => UM,
|
||||
_ => Invalid
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -180,68 +153,45 @@ public static bool Contains(this GameVersion g1, GameVersion g2)
|
|||
if (g1 == g2 || g1 == Any)
|
||||
return true;
|
||||
|
||||
switch (g1)
|
||||
return g1 switch
|
||||
{
|
||||
case RB:
|
||||
return g2 == RD || g2 == BU || g2 == GN;
|
||||
case Stadium:
|
||||
case EventsGBGen1:
|
||||
case VCEvents:
|
||||
case RBY:
|
||||
return RB.Contains(g2) || g2 == YW;
|
||||
case Gen1:
|
||||
return RBY.Contains(g2) || g2 == Stadium || g2 == EventsGBGen1 || g2 == VCEvents;
|
||||
|
||||
case GS: return g2 == GD || g2 == SV;
|
||||
case Stadium2:
|
||||
case EventsGBGen2:
|
||||
case GSC:
|
||||
return GS.Contains(g2) || g2 == C;
|
||||
case Gen2:
|
||||
return GSC.Contains(g2) || g2 == Stadium2 || g2 == EventsGBGen2;
|
||||
case GBCartEraOnly:
|
||||
return g2 == Stadium || g2 == Stadium2 || g2 == EventsGBGen1 || g2 == EventsGBGen2;
|
||||
|
||||
case RS: return g2 == R || g2 == S;
|
||||
case RSE:
|
||||
return RS.Contains(g2) || g2 == E;
|
||||
case FRLG: return g2 == FR || g2 == LG;
|
||||
case COLO:
|
||||
case XD: return g2 == CXD;
|
||||
case CXD: return g2 == COLO || g2 == XD;
|
||||
case RSBOX: return RS.Contains(g2) || g2 == E || FRLG.Contains(g2);
|
||||
case Gen3:
|
||||
return RSE.Contains(g2) || FRLG.Contains(g2) || CXD.Contains(g2) || g2 == RSBOX;
|
||||
|
||||
case DP: return g2 == D || g2 == P;
|
||||
case HGSS: return g2 == HG || g2 == SS;
|
||||
case DPPt:
|
||||
return DP.Contains(g2) || g2 == Pt;
|
||||
case BATREV: return DP.Contains(g2) || g2 == Pt || HGSS.Contains(g2);
|
||||
case Gen4:
|
||||
return DPPt.Contains(g2) || HGSS.Contains(g2) || g2 == BATREV;
|
||||
|
||||
case BW: return g2 == B || g2 == W;
|
||||
case B2W2: return g2 == B2 || g2 == W2;
|
||||
case Gen5:
|
||||
return BW.Contains(g2) || B2W2.Contains(g2);
|
||||
|
||||
case XY: return g2 == X || g2 == Y;
|
||||
case ORAS: return g2 == OR || g2 == AS;
|
||||
case Gen6:
|
||||
return XY.Contains(g2) || ORAS.Contains(g2);
|
||||
|
||||
case SM:
|
||||
return g2 == SN || g2 == MN;
|
||||
case USUM:
|
||||
return g2 == US || g2 == UM;
|
||||
case GG:
|
||||
return g2 == GP || g2 == GE;
|
||||
case Gen7:
|
||||
return SM.Contains(g2) || USUM.Contains(g2) || GG.Contains(g2);
|
||||
|
||||
default: return false;
|
||||
}
|
||||
RB => (g2 == RD || g2 == BU || g2 == GN),
|
||||
Stadium => (RB.Contains(g2) || g2 == YW),
|
||||
EventsGBGen1 => (RB.Contains(g2) || g2 == YW),
|
||||
VCEvents => (RB.Contains(g2) || g2 == YW),
|
||||
RBY => (RB.Contains(g2) || g2 == YW),
|
||||
Gen1 => (RBY.Contains(g2) || g2 == Stadium || g2 == EventsGBGen1 || g2 == VCEvents),
|
||||
GS => (g2 == GD || g2 == SV),
|
||||
Stadium2 => (GS.Contains(g2) || g2 == C),
|
||||
EventsGBGen2 => (GS.Contains(g2) || g2 == C),
|
||||
GSC => (GS.Contains(g2) || g2 == C),
|
||||
Gen2 => (GSC.Contains(g2) || g2 == Stadium2 || g2 == EventsGBGen2),
|
||||
GBCartEraOnly => (g2 == Stadium || g2 == Stadium2 || g2 == EventsGBGen1 || g2 == EventsGBGen2),
|
||||
RS => (g2 == R || g2 == S),
|
||||
RSE => (RS.Contains(g2) || g2 == E),
|
||||
FRLG => (g2 == FR || g2 == LG),
|
||||
COLO => (g2 == CXD),
|
||||
XD => (g2 == CXD),
|
||||
CXD => (g2 == COLO || g2 == XD),
|
||||
RSBOX => (RS.Contains(g2) || g2 == E || FRLG.Contains(g2)),
|
||||
Gen3 => (RSE.Contains(g2) || FRLG.Contains(g2) || CXD.Contains(g2) || g2 == RSBOX),
|
||||
DP => (g2 == D || g2 == P),
|
||||
HGSS => (g2 == HG || g2 == SS),
|
||||
DPPt => (DP.Contains(g2) || g2 == Pt),
|
||||
BATREV => (DP.Contains(g2) || g2 == Pt || HGSS.Contains(g2)),
|
||||
Gen4 => (DPPt.Contains(g2) || HGSS.Contains(g2) || g2 == BATREV),
|
||||
BW => (g2 == B || g2 == W),
|
||||
B2W2 => (g2 == B2 || g2 == W2),
|
||||
Gen5 => (BW.Contains(g2) || B2W2.Contains(g2)),
|
||||
XY => (g2 == X || g2 == Y),
|
||||
ORAS => (g2 == OR || g2 == AS),
|
||||
Gen6 => (XY.Contains(g2) || ORAS.Contains(g2)),
|
||||
SM => (g2 == SN || g2 == MN),
|
||||
USUM => (g2 == US || g2 == UM),
|
||||
GG => (g2 == GP || g2 == GE),
|
||||
Gen7 => (SM.Contains(g2) || USUM.Contains(g2) || GG.Contains(g2)),
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -192,6 +192,16 @@ public enum GameVersion
|
|||
/// Pokémon Let's Go Eevee (NX)
|
||||
/// </summary>
|
||||
GE = 43,
|
||||
|
||||
/// <summary>
|
||||
/// Pokémon Sword (NX)
|
||||
/// </summary>
|
||||
SW = 44,
|
||||
|
||||
/// <summary>
|
||||
/// Pokémon Shield (NX)
|
||||
/// </summary>
|
||||
SH = 45,
|
||||
#endregion
|
||||
|
||||
// The following values are not actually stored values in pkm data,
|
||||
|
|
@ -369,6 +379,14 @@ public enum GameVersion
|
|||
/// <see cref="GE"/>
|
||||
GG,
|
||||
|
||||
/// <summary>
|
||||
/// Pokémon Sword & Shield
|
||||
/// </summary>
|
||||
/// <remarks>Used to lump data from the associated games as data assets are shared.</remarks>
|
||||
/// <see cref="SW"/>
|
||||
/// <see cref="SH"/>
|
||||
SWSH,
|
||||
|
||||
/// <summary>
|
||||
/// Generation 1 Games
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -12,31 +12,27 @@ public Learnset6(byte[] data)
|
|||
Count = (data.Length / 4) - 1;
|
||||
Moves = new int[Count];
|
||||
Levels = new int[Count];
|
||||
using (var ms = new MemoryStream(data))
|
||||
using (var br = new BinaryReader(ms))
|
||||
using var ms = new MemoryStream(data);
|
||||
using var br = new BinaryReader(ms);
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
Moves[i] = br.ReadInt16();
|
||||
Levels[i] = br.ReadInt16();
|
||||
}
|
||||
Moves[i] = br.ReadInt16();
|
||||
Levels[i] = br.ReadInt16();
|
||||
}
|
||||
}
|
||||
|
||||
public override byte[] Write()
|
||||
{
|
||||
Count = (ushort)Moves.Length;
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
using (BinaryWriter bw = new BinaryWriter(ms))
|
||||
using MemoryStream ms = new MemoryStream();
|
||||
using BinaryWriter bw = new BinaryWriter(ms);
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
bw.Write((short)Moves[i]);
|
||||
bw.Write((short)Levels[i]);
|
||||
}
|
||||
bw.Write(-1);
|
||||
return ms.ToArray();
|
||||
bw.Write((short)Moves[i]);
|
||||
bw.Write((short)Levels[i]);
|
||||
}
|
||||
bw.Write(-1);
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
public static Learnset[] GetArray(byte[][] entries)
|
||||
|
|
|
|||
|
|
@ -31,18 +31,17 @@ public GameInfo(GameVersion game)
|
|||
|
||||
private Action GetInitMethod(GameVersion game)
|
||||
{
|
||||
switch (game)
|
||||
return game switch
|
||||
{
|
||||
case GameVersion.XY: return LoadXY;
|
||||
case GameVersion.ORASDEMO:
|
||||
case GameVersion.ORAS: return LoadAO;
|
||||
case GameVersion.SMDEMO:
|
||||
case GameVersion.SM: return LoadSM;
|
||||
case GameVersion.USUM: return LoadUSUM;
|
||||
case GameVersion.GG: return LoadGG;
|
||||
default:
|
||||
throw new ArgumentException(nameof(game));
|
||||
}
|
||||
GameVersion.XY => (Action) LoadXY,
|
||||
GameVersion.ORASDEMO => LoadAO,
|
||||
GameVersion.ORAS => LoadAO,
|
||||
GameVersion.SMDEMO => LoadSM,
|
||||
GameVersion.SM => LoadSM,
|
||||
GameVersion.USUM => LoadUSUM,
|
||||
GameVersion.GG => LoadGG,
|
||||
_ => throw new ArgumentException(nameof(game))
|
||||
};
|
||||
}
|
||||
|
||||
private void LoadXY()
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ public static int GetRandomForme(int species, bool mega, bool alola, PersonalTab
|
|||
/// <param name="level">Current Level.</param>
|
||||
/// <param name="factor">Modification factor.</param>
|
||||
/// <returns>Boosted (or reduced) level.</returns>
|
||||
public static int GetModifiedLevel(int level, decimal factor)
|
||||
public static int GetModifiedLevel(int level, double factor)
|
||||
{
|
||||
int newlvl = (int)(level * factor);
|
||||
if (newlvl < 1)
|
||||
|
|
|
|||
|
|
@ -24,15 +24,13 @@ public Trainer(byte[] data)
|
|||
|
||||
public byte[] Write()
|
||||
{
|
||||
using (var ms = new MemoryStream())
|
||||
using (var bw = new BinaryWriter(ms))
|
||||
{
|
||||
bw.Write(Class);
|
||||
bw.Write(Count);
|
||||
foreach (ushort Choice in Choices)
|
||||
bw.Write(Choice);
|
||||
return ms.ToArray();
|
||||
}
|
||||
using var ms = new MemoryStream();
|
||||
using var bw = new BinaryWriter(ms);
|
||||
bw.Write(Class);
|
||||
bw.Write(Count);
|
||||
foreach (ushort Choice in Choices)
|
||||
bw.Write(Choice);
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -72,23 +70,21 @@ public Pokemon(byte[] data)
|
|||
|
||||
public byte[] Write()
|
||||
{
|
||||
using (var ms = new MemoryStream())
|
||||
using (var bw = new BinaryWriter(ms))
|
||||
{
|
||||
bw.Write(Species);
|
||||
foreach (ushort Move in Moves)
|
||||
bw.Write(Move);
|
||||
using var ms = new MemoryStream();
|
||||
using var bw = new BinaryWriter(ms);
|
||||
bw.Write(Species);
|
||||
foreach (ushort Move in Moves)
|
||||
bw.Write(Move);
|
||||
|
||||
int ev = EV & 0xC0;
|
||||
for (int i = 0; i < EVs.Length; i++)
|
||||
ev |= EVs[i] ? 1 << i : 0;
|
||||
bw.Write((byte)ev);
|
||||
int ev = EV & 0xC0;
|
||||
for (int i = 0; i < EVs.Length; i++)
|
||||
ev |= EVs[i] ? 1 << i : 0;
|
||||
bw.Write((byte)ev);
|
||||
|
||||
bw.Write(Nature);
|
||||
bw.Write(Item);
|
||||
bw.Write(Form);
|
||||
return ms.ToArray();
|
||||
}
|
||||
bw.Write(Nature);
|
||||
bw.Write(Item);
|
||||
bw.Write(Form);
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ public static MegaEvolutionSet[] ReadArray(byte[] data)
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static byte[] WriteArray(MegaEvolutionSet[] data)
|
||||
{
|
||||
return data.SelectMany(z => z.Write()).ToArray();
|
||||
|
|
|
|||
|
|
@ -28,12 +28,10 @@ public class Entry
|
|||
|
||||
public CaptureRewardTable(byte[] data)
|
||||
{
|
||||
using (var ms = new MemoryStream(data))
|
||||
using (var br = new BinaryReader(ms))
|
||||
{
|
||||
ReadHeader(br);
|
||||
ReadEntries(br);
|
||||
}
|
||||
using var ms = new MemoryStream(data);
|
||||
using var br = new BinaryReader(ms);
|
||||
ReadHeader(br);
|
||||
ReadEntries(br);
|
||||
}
|
||||
|
||||
private void ReadEntries(BinaryReader br)
|
||||
|
|
@ -81,25 +79,23 @@ private void ReadHeader(BinaryReader br)
|
|||
|
||||
public byte[] Write()
|
||||
{
|
||||
using (var ms = new MemoryStream())
|
||||
using (var bw = new BinaryWriter(ms))
|
||||
using var ms = new MemoryStream();
|
||||
using var bw = new BinaryWriter(ms);
|
||||
foreach (var g in Table)
|
||||
{
|
||||
foreach (var g in Table)
|
||||
{
|
||||
bw.Write(g.CaptureCount);
|
||||
bw.Write(g.Entries.Count); // instead of using the read value, use the list count (allow modification)
|
||||
}
|
||||
foreach (var g in Table)
|
||||
{
|
||||
foreach (var e in g.Entries)
|
||||
{
|
||||
bw.Write(e.Item);
|
||||
bw.Write(e.Count);
|
||||
bw.Write(e.Rate);
|
||||
}
|
||||
}
|
||||
return ms.ToArray();
|
||||
bw.Write(g.CaptureCount);
|
||||
bw.Write(g.Entries.Count); // instead of using the read value, use the list count (allow modification)
|
||||
}
|
||||
foreach (var g in Table)
|
||||
{
|
||||
foreach (var e in g.Entries)
|
||||
{
|
||||
bw.Write(e.Item);
|
||||
bw.Write(e.Count);
|
||||
bw.Write(e.Rate);
|
||||
}
|
||||
}
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
public IEnumerable<string> Dump(string[] itemNames)
|
||||
|
|
|
|||
|
|
@ -37,4 +37,21 @@ public override byte[] Write()
|
|||
public int SpecialZ_ZMove { get => BitConverter.ToUInt16(Data, 0x50); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x50); }
|
||||
public bool LocalVariant { get => Data[0x52] == 1; set => Data[0x52] = (byte)(value ? 1 : 0); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="PersonalInfo"/> class with values from the <see cref="GameVersion.SWSH"/> games.
|
||||
/// </summary>
|
||||
public sealed class PersonalInfoSWSH : PersonalInfoSM
|
||||
{
|
||||
public new const int SIZE = PersonalInfoSM.SIZE;
|
||||
|
||||
// todo: this is a copy of lgpe class
|
||||
public PersonalInfoSWSH(byte[] data) : base(data)
|
||||
{
|
||||
TMHM = GetBits(Data, 0x28, 8); // only 60 TMs used
|
||||
TypeTutors = GetBits(Data, 0x38, 1); // at most 8 flags used
|
||||
}
|
||||
|
||||
public int GoSpecies { get => BitConverter.ToUInt16(Data, 0x48); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x48); }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,10 +34,13 @@ private static byte[][] SplitBytes(byte[] data, int size)
|
|||
return z => new PersonalInfoXY(z);
|
||||
case GameVersion.ORAS:
|
||||
return z => new PersonalInfoORAS(z);
|
||||
case GameVersion.SM:
|
||||
case GameVersion.USUM:
|
||||
return z => new PersonalInfoSM(z);
|
||||
case GameVersion.GG:
|
||||
return z => new PersonalInfoGG(z);
|
||||
default:
|
||||
return z => new PersonalInfoSM(z);
|
||||
return z => new PersonalInfoSWSH(z);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -52,6 +55,7 @@ private static int GetEntrySize(GameVersion format)
|
|||
case GameVersion.SM:
|
||||
case GameVersion.USUM:
|
||||
case GameVersion.GG: return PersonalInfoSM.SIZE;
|
||||
case GameVersion.SWSH: return PersonalInfoSWSH.SIZE; // todo
|
||||
|
||||
default: return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ namespace pkNX.Structures
|
|||
/// </summary>
|
||||
/// <remarks>https://github.com/compuphase/pawn</remarks>
|
||||
public class Amx
|
||||
{
|
||||
private const int MAX_NAME_LENGTH = 31;
|
||||
{
|
||||
private const int MAX_NAME_LENGTH = 31;
|
||||
|
||||
public readonly byte[] Data;
|
||||
public readonly AmxHeader Header;
|
||||
|
|
@ -32,19 +32,11 @@ public Amx(byte[] data)
|
|||
|
||||
Unpack();
|
||||
|
||||
Assert(Header != null);
|
||||
Assert(Header.Magic != 0);
|
||||
Assert(Header.Natives <= Header.Libraries);
|
||||
Trace.Assert(Header != null);
|
||||
Trace.Assert(Header.Magic != 0);
|
||||
Trace.Assert(Header.Natives <= Header.Libraries);
|
||||
}
|
||||
|
||||
private void Assert( bool condition )
|
||||
{
|
||||
if ( !condition )
|
||||
{
|
||||
throw new Exception("Assertion failed");
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] Write() => Data;
|
||||
public bool IsDebug => Header.Flags.HasFlagFast(AmxFlags.DEBUG);
|
||||
|
||||
|
|
@ -72,8 +64,8 @@ public IEnumerable<string> SummaryLines
|
|||
yield return $"Reserved Size: 0x{Header.StackTop:X4}";
|
||||
yield return $"Compressed Len: 0x{CompressedLength:X4}";
|
||||
yield return $"Decompressed Len: 0x{DecompressedLength:X4}";
|
||||
yield return $"Entry Point: 0x{Header.CurrentInstructionPointer:X4}";
|
||||
yield return $"Compression Ratio: {(DecompressedLength - CompressedLength) / (decimal) DecompressedLength:p1}";
|
||||
yield return $"Entry Point: 0x{Header.CurrentInstructionPointer:X4}";
|
||||
yield return $"Compression Ratio: {(DecompressedLength - CompressedLength) / (decimal)DecompressedLength:p1}";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -81,35 +73,35 @@ public IEnumerable<string> SummaryLines
|
|||
public TableRecord LookupPublic(string name) => Array.Find(this.Publics, t => t.Name == name);
|
||||
public TableRecord LookupPublic(uint addr) => Array.Find(this.Publics, t => t.Address == addr);
|
||||
|
||||
public Function[] Functions { get; protected set; }
|
||||
public TableRecord[] Publics { get; protected set; }
|
||||
public TableRecord[] Natives { get; protected set; }
|
||||
public TableRecord[] Libraries { get; protected set; }
|
||||
public TableRecord[] PublicVars { get; protected set; }
|
||||
public Variable[] Globals { get; protected set; }
|
||||
public Function[] Functions { get; protected set; }
|
||||
public TableRecord[] Publics { get; protected set; }
|
||||
public TableRecord[] Natives { get; protected set; }
|
||||
public TableRecord[] Libraries { get; protected set; }
|
||||
public TableRecord[] PublicVars { get; protected set; }
|
||||
public Variable[] Globals { get; protected set; }
|
||||
|
||||
public string ReadName(byte[] data, int offset)
|
||||
{
|
||||
var end = Array.FindIndex(data, offset, z => z == 0);
|
||||
if ( end < 0 )
|
||||
end = offset + MAX_NAME_LENGTH;
|
||||
if ( end >= data.Length )
|
||||
return null;
|
||||
if (end < 0)
|
||||
end = offset + MAX_NAME_LENGTH;
|
||||
if (end >= data.Length)
|
||||
return null;
|
||||
return System.Text.Encoding.UTF8.GetString(data, offset, end - offset);
|
||||
}
|
||||
|
||||
public void Unpack()
|
||||
{
|
||||
if (Header.Publics > 0)
|
||||
ReadPublics();
|
||||
if (Header.Natives > 0)
|
||||
ReadNatives();
|
||||
if (Header.Libraries > 0)
|
||||
ReadLibraries();
|
||||
if (Header.PublicVars > 0)
|
||||
ReadPublicVars();
|
||||
ReadPublics();
|
||||
if (Header.Natives > 0)
|
||||
ReadNatives();
|
||||
if (Header.Libraries > 0)
|
||||
ReadLibraries();
|
||||
if (Header.PublicVars > 0)
|
||||
ReadPublicVars();
|
||||
|
||||
if (IsDebug)
|
||||
if (IsDebug)
|
||||
{
|
||||
// todo
|
||||
}
|
||||
|
|
@ -117,284 +109,281 @@ public void Unpack()
|
|||
|
||||
public class Cell
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected void ReadPublics()
|
||||
{
|
||||
var count = (Header.Natives - Header.Publics) / Header.DefinitionSize;
|
||||
protected void ReadPublics()
|
||||
{
|
||||
var count = (Header.Natives - Header.Publics) / Header.DefinitionSize;
|
||||
|
||||
Publics = ReadTable( Header.Publics, count );
|
||||
}
|
||||
Publics = ReadTable(Header.Publics, count);
|
||||
}
|
||||
|
||||
protected void ReadNatives()
|
||||
{
|
||||
var count = (Header.Libraries - Header.Natives) / Header.DefinitionSize;
|
||||
protected void ReadNatives()
|
||||
{
|
||||
var count = (Header.Libraries - Header.Natives) / Header.DefinitionSize;
|
||||
|
||||
Natives = ReadTable( Header.Natives, count );
|
||||
}
|
||||
Natives = ReadTable(Header.Natives, count);
|
||||
}
|
||||
|
||||
protected void ReadLibraries()
|
||||
{
|
||||
var count = (Header.PublicVars - Header.Libraries) / Header.DefinitionSize;
|
||||
protected void ReadLibraries()
|
||||
{
|
||||
var count = (Header.PublicVars - Header.Libraries) / Header.DefinitionSize;
|
||||
|
||||
Libraries = ReadTable( Header.Libraries, count );
|
||||
}
|
||||
Libraries = ReadTable(Header.Libraries, count);
|
||||
}
|
||||
|
||||
protected void ReadPublicVars()
|
||||
{
|
||||
var count = (Header.Tags - Header.PublicVars) / Header.DefinitionSize;
|
||||
protected void ReadPublicVars()
|
||||
{
|
||||
var count = (Header.Tags - Header.PublicVars) / Header.DefinitionSize;
|
||||
|
||||
PublicVars = ReadTable( Header.PublicVars, count );
|
||||
}
|
||||
PublicVars = ReadTable(Header.PublicVars, count);
|
||||
}
|
||||
|
||||
protected TableRecord[] ReadTable( int offset, int count )
|
||||
{
|
||||
using ( var stream = new MemoryStream( Data, offset, count * Header.DefinitionSize ) )
|
||||
using ( var reader = new BinaryReader( stream ) )
|
||||
{
|
||||
var dest = new TableRecord[ count ];
|
||||
protected TableRecord[] ReadTable(int offset, int count)
|
||||
{
|
||||
using var stream = new MemoryStream(Data, offset, count * Header.DefinitionSize);
|
||||
using var reader = new BinaryReader(stream);
|
||||
var dest = new TableRecord[count];
|
||||
|
||||
for ( int i = 0; i < dest.Length; i++ )
|
||||
{
|
||||
var address = reader.ReadUInt32();
|
||||
var nameoffset = reader.ReadUInt32();
|
||||
var name = default( string );
|
||||
|
||||
if ( nameoffset < Data.Length )
|
||||
name = ReadName( Data, (int) nameoffset );
|
||||
for (int i = 0; i < dest.Length; i++)
|
||||
{
|
||||
var address = reader.ReadUInt32();
|
||||
var nameoffset = reader.ReadUInt32();
|
||||
var name = default(string);
|
||||
|
||||
name = name ?? "Unknown";
|
||||
dest[ i ] = new TableRecord( name, address );
|
||||
}
|
||||
if (nameoffset < Data.Length)
|
||||
name = ReadName(Data, (int)nameoffset);
|
||||
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
name ??= "Unknown";
|
||||
dest[i] = new TableRecord(name, address);
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
private int sysreq_flg;
|
||||
|
||||
public void ParseOp(AmxOpCode op, ref int cip, ref Cell tgt)
|
||||
{
|
||||
void GETPARAM_P( Cell v, AmxOpCode o ) { } // (v = ((Cell) (o) >> (int) (CellSize * 4)));}
|
||||
switch ( op )
|
||||
{
|
||||
case AmxOpCode.CONST:
|
||||
case AmxOpCode.CONST_S:
|
||||
cip += CellSize * 2;
|
||||
break;
|
||||
void GETPARAM_P(Cell v, AmxOpCode o) { } // (v = ((Cell) (o) >> (int) (CellSize * 4)));}
|
||||
switch (op)
|
||||
{
|
||||
case AmxOpCode.CONST:
|
||||
case AmxOpCode.CONST_S:
|
||||
cip += CellSize * 2;
|
||||
break;
|
||||
|
||||
/* Packed Instructions */
|
||||
case AmxOpCode.CONST_P_PRI:
|
||||
case AmxOpCode.CONST_P_ALT:
|
||||
case AmxOpCode.ADDR_P_PRI:
|
||||
case AmxOpCode.ADDR_P_ALT:
|
||||
case AmxOpCode.STRB_P_I:
|
||||
case AmxOpCode.LIDX_P_B:
|
||||
case AmxOpCode.IDXADDR_P_B:
|
||||
case AmxOpCode.ALIGN_P_PRI:
|
||||
case AmxOpCode.PUSH_P_C:
|
||||
case AmxOpCode.PUSH_P:
|
||||
case AmxOpCode.PUSH_P_S:
|
||||
case AmxOpCode.STACK_P:
|
||||
case AmxOpCode.HEAP_P:
|
||||
case AmxOpCode.SHL_P_C_PRI:
|
||||
case AmxOpCode.SHL_P_C_ALT:
|
||||
case AmxOpCode.ADD_P_C:
|
||||
case AmxOpCode.SMUL_P_C:
|
||||
case AmxOpCode.ZERO_P:
|
||||
case AmxOpCode.ZERO_P_S:
|
||||
case AmxOpCode.EQ_P_C_PRI:
|
||||
case AmxOpCode.EQ_P_C_ALT:
|
||||
case AmxOpCode.MOVS_P:
|
||||
case AmxOpCode.CMPS_P:
|
||||
case AmxOpCode.FILL_P:
|
||||
case AmxOpCode.HALT_P:
|
||||
case AmxOpCode.BOUNDS_P:
|
||||
case AmxOpCode.PUSH_P_ADR:
|
||||
break;
|
||||
/* Packed Instructions */
|
||||
case AmxOpCode.CONST_P_PRI:
|
||||
case AmxOpCode.CONST_P_ALT:
|
||||
case AmxOpCode.ADDR_P_PRI:
|
||||
case AmxOpCode.ADDR_P_ALT:
|
||||
case AmxOpCode.STRB_P_I:
|
||||
case AmxOpCode.LIDX_P_B:
|
||||
case AmxOpCode.IDXADDR_P_B:
|
||||
case AmxOpCode.ALIGN_P_PRI:
|
||||
case AmxOpCode.PUSH_P_C:
|
||||
case AmxOpCode.PUSH_P:
|
||||
case AmxOpCode.PUSH_P_S:
|
||||
case AmxOpCode.STACK_P:
|
||||
case AmxOpCode.HEAP_P:
|
||||
case AmxOpCode.SHL_P_C_PRI:
|
||||
case AmxOpCode.SHL_P_C_ALT:
|
||||
case AmxOpCode.ADD_P_C:
|
||||
case AmxOpCode.SMUL_P_C:
|
||||
case AmxOpCode.ZERO_P:
|
||||
case AmxOpCode.ZERO_P_S:
|
||||
case AmxOpCode.EQ_P_C_PRI:
|
||||
case AmxOpCode.EQ_P_C_ALT:
|
||||
case AmxOpCode.MOVS_P:
|
||||
case AmxOpCode.CMPS_P:
|
||||
case AmxOpCode.FILL_P:
|
||||
case AmxOpCode.HALT_P:
|
||||
case AmxOpCode.BOUNDS_P:
|
||||
case AmxOpCode.PUSH_P_ADR:
|
||||
break;
|
||||
|
||||
/* Packed Instructions referencing pointers */
|
||||
case AmxOpCode.LOAD_P_PRI:
|
||||
case AmxOpCode.LOAD_P_ALT:
|
||||
case AmxOpCode.INC_P:
|
||||
case AmxOpCode.DEC_P:
|
||||
GETPARAM_P( tgt, op );
|
||||
break;
|
||||
/* Packed Instructions referencing pointers */
|
||||
case AmxOpCode.LOAD_P_PRI:
|
||||
case AmxOpCode.LOAD_P_ALT:
|
||||
case AmxOpCode.INC_P:
|
||||
case AmxOpCode.DEC_P:
|
||||
GETPARAM_P(tgt, op);
|
||||
break;
|
||||
|
||||
/* Packed Instructions referencing stack */
|
||||
case AmxOpCode.LOAD_P_S_PRI:
|
||||
case AmxOpCode.LOAD_P_S_ALT:
|
||||
case AmxOpCode.LREF_P_S_PRI:
|
||||
case AmxOpCode.LREF_P_S_ALT:
|
||||
case AmxOpCode.INC_P_S:
|
||||
case AmxOpCode.DEC_P_S:
|
||||
GETPARAM_P( tgt, op ); /* verify address */
|
||||
break;
|
||||
/* Packed Instructions referencing stack */
|
||||
case AmxOpCode.LOAD_P_S_PRI:
|
||||
case AmxOpCode.LOAD_P_S_ALT:
|
||||
case AmxOpCode.LREF_P_S_PRI:
|
||||
case AmxOpCode.LREF_P_S_ALT:
|
||||
case AmxOpCode.INC_P_S:
|
||||
case AmxOpCode.DEC_P_S:
|
||||
GETPARAM_P(tgt, op); /* verify address */
|
||||
break;
|
||||
|
||||
/* Single-Value Instructions */
|
||||
case AmxOpCode.LODB_I:
|
||||
case AmxOpCode.CONST_PRI:
|
||||
case AmxOpCode.CONST_ALT:
|
||||
case AmxOpCode.ADDR_PRI:
|
||||
case AmxOpCode.ADDR_ALT:
|
||||
case AmxOpCode.STRB_I:
|
||||
case AmxOpCode.LIDX_B:
|
||||
case AmxOpCode.IDXADDR_B:
|
||||
case AmxOpCode.ALIGN_PRI:
|
||||
case AmxOpCode.LCTRL:
|
||||
case AmxOpCode.SCTRL:
|
||||
case AmxOpCode.PICK:
|
||||
case AmxOpCode.PUSH_C:
|
||||
case AmxOpCode.PUSH:
|
||||
case AmxOpCode.PUSH_S:
|
||||
case AmxOpCode.STACK:
|
||||
case AmxOpCode.HEAP:
|
||||
case AmxOpCode.SHL_C_PRI:
|
||||
case AmxOpCode.SHL_C_ALT:
|
||||
case AmxOpCode.ADD_C:
|
||||
case AmxOpCode.SMUL_C:
|
||||
case AmxOpCode.ZERO:
|
||||
case AmxOpCode.ZERO_S:
|
||||
case AmxOpCode.EQ_C_PRI:
|
||||
case AmxOpCode.EQ_C_ALT:
|
||||
case AmxOpCode.MOVS:
|
||||
case AmxOpCode.CMPS:
|
||||
case AmxOpCode.FILL:
|
||||
case AmxOpCode.HALT:
|
||||
case AmxOpCode.BOUNDS:
|
||||
case AmxOpCode.PUSH_ADR:
|
||||
cip += CellSize;
|
||||
break;
|
||||
/* Single-Value Instructions */
|
||||
case AmxOpCode.LODB_I:
|
||||
case AmxOpCode.CONST_PRI:
|
||||
case AmxOpCode.CONST_ALT:
|
||||
case AmxOpCode.ADDR_PRI:
|
||||
case AmxOpCode.ADDR_ALT:
|
||||
case AmxOpCode.STRB_I:
|
||||
case AmxOpCode.LIDX_B:
|
||||
case AmxOpCode.IDXADDR_B:
|
||||
case AmxOpCode.ALIGN_PRI:
|
||||
case AmxOpCode.LCTRL:
|
||||
case AmxOpCode.SCTRL:
|
||||
case AmxOpCode.PICK:
|
||||
case AmxOpCode.PUSH_C:
|
||||
case AmxOpCode.PUSH:
|
||||
case AmxOpCode.PUSH_S:
|
||||
case AmxOpCode.STACK:
|
||||
case AmxOpCode.HEAP:
|
||||
case AmxOpCode.SHL_C_PRI:
|
||||
case AmxOpCode.SHL_C_ALT:
|
||||
case AmxOpCode.ADD_C:
|
||||
case AmxOpCode.SMUL_C:
|
||||
case AmxOpCode.ZERO:
|
||||
case AmxOpCode.ZERO_S:
|
||||
case AmxOpCode.EQ_C_PRI:
|
||||
case AmxOpCode.EQ_C_ALT:
|
||||
case AmxOpCode.MOVS:
|
||||
case AmxOpCode.CMPS:
|
||||
case AmxOpCode.FILL:
|
||||
case AmxOpCode.HALT:
|
||||
case AmxOpCode.BOUNDS:
|
||||
case AmxOpCode.PUSH_ADR:
|
||||
cip += CellSize;
|
||||
break;
|
||||
|
||||
case AmxOpCode.LOAD_PRI:
|
||||
case AmxOpCode.LOAD_ALT:
|
||||
case AmxOpCode.INC:
|
||||
case AmxOpCode.DEC:
|
||||
//VerifyAddress(0, );
|
||||
cip += CellSize;
|
||||
break;
|
||||
case AmxOpCode.LOAD_PRI:
|
||||
case AmxOpCode.LOAD_ALT:
|
||||
case AmxOpCode.INC:
|
||||
case AmxOpCode.DEC:
|
||||
//VerifyAddress(0, );
|
||||
cip += CellSize;
|
||||
break;
|
||||
|
||||
case AmxOpCode.LOAD_S_PRI:
|
||||
case AmxOpCode.LOAD_S_ALT:
|
||||
case AmxOpCode.LREF_S_PRI:
|
||||
case AmxOpCode.LREF_S_ALT:
|
||||
case AmxOpCode.INC_S:
|
||||
case AmxOpCode.DEC_S:
|
||||
cip += CellSize;
|
||||
break;
|
||||
case AmxOpCode.LOAD_S_PRI:
|
||||
case AmxOpCode.LOAD_S_ALT:
|
||||
case AmxOpCode.LREF_S_PRI:
|
||||
case AmxOpCode.LREF_S_ALT:
|
||||
case AmxOpCode.INC_S:
|
||||
case AmxOpCode.DEC_S:
|
||||
cip += CellSize;
|
||||
break;
|
||||
|
||||
/* Parameterless Instructions */
|
||||
case AmxOpCode.LOAD_I:
|
||||
case AmxOpCode.STOR_I:
|
||||
case AmxOpCode.LIDX:
|
||||
case AmxOpCode.IDXADDR:
|
||||
case AmxOpCode.XCHG:
|
||||
case AmxOpCode.PUSH_PRI:
|
||||
case AmxOpCode.PUSH_ALT:
|
||||
case AmxOpCode.PPRI:
|
||||
case AmxOpCode.PALT:
|
||||
case AmxOpCode.PROC:
|
||||
case AmxOpCode.RET:
|
||||
case AmxOpCode.RETN:
|
||||
case AmxOpCode.SHL:
|
||||
case AmxOpCode.SHR:
|
||||
case AmxOpCode.SSHR:
|
||||
case AmxOpCode.SMUL:
|
||||
case AmxOpCode.SDIV:
|
||||
case AmxOpCode.ADD:
|
||||
case AmxOpCode.SUB:
|
||||
case AmxOpCode.AND:
|
||||
case AmxOpCode.OR:
|
||||
case AmxOpCode.XOR:
|
||||
case AmxOpCode.NOT:
|
||||
case AmxOpCode.NEG:
|
||||
case AmxOpCode.INVERT:
|
||||
case AmxOpCode.ZERO_PRI:
|
||||
case AmxOpCode.ZERO_ALT:
|
||||
case AmxOpCode.EQ:
|
||||
case AmxOpCode.NEQ:
|
||||
case AmxOpCode.SLESS:
|
||||
case AmxOpCode.SLEQ:
|
||||
case AmxOpCode.SGRTR:
|
||||
case AmxOpCode.SGEQ:
|
||||
case AmxOpCode.INC_PRI:
|
||||
case AmxOpCode.INC_ALT:
|
||||
case AmxOpCode.INC_I:
|
||||
case AmxOpCode.DEC_PRI:
|
||||
case AmxOpCode.DEC_ALT:
|
||||
case AmxOpCode.DEC_I:
|
||||
case AmxOpCode.SWAP_PRI:
|
||||
case AmxOpCode.SWAP_ALT:
|
||||
case AmxOpCode.NOP:
|
||||
case AmxOpCode.BREAK:
|
||||
break;
|
||||
/* Parameterless Instructions */
|
||||
case AmxOpCode.LOAD_I:
|
||||
case AmxOpCode.STOR_I:
|
||||
case AmxOpCode.LIDX:
|
||||
case AmxOpCode.IDXADDR:
|
||||
case AmxOpCode.XCHG:
|
||||
case AmxOpCode.PUSH_PRI:
|
||||
case AmxOpCode.PUSH_ALT:
|
||||
case AmxOpCode.PPRI:
|
||||
case AmxOpCode.PALT:
|
||||
case AmxOpCode.PROC:
|
||||
case AmxOpCode.RET:
|
||||
case AmxOpCode.RETN:
|
||||
case AmxOpCode.SHL:
|
||||
case AmxOpCode.SHR:
|
||||
case AmxOpCode.SSHR:
|
||||
case AmxOpCode.SMUL:
|
||||
case AmxOpCode.SDIV:
|
||||
case AmxOpCode.ADD:
|
||||
case AmxOpCode.SUB:
|
||||
case AmxOpCode.AND:
|
||||
case AmxOpCode.OR:
|
||||
case AmxOpCode.XOR:
|
||||
case AmxOpCode.NOT:
|
||||
case AmxOpCode.NEG:
|
||||
case AmxOpCode.INVERT:
|
||||
case AmxOpCode.ZERO_PRI:
|
||||
case AmxOpCode.ZERO_ALT:
|
||||
case AmxOpCode.EQ:
|
||||
case AmxOpCode.NEQ:
|
||||
case AmxOpCode.SLESS:
|
||||
case AmxOpCode.SLEQ:
|
||||
case AmxOpCode.SGRTR:
|
||||
case AmxOpCode.SGEQ:
|
||||
case AmxOpCode.INC_PRI:
|
||||
case AmxOpCode.INC_ALT:
|
||||
case AmxOpCode.INC_I:
|
||||
case AmxOpCode.DEC_PRI:
|
||||
case AmxOpCode.DEC_ALT:
|
||||
case AmxOpCode.DEC_I:
|
||||
case AmxOpCode.SWAP_PRI:
|
||||
case AmxOpCode.SWAP_ALT:
|
||||
case AmxOpCode.NOP:
|
||||
case AmxOpCode.BREAK:
|
||||
break;
|
||||
|
||||
/* Jump w/ Relocation */
|
||||
case AmxOpCode.CALL:
|
||||
case AmxOpCode.JUMP:
|
||||
case AmxOpCode.JZER:
|
||||
case AmxOpCode.JNZ:
|
||||
case AmxOpCode.JEQ:
|
||||
case AmxOpCode.JNEQ:
|
||||
case AmxOpCode.JSLESS:
|
||||
case AmxOpCode.JSLEQ:
|
||||
case AmxOpCode.JSGRTR:
|
||||
case AmxOpCode.JSGEQ:
|
||||
case AmxOpCode.SWITCH:
|
||||
/* if this file is an older version (absolute references instead of the
|
||||
/* Jump w/ Relocation */
|
||||
case AmxOpCode.CALL:
|
||||
case AmxOpCode.JUMP:
|
||||
case AmxOpCode.JZER:
|
||||
case AmxOpCode.JNZ:
|
||||
case AmxOpCode.JEQ:
|
||||
case AmxOpCode.JNEQ:
|
||||
case AmxOpCode.JSLESS:
|
||||
case AmxOpCode.JSLEQ:
|
||||
case AmxOpCode.JSGRTR:
|
||||
case AmxOpCode.JSGEQ:
|
||||
case AmxOpCode.SWITCH:
|
||||
/* if this file is an older version (absolute references instead of the
|
||||
* current use of position-independent code), convert the parameter
|
||||
* to position-independent code first
|
||||
*/
|
||||
cip += CellSize;
|
||||
break;
|
||||
cip += CellSize;
|
||||
break;
|
||||
|
||||
/* overlay opcodes (overlays must be enabled) */
|
||||
case AmxOpCode.ISWITCH:
|
||||
Debug.Assert( Header.FileVersion >= 10 );
|
||||
/* drop through */
|
||||
goto case AmxOpCode.ICALL;
|
||||
case AmxOpCode.ICALL:
|
||||
cip += CellSize;
|
||||
/* drop through */
|
||||
goto case AmxOpCode.IRETN;
|
||||
case AmxOpCode.IRETN:
|
||||
Debug.Assert( Header.Overlays != 0 && Header.Overlays != Header.NameTable );
|
||||
//return AmxError.OVERLAY; /* no overlay callback */
|
||||
break;
|
||||
case AmxOpCode.ICASETBL:
|
||||
{
|
||||
Cell num;
|
||||
//DBGPARAM(num); /* number of records follows the opcode */
|
||||
//cip += (2 * num + 1) * CellSize;
|
||||
//if (Header.Overlays == 0)
|
||||
// return AmxError.OVERLAY; /* no overlay callback */
|
||||
break;
|
||||
} /* case */
|
||||
/* overlay opcodes (overlays must be enabled) */
|
||||
case AmxOpCode.ISWITCH:
|
||||
Debug.Assert(Header.FileVersion >= 10);
|
||||
/* drop through */
|
||||
goto case AmxOpCode.ICALL;
|
||||
case AmxOpCode.ICALL:
|
||||
cip += CellSize;
|
||||
/* drop through */
|
||||
goto case AmxOpCode.IRETN;
|
||||
case AmxOpCode.IRETN:
|
||||
Debug.Assert(Header.Overlays != 0 && Header.Overlays != Header.NameTable);
|
||||
//return AmxError.OVERLAY; /* no overlay callback */
|
||||
break;
|
||||
case AmxOpCode.ICASETBL:
|
||||
{
|
||||
// Cell num;
|
||||
//DBGPARAM(num); /* number of records follows the opcode */
|
||||
//cip += (2 * num + 1) * CellSize;
|
||||
//if (Header.Overlays == 0)
|
||||
// return AmxError.OVERLAY; /* no overlay callback */
|
||||
break;
|
||||
} /* case */
|
||||
|
||||
case AmxOpCode.SYSREQ_C:
|
||||
cip += CellSize;
|
||||
sysreq_flg |= 0x01; /* mark SYSREQ found */
|
||||
break;
|
||||
case AmxOpCode.SYSREQ_N:
|
||||
cip += CellSize * 2;
|
||||
sysreq_flg |= 0x02; /* mark SYSREQ.N found */
|
||||
break;
|
||||
case AmxOpCode.SYSREQ_C:
|
||||
cip += CellSize;
|
||||
sysreq_flg |= 0x01; /* mark SYSREQ found */
|
||||
break;
|
||||
case AmxOpCode.SYSREQ_N:
|
||||
cip += CellSize * 2;
|
||||
sysreq_flg |= 0x02; /* mark SYSREQ.N found */
|
||||
break;
|
||||
|
||||
case AmxOpCode.CASETBL:
|
||||
{
|
||||
DBGPARAM( out var num );
|
||||
//cip += (2 * num + 1) * CellSize;
|
||||
break;
|
||||
}
|
||||
case AmxOpCode.CASETBL:
|
||||
{
|
||||
DBGPARAM(out _);
|
||||
//cip += (2 * num + 1) * CellSize;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Header.Flags &= ~AmxFlags.VERIFY;
|
||||
//return AmxError.INVINSTR;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Header.Flags &= ~AmxFlags.VERIFY;
|
||||
//return AmxError.INVINSTR;
|
||||
break;
|
||||
}
|
||||
|
||||
void DBGPARAM( out Cell v ) => v = null; // v = (Cell)(amx->code + (int)cip), cip += CellSize)
|
||||
void DBGPARAM(out Cell v) => v = null; // v = (Cell)(amx->code + (int)cip), cip += CellSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace pkNX.Structures
|
|||
/// Flag version listed here is for CUR_FILE_VERSION = 10, circa 2008
|
||||
/// </remarks>
|
||||
[Flags]
|
||||
public enum AmxFlags : short
|
||||
public enum AmxFlags : ushort
|
||||
{
|
||||
NONE,
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ public enum AmxFlags : short
|
|||
VERIFY = 0x4000,
|
||||
|
||||
/// <summary> AMX has been initialized </summary>
|
||||
INIT = 8000
|
||||
INIT = 0x8000
|
||||
}
|
||||
|
||||
public static class AmxFlagsExtensions
|
||||
|
|
|
|||
|
|
@ -71,14 +71,13 @@ public int CellSize
|
|||
{
|
||||
get
|
||||
{
|
||||
switch (Magic)
|
||||
return Magic switch
|
||||
{
|
||||
case MAGIC_16: return 16;
|
||||
case MAGIC_32: return 32;
|
||||
case MAGIC_64: return 64;
|
||||
default:
|
||||
throw new ArgumentException("Invalid Magic identifier.");
|
||||
}
|
||||
MAGIC_16 => 16,
|
||||
MAGIC_32 => 32,
|
||||
MAGIC_64 => 64,
|
||||
_ => throw new ArgumentException("Invalid Magic identifier.")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,269 +1,253 @@
|
|||
using System.Diagnostics;
|
||||
using System;
|
||||
|
||||
namespace pkNX.Structures
|
||||
{
|
||||
// https://github.com/gameswop/mtasa-resources/blob/d557a72fefef57ac34780a76edf16383d3dff0e8/%5Bgamemodes%5D/%5Bamx%5D/amx-deps/src/amx/amx.c#L143
|
||||
public enum AmxOpCode : uint
|
||||
{
|
||||
NONE,
|
||||
LOAD_PRI,
|
||||
LOAD_ALT,
|
||||
LOAD_S_PRI,
|
||||
LOAD_S_ALT,
|
||||
LREF_PRI,
|
||||
LREF_ALT,
|
||||
LREF_S_PRI,
|
||||
LREF_S_ALT,
|
||||
LOAD_I,
|
||||
LODB_I,
|
||||
CONST_PRI,
|
||||
CONST_ALT,
|
||||
ADDR_PRI,
|
||||
ADDR_ALT,
|
||||
STOR_PRI,
|
||||
STOR_ALT,
|
||||
STOR_S_PRI,
|
||||
STOR_S_ALT,
|
||||
SREF_PRI,
|
||||
SREF_ALT,
|
||||
SREF_S_PRI,
|
||||
SREF_S_ALT,
|
||||
STOR_I,
|
||||
STRB_I,
|
||||
LIDX,
|
||||
LIDX_B,
|
||||
IDXADDR,
|
||||
IDXADDR_B,
|
||||
ALIGN_PRI,
|
||||
ALIGN_ALT,
|
||||
LCTRL,
|
||||
SCTRL,
|
||||
MOVE_PRI,
|
||||
MOVE_ALT,
|
||||
XCHG,
|
||||
PUSH_PRI,
|
||||
PUSH_ALT,
|
||||
PICK,
|
||||
PUSH_C,
|
||||
PUSH,
|
||||
PUSH_S,
|
||||
PPRI,
|
||||
PALT,
|
||||
STACK,
|
||||
HEAP,
|
||||
PROC,
|
||||
RET,
|
||||
RETN,
|
||||
CALL,
|
||||
CALL_PRI,
|
||||
JUMP,
|
||||
JREL,
|
||||
JZER,
|
||||
JNZ,
|
||||
JEQ,
|
||||
JNEQ,
|
||||
JLESS,
|
||||
JLEQ,
|
||||
JGRTR,
|
||||
JGEQ,
|
||||
JSLESS,
|
||||
JSLEQ,
|
||||
JSGRTR,
|
||||
JSGEQ,
|
||||
SHL,
|
||||
SHR,
|
||||
SSHR,
|
||||
SHL_C_PRI,
|
||||
SHL_C_ALT,
|
||||
SHR_C_PRI,
|
||||
SHR_C_ALT,
|
||||
SMUL,
|
||||
SDIV,
|
||||
SDIV_ALT,
|
||||
UMUL,
|
||||
UDIV,
|
||||
UDIV_ALT,
|
||||
ADD,
|
||||
SUB,
|
||||
SUB_ALT,
|
||||
AND,
|
||||
OR,
|
||||
XOR,
|
||||
NOT,
|
||||
NEG,
|
||||
INVERT,
|
||||
ADD_C,
|
||||
SMUL_C,
|
||||
ZERO_PRI,
|
||||
ZERO_ALT,
|
||||
ZERO,
|
||||
ZERO_S,
|
||||
SIGN_PRI,
|
||||
SIGN_ALT,
|
||||
EQ,
|
||||
NEQ,
|
||||
LESS,
|
||||
LEQ,
|
||||
GRTR,
|
||||
GEQ,
|
||||
SLESS,
|
||||
SLEQ,
|
||||
SGRTR,
|
||||
SGEQ,
|
||||
EQ_C_PRI,
|
||||
EQ_C_ALT,
|
||||
INC_PRI,
|
||||
INC_ALT,
|
||||
INC,
|
||||
INC_S,
|
||||
INC_I,
|
||||
DEC_PRI,
|
||||
DEC_ALT,
|
||||
DEC,
|
||||
DEC_S,
|
||||
DEC_I,
|
||||
MOVS,
|
||||
CMPS,
|
||||
FILL,
|
||||
HALT,
|
||||
BOUNDS,
|
||||
SYSREQ_PRI,
|
||||
SYSREQ_C,
|
||||
FILE,
|
||||
LINE,
|
||||
SYMBOL,
|
||||
SRANGE,
|
||||
JUMP_PRI,
|
||||
SWITCH,
|
||||
CASETBL,
|
||||
SWAP_PRI,
|
||||
SWAP_ALT,
|
||||
PUSH_ADR,
|
||||
NOP,
|
||||
SYSREQ_N,
|
||||
SYMTAG,
|
||||
BREAK,
|
||||
PUSH2_C,
|
||||
PUSH2,
|
||||
PUSH2_S,
|
||||
PUSH2_ADR,
|
||||
PUSH3_C,
|
||||
PUSH3,
|
||||
PUSH3_S,
|
||||
PUSH3_ADR,
|
||||
PUSH4_C,
|
||||
PUSH4,
|
||||
PUSH4_S,
|
||||
PUSH4_ADR,
|
||||
PUSH5_C,
|
||||
PUSH5,
|
||||
PUSH5_S,
|
||||
PUSH5_ADR,
|
||||
LOAD_BOTH,
|
||||
LOAD_S_BOTH,
|
||||
CONST,
|
||||
CONST_S,
|
||||
/* overlay instructions */
|
||||
ICALL,
|
||||
IRETN,
|
||||
ISWITCH,
|
||||
ICASETBL,
|
||||
/* packed instructions */
|
||||
LOAD_P_PRI,
|
||||
LOAD_P_ALT,
|
||||
LOAD_P_S_PRI,
|
||||
LOAD_P_S_ALT,
|
||||
LREF_P_PRI,
|
||||
LREF_P_ALT,
|
||||
LREF_P_S_PRI,
|
||||
LREF_P_S_ALT,
|
||||
LODB_P_I,
|
||||
CONST_P_PRI,
|
||||
CONST_P_ALT,
|
||||
ADDR_P_PRI,
|
||||
ADDR_P_ALT,
|
||||
STOR_P_PRI,
|
||||
STOR_P_ALT,
|
||||
STOR_P_S_PRI,
|
||||
STOR_P_S_ALT,
|
||||
SREF_P_PRI,
|
||||
SREF_P_ALT,
|
||||
SREF_P_S_PRI,
|
||||
SREF_P_S_ALT,
|
||||
STRB_P_I,
|
||||
LIDX_P_B,
|
||||
IDXADDR_P_B,
|
||||
ALIGN_P_PRI,
|
||||
ALIGN_P_ALT,
|
||||
PUSH_P_C,
|
||||
PUSH_P,
|
||||
PUSH_P_S,
|
||||
STACK_P,
|
||||
HEAP_P,
|
||||
SHL_P_C_PRI,
|
||||
SHL_P_C_ALT,
|
||||
SHR_P_C_PRI,
|
||||
SHR_P_C_ALT,
|
||||
ADD_P_C,
|
||||
SMUL_P_C,
|
||||
ZERO_P,
|
||||
ZERO_P_S,
|
||||
EQ_P_C_PRI,
|
||||
EQ_P_C_ALT,
|
||||
INC_P,
|
||||
INC_P_S,
|
||||
DEC_P,
|
||||
DEC_P_S,
|
||||
MOVS_P,
|
||||
CMPS_P,
|
||||
FILL_P,
|
||||
HALT_P,
|
||||
BOUNDS_P,
|
||||
PUSH_P_ADR,
|
||||
public enum AmxOpCode : uint
|
||||
{
|
||||
NONE,
|
||||
LOAD_PRI,
|
||||
LOAD_ALT,
|
||||
LOAD_S_PRI,
|
||||
LOAD_S_ALT,
|
||||
LREF_PRI,
|
||||
LREF_ALT,
|
||||
LREF_S_PRI,
|
||||
LREF_S_ALT,
|
||||
LOAD_I,
|
||||
LODB_I,
|
||||
CONST_PRI,
|
||||
CONST_ALT,
|
||||
ADDR_PRI,
|
||||
ADDR_ALT,
|
||||
STOR_PRI,
|
||||
STOR_ALT,
|
||||
STOR_S_PRI,
|
||||
STOR_S_ALT,
|
||||
SREF_PRI,
|
||||
SREF_ALT,
|
||||
SREF_S_PRI,
|
||||
SREF_S_ALT,
|
||||
STOR_I,
|
||||
STRB_I,
|
||||
LIDX,
|
||||
LIDX_B,
|
||||
IDXADDR,
|
||||
IDXADDR_B,
|
||||
ALIGN_PRI,
|
||||
ALIGN_ALT,
|
||||
LCTRL,
|
||||
SCTRL,
|
||||
MOVE_PRI,
|
||||
MOVE_ALT,
|
||||
XCHG,
|
||||
PUSH_PRI,
|
||||
PUSH_ALT,
|
||||
PICK,
|
||||
PUSH_C,
|
||||
PUSH,
|
||||
PUSH_S,
|
||||
PPRI,
|
||||
PALT,
|
||||
STACK,
|
||||
HEAP,
|
||||
PROC,
|
||||
RET,
|
||||
RETN,
|
||||
CALL,
|
||||
CALL_PRI,
|
||||
JUMP,
|
||||
JREL,
|
||||
JZER,
|
||||
JNZ,
|
||||
JEQ,
|
||||
JNEQ,
|
||||
JLESS,
|
||||
JLEQ,
|
||||
JGRTR,
|
||||
JGEQ,
|
||||
JSLESS,
|
||||
JSLEQ,
|
||||
JSGRTR,
|
||||
JSGEQ,
|
||||
SHL,
|
||||
SHR,
|
||||
SSHR,
|
||||
SHL_C_PRI,
|
||||
SHL_C_ALT,
|
||||
SHR_C_PRI,
|
||||
SHR_C_ALT,
|
||||
SMUL,
|
||||
SDIV,
|
||||
SDIV_ALT,
|
||||
UMUL,
|
||||
UDIV,
|
||||
UDIV_ALT,
|
||||
ADD,
|
||||
SUB,
|
||||
SUB_ALT,
|
||||
AND,
|
||||
OR,
|
||||
XOR,
|
||||
NOT,
|
||||
NEG,
|
||||
INVERT,
|
||||
ADD_C,
|
||||
SMUL_C,
|
||||
ZERO_PRI,
|
||||
ZERO_ALT,
|
||||
ZERO,
|
||||
ZERO_S,
|
||||
SIGN_PRI,
|
||||
SIGN_ALT,
|
||||
EQ,
|
||||
NEQ,
|
||||
LESS,
|
||||
LEQ,
|
||||
GRTR,
|
||||
GEQ,
|
||||
SLESS,
|
||||
SLEQ,
|
||||
SGRTR,
|
||||
SGEQ,
|
||||
EQ_C_PRI,
|
||||
EQ_C_ALT,
|
||||
INC_PRI,
|
||||
INC_ALT,
|
||||
INC,
|
||||
INC_S,
|
||||
INC_I,
|
||||
DEC_PRI,
|
||||
DEC_ALT,
|
||||
DEC,
|
||||
DEC_S,
|
||||
DEC_I,
|
||||
MOVS,
|
||||
CMPS,
|
||||
FILL,
|
||||
HALT,
|
||||
BOUNDS,
|
||||
SYSREQ_PRI,
|
||||
SYSREQ_C,
|
||||
FILE,
|
||||
LINE,
|
||||
SYMBOL,
|
||||
SRANGE,
|
||||
JUMP_PRI,
|
||||
SWITCH,
|
||||
CASETBL,
|
||||
SWAP_PRI,
|
||||
SWAP_ALT,
|
||||
PUSH_ADR,
|
||||
NOP,
|
||||
SYSREQ_N,
|
||||
SYMTAG,
|
||||
BREAK,
|
||||
PUSH2_C,
|
||||
PUSH2,
|
||||
PUSH2_S,
|
||||
PUSH2_ADR,
|
||||
PUSH3_C,
|
||||
PUSH3,
|
||||
PUSH3_S,
|
||||
PUSH3_ADR,
|
||||
PUSH4_C,
|
||||
PUSH4,
|
||||
PUSH4_S,
|
||||
PUSH4_ADR,
|
||||
PUSH5_C,
|
||||
PUSH5,
|
||||
PUSH5_S,
|
||||
PUSH5_ADR,
|
||||
LOAD_BOTH,
|
||||
LOAD_S_BOTH,
|
||||
CONST,
|
||||
CONST_S,
|
||||
/* overlay instructions */
|
||||
ICALL,
|
||||
IRETN,
|
||||
ISWITCH,
|
||||
ICASETBL,
|
||||
/* packed instructions */
|
||||
LOAD_P_PRI,
|
||||
LOAD_P_ALT,
|
||||
LOAD_P_S_PRI,
|
||||
LOAD_P_S_ALT,
|
||||
LREF_P_PRI,
|
||||
LREF_P_ALT,
|
||||
LREF_P_S_PRI,
|
||||
LREF_P_S_ALT,
|
||||
LODB_P_I,
|
||||
CONST_P_PRI,
|
||||
CONST_P_ALT,
|
||||
ADDR_P_PRI,
|
||||
ADDR_P_ALT,
|
||||
STOR_P_PRI,
|
||||
STOR_P_ALT,
|
||||
STOR_P_S_PRI,
|
||||
STOR_P_S_ALT,
|
||||
SREF_P_PRI,
|
||||
SREF_P_ALT,
|
||||
SREF_P_S_PRI,
|
||||
SREF_P_S_ALT,
|
||||
STRB_P_I,
|
||||
LIDX_P_B,
|
||||
IDXADDR_P_B,
|
||||
ALIGN_P_PRI,
|
||||
ALIGN_P_ALT,
|
||||
PUSH_P_C,
|
||||
PUSH_P,
|
||||
PUSH_P_S,
|
||||
STACK_P,
|
||||
HEAP_P,
|
||||
SHL_P_C_PRI,
|
||||
SHL_P_C_ALT,
|
||||
SHR_P_C_PRI,
|
||||
SHR_P_C_ALT,
|
||||
ADD_P_C,
|
||||
SMUL_P_C,
|
||||
ZERO_P,
|
||||
ZERO_P_S,
|
||||
EQ_P_C_PRI,
|
||||
EQ_P_C_ALT,
|
||||
INC_P,
|
||||
INC_P_S,
|
||||
DEC_P,
|
||||
DEC_P_S,
|
||||
MOVS_P,
|
||||
CMPS_P,
|
||||
FILL_P,
|
||||
HALT_P,
|
||||
BOUNDS_P,
|
||||
PUSH_P_ADR,
|
||||
|
||||
SYSREQ_D,
|
||||
SYSREQ_ND,
|
||||
NUM_OPCODES,
|
||||
}
|
||||
SYSREQ_D,
|
||||
SYSREQ_ND,
|
||||
NUM_OPCODES,
|
||||
}
|
||||
|
||||
public static class AmxOpCodeExtensions
|
||||
{
|
||||
public static AmxOpCode Invert(this AmxOpCode spop)
|
||||
{
|
||||
switch (spop)
|
||||
return spop switch
|
||||
{
|
||||
case AmxOpCode.JSLEQ:
|
||||
return AmxOpCode.JSGRTR;
|
||||
case AmxOpCode.JSLESS:
|
||||
return AmxOpCode.JSGEQ;
|
||||
case AmxOpCode.JSGRTR:
|
||||
return AmxOpCode.JSLEQ;
|
||||
case AmxOpCode.JSGEQ:
|
||||
return AmxOpCode.JSLESS;
|
||||
case AmxOpCode.JEQ:
|
||||
return AmxOpCode.JNEQ;
|
||||
case AmxOpCode.JNEQ:
|
||||
return AmxOpCode.JEQ;
|
||||
case AmxOpCode.JNZ:
|
||||
return AmxOpCode.JZER;
|
||||
case AmxOpCode.JZER:
|
||||
return AmxOpCode.JNZ;
|
||||
case AmxOpCode.SLEQ:
|
||||
return AmxOpCode.SGRTR;
|
||||
case AmxOpCode.SLESS:
|
||||
return AmxOpCode.SGEQ;
|
||||
case AmxOpCode.SGRTR:
|
||||
return AmxOpCode.SLEQ;
|
||||
case AmxOpCode.SGEQ:
|
||||
return AmxOpCode.SLESS;
|
||||
case AmxOpCode.EQ:
|
||||
return AmxOpCode.NEQ;
|
||||
case AmxOpCode.NEQ:
|
||||
return AmxOpCode.EQ;
|
||||
default:
|
||||
Trace.Fail(nameof(spop));
|
||||
return spop;
|
||||
}
|
||||
AmxOpCode.JSLEQ => AmxOpCode.JSGRTR,
|
||||
AmxOpCode.JSLESS => AmxOpCode.JSGEQ,
|
||||
AmxOpCode.JSGRTR => AmxOpCode.JSLEQ,
|
||||
AmxOpCode.JSGEQ => AmxOpCode.JSLESS,
|
||||
AmxOpCode.JEQ => AmxOpCode.JNEQ,
|
||||
AmxOpCode.JNEQ => AmxOpCode.JEQ,
|
||||
AmxOpCode.JNZ => AmxOpCode.JZER,
|
||||
AmxOpCode.JZER => AmxOpCode.JNZ,
|
||||
AmxOpCode.SLEQ => AmxOpCode.SGRTR,
|
||||
AmxOpCode.SLESS => AmxOpCode.SGEQ,
|
||||
AmxOpCode.SGRTR => AmxOpCode.SLEQ,
|
||||
AmxOpCode.SGEQ => AmxOpCode.SLESS,
|
||||
AmxOpCode.EQ => AmxOpCode.NEQ,
|
||||
AmxOpCode.NEQ => AmxOpCode.EQ,
|
||||
_ => throw new ArgumentException(nameof(spop))
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace pkNX.Structures
|
||||
namespace pkNX.Structures
|
||||
{
|
||||
public enum AmxOpCodeType
|
||||
{
|
||||
Unknown = -1,
|
||||
NoParams,
|
||||
OneParam,
|
||||
TwoParams,
|
||||
ThreeParams,
|
||||
FourParams,
|
||||
FiveParams,
|
||||
Jump,
|
||||
Packed,
|
||||
CaseTable,
|
||||
}
|
||||
}
|
||||
Unknown = -1,
|
||||
NoParams,
|
||||
OneParam,
|
||||
TwoParams,
|
||||
ThreeParams,
|
||||
FourParams,
|
||||
FiveParams,
|
||||
Jump,
|
||||
Packed,
|
||||
CaseTable,
|
||||
}
|
||||
}
|
||||
|
|
@ -2,227 +2,227 @@
|
|||
|
||||
namespace pkNX.Structures
|
||||
{
|
||||
public static partial class PawnUtil
|
||||
{
|
||||
public static readonly Dictionary<AmxOpCode, AmxOpCodeType> OpCodeTypes = new Dictionary<AmxOpCode, AmxOpCodeType> {
|
||||
{ AmxOpCode.NONE, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.LOAD_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LOAD_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LOAD_S_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LOAD_S_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LREF_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LREF_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LREF_S_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LREF_S_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LOAD_I, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.LODB_I, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.CONST_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.CONST_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.ADDR_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.ADDR_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.STOR_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.STOR_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.STOR_S_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.STOR_S_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SREF_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SREF_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SREF_S_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SREF_S_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.STOR_I, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.STRB_I, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LIDX, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.LIDX_B, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.IDXADDR, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.IDXADDR_B, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.ALIGN_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.ALIGN_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LCTRL, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SCTRL, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.MOVE_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.MOVE_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.XCHG, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.PUSH_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.PUSH_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.PICK, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.PUSH_C, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.PUSH, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.PUSH_S, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.PPRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.PALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.STACK, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.HEAP, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.PROC, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.RET, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.RETN, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.CALL, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.CALL_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.JUMP, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JREL, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JZER, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JNZ, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JEQ, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JNEQ, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JLESS, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JLEQ, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JGRTR, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JGEQ, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JSLESS, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JSLEQ, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JSGRTR, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JSGEQ, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.SHL, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SHR, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SSHR, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SHL_C_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SHL_C_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SHR_C_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SHR_C_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SMUL, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SDIV, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SDIV_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.UMUL, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.UDIV, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.UDIV_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.ADD, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SUB, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SUB_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.AND, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.OR, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.XOR, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.NOT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.NEG, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.INVERT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.ADD_C, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SMUL_C, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.ZERO_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.ZERO_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.ZERO, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.ZERO_S, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SIGN_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SIGN_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.EQ, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.NEQ, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.LESS, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.LEQ, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.GRTR, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.GEQ, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SLESS, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SLEQ, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SGRTR, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SGEQ, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.EQ_C_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.EQ_C_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.INC_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.INC_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.INC, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.INC_S, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.INC_I, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.DEC_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.DEC_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.DEC, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.DEC_S, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.DEC_I, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.MOVS, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.CMPS, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.FILL, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.HALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.BOUNDS, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SYSREQ_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SYSREQ_C, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.FILE, AmxOpCodeType.ThreeParams },
|
||||
{ AmxOpCode.LINE, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.SYMBOL, AmxOpCodeType.FourParams },
|
||||
{ AmxOpCode.SRANGE, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.JUMP_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SWITCH, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.CASETBL, AmxOpCodeType.CaseTable },
|
||||
{ AmxOpCode.SWAP_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SWAP_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.PUSH_ADR, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.NOP, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SYSREQ_N, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.SYMTAG, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.BREAK, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.PUSH2_C, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.PUSH2, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.PUSH2_S, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.PUSH2_ADR, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.PUSH3_C, AmxOpCodeType.ThreeParams },
|
||||
{ AmxOpCode.PUSH3, AmxOpCodeType.ThreeParams },
|
||||
{ AmxOpCode.PUSH3_S, AmxOpCodeType.ThreeParams },
|
||||
{ AmxOpCode.PUSH3_ADR, AmxOpCodeType.ThreeParams },
|
||||
{ AmxOpCode.PUSH4_C, AmxOpCodeType.FourParams },
|
||||
{ AmxOpCode.PUSH4, AmxOpCodeType.FourParams },
|
||||
{ AmxOpCode.PUSH4_S, AmxOpCodeType.FourParams },
|
||||
{ AmxOpCode.PUSH4_ADR, AmxOpCodeType.FourParams },
|
||||
{ AmxOpCode.PUSH5_C, AmxOpCodeType.FiveParams },
|
||||
{ AmxOpCode.PUSH5, AmxOpCodeType.FiveParams },
|
||||
{ AmxOpCode.PUSH5_S, AmxOpCodeType.FiveParams },
|
||||
{ AmxOpCode.PUSH5_ADR, AmxOpCodeType.FiveParams },
|
||||
{ AmxOpCode.LOAD_BOTH, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.LOAD_S_BOTH, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.CONST, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.CONST_S, AmxOpCodeType.TwoParams },
|
||||
public static partial class PawnUtil
|
||||
{
|
||||
public static readonly Dictionary<AmxOpCode, AmxOpCodeType> OpCodeTypes = new Dictionary<AmxOpCode, AmxOpCodeType> {
|
||||
{ AmxOpCode.NONE, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.LOAD_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LOAD_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LOAD_S_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LOAD_S_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LREF_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LREF_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LREF_S_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LREF_S_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LOAD_I, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.LODB_I, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.CONST_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.CONST_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.ADDR_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.ADDR_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.STOR_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.STOR_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.STOR_S_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.STOR_S_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SREF_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SREF_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SREF_S_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SREF_S_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.STOR_I, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.STRB_I, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LIDX, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.LIDX_B, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.IDXADDR, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.IDXADDR_B, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.ALIGN_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.ALIGN_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.LCTRL, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SCTRL, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.MOVE_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.MOVE_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.XCHG, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.PUSH_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.PUSH_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.PICK, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.PUSH_C, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.PUSH, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.PUSH_S, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.PPRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.PALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.STACK, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.HEAP, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.PROC, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.RET, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.RETN, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.CALL, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.CALL_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.JUMP, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JREL, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JZER, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JNZ, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JEQ, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JNEQ, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JLESS, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JLEQ, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JGRTR, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JGEQ, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JSLESS, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JSLEQ, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JSGRTR, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.JSGEQ, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.SHL, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SHR, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SSHR, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SHL_C_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SHL_C_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SHR_C_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SHR_C_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SMUL, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SDIV, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SDIV_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.UMUL, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.UDIV, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.UDIV_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.ADD, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SUB, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SUB_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.AND, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.OR, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.XOR, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.NOT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.NEG, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.INVERT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.ADD_C, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SMUL_C, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.ZERO_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.ZERO_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.ZERO, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.ZERO_S, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SIGN_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SIGN_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.EQ, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.NEQ, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.LESS, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.LEQ, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.GRTR, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.GEQ, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SLESS, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SLEQ, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SGRTR, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SGEQ, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.EQ_C_PRI, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.EQ_C_ALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.INC_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.INC_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.INC, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.INC_S, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.INC_I, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.DEC_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.DEC_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.DEC, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.DEC_S, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.DEC_I, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.MOVS, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.CMPS, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.FILL, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.HALT, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.BOUNDS, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SYSREQ_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SYSREQ_C, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.FILE, AmxOpCodeType.ThreeParams },
|
||||
{ AmxOpCode.LINE, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.SYMBOL, AmxOpCodeType.FourParams },
|
||||
{ AmxOpCode.SRANGE, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.JUMP_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SWITCH, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.CASETBL, AmxOpCodeType.CaseTable },
|
||||
{ AmxOpCode.SWAP_PRI, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SWAP_ALT, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.PUSH_ADR, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.NOP, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.SYSREQ_N, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.SYMTAG, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.BREAK, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.PUSH2_C, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.PUSH2, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.PUSH2_S, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.PUSH2_ADR, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.PUSH3_C, AmxOpCodeType.ThreeParams },
|
||||
{ AmxOpCode.PUSH3, AmxOpCodeType.ThreeParams },
|
||||
{ AmxOpCode.PUSH3_S, AmxOpCodeType.ThreeParams },
|
||||
{ AmxOpCode.PUSH3_ADR, AmxOpCodeType.ThreeParams },
|
||||
{ AmxOpCode.PUSH4_C, AmxOpCodeType.FourParams },
|
||||
{ AmxOpCode.PUSH4, AmxOpCodeType.FourParams },
|
||||
{ AmxOpCode.PUSH4_S, AmxOpCodeType.FourParams },
|
||||
{ AmxOpCode.PUSH4_ADR, AmxOpCodeType.FourParams },
|
||||
{ AmxOpCode.PUSH5_C, AmxOpCodeType.FiveParams },
|
||||
{ AmxOpCode.PUSH5, AmxOpCodeType.FiveParams },
|
||||
{ AmxOpCode.PUSH5_S, AmxOpCodeType.FiveParams },
|
||||
{ AmxOpCode.PUSH5_ADR, AmxOpCodeType.FiveParams },
|
||||
{ AmxOpCode.LOAD_BOTH, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.LOAD_S_BOTH, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.CONST, AmxOpCodeType.TwoParams },
|
||||
{ AmxOpCode.CONST_S, AmxOpCodeType.TwoParams },
|
||||
/* overlay instructions */
|
||||
{ AmxOpCode.ICALL, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.IRETN, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.ISWITCH, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.ICASETBL, AmxOpCodeType.CaseTable },
|
||||
{ AmxOpCode.IRETN, AmxOpCodeType.NoParams },
|
||||
{ AmxOpCode.ISWITCH, AmxOpCodeType.Jump },
|
||||
{ AmxOpCode.ICASETBL, AmxOpCodeType.CaseTable },
|
||||
/* packed instructions */
|
||||
{ AmxOpCode.LOAD_P_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.LOAD_P_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.LOAD_P_S_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.LOAD_P_S_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.LREF_P_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.LREF_P_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.LREF_P_S_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.LREF_P_S_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.LODB_P_I, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.CONST_P_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.CONST_P_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.ADDR_P_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.ADDR_P_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.STOR_P_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.STOR_P_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.STOR_P_S_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.STOR_P_S_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.SREF_P_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.SREF_P_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.SREF_P_S_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.SREF_P_S_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.STRB_P_I, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.LIDX_P_B, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.IDXADDR_P_B, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.ALIGN_P_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.ALIGN_P_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.PUSH_P_C, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.PUSH_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.PUSH_P_S, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.STACK_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.HEAP_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.SHL_P_C_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.SHL_P_C_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.SHR_P_C_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.SHR_P_C_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.ADD_P_C, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.SMUL_P_C, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.ZERO_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.ZERO_P_S, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.EQ_P_C_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.EQ_P_C_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.INC_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.INC_P_S, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.DEC_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.DEC_P_S, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.MOVS_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.CMPS_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.FILL_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.HALT_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.BOUNDS_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.PUSH_P_ADR, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.LOAD_P_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.LOAD_P_S_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.LOAD_P_S_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.LREF_P_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.LREF_P_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.LREF_P_S_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.LREF_P_S_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.LODB_P_I, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.CONST_P_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.CONST_P_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.ADDR_P_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.ADDR_P_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.STOR_P_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.STOR_P_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.STOR_P_S_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.STOR_P_S_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.SREF_P_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.SREF_P_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.SREF_P_S_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.SREF_P_S_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.STRB_P_I, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.LIDX_P_B, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.IDXADDR_P_B, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.ALIGN_P_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.ALIGN_P_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.PUSH_P_C, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.PUSH_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.PUSH_P_S, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.STACK_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.HEAP_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.SHL_P_C_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.SHL_P_C_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.SHR_P_C_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.SHR_P_C_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.ADD_P_C, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.SMUL_P_C, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.ZERO_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.ZERO_P_S, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.EQ_P_C_PRI, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.EQ_P_C_ALT, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.INC_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.INC_P_S, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.DEC_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.DEC_P_S, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.MOVS_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.CMPS_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.FILL_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.HALT_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.BOUNDS_P, AmxOpCodeType.Packed },
|
||||
{ AmxOpCode.PUSH_P_ADR, AmxOpCodeType.Packed },
|
||||
|
||||
{ AmxOpCode.SYSREQ_D, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SYSREQ_ND, AmxOpCodeType.TwoParams },
|
||||
};
|
||||
}
|
||||
{ AmxOpCode.SYSREQ_D, AmxOpCodeType.OneParam },
|
||||
{ AmxOpCode.SYSREQ_ND, AmxOpCodeType.TwoParams },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -1,79 +1,76 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace pkNX.Structures
|
||||
{
|
||||
public static partial class PawnUtil
|
||||
{
|
||||
// FireFly's (github.com/FireyFly) concise decompression (ported c->c#):
|
||||
// https://github.com/FireyFly/poketools/blob/e74538a5b5e5dab1e78c1cd313c55d158f37534d/src/formats/script.c#L61
|
||||
public static uint[] QuickDecompress( byte[] data, int count )
|
||||
{
|
||||
uint[] code = new uint[ count ];
|
||||
uint i = 0, j = 0, x = 0, f = 0;
|
||||
while ( i < code.Length )
|
||||
{
|
||||
int b = data[ f++ ],
|
||||
v = b & 0x7F,
|
||||
c = b & 0x80;
|
||||
if ( ++j == 1 ) // sign extension possible
|
||||
x = (uint) ( ( ( ( v >> 6 == 0 ? 1 : 0 ) - 1 ) << 6 ) | v ); // only for bit6 being set
|
||||
else
|
||||
x = ( x << 7 ) | (byte) v; // shift data into place
|
||||
public static partial class PawnUtil
|
||||
{
|
||||
// FireFly's (github.com/FireyFly) concise decompression (ported c->c#):
|
||||
// https://github.com/FireyFly/poketools/blob/e74538a5b5e5dab1e78c1cd313c55d158f37534d/src/formats/script.c#L61
|
||||
public static uint[] QuickDecompress(byte[] data, int count)
|
||||
{
|
||||
uint[] code = new uint[count];
|
||||
uint i = 0, j = 0, x = 0, f = 0;
|
||||
while (i < code.Length)
|
||||
{
|
||||
int b = data[f++],
|
||||
v = b & 0x7F,
|
||||
c = b & 0x80;
|
||||
if (++j == 1) // sign extension possible
|
||||
x = (uint)((((v >> 6 == 0 ? 1 : 0) - 1) << 6) | v); // only for bit6 being set
|
||||
else
|
||||
x = (x << 7) | (byte)v; // shift data into place
|
||||
|
||||
if ( c > 0 )
|
||||
continue; // more data to read
|
||||
if (c > 0)
|
||||
continue; // more data to read
|
||||
|
||||
code[ i++ ] = x;
|
||||
j = 0; // write finalized instruction
|
||||
}
|
||||
code[i++] = x;
|
||||
j = 0; // write finalized instruction
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
// https://github.com/gameswop/mtasa-resources/blob/d557a72fefef57ac34780a76edf16383d3dff0e8/%5Bgamemodes%5D/%5Bamx%5D/amx-deps/src/amx/amx.c#L1119
|
||||
// Slightly more readable, but potentially slower
|
||||
public static uint[] QuickDecompress2( byte[] data, int count )
|
||||
{
|
||||
var memsize = count * sizeof( uint );
|
||||
var instructions = new uint[ count ];
|
||||
uint cell;
|
||||
int shift;
|
||||
int i = data.Length;
|
||||
// https://github.com/gameswop/mtasa-resources/blob/d557a72fefef57ac34780a76edf16383d3dff0e8/%5Bgamemodes%5D/%5Bamx%5D/amx-deps/src/amx/amx.c#L1119
|
||||
// Slightly more readable, but potentially slower
|
||||
public static uint[] QuickDecompress2(byte[] data, int count)
|
||||
{
|
||||
var memsize = count * sizeof(uint);
|
||||
var instructions = new uint[count];
|
||||
int i = data.Length;
|
||||
|
||||
while ( i > 0 )
|
||||
{
|
||||
cell = 0;
|
||||
shift = 0;
|
||||
while (i > 0)
|
||||
{
|
||||
uint cell = 0;
|
||||
var shift = 0;
|
||||
|
||||
do
|
||||
{
|
||||
i--;
|
||||
cell |= (uint) ( data[ i ] & 0x7f ) << shift;
|
||||
shift += 7;
|
||||
}
|
||||
while ( i > 0 && ( data[ i - 1 ] & 0x80 ) != 0 );
|
||||
do
|
||||
{
|
||||
i--;
|
||||
cell |= (uint)(data[i] & 0x7f) << shift;
|
||||
shift += 7;
|
||||
}
|
||||
while (i > 0 && (data[i - 1] & 0x80) != 0);
|
||||
|
||||
if ( ( data[ i ] & 0x40 ) != 0 )
|
||||
{
|
||||
while ( shift < 8 * sizeof( uint ) )
|
||||
{
|
||||
cell |= (uint) 0xff << shift;
|
||||
shift += 8;
|
||||
}
|
||||
}
|
||||
if ((data[i] & 0x40) != 0)
|
||||
{
|
||||
while (shift < 8 * sizeof(uint))
|
||||
{
|
||||
cell |= (uint)0xff << shift;
|
||||
shift += 8;
|
||||
}
|
||||
}
|
||||
|
||||
memsize -= sizeof( uint );
|
||||
instructions[ memsize / sizeof( uint ) ] = cell;
|
||||
}
|
||||
memsize -= sizeof(uint);
|
||||
instructions[memsize / sizeof(uint)] = cell;
|
||||
}
|
||||
|
||||
return instructions;
|
||||
}
|
||||
return instructions;
|
||||
}
|
||||
|
||||
// Compression
|
||||
/*public static byte[] CompressScript(byte[] data)
|
||||
// Compression
|
||||
/*public static byte[] CompressScript(byte[] data)
|
||||
{
|
||||
if (data == null || data.Length % 4 != 0) // Bad Input
|
||||
return null;
|
||||
|
|
@ -90,255 +87,257 @@ public static uint[] QuickDecompress2( byte[] data, int count )
|
|||
}
|
||||
}*/
|
||||
|
||||
public static byte[] CompressScript( uint[] instructions )
|
||||
=> instructions.SelectMany( CompressInstruction ).ToArray();
|
||||
public static byte[] CompressScript(uint[] instructions)
|
||||
=> instructions.SelectMany(CompressInstruction).ToArray();
|
||||
|
||||
private static byte[] CompressInstruction( uint instruction )
|
||||
{
|
||||
var bytes = new List<byte>();
|
||||
var sign = ( instruction & 0x80000000 ) > 0;
|
||||
private static byte[] CompressInstruction(uint instruction)
|
||||
{
|
||||
var bytes = new List<byte>();
|
||||
var sign = (instruction & 0x80000000) > 0;
|
||||
|
||||
// Signed (negative) values are handled opposite of unsigned (positive) values.
|
||||
// Positive values are "done" when we've shifted the value down to zero, but
|
||||
// we don't need to store the highest 1s in a signed value. We handle this by
|
||||
// tracking the loop via a NOTed shadow copy of the instruction if it's signed.
|
||||
var shadow = sign ? ~instruction : instruction;
|
||||
// Signed (negative) values are handled opposite of unsigned (positive) values.
|
||||
// Positive values are "done" when we've shifted the value down to zero, but
|
||||
// we don't need to store the highest 1s in a signed value. We handle this by
|
||||
// tracking the loop via a NOTed shadow copy of the instruction if it's signed.
|
||||
var shadow = sign ? ~instruction : instruction;
|
||||
|
||||
do
|
||||
{
|
||||
var least7 = instruction & 0b01111111;
|
||||
var byteVal = (byte) least7;
|
||||
do
|
||||
{
|
||||
var least7 = instruction & 0b01111111;
|
||||
var byteVal = (byte)least7;
|
||||
|
||||
if ( bytes.Any() )
|
||||
// Continuation bit on all but the lowest byte
|
||||
byteVal |= 0x80;
|
||||
if (bytes.Count > 0)
|
||||
{
|
||||
// Continuation bit on all but the lowest byte
|
||||
byteVal |= 0x80;
|
||||
}
|
||||
|
||||
bytes.Add( byteVal );
|
||||
bytes.Add(byteVal);
|
||||
|
||||
instruction >>= 7;
|
||||
shadow >>= 7;
|
||||
}
|
||||
while ( shadow != 0 );
|
||||
instruction >>= 7;
|
||||
shadow >>= 7;
|
||||
}
|
||||
while (shadow != 0);
|
||||
|
||||
if ( bytes.Count < 5 )
|
||||
{
|
||||
// Ensure "sign bit" (bit just to the right of highest continuation bit) is
|
||||
// correct. Add an extra empty continuation byte if we need to. Values can't
|
||||
// be longer than 5 bytes, though.
|
||||
if (bytes.Count < 5)
|
||||
{
|
||||
// Ensure "sign bit" (bit just to the right of highest continuation bit) is
|
||||
// correct. Add an extra empty continuation byte if we need to. Values can't
|
||||
// be longer than 5 bytes, though.
|
||||
|
||||
var signBit = sign ? 0x40 : 0x00;
|
||||
var signBit = sign ? 0x40 : 0x00;
|
||||
|
||||
if ( ( bytes.Last() & 0x40 ) != signBit )
|
||||
bytes.Add( (byte) ( sign ? 0xFF : 0x80 ) );
|
||||
}
|
||||
if ((bytes.Last() & 0x40) != signBit)
|
||||
bytes.Add((byte)(sign ? 0xFF : 0x80));
|
||||
}
|
||||
|
||||
// Little endian to big endian
|
||||
bytes.Reverse();
|
||||
// Little endian to big endian
|
||||
bytes.Reverse();
|
||||
|
||||
return bytes.ToArray();
|
||||
}
|
||||
return bytes.ToArray();
|
||||
}
|
||||
|
||||
// Interpreting
|
||||
public static string[] ParseScript( uint[] cmd, int sanity = -1 )
|
||||
{
|
||||
// sub_148CBC Moon v1.0
|
||||
List<string> parse = new List<string>();
|
||||
int sanityMode = 0;
|
||||
// Interpreting
|
||||
public static string[] ParseScript(uint[] cmd, int sanity = -1)
|
||||
{
|
||||
// sub_148CBC Moon v1.0
|
||||
List<string> parse = new List<string>();
|
||||
const int sanityMode = 0; // todo
|
||||
|
||||
string ErrorNear( int line, string error )
|
||||
{
|
||||
var start = Math.Max( line - 6, 0 );
|
||||
var end = Math.Min( line + 6, cmd.Length - 1 );
|
||||
var toPrint = cmd.Skip( start ).Take( end - start );
|
||||
var message = $"Error at line {line}:" + Environment.NewLine;
|
||||
string ErrorNear(int line, string error)
|
||||
{
|
||||
var start = Math.Max(line - 6, 0);
|
||||
var end = Math.Min(line + 6, cmd.Length - 1);
|
||||
var toPrint = cmd.Skip(start).Take(end - start);
|
||||
var message = $"Error at line {line}:" + Environment.NewLine;
|
||||
|
||||
message += string.Join( " ", toPrint.Select( b => $"{b:X2}" ) ) + Environment.NewLine;
|
||||
message += string.Join(" ", toPrint.Select(b => $"{b:X2}")) + Environment.NewLine;
|
||||
|
||||
for ( var x = 0; x < line - start; x++ )
|
||||
message += " ";
|
||||
for (var x = 0; x < line - start; x++)
|
||||
message += " ";
|
||||
|
||||
message += "^^" + Environment.NewLine;
|
||||
message += error;
|
||||
message += "^^" + Environment.NewLine;
|
||||
message += error;
|
||||
|
||||
return message;
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
int i = 0; // Current Offset of decompressed instructions
|
||||
while ( i < cmd.Length ) // read away
|
||||
{
|
||||
// Read a Command
|
||||
int i = 0; // Current Offset of decompressed instructions
|
||||
while (i < cmd.Length) // read away
|
||||
{
|
||||
// Read a Command
|
||||
|
||||
string instrLine;
|
||||
var line = i;
|
||||
var opcodeval = cmd[ i++ ];
|
||||
var opcodesafe = opcodeval & 0xFFFF;
|
||||
string instrLine;
|
||||
var line = i;
|
||||
var opcodeval = cmd[i++];
|
||||
var opcodesafe = opcodeval & 0xFFFF;
|
||||
|
||||
if ( !Enum.IsDefined( typeof( AmxOpCode ), opcodesafe ) )
|
||||
throw new ArgumentException( ErrorNear( line, $"Invalid command ID: {opcodesafe:X4} ({opcodesafe})" ) );
|
||||
if (!Enum.IsDefined(typeof(AmxOpCode), opcodesafe))
|
||||
throw new ArgumentException(ErrorNear(line, $"Invalid command ID: {opcodesafe:X4} ({opcodesafe})"));
|
||||
|
||||
var opcode = (AmxOpCode) opcodesafe;
|
||||
var opcode = (AmxOpCode)opcodesafe;
|
||||
|
||||
if ( !OpCodeTypes.TryGetValue( opcode, out var optype ) )
|
||||
throw new ArgumentException( ErrorNear( line, $"Unknown opcode: {opcodesafe:X4} ({opcodesafe})" ) );
|
||||
if (!OpCodeTypes.TryGetValue(opcode, out var optype))
|
||||
throw new ArgumentException(ErrorNear(line, $"Unknown OpCode: {opcodesafe:X4} ({opcodesafe})"));
|
||||
|
||||
switch ( optype )
|
||||
{
|
||||
default:
|
||||
throw new ArgumentException( "Invalid Command Type" );
|
||||
switch (optype)
|
||||
{
|
||||
default:
|
||||
throw new ArgumentException("Invalid Command Type");
|
||||
|
||||
case AmxOpCodeType.NoParams:
|
||||
{
|
||||
instrLine = EchoIntCommand( opcode );
|
||||
break;
|
||||
}
|
||||
case AmxOpCodeType.NoParams:
|
||||
{
|
||||
instrLine = EchoIntCommand(opcode);
|
||||
break;
|
||||
}
|
||||
|
||||
case AmxOpCodeType.OneParam:
|
||||
{
|
||||
var param = (int) cmd[ i++ ];
|
||||
case AmxOpCodeType.OneParam:
|
||||
{
|
||||
var param = (int)cmd[i++];
|
||||
|
||||
instrLine = EchoIntCommand( opcode, param );
|
||||
break;
|
||||
}
|
||||
instrLine = EchoIntCommand(opcode, param);
|
||||
break;
|
||||
}
|
||||
|
||||
case AmxOpCodeType.TwoParams:
|
||||
{
|
||||
var param1 = (int) cmd[ i++ ];
|
||||
var param2 = (int) cmd[ i++ ];
|
||||
case AmxOpCodeType.TwoParams:
|
||||
{
|
||||
var param1 = (int)cmd[i++];
|
||||
var param2 = (int)cmd[i++];
|
||||
|
||||
instrLine = EchoIntCommand( opcode, param1, param2 );
|
||||
break;
|
||||
}
|
||||
instrLine = EchoIntCommand(opcode, param1, param2);
|
||||
break;
|
||||
}
|
||||
|
||||
case AmxOpCodeType.ThreeParams:
|
||||
{
|
||||
var param1 = (int) cmd[ i++ ];
|
||||
var param2 = (int) cmd[ i++ ];
|
||||
var param3 = (int) cmd[ i++ ];
|
||||
case AmxOpCodeType.ThreeParams:
|
||||
{
|
||||
var param1 = (int)cmd[i++];
|
||||
var param2 = (int)cmd[i++];
|
||||
var param3 = (int)cmd[i++];
|
||||
|
||||
instrLine = EchoIntCommand( opcode, param1, param2, param3 );
|
||||
break;
|
||||
}
|
||||
instrLine = EchoIntCommand(opcode, param1, param2, param3);
|
||||
break;
|
||||
}
|
||||
|
||||
case AmxOpCodeType.FourParams:
|
||||
{
|
||||
var param1 = (int) cmd[ i++ ];
|
||||
var param2 = (int) cmd[ i++ ];
|
||||
var param3 = (int) cmd[ i++ ];
|
||||
var param4 = (int) cmd[ i++ ];
|
||||
case AmxOpCodeType.FourParams:
|
||||
{
|
||||
var param1 = (int)cmd[i++];
|
||||
var param2 = (int)cmd[i++];
|
||||
var param3 = (int)cmd[i++];
|
||||
var param4 = (int)cmd[i++];
|
||||
|
||||
instrLine = EchoIntCommand( opcode, param1, param2, param3, param4 );
|
||||
break;
|
||||
}
|
||||
instrLine = EchoIntCommand(opcode, param1, param2, param3, param4);
|
||||
break;
|
||||
}
|
||||
|
||||
case AmxOpCodeType.FiveParams:
|
||||
{
|
||||
var param1 = (int) cmd[ i++ ];
|
||||
var param2 = (int) cmd[ i++ ];
|
||||
var param3 = (int) cmd[ i++ ];
|
||||
var param4 = (int) cmd[ i++ ];
|
||||
var param5 = (int) cmd[ i++ ];
|
||||
case AmxOpCodeType.FiveParams:
|
||||
{
|
||||
var param1 = (int)cmd[i++];
|
||||
var param2 = (int)cmd[i++];
|
||||
var param3 = (int)cmd[i++];
|
||||
var param4 = (int)cmd[i++];
|
||||
var param5 = (int)cmd[i++];
|
||||
|
||||
instrLine = EchoIntCommand( opcode, param1, param2, param3, param4, param5 );
|
||||
break;
|
||||
}
|
||||
instrLine = EchoIntCommand(opcode, param1, param2, param3, param4, param5);
|
||||
break;
|
||||
}
|
||||
|
||||
case AmxOpCodeType.Jump:
|
||||
{
|
||||
var jumpOffset = (int) cmd[ i++ ];
|
||||
var jumpDest = ( line * 4 ) + jumpOffset;
|
||||
case AmxOpCodeType.Jump:
|
||||
{
|
||||
var jumpOffset = (int)cmd[i++];
|
||||
var jumpDest = (line * 4) + jumpOffset;
|
||||
|
||||
instrLine = $"{Commands[ opcode ].PadRight( MaxCommandLength, ' ' )} => 0x{jumpDest:X4} ({jumpOffset})";
|
||||
break;
|
||||
}
|
||||
instrLine = $"{Commands[opcode].PadRight(MaxCommandLength, ' ')} => 0x{jumpDest:X4} ({jumpOffset})";
|
||||
break;
|
||||
}
|
||||
|
||||
case AmxOpCodeType.Packed:
|
||||
{
|
||||
var param = (short) ( opcodeval >> 16 );
|
||||
case AmxOpCodeType.Packed:
|
||||
{
|
||||
var param = (short)(opcodeval >> 16);
|
||||
|
||||
instrLine = EchoIntCommand( opcode, param );
|
||||
break;
|
||||
}
|
||||
instrLine = EchoIntCommand(opcode, param);
|
||||
break;
|
||||
}
|
||||
|
||||
case AmxOpCodeType.CaseTable:
|
||||
{
|
||||
//var jOffset = (i * 4) - 4; // this may be the correct jump start point...
|
||||
var count = cmd[ i++ ]; // switch case table
|
||||
// sanity check
|
||||
case AmxOpCodeType.CaseTable:
|
||||
{
|
||||
//var jOffset = (i * 4) - 4; // this may be the correct jump start point...
|
||||
var count = cmd[i++]; // switch case table
|
||||
// sanity check
|
||||
|
||||
// Populate Switch-Case Tree
|
||||
var tree = new List<string>();
|
||||
// Populate Switch-Case Tree
|
||||
var tree = new List<string>();
|
||||
|
||||
// Cases
|
||||
for ( int j = 0; j < count; j++ )
|
||||
{
|
||||
var jmp = (int) cmd[ i++ ];
|
||||
var toOffset = ( ( i - 2 ) * 4 ) + jmp;
|
||||
var ifValue = (int) cmd[ i++ ];
|
||||
tree.Add( $"\t{ifValue} => 0x{toOffset:X4} ({jmp})" );
|
||||
}
|
||||
// Cases
|
||||
for (int j = 0; j < count; j++)
|
||||
{
|
||||
var jmp = (int)cmd[i++];
|
||||
var toOffset = ((i - 2) * 4) + jmp;
|
||||
var ifValue = (int)cmd[i++];
|
||||
tree.Add($"\t{ifValue} => 0x{toOffset:X4} ({jmp})");
|
||||
}
|
||||
|
||||
// Default
|
||||
{
|
||||
int jmp = (int) cmd[ i++ ];
|
||||
var toOffset = ( ( i - 2 ) * 4 ) + jmp;
|
||||
tree.Add( $"\t* => 0x{toOffset:X4} ({jmp})" );
|
||||
}
|
||||
// Default
|
||||
{
|
||||
int jmp = (int)cmd[i++];
|
||||
var toOffset = ((i - 2) * 4) + jmp;
|
||||
tree.Add($"\t* => 0x{toOffset:X4} ({jmp})");
|
||||
}
|
||||
|
||||
instrLine = Commands[ opcode ] + Environment.NewLine + string.Join( Environment.NewLine, tree );
|
||||
break;
|
||||
}
|
||||
}
|
||||
instrLine = Commands[opcode] + Environment.NewLine + string.Join(Environment.NewLine, tree);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( opcode == AmxOpCode.RET || opcode == AmxOpCode.RETN || opcode == AmxOpCode.IRETN )
|
||||
{
|
||||
// Newline after return
|
||||
instrLine += Environment.NewLine;
|
||||
}
|
||||
if (opcode == AmxOpCode.RET || opcode == AmxOpCode.RETN || opcode == AmxOpCode.IRETN)
|
||||
{
|
||||
// Newline after return
|
||||
instrLine += Environment.NewLine;
|
||||
}
|
||||
|
||||
if ( parse.Count == 0 && opcode == AmxOpCode.HALT_P )
|
||||
{
|
||||
// Newline after 0x0000 HALT.P
|
||||
instrLine += Environment.NewLine;
|
||||
}
|
||||
if (parse.Count == 0 && opcode == AmxOpCode.HALT_P)
|
||||
{
|
||||
// Newline after 0x0000 HALT.P
|
||||
instrLine += Environment.NewLine;
|
||||
}
|
||||
|
||||
parse.Add( $"0x{line * 4:X4}: [{opcodeval & 0x7FF:X2}] {instrLine}" );
|
||||
}
|
||||
parse.Add($"0x{line * 4:X4}: [{opcodeval & 0x7FF:X2}] {instrLine}");
|
||||
}
|
||||
|
||||
if ( sanity >= 0 && sanity != sanityMode )
|
||||
throw new ArgumentException();
|
||||
if (sanity >= 0 && sanity != sanityMode)
|
||||
throw new ArgumentException();
|
||||
|
||||
return parse.ToArray();
|
||||
}
|
||||
return parse.ToArray();
|
||||
}
|
||||
|
||||
internal static string[] ParseMovement( uint[] cmd ) => Util.GetHexLines( cmd );
|
||||
internal static string[] ParseMovement(uint[] cmd) => Util.GetHexLines(cmd);
|
||||
|
||||
internal static string EchoIntCommand( AmxOpCode c, params int[] arr )
|
||||
{
|
||||
string FormatParameter( int param )
|
||||
{
|
||||
if ( param < -100 || param > 100 )
|
||||
return $"0x{param:X4}";
|
||||
return param.ToString();
|
||||
}
|
||||
internal static string EchoIntCommand(AmxOpCode c, params int[] arr)
|
||||
{
|
||||
static string FormatParameter(int param)
|
||||
{
|
||||
if (param < -100 || param > 100)
|
||||
return $"0x{param:X4}";
|
||||
return param.ToString();
|
||||
}
|
||||
|
||||
string commandLeft = Commands[ c ].PadRight( MaxCommandLength, ' ' );
|
||||
string parameters = arr.Length == 0 ? "" : string.Join( ", ", arr.Select( FormatParameter ) );
|
||||
return $"{commandLeft} {parameters}";
|
||||
}
|
||||
string commandLeft = Commands[c].PadRight(MaxCommandLength, ' ');
|
||||
string parameters = arr.Length == 0 ? "" : string.Join(", ", arr.Select(FormatParameter));
|
||||
return $"{commandLeft} {parameters}";
|
||||
}
|
||||
|
||||
private static readonly Func<uint, float> getFloat = val => BitConverter.ToSingle( BitConverter.GetBytes( val ), 0 );
|
||||
private static readonly Func<uint, float> getFloat = val => BitConverter.ToSingle(BitConverter.GetBytes(val), 0);
|
||||
|
||||
internal static string EchoFloatCommand( AmxOpCode c, params uint[] arr )
|
||||
{
|
||||
string commandLeft = Commands[ c ].PadRight( MaxCommandLength, ' ' );
|
||||
string parameters = arr.Length == 1 ? "" : string.Join( ", ", arr.Select( getFloat ) );
|
||||
return $"{commandLeft} {parameters}";
|
||||
}
|
||||
internal static string EchoFloatCommand(AmxOpCode c, params uint[] arr)
|
||||
{
|
||||
string commandLeft = Commands[c].PadRight(MaxCommandLength, ' ');
|
||||
string parameters = arr.Length == 1 ? "" : string.Join(", ", arr.Select(getFloat));
|
||||
return $"{commandLeft} {parameters}";
|
||||
}
|
||||
|
||||
private static readonly Dictionary<AmxOpCode, string> Commands = Enum.GetValues( typeof( AmxOpCode ) )
|
||||
.Cast<AmxOpCode>()
|
||||
.ToDictionary( v => v, v => v.ToString().Replace( '_', '.' ) );
|
||||
private static readonly Dictionary<AmxOpCode, string> Commands = Enum.GetValues(typeof(AmxOpCode))
|
||||
.Cast<AmxOpCode>()
|
||||
.ToDictionary(v => v, v => v.ToString().Replace('_', '.'));
|
||||
|
||||
private static readonly int MaxCommandLength = Commands.Values.Max( cmd => cmd.Length );
|
||||
}
|
||||
private static readonly int MaxCommandLength = Commands.Values.Max(cmd => cmd.Length);
|
||||
}
|
||||
}
|
||||
|
|
@ -20,21 +20,15 @@ public static class VariableTypeExtensions
|
|||
|
||||
public static VariableType FromIdent(this byte ident)
|
||||
{
|
||||
switch (ident)
|
||||
return ident switch
|
||||
{
|
||||
case IDENT_VARIABLE:
|
||||
return VariableType.Normal;
|
||||
case IDENT_REFERENCE:
|
||||
return VariableType.Reference;
|
||||
case IDENT_ARRAY:
|
||||
return VariableType.Array;
|
||||
case IDENT_REFARRAY:
|
||||
return VariableType.ArrayReference;
|
||||
case IDENT_VARARGS:
|
||||
return VariableType.Variadic;
|
||||
default:
|
||||
return VariableType.Normal;
|
||||
}
|
||||
IDENT_VARIABLE => VariableType.Normal,
|
||||
IDENT_REFERENCE => VariableType.Reference,
|
||||
IDENT_ARRAY => VariableType.Array,
|
||||
IDENT_REFARRAY => VariableType.ArrayReference,
|
||||
IDENT_VARARGS => VariableType.Variadic,
|
||||
_ => VariableType.Normal
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -180,68 +180,74 @@ private byte[] GetLineData(string line)
|
|||
if (line == null)
|
||||
return new byte[2];
|
||||
|
||||
using (var ms = new MemoryStream())
|
||||
using (var bw = new BinaryWriter(ms))
|
||||
using var ms = new MemoryStream();
|
||||
using var bw = new BinaryWriter(ms);
|
||||
int i = 0;
|
||||
while (i < line.Length)
|
||||
{
|
||||
int i = 0;
|
||||
while (i < line.Length)
|
||||
{
|
||||
ushort val = line[i++];
|
||||
val = TryRemapChar(val);
|
||||
ushort val = line[i++];
|
||||
val = TryRemapChar(val);
|
||||
|
||||
switch (val)
|
||||
{
|
||||
case '[':
|
||||
// grab the string
|
||||
int bracket = line.IndexOf(']', i);
|
||||
if (bracket < 0)
|
||||
throw new ArgumentException("Variable text is not capped properly: " + line);
|
||||
string varText = line.Substring(i, bracket - i);
|
||||
var varValues = GetVariableValues(varText);
|
||||
foreach (ushort v in varValues) bw.Write(v);
|
||||
i += 1 + varText.Length;
|
||||
break;
|
||||
case '\\':
|
||||
var escapeValues = GetEscapeValues(line[i++]);
|
||||
foreach (ushort v in escapeValues)
|
||||
bw.Write(v);
|
||||
break;
|
||||
default:
|
||||
bw.Write(val);
|
||||
break;
|
||||
}
|
||||
switch (val)
|
||||
{
|
||||
case '[':
|
||||
// grab the string
|
||||
int bracket = line.IndexOf(']', i);
|
||||
if (bracket < 0)
|
||||
throw new ArgumentException("Variable text is not capped properly: " + line);
|
||||
string varText = line.Substring(i, bracket - i);
|
||||
var varValues = GetVariableValues(varText);
|
||||
foreach (ushort v in varValues) bw.Write(v);
|
||||
i += 1 + varText.Length;
|
||||
break;
|
||||
case '\\':
|
||||
var escapeValues = GetEscapeValues(line[i++]);
|
||||
foreach (ushort v in escapeValues)
|
||||
bw.Write(v);
|
||||
break;
|
||||
default:
|
||||
bw.Write(val);
|
||||
break;
|
||||
}
|
||||
bw.Write(KEY_TERMINATOR); // cap the line off
|
||||
return ms.ToArray();
|
||||
}
|
||||
bw.Write(KEY_TERMINATOR); // cap the line off
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
private ushort TryRemapChar(ushort val)
|
||||
{
|
||||
if (!RemapChars)
|
||||
return val;
|
||||
switch (val)
|
||||
return val switch
|
||||
{
|
||||
case 0x202F: return 0xE07F; // nbsp
|
||||
case 0x2026: return 0xE08D; // …
|
||||
case 0x2642: return 0xE08E; // ♂
|
||||
case 0x2640: return 0xE08F; // ♀
|
||||
default: return val;
|
||||
}
|
||||
0x202F => 0xE07F // nbsp
|
||||
,
|
||||
0x2026 => 0xE08D // …
|
||||
,
|
||||
0x2642 => 0xE08E // ♂
|
||||
,
|
||||
0x2640 => 0xE08F // ♀
|
||||
,
|
||||
_ => val
|
||||
};
|
||||
}
|
||||
|
||||
private ushort TryUnmapChar(ushort val)
|
||||
{
|
||||
if (!RemapChars)
|
||||
return val;
|
||||
switch (val)
|
||||
return val switch
|
||||
{
|
||||
case 0xE07F: return 0x202F; // nbsp
|
||||
case 0xE08D: return 0x2026; // …
|
||||
case 0xE08E: return 0x2642; // ♂
|
||||
case 0xE08F: return 0x2640; // ♀
|
||||
default: return val;
|
||||
}
|
||||
0xE07F => 0x202F // nbsp
|
||||
,
|
||||
0xE08D => 0x2026 // …
|
||||
,
|
||||
0xE08E => 0x2642 // ♂
|
||||
,
|
||||
0xE08F => 0x2640 // ♀
|
||||
,
|
||||
_ => val
|
||||
};
|
||||
}
|
||||
|
||||
private string GetLineString(byte[] data)
|
||||
|
|
|
|||
|
|
@ -17,52 +17,48 @@ public class TrPoke6
|
|||
|
||||
public TrPoke6(byte[] data, bool HasItem, bool HasMoves)
|
||||
{
|
||||
using (var ms = new MemoryStream(data))
|
||||
using (var br = new BinaryReader(ms))
|
||||
{
|
||||
IVs = br.ReadByte();
|
||||
PID = br.ReadByte();
|
||||
Level = br.ReadUInt16();
|
||||
Species = br.ReadUInt16();
|
||||
Form = br.ReadUInt16();
|
||||
using var ms = new MemoryStream(data);
|
||||
using var br = new BinaryReader(ms);
|
||||
IVs = br.ReadByte();
|
||||
PID = br.ReadByte();
|
||||
Level = br.ReadUInt16();
|
||||
Species = br.ReadUInt16();
|
||||
Form = br.ReadUInt16();
|
||||
|
||||
Ability = PID >> 4;
|
||||
Gender = PID & 3;
|
||||
uBit = (PID >> 3) & 1;
|
||||
Ability = PID >> 4;
|
||||
Gender = PID & 3;
|
||||
uBit = (PID >> 3) & 1;
|
||||
|
||||
if (HasItem)
|
||||
Item = br.ReadUInt16();
|
||||
if (HasItem)
|
||||
Item = br.ReadUInt16();
|
||||
|
||||
if (!HasMoves)
|
||||
return;
|
||||
if (!HasMoves)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
Moves[i] = br.ReadUInt16();
|
||||
}
|
||||
for (int i = 0; i < 4; i++)
|
||||
Moves[i] = br.ReadUInt16();
|
||||
}
|
||||
|
||||
public byte[] Write(bool HasItem, bool HasMoves)
|
||||
{
|
||||
using (var ms = new MemoryStream())
|
||||
using (var bw = new BinaryWriter(ms))
|
||||
{
|
||||
bw.Write(IVs);
|
||||
PID = (byte)(((Ability & 0xF) << 4) | ((uBit & 1) << 3) | (Gender & 0x7));
|
||||
bw.Write(PID);
|
||||
bw.Write(Level);
|
||||
bw.Write(Species);
|
||||
bw.Write(Form);
|
||||
|
||||
if (HasItem)
|
||||
bw.Write(Item);
|
||||
if (!HasMoves)
|
||||
return ms.ToArray();
|
||||
|
||||
foreach (ushort Move in Moves)
|
||||
bw.Write(Move);
|
||||
using var ms = new MemoryStream();
|
||||
using var bw = new BinaryWriter(ms);
|
||||
bw.Write(IVs);
|
||||
PID = (byte)(((Ability & 0xF) << 4) | ((uBit & 1) << 3) | (Gender & 0x7));
|
||||
bw.Write(PID);
|
||||
bw.Write(Level);
|
||||
bw.Write(Species);
|
||||
bw.Write(Form);
|
||||
|
||||
if (HasItem)
|
||||
bw.Write(Item);
|
||||
if (!HasMoves)
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
foreach (ushort Move in Moves)
|
||||
bw.Write(Move);
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -88,17 +88,16 @@ public static void SetAV(this IAwakened pk, int index, int value)
|
|||
/// <param name="index">Index to get</param>
|
||||
public static int GetAV(this IAwakened pk, int index)
|
||||
{
|
||||
switch (index)
|
||||
return index switch
|
||||
{
|
||||
case 0: return pk.AV_HP;
|
||||
case 1: return pk.AV_ATK;
|
||||
case 2: return pk.AV_DEF;
|
||||
case 3: return pk.AV_SPE;
|
||||
case 4: return pk.AV_SPA;
|
||||
case 5: return pk.AV_SPD;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
0 => pk.AV_HP,
|
||||
1 => pk.AV_ATK,
|
||||
2 => pk.AV_DEF,
|
||||
3 => pk.AV_SPE,
|
||||
4 => pk.AV_SPA,
|
||||
5 => pk.AV_SPD,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(index))
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -57,17 +57,16 @@ public virtual ushort[] GetStats(PersonalInfo p)
|
|||
|
||||
public int GetIV(int index)
|
||||
{
|
||||
switch (index)
|
||||
return index switch
|
||||
{
|
||||
case 0: return IV_HP;
|
||||
case 1: return IV_ATK;
|
||||
case 2: return IV_DEF;
|
||||
case 3: return IV_SPE;
|
||||
case 4: return IV_SPA;
|
||||
case 5: return IV_SPD;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
0 => IV_HP,
|
||||
1 => IV_ATK,
|
||||
2 => IV_DEF,
|
||||
3 => IV_SPE,
|
||||
4 => IV_SPA,
|
||||
5 => IV_SPD,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(index))
|
||||
};
|
||||
}
|
||||
|
||||
public void SetIV(int index, int value)
|
||||
|
|
@ -87,17 +86,16 @@ public void SetIV(int index, int value)
|
|||
|
||||
public int GetEV(int index)
|
||||
{
|
||||
switch (index)
|
||||
return index switch
|
||||
{
|
||||
case 0: return EV_HP;
|
||||
case 1: return EV_ATK;
|
||||
case 2: return EV_DEF;
|
||||
case 3: return EV_SPE;
|
||||
case 4: return EV_SPA;
|
||||
case 5: return EV_SPD;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
0 => EV_HP,
|
||||
1 => EV_ATK,
|
||||
2 => EV_DEF,
|
||||
3 => EV_SPE,
|
||||
4 => EV_SPA,
|
||||
5 => EV_SPD,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(index))
|
||||
};
|
||||
}
|
||||
|
||||
public void SetEV(int index, int value)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ namespace pkNX.Structures
|
|||
[Flags]
|
||||
public enum TrainerAI : byte
|
||||
{
|
||||
None = 0,
|
||||
|
||||
Basic = 1 << 0,
|
||||
Strong = 1 << 1,
|
||||
Expert = 1 << 2,
|
||||
|
|
|
|||
|
|
@ -131,12 +131,14 @@ private static int GetStat(int baseStat, int iv, int level, int nature, int stat
|
|||
|
||||
private static int AmplifyStat(int nature, int index, int initial)
|
||||
{
|
||||
switch (AbilityAmpTable[(5 * nature) + index])
|
||||
return AbilityAmpTable[(5 * nature) + index] switch
|
||||
{
|
||||
case 1: return 110 * initial / 100; // 110%
|
||||
case -1: return 90 * initial / 100; // 90%
|
||||
default: return initial; // 100%
|
||||
}
|
||||
1 => (110 * initial / 100) // 110%
|
||||
,
|
||||
-1 => (90 * initial / 100) // 90%
|
||||
,
|
||||
_ => initial
|
||||
};
|
||||
}
|
||||
|
||||
private static readonly sbyte[] AbilityAmpTable =
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0;net46</TargetFrameworks>
|
||||
<Description>Data Structures</Description>
|
||||
<LangVersion>8</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
<LangVersion>8</LangVersion>
|
||||
|
||||
<Description>Ensuring functionality works as intended</Description>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -76,19 +76,18 @@ public void SaveEvolution()
|
|||
|
||||
private static string[] GetArgs(EvolutionTypeArgumentType type)
|
||||
{
|
||||
switch (type)
|
||||
return type switch
|
||||
{
|
||||
case EvolutionTypeArgumentType.NoArg: return None;
|
||||
case EvolutionTypeArgumentType.Level: return Levels;
|
||||
case EvolutionTypeArgumentType.Items: return items;
|
||||
case EvolutionTypeArgumentType.Moves: return movelist;
|
||||
case EvolutionTypeArgumentType.Species: return species;
|
||||
case EvolutionTypeArgumentType.Stat: return Stats;
|
||||
case EvolutionTypeArgumentType.Type: return types;
|
||||
case EvolutionTypeArgumentType.Version: return Stats;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(type), type, null);
|
||||
}
|
||||
EvolutionTypeArgumentType.NoArg => None,
|
||||
EvolutionTypeArgumentType.Level => Levels,
|
||||
EvolutionTypeArgumentType.Items => items,
|
||||
EvolutionTypeArgumentType.Moves => movelist,
|
||||
EvolutionTypeArgumentType.Species => species,
|
||||
EvolutionTypeArgumentType.Stat => Stats,
|
||||
EvolutionTypeArgumentType.Type => types,
|
||||
EvolutionTypeArgumentType.Version => Stats,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ private void ChangeLanguage(object sender, EventArgs e)
|
|||
|
||||
private void Menu_Open_Click(object sender, EventArgs e)
|
||||
{
|
||||
var fbd = new FolderBrowserDialog();
|
||||
using var fbd = new FolderBrowserDialog();
|
||||
if (fbd.ShowDialog() == DialogResult.OK)
|
||||
OpenPath(fbd.SelectedPath);
|
||||
}
|
||||
|
|
@ -110,7 +110,7 @@ private void OpenPath(string path)
|
|||
OpenFile(path);
|
||||
}
|
||||
|
||||
private void OpenFile(string path)
|
||||
private static void OpenFile(string path)
|
||||
{
|
||||
var result = FileRipper.TryOpenFile(path);
|
||||
if (result.Code != RipResultCode.Success)
|
||||
|
|
|
|||
|
|
@ -31,38 +31,34 @@ public static void LoadSettings(GameVersion game)
|
|||
return;
|
||||
}
|
||||
|
||||
using (var file = File.OpenRead(path))
|
||||
using var file = File.OpenRead(path);
|
||||
var reader = new XmlSerializer(typeof(SharedSettings));
|
||||
try
|
||||
{
|
||||
var reader = new XmlSerializer(typeof(SharedSettings));
|
||||
try
|
||||
{
|
||||
Settings = (SharedSettings) reader.Deserialize(file);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.WriteLine(e.Message);
|
||||
}
|
||||
Settings = (SharedSettings) reader.Deserialize(file);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.WriteLine(e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SaveSettings(GameVersion game)
|
||||
{
|
||||
string path = GetSettingsFileName(game);
|
||||
using (var file = File.Create(path))
|
||||
using var file = File.Create(path);
|
||||
var writer = new XmlSerializer(typeof(SharedSettings));
|
||||
try
|
||||
{
|
||||
var writer = new XmlSerializer(typeof(SharedSettings));
|
||||
try
|
||||
{
|
||||
writer.Serialize(file, Settings);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.WriteLine(e.Message);
|
||||
if (!File.Exists(path))
|
||||
return;
|
||||
file.Close();
|
||||
File.Delete(path);
|
||||
}
|
||||
writer.Serialize(file, Settings);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.WriteLine(e.Message);
|
||||
if (!File.Exists(path))
|
||||
return;
|
||||
file.Close();
|
||||
File.Delete(path);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ public void EditCommon()
|
|||
var text = ROM.GetFilteredFolder(GameFile.GameText, z => Path.GetExtension(z) == ".dat");
|
||||
var config = new TextConfig(ROM.Game);
|
||||
var tc = new TextContainer(text, config);
|
||||
var form = new TextEditor(tc, TextEditor.TextEditorMode.Common);
|
||||
using var form = new TextEditor(tc, TextEditor.TextEditorMode.Common);
|
||||
form.ShowDialog();
|
||||
if (!form.Modified)
|
||||
text.CancelEdits();
|
||||
|
|
@ -29,7 +29,7 @@ public void EditScript()
|
|||
var text = ROM.GetFilteredFolder(GameFile.StoryText, z => Path.GetExtension(z) == ".dat");
|
||||
var config = new TextConfig(ROM.Game);
|
||||
var tc = new TextContainer(text, config);
|
||||
var form = new TextEditor(tc, TextEditor.TextEditorMode.Script);
|
||||
using var form = new TextEditor(tc, TextEditor.TextEditorMode.Script);
|
||||
form.ShowDialog();
|
||||
if (!form.Modified)
|
||||
text.CancelEdits();
|
||||
|
|
@ -49,7 +49,7 @@ public void EditTrainers()
|
|||
TrainerClass = ROM.GetFilteredFolder(GameFile.TrainerClass),
|
||||
};
|
||||
editor.Initialize();
|
||||
var form = new BTTE(ROM, editor);
|
||||
using var form = new BTTE(ROM, editor);
|
||||
form.ShowDialog();
|
||||
if (!form.Modified)
|
||||
editor.CancelEdits();
|
||||
|
|
@ -66,7 +66,7 @@ public void EditTrainers()
|
|||
Mega = ROM.Data.MegaEvolutionData,
|
||||
Personal = ROM.Data.PersonalData,
|
||||
};
|
||||
var form = new PokeDataUI(editor, ROM);
|
||||
using var form = new PokeDataUI(editor, ROM);
|
||||
form.ShowDialog();
|
||||
if (!form.Modified)
|
||||
editor.CancelEdits();
|
||||
|
|
@ -82,7 +82,7 @@ public void EditItems()
|
|||
Create = Item.FromBytes,
|
||||
Write = item => item.Write(),
|
||||
};
|
||||
var form = new GenericEditor<Item>(cache, ROM.GetStrings(TextName.ItemNames), "Item Editor");
|
||||
using var form = new GenericEditor<Item>(cache, ROM.GetStrings(TextName.ItemNames), "Item Editor");
|
||||
form.ShowDialog();
|
||||
if (!form.Modified)
|
||||
cache.CancelEdits();
|
||||
|
|
@ -98,7 +98,7 @@ public void EditMoves()
|
|||
Create = data => new Move7(data),
|
||||
Write = move => move.Write(),
|
||||
};
|
||||
var form = new GenericEditor<Move7>(cache, ROM.GetStrings(TextName.MoveNames), "Move Editor");
|
||||
using var form = new GenericEditor<Move7>(cache, ROM.GetStrings(TextName.MoveNames), "Move Editor");
|
||||
form.ShowDialog();
|
||||
if (!form.Modified)
|
||||
cache.CancelEdits();
|
||||
|
|
@ -127,7 +127,7 @@ void Randomize()
|
|||
}
|
||||
}
|
||||
|
||||
var form = new GenericEditor<EncounterGift7b>(cache, names, "Gift Editor", Randomize);
|
||||
using var form = new GenericEditor<EncounterGift7b>(cache, names, "Gift Editor", Randomize);
|
||||
form.ShowDialog();
|
||||
if (!form.Modified)
|
||||
file.CancelEdits();
|
||||
|
|
@ -157,7 +157,7 @@ void Randomize()
|
|||
}
|
||||
}
|
||||
|
||||
var form = new GenericEditor<EncounterTrade7b>(cache, names, "Trade Editor", Randomize);
|
||||
using var form = new GenericEditor<EncounterTrade7b>(cache, names, "Trade Editor", Randomize);
|
||||
form.ShowDialog();
|
||||
if (!form.Modified)
|
||||
file.CancelEdits();
|
||||
|
|
@ -187,7 +187,7 @@ void Randomize()
|
|||
}
|
||||
}
|
||||
|
||||
var form = new GenericEditor<EncounterStatic7b>(cache, names, "Static Encounter Editor", Randomize);
|
||||
using var form = new GenericEditor<EncounterStatic7b>(cache, names, "Static Encounter Editor", Randomize);
|
||||
form.ShowDialog();
|
||||
if (!form.Modified)
|
||||
file.CancelEdits();
|
||||
|
|
@ -210,13 +210,13 @@ public void EditWild()
|
|||
return;
|
||||
}
|
||||
var json = File.ReadAllText(path);
|
||||
var form = new GGWE(ROM, json);
|
||||
using var form = new GGWE(ROM, json);
|
||||
form.ShowDialog();
|
||||
var result = form.Result;
|
||||
if (string.IsNullOrWhiteSpace(result))
|
||||
return; // no save
|
||||
|
||||
var sfd = new SaveFileDialog { Filter = "json files (*.json)|*.json|All files (*.*)|*.*" };
|
||||
using var sfd = new SaveFileDialog { Filter = "json files (*.json)|*.json|All files (*.*)|*.*" };
|
||||
if (sfd.ShowDialog() != DialogResult.OK)
|
||||
return;
|
||||
path = sfd.FileName;
|
||||
|
|
@ -232,11 +232,11 @@ public void EditShinyRate()
|
|||
var shiny = new ShinyRateGG(nso.DecompressedText);
|
||||
if (!shiny.IsEditable)
|
||||
{
|
||||
WinFormsUtil.Alert("Not able to find shiny rate logic in exefs.");
|
||||
WinFormsUtil.Alert("Not able to find shiny rate logic in ExeFS.");
|
||||
return;
|
||||
}
|
||||
|
||||
var editor = new ShinyRate(shiny);
|
||||
using var editor = new ShinyRate(shiny);
|
||||
editor.ShowDialog();
|
||||
if (!editor.Modified)
|
||||
return;
|
||||
|
|
@ -252,14 +252,14 @@ public void EditTM()
|
|||
var list = new TMEditorGG(data);
|
||||
if (!list.Valid)
|
||||
{
|
||||
WinFormsUtil.Alert("Not able to find tm data in exefs.");
|
||||
WinFormsUtil.Alert("Not able to find tm data in ExeFS.");
|
||||
return;
|
||||
}
|
||||
|
||||
var moves = list.GetMoves();
|
||||
var allowed = Legal.GetAllowedMoves(ROM.Game, ROM.Data.MoveData.Length);
|
||||
var names = ROM.GetStrings(TextName.MoveNames);
|
||||
var editor = new TMList(moves, allowed, names);
|
||||
using var editor = new TMList(moves, allowed, names);
|
||||
editor.ShowDialog();
|
||||
if (!editor.Modified)
|
||||
return;
|
||||
|
|
@ -284,7 +284,7 @@ public void EditTypeChart()
|
|||
int ofs = CodePattern.IndexOfBytes(nso.DecompressedRO, pattern);
|
||||
if (ofs < 0)
|
||||
{
|
||||
WinFormsUtil.Alert("Not able to find type chart data in exefs.");
|
||||
WinFormsUtil.Alert("Not able to find type chart data in ExeFS.");
|
||||
return;
|
||||
}
|
||||
ofs += pattern.Length + 0x24; // 0x5B4C0C in lgpe 1.0 RO
|
||||
|
|
@ -293,7 +293,7 @@ public void EditTypeChart()
|
|||
var types = ROM.GetStrings(TextName.Types);
|
||||
Array.Copy(nso.DecompressedRO, ofs, cdata, 0, cdata.Length);
|
||||
var chart = new TypeChartEditor(cdata);
|
||||
var editor = new TypeChart(chart, types);
|
||||
using var editor = new TypeChart(chart, types);
|
||||
editor.ShowDialog();
|
||||
if (!editor.Modified)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ internal class EditorUU : EditorBase
|
|||
|
||||
public void TestButton()
|
||||
{
|
||||
new Form().ShowDialog();
|
||||
using var form = new Form();
|
||||
form.ShowDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -85,16 +85,14 @@ public static RipResult TryOpenFile(string path, ContainerHandler handler = null
|
|||
|
||||
try
|
||||
{
|
||||
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
if (br.BaseStream.Length < 4)
|
||||
return new RipResult(RipResultCode.BadSize);
|
||||
var header = br.ReadUInt32();
|
||||
var result = TryLoadFile(br, header, path, handler);
|
||||
if (result.Code == RipResultCode.Success)
|
||||
return result;
|
||||
}
|
||||
using var fs = new FileStream(path, FileMode.Open, FileAccess.Read);
|
||||
using var br = new BinaryReader(fs);
|
||||
if (br.BaseStream.Length < 4)
|
||||
return new RipResult(RipResultCode.BadSize);
|
||||
var header = br.ReadUInt32();
|
||||
var result = TryLoadFile(br, header, path, handler);
|
||||
if (result.Code == RipResultCode.Success)
|
||||
return result;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -104,8 +104,7 @@ private void ClickView(object sender, EventArgs e)
|
|||
var pk = Trainers[entry].Team[slot];
|
||||
if (pk.Species != 0)
|
||||
{
|
||||
try { PopulateFields(pk); }
|
||||
catch (Exception ex) { Console.WriteLine(ex.Message); }
|
||||
PopulateFields(pk);
|
||||
// Visual to display what slot is currently loaded.
|
||||
GetSlotColor(slot, Sprites.Properties.Resources.slotView);
|
||||
}
|
||||
|
|
@ -431,20 +430,17 @@ protected override void OnFormClosing(FormClosingEventArgs e)
|
|||
|
||||
private void DumpTxt(object sender, EventArgs e)
|
||||
{
|
||||
using (var sfd = new SaveFileDialog())
|
||||
using var sfd = new SaveFileDialog {FileName = "Trainers.txt"};
|
||||
if (sfd.ShowDialog() != DialogResult.OK)
|
||||
return;
|
||||
var sb = new StringBuilder();
|
||||
for (int i = 0; i < Trainers.Length; i++)
|
||||
{
|
||||
sfd.FileName = "Trainers.txt";
|
||||
if (sfd.ShowDialog() != DialogResult.OK)
|
||||
return;
|
||||
var sb = new StringBuilder();
|
||||
for (int i = 0; i < Trainers.Length; i++)
|
||||
{
|
||||
var tr = Trainers[i];
|
||||
tr.Name = trName[i];
|
||||
sb.Append(GetTrainerString(tr));
|
||||
}
|
||||
File.WriteAllText(sfd.FileName, sb.ToString());
|
||||
var tr = Trainers[i];
|
||||
tr.Name = trName[i];
|
||||
sb.Append(GetTrainerString(tr));
|
||||
}
|
||||
File.WriteAllText(sfd.FileName, sb.ToString());
|
||||
}
|
||||
|
||||
private string GetTrainerString(VsTrainer Trainer)
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ public TextEditor(TextContainer c, TextEditorMode mode)
|
|||
private void B_Export_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (TextData.Length <= 0) return;
|
||||
var dump = new SaveFileDialog {Filter = "Text File|*.txt"};
|
||||
using var dump = new SaveFileDialog {Filter = "Text File|*.txt"};
|
||||
if (dump.ShowDialog() != DialogResult.OK)
|
||||
return;
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ private void B_Export_Click(object sender, EventArgs e)
|
|||
private void B_Import_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (TextData.Length <= 0) return;
|
||||
var dump = new OpenFileDialog { Filter = "Text File|*.txt" };
|
||||
using var dump = new OpenFileDialog { Filter = "Text File|*.txt" };
|
||||
if (dump.ShowDialog() != DialogResult.OK)
|
||||
return;
|
||||
|
||||
|
|
@ -66,21 +66,19 @@ private void B_Import_Click(object sender, EventArgs e)
|
|||
|
||||
public static void ExportTextFile(string fileName, bool newline, TextContainer lineData)
|
||||
{
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
using MemoryStream ms = new MemoryStream();
|
||||
ms.Write(new byte[] {0xFF, 0xFE}, 0, 2); // Write Unicode BOM
|
||||
using (TextWriter tw = new StreamWriter(ms, new UnicodeEncoding()))
|
||||
{
|
||||
ms.Write(new byte[] {0xFF, 0xFE}, 0, 2); // Write Unicode BOM
|
||||
using (TextWriter tw = new StreamWriter(ms, new UnicodeEncoding()))
|
||||
for (int i = 0; i < lineData.Length; i++)
|
||||
{
|
||||
for (int i = 0; i < lineData.Length; i++)
|
||||
{
|
||||
// Get Strings for the File
|
||||
string[] data = lineData[i];
|
||||
string fn = lineData.GetFileName(i);
|
||||
WriteTextFile(tw, fn, data, newline);
|
||||
}
|
||||
// Get Strings for the File
|
||||
string[] data = lineData[i];
|
||||
string fn = lineData.GetFileName(i);
|
||||
WriteTextFile(tw, fn, data, newline);
|
||||
}
|
||||
File.WriteAllBytes(fileName, ms.ToArray());
|
||||
}
|
||||
File.WriteAllBytes(fileName, ms.ToArray());
|
||||
}
|
||||
|
||||
private static void WriteTextFile(TextWriter tw, string fn, string[] data, bool newline = false)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ public sealed partial class TypeChart : Form
|
|||
|
||||
public byte[] Chart { get; set; }
|
||||
public bool Modified { get; set; }
|
||||
private int TypeWidth => 32; // px
|
||||
private const int TypeWidth = 32; // px
|
||||
private int TypeCount => types.Length;
|
||||
|
||||
public TypeChart(TypeChartEditor editor, string[] types)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
|
|
@ -35,6 +36,7 @@
|
|||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>icon.ico</ApplicationIcon>
|
||||
|
|
|
|||
2
pkNX.WinForms/pkNX.WinForms.csproj.DotSettings
Normal file
2
pkNX.WinForms/pkNX.WinForms.csproj.DotSettings
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp80</s:String></wpf:ResourceDictionary>
|
||||
Loading…
Reference in New Issue
Block a user