Add automatic byteswap

This commit is contained in:
Kurt 2020-09-30 22:46:07 -07:00
parent ee207a3fda
commit 2c8e0bc8f7
4 changed files with 104 additions and 27 deletions

View file

@ -52,6 +52,16 @@ namespace PKHeX.Core
public override int GetPartyOffset(int slot) => -1;
private readonly bool IsPairSwapped;
protected override byte[] GetFinalData()
{
var result = base.GetFinalData();
if (IsPairSwapped)
BigEndian.SwapBytes32(result = (byte[])result.Clone());
return result;
}
public override bool ChecksumsValid => GetBoxChecksumsValid();
protected override void SetChecksums() => SetBoxChecksums();
@ -104,6 +114,12 @@ namespace PKHeX.Core
public SAV1Stadium(byte[] data, bool japanese) : base(data)
{
Japanese = japanese;
var swap = StadiumUtil.IsMagicPresentSwap(data, TeamSize, MAGIC_POKE);
if (swap)
{
BigEndian.SwapBytes32(Data);
IsPairSwapped = true;
}
Box = 0xC000;
}
@ -163,34 +179,20 @@ namespace PKHeX.Core
base.WriteBoxSlot(pkm, Data, offset);
}
private const int MAGIC_POKE = 0x454B4F50;
private const uint MAGIC_POKE = 0x454B4F50;
public static bool IsStadiumU(byte[] data)
{
if (data.Length != SaveUtil.SIZE_G1STAD)
return false;
// Check footers of first few teams to see if the magic value is there.
for (int i = 0; i < 10; i++)
{
if (BitConverter.ToUInt32(data, TeamSizeU - ListFooterSize + (i * TeamSizeU)) != MAGIC_POKE) // POKE
return false;
}
return true;
return StadiumUtil.IsMagicPresentEither(data, TeamSizeU, MAGIC_POKE);
}
public static bool IsStadiumJ(byte[] data)
{
if (data.Length != SaveUtil.SIZE_G1STAD)
return false;
// Check footers of first few teams to see if the magic value is there.
for (int i = 0; i < 10; i++)
{
if (BitConverter.ToUInt32(data, TeamSizeJ - ListFooterSize + (i * TeamSizeJ)) != MAGIC_POKE) // POKE
return false;
}
return true;
return StadiumUtil.IsMagicPresentEither(data, TeamSizeJ, MAGIC_POKE);
}
}

View file

@ -14,7 +14,7 @@ namespace PKHeX.Core
// Required since PK1 logic comparing a save file assumes the save file can be U/J
public int SaveRevision => 0;
public string SaveRevisionString => string.Empty;
public string SaveRevisionString => "0"; // so we're different from Japanese SAV1Stadium naming...
public bool Japanese => true;
public bool Korean => false;
@ -54,6 +54,16 @@ namespace PKHeX.Core
public override int GetPartyOffset(int slot) => -1;
private readonly bool IsPairSwapped;
protected override byte[] GetFinalData()
{
var result = base.GetFinalData();
if (IsPairSwapped)
BigEndian.SwapBytes32(result = (byte[])result.Clone());
return result;
}
public override bool ChecksumsValid => GetBoxChecksumsValid();
protected override void SetChecksums() => SetBoxChecksums();
@ -102,6 +112,12 @@ namespace PKHeX.Core
public SAV1StadiumJ(byte[] data) : base(data)
{
var swap = StadiumUtil.IsMagicPresentSwap(data, TeamSizeJ, MAGIC_POKE);
if (swap)
{
BigEndian.SwapBytes32(Data);
IsPairSwapped = true;
}
Box = 0x2500;
}
@ -156,20 +172,13 @@ namespace PKHeX.Core
base.WriteBoxSlot(pkm, Data, offset);
}
private const int MAGIC_POKE = 0x454B4F50;
private const uint MAGIC_POKE = 0x454B4F50;
public static bool IsStadiumJ(byte[] data)
{
if (data.Length != SaveUtil.SIZE_G1STADJ)
return false;
// Check footers of first few teams to see if the magic value is there.
for (int i = 0; i < 10; i++)
{
if (BitConverter.ToUInt32(data, TeamSizeJ - ListFooterSize + (i * TeamSizeJ)) != MAGIC_POKE) // POKE
return false;
}
return true;
return StadiumUtil.IsMagicPresentEither(data, TeamSizeJ, MAGIC_POKE);
}
}
}

View file

@ -0,0 +1,48 @@
using System;
namespace PKHeX.Core
{
public static class StadiumUtil
{
public static bool IsMagicPresentEither(byte[] data, int size, uint magic)
{
if (IsMagicPresent(data, size, magic))
return true;
if (IsMagicPresentSwap(data, size, magic))
return true;
return false;
}
public static bool IsMagicPresent(byte[] data, int size, uint magic)
{
// Check footers of first few teams to see if the magic value is there.
for (int i = 0; i < 10; i++)
{
if (BitConverter.ToUInt32(data, size - 6 + (i * size)) != magic)
return false;
}
return true;
}
public static bool IsMagicPresentSwap(byte[] data, int size, uint magic)
{
// Check footers of first few teams to see if the magic value is there.
var left = (ushort)magic;
var right = (ushort)(magic >> 16);
left = (ushort)((left >> 8) | (left << 8));
right = (ushort)((right >> 8) | (right << 8));
for (int i = 0; i < 10; i++)
{
var ofs = size - 6 + (i * size);
if (BitConverter.ToUInt16(data, ofs - 2) != left) // OP
return false;
if (BitConverter.ToUInt16(data, ofs + 4) != right) // EK
return false;
}
return true;
}
}
}

View file

@ -75,6 +75,24 @@ namespace PKHeX.Core
return data;
}
/// <summary>
/// Swaps byte ordering in a byte array based on 32bit value writes.
/// </summary>
/// <remarks>The <see cref="data"/> is reversed in-place.</remarks>
public static void SwapBytes32(byte[] data)
{
for (int i = 0; i < data.Length; i += 4)
{
byte tmp = data[0 + i];
data[0 + i] = data[3 + i];
data[3 + i] = tmp;
byte tmp1 = data[1 + i];
data[1 + i] = data[2 + i];
data[2 + i] = tmp1;
}
}
/// <summary>
/// Returns a 32-bit signed integer converted from bytes in a Binary Coded Decimal format byte array.
/// </summary>