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:
Kurt 2019-10-15 18:47:20 -07:00
parent 0a6146b47d
commit 537ce93efa
70 changed files with 1770 additions and 1856 deletions

View File

@ -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();

View File

@ -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();

View File

@ -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);
}
}
}

View File

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

View File

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

View File

@ -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();
}
}
}

View File

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

View File

@ -1,8 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net46</TargetFrameworks>
<Description>Packing &amp; Unpacking</Description>
<LangVersion>8</LangVersion>
</PropertyGroup>
<ItemGroup>

View File

@ -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() { }

View File

@ -2,6 +2,5 @@
{
public class EditorBase
{
}
}

View File

@ -1,6 +1,6 @@
namespace pkNX.Game
{
class EditorFactory
public class EditorFactory
{
}
}

View File

@ -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++)
{

View File

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

View File

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

View File

@ -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))
};
}
}
}

View File

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

View File

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

View File

@ -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.")]

View File

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

View File

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

View File

@ -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>();

View File

@ -2,6 +2,5 @@ namespace pkNX.Randomization
{
public class RandSettings
{
}
}

View File

@ -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)); // *
}

View File

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

View File

@ -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);
}

View File

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

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}

View File

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

View File

@ -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();
}
}
}

View File

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

View File

@ -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 &amp; 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>

View File

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

View File

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

View File

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

View File

@ -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();
}
}
}

View File

@ -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();

View File

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

View File

@ -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); }
}
}

View File

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

View File

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

View File

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

View File

@ -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.")
};
}
}
}

View File

@ -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))
};
}
}
}

View File

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

View File

@ -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 },
};
}
}

View File

@ -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);
}
}

View File

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

View File

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

View File

@ -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();
}
}
}

View File

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

View File

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

View File

@ -5,6 +5,8 @@ namespace pkNX.Structures
[Flags]
public enum TrainerAI : byte
{
None = 0,
Basic = 1 << 0,
Strong = 1 << 1,
Expert = 1 << 2,

View File

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

View File

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

View File

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

View File

@ -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)
};
}
}
}

View File

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

View File

@ -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);
}
}

View File

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

View File

@ -9,7 +9,8 @@ internal class EditorUU : EditorBase
public void TestButton()
{
new Form().ShowDialog();
using var form = new Form();
form.ShowDialog();
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

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