Remove structconverter

Won't work on bigendian architecture for non-byte fields, so just do it manually.
This commit is contained in:
Kurt
2022-03-25 19:47:23 -07:00
parent 51f2fe35a4
commit 8bf618008a
8 changed files with 68 additions and 124 deletions

View File

@@ -150,18 +150,16 @@ public PokeBlock3Case PokeBlocks
protected override int SeenOffset2 => 0x988;
public DecorationInventory3 Decorations
{
get => Large.Slice(0x2734, DecorationInventory3.SIZE).ToStructure<DecorationInventory3>();
set => SetData(Large, value.ToBytes(), 0x2734);
}
public DecorationInventory3 Decorations => new(Large.AsSpan(0x2734, DecorationInventory3.SIZE));
public Swarm3 Swarm
{
get => Large.Slice(0x2B90, Swarm3.SIZE).ToClass<Swarm3>();
set => SetData(Large, value.ToBytesClass(), 0x2B90);
get => new(Large.Slice(0x2B90, Swarm3.SIZE));
set => SetData(Large, value.Data, 0x2B90);
}
private void ClearSwarm() => Large.AsSpan(0x2B90, Swarm3.SIZE).Clear();
public IReadOnlyList<Swarm3> DefaultSwarms => Swarm3Details.Swarms_E;
public int SwarmIndex
@@ -170,7 +168,10 @@ public int SwarmIndex
set
{
var arr = DefaultSwarms;
Swarm = (uint)value >= arr.Count ? new Swarm3() : arr[value];
if ((uint)value >= arr.Count)
ClearSwarm();
else
Swarm = arr[value];
}
}

View File

@@ -113,18 +113,16 @@ public PokeBlock3Case PokeBlocks
protected override int SeenOffset2 => 0x938;
public DecorationInventory3 Decorations
{
get => Large.Slice(0x26A0, DecorationInventory3.SIZE).ToStructure<DecorationInventory3>();
set => SetData(Large, value.ToBytes(), 0x26A0);
}
public DecorationInventory3 Decorations => new(Large.AsSpan(0x26A0, DecorationInventory3.SIZE));
public Swarm3 Swarm
{
get => Large.Slice(0x2AFC, Swarm3.SIZE).ToClass<Swarm3>();
set => SetData(Large, value.ToBytesClass(), 0x2AFC);
get => new(Large.Slice(0x2AFC, Swarm3.SIZE));
set => SetData(Large, value.Data, 0x2AFC);
}
private void ClearSwarm() => Large.AsSpan(0x2AFC, Swarm3.SIZE).Clear();
public IReadOnlyList<Swarm3> DefaultSwarms => Swarm3Details.Swarms_RS;
public int SwarmIndex
@@ -133,7 +131,10 @@ public int SwarmIndex
set
{
var arr = DefaultSwarms;
Swarm = (uint)value >= arr.Count ? new Swarm3() : arr[value];
if ((uint)value >= arr.Count)
ClearSwarm();
else
Swarm = arr[value];
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core
@@ -177,16 +178,15 @@ public int Badges16
public PokegearNumber[] GetPokeGearRoloDex()
{
var arr = new PokegearNumber[GearMaxCallers];
for (int i = 0; i < arr.Length; i++)
arr[i] = GetCallerAtIndex(i);
return arr;
var arr = General.AsSpan(OFS_GearRolodex, GearMaxCallers);
return MemoryMarshal.Cast<byte, PokegearNumber>(arr).ToArray();
}
public void SetPokeGearRoloDex(IReadOnlyList<PokegearNumber> value)
public void SetPokeGearRoloDex(ReadOnlySpan<PokegearNumber> value)
{
for (int i = 0; i < value.Count; i++)
SetCallerAtIndex(i, value[i]);
if (value.Length > GearMaxCallers)
throw new ArgumentOutOfRangeException(nameof(value));
MemoryMarshal.Cast<PokegearNumber, byte>(value).CopyTo(General.AsSpan(OFS_GearRolodex, GearMaxCallers));
}
public void PokeGearUnlockAllCallers()

View File

@@ -1,27 +1,23 @@
using System.Runtime.InteropServices;
using System;
using System.Runtime.InteropServices;
namespace PKHeX.Core
{
[StructLayout(LayoutKind.Sequential)]
public readonly struct DecorationInventory3
public readonly ref struct DecorationInventory3
{
public const int SIZE = 150;
private readonly Span<byte> Data;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public readonly Decoration3[] Desk;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public readonly Decoration3[] Chair;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public readonly Decoration3[] Plant;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)]
public readonly Decoration3[] Ornament;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)]
public readonly Decoration3[] Mat;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public readonly Decoration3[] Poster;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
public readonly Decoration3[] Doll;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public readonly Decoration3[] Cushion;
public DecorationInventory3(Span<byte> data) => Data = data;
public Span<Decoration3> Desk => MemoryMarshal.Cast<byte, Decoration3>(Data[..10]);
public Span<Decoration3> Chair => MemoryMarshal.Cast<byte, Decoration3>(Data.Slice(10, 10));
public Span<Decoration3> Plant => MemoryMarshal.Cast<byte, Decoration3>(Data.Slice(20, 10));
public Span<Decoration3> Ornament => MemoryMarshal.Cast<byte, Decoration3>(Data.Slice(30, 30));
public Span<Decoration3> Mat => MemoryMarshal.Cast<byte, Decoration3>(Data.Slice(60, 30));
public Span<Decoration3> Poster => MemoryMarshal.Cast<byte, Decoration3>(Data.Slice(90, 10));
public Span<Decoration3> Doll => MemoryMarshal.Cast<byte, Decoration3>(Data.Slice(100, 40));
public Span<Decoration3> Cushion => MemoryMarshal.Cast<byte, Decoration3>(Data.Slice(140, 10));
}
}

View File

@@ -10,7 +10,7 @@ public interface IGen3Hoenn
RTC3 ClockInitial { get; set; }
RTC3 ClockElapsed { get; set; }
PokeBlock3Case PokeBlocks { get; set; }
DecorationInventory3 Decorations { get; set; }
DecorationInventory3 Decorations { get; }
Swarm3 Swarm { get; set; }
IReadOnlyList<Swarm3> DefaultSwarms { get; }

View File

@@ -1,46 +0,0 @@
using System;
using System.Runtime.InteropServices;
namespace PKHeX.Core
{
public static class StructConverter
{
public static T ToStructure<T>(this byte[] bytes) where T : struct
{
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
try { return (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); }
finally { handle.Free(); }
}
public static T ToClass<T>(this byte[] bytes) where T : class
{
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
try { return (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); }
finally { handle.Free(); }
}
public static byte[] ToBytesClass<T>(this T obj) where T : class
{
int size = Marshal.SizeOf(obj);
byte[] arr = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(obj, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
public static byte[] ToBytes<T>(this T obj) where T : struct
{
int size = Marshal.SizeOf(obj);
byte[] arr = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(obj, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
}
}

View File

@@ -1,6 +1,8 @@
using System.Runtime.InteropServices;
using System;
using System.Runtime.InteropServices;
using static PKHeX.Core.Move;
using static PKHeX.Core.Species;
using static System.Buffers.Binary.BinaryPrimitives;
namespace PKHeX.Core
{
@@ -8,24 +10,27 @@ namespace PKHeX.Core
public sealed class Swarm3
{
public const int SIZE = 0x14;
public readonly byte[] Data;
public ushort Gen3Species { get; set; }
public byte MapNum { get; set; }
public byte MapGroup { get; set; }
public byte Level { get; set; }
public byte Unused1 { get; set; }
public ushort Unused2 { get; set; }
public ushort Move1 { get; set; }
public ushort Move2 { get; set; }
public ushort Move3 { get; set; }
public ushort Move4 { get; set; }
public byte Unused3 { get; set; }
public byte EncounterProbability { get; set; }
public ushort DaysLeft { get; set; }
private Span<byte> Raw => Data.AsSpan();
public Swarm3() {}
public ushort Gen3Species { get => ReadUInt16LittleEndian(Raw); set => WriteUInt16LittleEndian(Raw, value); }
public byte MapNum { get => Raw[2]; set => Raw[2] = value; }
public byte MapGroup { get => Raw[3]; set => Raw[3] = value; }
public byte Level { get => Raw[4]; set => Raw[4] = value; }
public byte Unused1 { get => Raw[5]; set => Raw[5] = value; }
public ushort Unused2 { get => ReadUInt16LittleEndian(Raw[0x6..]); set => WriteUInt16LittleEndian(Raw[0x6..], value); }
public ushort Move1 { get => ReadUInt16LittleEndian(Raw[0x8..]); set => WriteUInt16LittleEndian(Raw[0x8..], value); }
public ushort Move2 { get => ReadUInt16LittleEndian(Raw[0xA..]); set => WriteUInt16LittleEndian(Raw[0xA..], value); }
public ushort Move3 { get => ReadUInt16LittleEndian(Raw[0xC..]); set => WriteUInt16LittleEndian(Raw[0xC..], value); }
public ushort Move4 { get => ReadUInt16LittleEndian(Raw[0xE..]); set => WriteUInt16LittleEndian(Raw[0xE..], value); }
public byte Unused3 { get => Raw[0x10]; set => Raw[0x10] = value; }
public byte EncounterProbability { get => Raw[0x11]; set => Raw[0x11] = value; }
public ushort DaysLeft { get => ReadUInt16LittleEndian(Raw[0x12..]); set => WriteUInt16LittleEndian(Raw[0x12..], value); }
public Swarm3(Species species, byte level, byte map, Move m1, Move m2 = 0, Move m3 = 0, Move m4 = 0)
public Swarm3(byte[] data) => Data = data;
public Swarm3(Species species, byte level, byte map, Move m1, Move m2 = 0, Move m3 = 0, Move m4 = 0) : this(new byte[SIZE])
{
Gen3Species = (ushort)SpeciesConverter.GetG3Species((int)species);
Level = level;

View File

@@ -3,27 +3,14 @@
using PKHeX.Core;
using Xunit;
namespace PKHeX.Tests.General
namespace PKHeX.Tests.General;
public class MarshalTests
{
public class MarshalTests
[Fact]
public void MarshalSize()
{
[Fact]
public void MarshalStructure()
{
new DecorationInventory3().ToBytes().Length.Should().Be(DecorationInventory3.SIZE);
}
[Fact]
public void MarshalClass()
{
new Swarm3().ToBytesClass().Length.Should().Be(Swarm3.SIZE);
}
[Fact]
public void MarshalSize()
{
Marshal.SizeOf(typeof(NPCLock)).Should().Be(8);
Marshal.SizeOf(typeof(PIDIV)).Should().Be(8);
}
Marshal.SizeOf(typeof(NPCLock)).Should().Be(8);
Marshal.SizeOf(typeof(PIDIV)).Should().Be(8);
}
}