mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-08-23 18:35:41 -05:00
Remove structconverter
Won't work on bigendian architecture for non-byte fields, so just do it manually.
This commit is contained in:
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user