mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-10 06:34:19 +00:00
SAV6AO: Fix dexnav get/set
Was looking in the wrong segment of save data. Now points to the correct span (pokedex). Extract a few more save blocks and interactions. Basically try to get rid of any remaining `SAV.Data` references. Still a few left, but aren't broken. Closes #4259
This commit is contained in:
parent
0f4024952e
commit
ad0c9b147d
15 changed files with 195 additions and 94 deletions
|
@ -19,4 +19,5 @@ public interface ISaveBlock6Main : ISaveBlock6Core
|
|||
MaisonBlock Maison { get; }
|
||||
SubEventLog6 SUBE { get; }
|
||||
Encount6 Encount { get; }
|
||||
HallOfFame6 HallOfFame { get; }
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
namespace PKHeX.Core;
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for Accessing named blocks within a Generation 6 save file.
|
||||
|
@ -9,4 +9,5 @@ public interface ISaveBlock6XY : ISaveBlock6Main
|
|||
Misc6XY Misc { get; }
|
||||
Zukan6XY Zukan { get; }
|
||||
Fashion6XY Fashion { get; }
|
||||
BerryField6XY BerryField { get; }
|
||||
}
|
||||
|
|
|
@ -91,6 +91,7 @@ public sealed class SaveBlockAccessor6AO(SAV6AO sav) : ISaveBlockAccessor<BlockI
|
|||
public OPower6 OPower { get; } = new(sav, Block(sav, 25));
|
||||
public GTS6 GTS { get; } = new(sav, Block(sav, 28));
|
||||
public Encount6 Encount { get; } = new(sav, Block(sav, 31));
|
||||
public HallOfFame6 HallOfFame { get; } = new(sav, Block(sav, 36));
|
||||
public MaisonBlock Maison { get; } = new(sav, Block(sav, 37));
|
||||
public Daycare6AO Daycare { get; } = new(sav, Block(sav, 38));
|
||||
public BerryField6AO BerryField { get; } = new(sav, Block(sav, 40));
|
||||
|
@ -99,6 +100,7 @@ public sealed class SaveBlockAccessor6AO(SAV6AO sav) : ISaveBlockAccessor<BlockI
|
|||
public RecordBlock6AO Records { get; } = new(sav, Block(sav, 44));
|
||||
public SuperTrainBlock SuperTrain { get; } = new(sav, Block(sav, 46));
|
||||
public LinkBlock6 Link { get; } = new(sav, Block(sav, 48));
|
||||
public Contest6 Contest { get; } = new(sav, Block(sav, 53));
|
||||
public SecretBase6Block SecretBase { get; } = new(sav, Block(sav, 54));
|
||||
public SangoInfoBlock Sango { get; } = new(sav, Block(sav, 55));
|
||||
|
||||
|
|
|
@ -89,8 +89,10 @@ public sealed class SaveBlockAccessor6XY(SAV6XY sav) : ISaveBlockAccessor<BlockI
|
|||
public OPower6 OPower { get; } = new(sav, Block(sav, 25));
|
||||
public GTS6 GTS { get; } = new(sav, Block(sav, 28));
|
||||
public Encount6 Encount { get; } = new(sav, Block(sav, 31));
|
||||
public HallOfFame6 HallOfFame { get; } = new(sav, Block(sav, 36));
|
||||
public MaisonBlock Maison { get; } = new(sav, Block(sav, 37));
|
||||
public Daycare6XY Daycare { get; } = new(sav, Block(sav, 38));
|
||||
public BerryField6XY BerryField { get; } = new(sav, Block(sav, 40));
|
||||
public MysteryBlock6 MysteryGift { get; } = new(sav, Block(sav, 41));
|
||||
public SubEventLog6XY SUBE { get; } = new(sav, Block(sav, 42));
|
||||
public RecordBlock6XY Records { get; } = new(sav, Block(sav, 44));
|
||||
|
|
|
@ -42,7 +42,6 @@ public sealed class SAV6AO : SAV6, ISaveBlock6AO, IMultiplayerSprite, IBoxDetail
|
|||
}
|
||||
|
||||
/// <summary> Offset of the Contest data block. </summary>
|
||||
public const int Contest = 0x23600;
|
||||
|
||||
#region Blocks
|
||||
public override IReadOnlyList<BlockInfo> AllBlocks => Blocks.BlockInfo;
|
||||
|
@ -71,6 +70,8 @@ public sealed class SAV6AO : SAV6, ISaveBlock6AO, IMultiplayerSprite, IBoxDetail
|
|||
public Zukan6AO Zukan => Blocks.Zukan;
|
||||
public SecretBase6Block SecretBase => Blocks.SecretBase;
|
||||
public BerryField6AO BerryField => Blocks.BerryField;
|
||||
public Contest6 Contest => Blocks.Contest;
|
||||
public HallOfFame6 HallOfFame => Blocks.HallOfFame;
|
||||
|
||||
MyItem ISaveBlock6Core.Items => Items;
|
||||
SubEventLog6 ISaveBlock6Main.SUBE => SUBE;
|
||||
|
|
|
@ -43,8 +43,6 @@ public sealed class SAV6XY : SAV6, ISaveBlock6XY, IMultiplayerSprite, IBoxDetail
|
|||
JPEG = 0x57200;
|
||||
}
|
||||
|
||||
public const int BerryField = 0x1B800;
|
||||
|
||||
#region Blocks
|
||||
public override IReadOnlyList<BlockInfo> AllBlocks => Blocks.BlockInfo;
|
||||
public override MyItem Items => Blocks.Items;
|
||||
|
@ -71,6 +69,8 @@ public sealed class SAV6XY : SAV6, ISaveBlock6XY, IMultiplayerSprite, IBoxDetail
|
|||
public SubEventLog6 SUBE => Blocks.SUBE;
|
||||
public ConfigSave6 Config => Blocks.Config;
|
||||
public Encount6 Encount => Blocks.Encount;
|
||||
public BerryField6XY BerryField => Blocks.BerryField;
|
||||
public HallOfFame6 HallOfFame => Blocks.HallOfFame;
|
||||
|
||||
IMysteryGiftStorage IMysteryGiftStorageProvider.MysteryGiftStorage => MysteryGift;
|
||||
#endregion
|
||||
|
|
19
PKHeX.Core/Saves/Substructures/Gen6/BerryField6XY.cs
Normal file
19
PKHeX.Core/Saves/Substructures/Gen6/BerryField6XY.cs
Normal file
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public sealed class BerryField6XY(SAV6XY sav, Memory<byte> raw) : SaveBlock<SAV6XY>(sav, raw)
|
||||
{
|
||||
// Is this the same as the BerryField6AO class?
|
||||
|
||||
public const int Size = 16; // bytes per entry
|
||||
public const int Count = 32; // 32+25 = 57 allocated?
|
||||
|
||||
private const int PlotStart = 0xC;
|
||||
|
||||
public Span<byte> GetPlot(int index)
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual((uint)index, (uint)Count);
|
||||
return Data.Slice(PlotStart + (index * Size), Size);
|
||||
}
|
||||
}
|
26
PKHeX.Core/Saves/Substructures/Gen6/Contest6.cs
Normal file
26
PKHeX.Core/Saves/Substructures/Gen6/Contest6.cs
Normal file
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public sealed class Contest6(SAV6AO sav, Memory<byte> raw) : SaveBlock<SAV6AO>(sav, raw)
|
||||
{
|
||||
public const int CountBlock = 12;
|
||||
public const uint MaxBlock = 999;
|
||||
|
||||
public uint GetBlockCount(int index)
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual((uint)index, (uint)CountBlock);
|
||||
return ReadUInt32LittleEndian(Data[(index * 4)..]);
|
||||
}
|
||||
|
||||
public void SetBlockCount(int index, uint value)
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual((uint)index, (uint)CountBlock);
|
||||
if (value > MaxBlock)
|
||||
value = MaxBlock;
|
||||
WriteUInt32LittleEndian(Data[(index * 4)..], value);
|
||||
}
|
||||
|
||||
// 0x48.. ???
|
||||
}
|
|
@ -57,3 +57,26 @@ public readonly ref struct HallFame6Entity
|
|||
set => StringConverter6.SetString(OriginalTrainerTrash, value, 12, Option);
|
||||
}
|
||||
}
|
||||
|
||||
public readonly ref struct HallFame6Index
|
||||
{
|
||||
public const int SIZE = 0x4;
|
||||
private readonly Span<byte> Data;
|
||||
// ReSharper disable once ConvertToPrimaryConstructor
|
||||
public HallFame6Index(Span<byte> data) => Data = data;
|
||||
|
||||
public uint Value { get => ReadUInt32LittleEndian(Data); set => WriteUInt32LittleEndian(Data, value); }
|
||||
|
||||
// Structure:
|
||||
// u32:14 - Clear Index (how many times Fame has been completed/cleared)
|
||||
// u32:08 - Year (since 2000)
|
||||
// u32:04 - Month
|
||||
// u32:05 - Day
|
||||
// u32:01 - Index has Data bool flag (0 = no data, 1 = has data)
|
||||
|
||||
public uint ClearIndex { get => Value & 0x3FFFu; set => Value = (Value & ~0x3FFFu) | (value & 0x3FFFu); }
|
||||
public uint Year { get => (Value >> 14) & 0xFFu; set => Value = (Value & ~(0xFFu << 14)) | ((value & 0xFFu) << 14); }
|
||||
public uint Month { get => (Value >> 22) & 0xFu; set => Value = (Value & ~(0xFu << 22)) | ((value & 0xFu) << 22); }
|
||||
public uint Day { get => (Value >> 26) & 0x1Fu; set => Value = (Value & ~(0x1Fu << 26)) | ((value & 0x1Fu) << 26); }
|
||||
public bool HasData { get => (Value >> 31) == 1; set => Value = (Value & ~(0x1u << 31)) | ((value ? 1u : 0u) << 31); }
|
||||
}
|
||||
|
|
58
PKHeX.Core/Saves/Substructures/Gen6/HallOfFame6.cs
Normal file
58
PKHeX.Core/Saves/Substructures/Gen6/HallOfFame6.cs
Normal file
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public sealed class HallOfFame6(SAV6 sav, Memory<byte> raw) : SaveBlock<SAV6>(sav, raw)
|
||||
{
|
||||
public const int Entries = 16; // First clear, and 15 most-recent entries.
|
||||
public const int PokeSize = HallFame6Entity.SIZE; // 0x48
|
||||
public const int PokeCount = 6;
|
||||
public const int EntrySize = (PokeCount * PokeSize) + HallFame6Index.SIZE; // 0x1B4
|
||||
|
||||
public const int MaxComplete = 9999;
|
||||
|
||||
public Span<byte> GetEntry(int index)
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual((uint)index, (uint)Entries);
|
||||
return Data.Slice(index * EntrySize, EntrySize);
|
||||
}
|
||||
|
||||
public uint GetInsertIndex(out uint clear)
|
||||
{
|
||||
// Check for empty slots (where player hasn't yet registered enough Fame clears)
|
||||
clear = 0;
|
||||
for (uint i = 0; i < Entries; i++)
|
||||
{
|
||||
var entry = GetEntry((int)i);
|
||||
var vnd = new HallFame6Index(entry[^4..]);
|
||||
if (!vnd.HasData)
|
||||
return clear = i;
|
||||
clear = vnd.ClearIndex;
|
||||
}
|
||||
|
||||
// No empty slots, return the last slot.
|
||||
ClearEntry(1);
|
||||
clear = new HallFame6Index(GetEntry(14)).ClearIndex + 1;
|
||||
return 15;
|
||||
}
|
||||
|
||||
public void ClearEntry(int index)
|
||||
{
|
||||
int offset = index * EntrySize;
|
||||
if (index != 15)
|
||||
{
|
||||
// Shift down
|
||||
var dest = Data[offset..];
|
||||
var above = Data.Slice(offset + EntrySize, EntrySize * (Entries - 1 - index));
|
||||
above.CopyTo(dest);
|
||||
}
|
||||
|
||||
// Ensure Last Entry is Cleared
|
||||
Data.Slice(EntrySize * (Entries - 1), EntrySize).Clear();
|
||||
}
|
||||
|
||||
public Span<byte> GetEntity(int team, int member)
|
||||
{
|
||||
return GetEntry(team).Slice(member * PokeSize, PokeSize);
|
||||
}
|
||||
}
|
|
@ -198,13 +198,13 @@ public sealed class Zukan6AO : Zukan6
|
|||
public ushort GetEncounterCount(int index)
|
||||
{
|
||||
var ofs = 0x686 + (index * 2);
|
||||
return ReadUInt16LittleEndian(SAV.Data.AsSpan(ofs));
|
||||
return ReadUInt16LittleEndian(Data[ofs..]);
|
||||
}
|
||||
|
||||
public void SetEncounterCount(int index, ushort value)
|
||||
{
|
||||
var ofs = 0x686 + (index * 2);
|
||||
WriteUInt16LittleEndian(SAV.Data.AsSpan(ofs), value);
|
||||
WriteUInt16LittleEndian(Data[ofs..], value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ namespace PKHeX.Core;
|
|||
public sealed class Zukan7b(SAV7b sav, Memory<byte> dex, int langflag) : Zukan7(sav, dex, langflag)
|
||||
{
|
||||
private const int UNSET = 0x007F00FE;
|
||||
private const int BaseOffset = 0x2A00;
|
||||
private const int EntryStart = 0xF78; // 0x3978 - 0x2A00
|
||||
private const int EntryCount = 186;
|
||||
private const int EntrySize = 6;
|
||||
|
@ -46,7 +45,7 @@ public sealed class Zukan7b(SAV7b sav, Memory<byte> dex, int langflag) : Zukan7(
|
|||
public bool GetSizeData(DexSizeType group, int index, out byte height, out byte weight, out bool isFlagged)
|
||||
{
|
||||
var ofs = GetDexSizeOffset(group, index);
|
||||
var entry = SAV.Data.AsSpan(ofs);
|
||||
var entry = Data.Slice(ofs, EntrySize);
|
||||
height = entry[0];
|
||||
isFlagged = entry[1] == 1;
|
||||
weight = entry[2];
|
||||
|
@ -66,7 +65,7 @@ public sealed class Zukan7b(SAV7b sav, Memory<byte> dex, int langflag) : Zukan7(
|
|||
if (pk.HeightAbsolute < pi.Height) // possible minimum height
|
||||
{
|
||||
int ofs = GetDexSizeOffset(DexSizeType.MinHeight, index);
|
||||
var entry = SAV.Data.AsSpan(ofs, EntrySize);
|
||||
var entry = Data.Slice(ofs, EntrySize);
|
||||
var minHeight = entry[0];
|
||||
if (pk.HeightScalar < minHeight || IsUnset(entry))
|
||||
SetSizeData(pk, DexSizeType.MinHeight);
|
||||
|
@ -74,7 +73,7 @@ public sealed class Zukan7b(SAV7b sav, Memory<byte> dex, int langflag) : Zukan7(
|
|||
else if (pk.HeightAbsolute > pi.Height) // possible maximum height
|
||||
{
|
||||
int ofs = GetDexSizeOffset(DexSizeType.MaxHeight, index);
|
||||
var entry = SAV.Data.AsSpan(ofs, EntrySize);
|
||||
var entry = Data.Slice(ofs, EntrySize);
|
||||
var maxHeight = entry[0];
|
||||
if (pk.HeightScalar > maxHeight || IsUnset(entry))
|
||||
SetSizeData(pk, DexSizeType.MaxHeight);
|
||||
|
@ -83,7 +82,7 @@ public sealed class Zukan7b(SAV7b sav, Memory<byte> dex, int langflag) : Zukan7(
|
|||
if (pk.WeightAbsolute < pi.Weight) // possible minimum weight
|
||||
{
|
||||
int ofs = GetDexSizeOffset(DexSizeType.MinWeight, index);
|
||||
var entry = SAV.Data.AsSpan(ofs, EntrySize);
|
||||
var entry = Data.Slice(ofs, EntrySize);
|
||||
var minHeight = entry[0];
|
||||
var minWeight = entry[2];
|
||||
var calcWeight = PB7.GetWeightAbsolute(pi, minHeight, minWeight);
|
||||
|
@ -93,7 +92,7 @@ public sealed class Zukan7b(SAV7b sav, Memory<byte> dex, int langflag) : Zukan7(
|
|||
else if (pk.WeightAbsolute > pi.Weight) // possible maximum weight
|
||||
{
|
||||
int ofs = GetDexSizeOffset(DexSizeType.MaxWeight, index);
|
||||
var entry = SAV.Data.AsSpan(ofs, EntrySize);
|
||||
var entry = Data.Slice(ofs, EntrySize);
|
||||
var maxHeight = entry[0];
|
||||
var maxWeight = entry[2];
|
||||
var calcWeight = PB7.GetWeightAbsolute(pi, maxHeight, maxWeight);
|
||||
|
@ -105,7 +104,7 @@ public sealed class Zukan7b(SAV7b sav, Memory<byte> dex, int langflag) : Zukan7(
|
|||
private static bool IsUnset(Span<byte> entry) => ReadUInt32LittleEndian(entry) == UNSET;
|
||||
|
||||
// blockofs + 0xF78 + ([186*6]*n) + x*6
|
||||
private static int GetDexSizeOffset(DexSizeType group, int index) => BaseOffset + EntryStart + (EntrySize * (index + ((int)group * EntryCount)));
|
||||
private static int GetDexSizeOffset(DexSizeType group, int index) => EntryStart + (EntrySize * (index + ((int)group * EntryCount)));
|
||||
|
||||
private void SetSizeData(PB7 pk, DexSizeType group, bool flag = false)
|
||||
{
|
||||
|
@ -131,7 +130,7 @@ public sealed class Zukan7b(SAV7b sav, Memory<byte> dex, int langflag) : Zukan7(
|
|||
public void SetSizeData(DexSizeType group, int index, byte height, byte weight, bool flag = false)
|
||||
{
|
||||
var ofs = GetDexSizeOffset(group, index);
|
||||
var span = SAV.Data.AsSpan(ofs);
|
||||
var span = Data.Slice(ofs, EntrySize);
|
||||
span[0] = height;
|
||||
span[1] = flag ? (byte)1 : (byte)0;
|
||||
span[2] = weight;
|
||||
|
|
|
@ -22,15 +22,15 @@ public partial class SAV_BerryFieldXY : Form
|
|||
// Change Berry Field
|
||||
|
||||
// Gather Data
|
||||
int ofs = SAV6XY.BerryField + 0xC + (listBox1.SelectedIndex * 0x18);
|
||||
int berry = ReadUInt16LittleEndian(SAV.Data.AsSpan(ofs + (2 * 0)));
|
||||
int u1 = ReadUInt16LittleEndian(SAV.Data.AsSpan(ofs + (2 * 1)));
|
||||
int u2 = ReadUInt16LittleEndian(SAV.Data.AsSpan(ofs + (2 * 2)));
|
||||
int u3 = ReadUInt16LittleEndian(SAV.Data.AsSpan(ofs + (2 * 3)));
|
||||
int u4 = ReadUInt16LittleEndian(SAV.Data.AsSpan(ofs + (2 * 4)));
|
||||
int u5 = ReadUInt16LittleEndian(SAV.Data.AsSpan(ofs + (2 * 5)));
|
||||
int u6 = ReadUInt16LittleEndian(SAV.Data.AsSpan(ofs + (2 * 6)));
|
||||
int u7 = ReadUInt16LittleEndian(SAV.Data.AsSpan(ofs + (2 * 7)));
|
||||
var span = SAV.BerryField.GetPlot(listBox1.SelectedIndex);
|
||||
int berry = ReadUInt16LittleEndian(span);
|
||||
int u1 = ReadUInt16LittleEndian(span[(2 * 1)..]);
|
||||
int u2 = ReadUInt16LittleEndian(span[(2 * 2)..]);
|
||||
int u3 = ReadUInt16LittleEndian(span[(2 * 3)..]);
|
||||
int u4 = ReadUInt16LittleEndian(span[(2 * 4)..]);
|
||||
int u5 = ReadUInt16LittleEndian(span[(2 * 5)..]);
|
||||
int u6 = ReadUInt16LittleEndian(span[(2 * 6)..]);
|
||||
int u7 = ReadUInt16LittleEndian(span[(2 * 7)..]);
|
||||
|
||||
// Display Data
|
||||
TB_Berry.Text = berry.ToString();
|
||||
|
@ -43,8 +43,5 @@ public partial class SAV_BerryFieldXY : Form
|
|||
TB_u7.Text = u7.ToString();
|
||||
}
|
||||
|
||||
private void B_Cancel_Click(object sender, EventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
private void B_Cancel_Click(object sender, EventArgs e) => Close();
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ using System.Drawing;
|
|||
using System.Windows.Forms;
|
||||
using PKHeX.Core;
|
||||
using PKHeX.Drawing.PokeSprite;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.WinForms;
|
||||
|
||||
|
@ -12,24 +11,19 @@ public partial class SAV_HallOfFame : Form
|
|||
{
|
||||
private readonly SAV6 Origin;
|
||||
private readonly SAV6 SAV;
|
||||
private readonly HallOfFame6 Fame;
|
||||
|
||||
private bool editing;
|
||||
|
||||
private readonly IReadOnlyList<string> gendersymbols = Main.GenderSymbols;
|
||||
private readonly Memory<byte> Raw;
|
||||
private Span<byte> Data => Raw.Span;
|
||||
|
||||
private const int Count = 16;
|
||||
private const int StructureSize = 0x1B4;
|
||||
private const int StructureTotal = Count * StructureSize;
|
||||
|
||||
public SAV_HallOfFame(SAV6 sav)
|
||||
{
|
||||
InitializeComponent();
|
||||
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
|
||||
SAV = (SAV6)(Origin = sav).Clone();
|
||||
Fame = ((ISaveBlock6Main)SAV).HallOfFame;
|
||||
|
||||
Raw = SAV.Data.AsSpan(SAV.HoF, StructureTotal).ToArray(); // Copy HoF section of save into Data
|
||||
Setup();
|
||||
LB_DataEntry.SelectedIndex = 0;
|
||||
NUP_PartyIndex_ValueChanged(this, EventArgs.Empty);
|
||||
|
@ -69,7 +63,7 @@ public partial class SAV_HallOfFame : Form
|
|||
|
||||
private void B_Close_Click(object sender, EventArgs e)
|
||||
{
|
||||
Origin.SetData(Data, SAV.HoF);
|
||||
Origin.CopyChangesFrom(SAV);
|
||||
Close();
|
||||
}
|
||||
|
||||
|
@ -79,17 +73,12 @@ public partial class SAV_HallOfFame : Form
|
|||
RTB.Font = new Font("Courier New", 8);
|
||||
RTB.LanguageOption = RichTextBoxLanguageOptions.DualFont;
|
||||
int index = LB_DataEntry.SelectedIndex;
|
||||
int offset = index * StructureSize;
|
||||
|
||||
uint vnd = ReadUInt32LittleEndian(Data[(offset + 0x1B0)..]);
|
||||
uint vn = vnd & 0xFF;
|
||||
TB_VN.Text = vn.ToString("000");
|
||||
var s = new List<string> { $"Entry #{vn}" };
|
||||
uint date = (vnd >> 14) & 0x1FFFF;
|
||||
uint month = (date >> 8) & 0xF;
|
||||
uint year = (date & 0xFF) + 2000;
|
||||
uint day = date >> 12;
|
||||
if (day == 0)
|
||||
var span = Fame.GetEntry(index);
|
||||
var vnd = new HallFame6Index(span[^4..]);
|
||||
TB_VN.Text = vnd.ClearIndex.ToString("000");
|
||||
var s = new List<string> { $"Entry #{vnd.ClearIndex}" };
|
||||
if (!vnd.HasData)
|
||||
{
|
||||
s.Add("No records in this slot.");
|
||||
groupBox1.Enabled = false;
|
||||
|
@ -100,7 +89,7 @@ public partial class SAV_HallOfFame : Form
|
|||
else
|
||||
{
|
||||
groupBox1.Enabled = true;
|
||||
var moncount = AddEntries(offset, s, year, month, day);
|
||||
var moncount = AddEntries(span, s, vnd);
|
||||
|
||||
if (sender != this)
|
||||
{
|
||||
|
@ -118,24 +107,25 @@ public partial class SAV_HallOfFame : Form
|
|||
RTB.Font = new Font("Courier New", 8);
|
||||
}
|
||||
|
||||
private int AddEntries(int offset, List<string> s, uint year, uint month, uint day)
|
||||
private int AddEntries(Span<byte> data, List<string> s, HallFame6Index vnd)
|
||||
{
|
||||
var year = vnd.Year + 2000;
|
||||
var month = vnd.Month;
|
||||
var day = vnd.Day;
|
||||
|
||||
s.Add($"Date: {year}/{month:00}/{day:00}");
|
||||
s.Add(string.Empty);
|
||||
CAL_MetDate.Value = new DateTime((int)year, (int)month, (int)day);
|
||||
int moncount = 0;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
var entry = new HallFame6Entity(Data.Slice(offset, HallFame6Entity.SIZE));
|
||||
var slice = data[(i * HallFame6Entity.SIZE)..];
|
||||
var entry = new HallFame6Entity(slice);
|
||||
if (entry.Species == 0)
|
||||
continue;
|
||||
|
||||
moncount++;
|
||||
AddEntryDescription(s, entry);
|
||||
|
||||
offset += HallFame6Entity.SIZE;
|
||||
}
|
||||
|
||||
return moncount;
|
||||
}
|
||||
|
||||
|
@ -164,12 +154,9 @@ public partial class SAV_HallOfFame : Form
|
|||
{
|
||||
editing = false;
|
||||
int index = LB_DataEntry.SelectedIndex;
|
||||
int offset = (index * StructureSize) + ((Convert.ToInt32(NUP_PartyIndex.Value) - 1) * HallFame6Entity.SIZE);
|
||||
|
||||
if (offset < 0)
|
||||
return;
|
||||
|
||||
var entry = new HallFame6Entity(Data.Slice(offset, HallFame6Entity.SIZE));
|
||||
var member = (Convert.ToInt32(NUP_PartyIndex.Value) - 1);
|
||||
var slice = Fame.GetEntity(index, member);
|
||||
var entry = new HallFame6Entity(slice);
|
||||
CB_Species.SelectedValue = (int)entry.Species;
|
||||
CB_HeldItem.SelectedValue = (int)entry.HeldItem;
|
||||
CB_Move1.SelectedValue = (int)entry.Move1;
|
||||
|
@ -206,10 +193,10 @@ public partial class SAV_HallOfFame : Form
|
|||
Validate_TextBoxes();
|
||||
|
||||
int index = LB_DataEntry.SelectedIndex;
|
||||
int partymember = Convert.ToInt32(NUP_PartyIndex.Value) - 1;
|
||||
int offset = (index * StructureSize) + (partymember * HallFame6Entity.SIZE);
|
||||
var span = Data.Slice(offset, HallFame6Entity.SIZE);
|
||||
var entry = new HallFame6Entity(span)
|
||||
int member = Convert.ToInt32(NUP_PartyIndex.Value) - 1;
|
||||
|
||||
var slice = Fame.GetEntity(index, member);
|
||||
var entry = new HallFame6Entity(slice)
|
||||
{
|
||||
Species = Convert.ToUInt16(CB_Species.SelectedValue),
|
||||
HeldItem = Convert.ToUInt16(CB_HeldItem.SelectedValue),
|
||||
|
@ -230,19 +217,15 @@ public partial class SAV_HallOfFame : Form
|
|||
OriginalTrainerGender = (uint)EntityGender.GetFromString(Label_OTGender.Text) & 1,
|
||||
};
|
||||
|
||||
offset = index * StructureSize;
|
||||
|
||||
uint vnd = 0;
|
||||
uint date = 0;
|
||||
vnd |= Convert.ToUInt32(TB_VN.Text) & 0xFF;
|
||||
date |= (uint)((CAL_MetDate.Value.Year - 2000) & 0xFF);
|
||||
date |= (uint)((CAL_MetDate.Value.Month & 0xF) << 8);
|
||||
date |= (uint)((CAL_MetDate.Value.Day & 0x1F) << 12);
|
||||
vnd |= (date & 0x1FFFF) << 14;
|
||||
//Fix for top bit
|
||||
uint rawvnd = ReadUInt32LittleEndian(Data[(offset + 0x1B0)..]);
|
||||
vnd |= rawvnd & 0x80000000;
|
||||
WriteUInt32LittleEndian(Data[(offset + 0x1B0)..], vnd);
|
||||
var span = Fame.GetEntry(index);
|
||||
_ = new HallFame6Index(span[^4..])
|
||||
{
|
||||
ClearIndex = Convert.ToUInt16(TB_VN.Text),
|
||||
Year = (uint)CAL_MetDate.Value.Year - 2000,
|
||||
Month = (uint)CAL_MetDate.Value.Month,
|
||||
Day = (uint)CAL_MetDate.Value.Day,
|
||||
HasData = true,
|
||||
};
|
||||
|
||||
var shiny = entry.IsShiny ? Shiny.Always : Shiny.Never;
|
||||
bpkx.Image = SpriteUtil.GetSprite(entry.Species, entry.Form, (byte)entry.Gender, 0, entry.HeldItem, false, shiny, EntityContext.Gen6);
|
||||
|
@ -372,17 +355,7 @@ public partial class SAV_HallOfFame : Form
|
|||
if (prompt != DialogResult.Yes)
|
||||
return;
|
||||
|
||||
int offset = index * StructureSize;
|
||||
if (index != 15)
|
||||
{
|
||||
// Shift down
|
||||
var dest = Data[offset..];
|
||||
var above = Data.Slice(offset + StructureSize, StructureSize * (Count - 1 - index));
|
||||
above.CopyTo(dest);
|
||||
}
|
||||
|
||||
// Ensure Last Entry is Cleared
|
||||
Data.Slice(StructureSize * (Count - 1), StructureSize).Clear();
|
||||
Fame.ClearEntry(index);
|
||||
DisplayEntry(LB_DataEntry, EventArgs.Empty);
|
||||
}
|
||||
|
||||
|
@ -395,8 +368,8 @@ public partial class SAV_HallOfFame : Form
|
|||
|
||||
var team = LB_DataEntry.SelectedIndex;
|
||||
var member = (int)NUP_PartyIndex.Value - 1;
|
||||
int offset = (team * (4 + (6 * HallFame6Entity.SIZE))) + (member * HallFame6Entity.SIZE);
|
||||
var nicktrash = Data.Slice(0x18 + offset, 26);
|
||||
var data = Fame.GetEntity(team, member);
|
||||
var nicktrash = data.Slice(0x18, 26);
|
||||
var text = tb.Text;
|
||||
SAV.SetString(nicktrash, text, 12, StringConverterOption.ClearZero);
|
||||
var d = new TrashEditor(tb, nicktrash, SAV, SAV.Generation);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System;
|
||||
using System.Windows.Forms;
|
||||
using PKHeX.Core;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.WinForms;
|
||||
|
||||
|
@ -18,11 +17,11 @@ public partial class SAV_PokeBlockORAS : Form
|
|||
nup_spec = [NUP_Red, NUP_Blue, NUP_Pink, NUP_Green, NUP_Yellow, NUP_Rainbow, NUP_RedPlus, NUP_BluePlus, NUP_PinkPlus, NUP_GreenPlus, NUP_YellowPlus, NUP_RainbowPlus];
|
||||
Label[] lbl_spec = [L_Red, L_Blue, L_Pink, L_Green, L_Yellow, L_Rainbow, L_RedPlus, L_BluePlus, L_PinkPlus, L_GreenPlus, L_YellowPlus, L_RainbowPlus];
|
||||
|
||||
var span = SAV.Data.AsSpan(SAV6AO.Contest);
|
||||
var contest = SAV.Contest;
|
||||
for (int i = 0; i < lbl_spec.Length; i++)
|
||||
{
|
||||
lbl_spec[i].Text = $"{GameInfo.Strings.pokeblocks[94 + i]}:";
|
||||
nup_spec[i].Value = ReadUInt32LittleEndian(span[(i * 4)..]);
|
||||
nup_spec[i].Value = contest.GetBlockCount(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,9 +34,9 @@ public partial class SAV_PokeBlockORAS : Form
|
|||
|
||||
private void B_Save_Click(object sender, EventArgs e)
|
||||
{
|
||||
var span = SAV.Data.AsSpan(SAV6AO.Contest);
|
||||
var contest = SAV.Contest;
|
||||
for (int i = 0; i < nup_spec.Length; i++)
|
||||
WriteUInt32LittleEndian(span[(i * 4)..], (uint)nup_spec[i].Value);
|
||||
contest.SetBlockCount(i, (uint)nup_spec[i].Value);
|
||||
Origin.CopyChangesFrom(SAV);
|
||||
Close();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue