mirror of
https://github.com/kwsch/PKHeX
synced 2025-02-17 05:48:44 +00:00
Add more savedata abstractions
Array sizes for the top level structures are now noted, should make it easier to determine the shape of them & offsets.
This commit is contained in:
parent
5b04a10fa3
commit
95bdde69a7
6 changed files with 65 additions and 36 deletions
|
@ -21,10 +21,10 @@ namespace PKHeX.Core
|
|||
Work = new FlagWork8b(this, 0x00004);
|
||||
Items = new MyItem8b(this, 0x0563C);
|
||||
Underground = new UndergroundItemList8b(this, 0x111BC);
|
||||
// saveItemShortcut
|
||||
// saveItemShortcut; ushort[4]
|
||||
PartyInfo = new Party8b(this, 0x14098);
|
||||
BoxLayout = new BoxLayout8b(this, 0x148AA);
|
||||
// Box[]
|
||||
// Box[40]
|
||||
|
||||
// PLAYER_DATA:
|
||||
Config = new ConfigSave8b(this, 0x79B74); // size: 0x40
|
||||
|
@ -37,28 +37,29 @@ namespace PKHeX.Core
|
|||
// 0x7E9F8 - Menu selections (TopMenuItemTypeInt32, bool IsNew)[8], TopMenuItemTypeInt32 LastSelected
|
||||
// 0x7EA3C - _FIELDOBJ_SAVE Objects[1000] (sizeof (0x44, 17 int fields), total size 0x109A0
|
||||
Records = new Record8b(this, 0x8F3DC); // size: 0x78
|
||||
// 0x8F454 - ENC_SV_DATA
|
||||
// 0x8F454 - ENC_SV_DATA; 21 honey trees, 3 sway grass info, 2 mvpoke
|
||||
// PLAYER_SAVE_DATA
|
||||
// SaveBallDecoData
|
||||
// SaveBallDecoData CapsuleData[99], AffixSealData[20]
|
||||
SealList = new SealList8b(this, 0x93E0C); // size: 0x960 SaveSealData[200]
|
||||
// _RANDOM_GROUP
|
||||
// FIeldGimmickSaveData; int[3] gearRotate
|
||||
BerryTrees = new BerryTreeGrowSave8b(this, 0x94DA8); // size: 0x808
|
||||
Poffins = new PoffinSaveData8b(this, 0x955B0); // size: 0x644
|
||||
BattleTower = new BattleTowerWork8b(this, 0x95BF4); // size: 0x1B8
|
||||
System = new SystemData8b(this, 0x95DAC);
|
||||
Poketch = new Poketch8b(this, 0); // todo
|
||||
Daycare = new Daycare8b(this, 0x96080); // 0x2C0
|
||||
// 0x96340 - _DENDOU_SAVEDATA
|
||||
// BadgeSaveData
|
||||
// BoukenNote
|
||||
// TV_DATA
|
||||
// 0x96340 - _DENDOU_SAVEDATA; DENDOU_RECORD[30], POKEMON_DATA_INSIDE[6], ushort[4] ?
|
||||
// BadgeSaveData; byte[8]
|
||||
// BoukenNote; byte[24]
|
||||
// TV_DATA (int[48], TV_STR_DATA[42]), (int[37], bool[37])*2, (int[8], int[8]), TV_STR_DATA[10]; 144 128bit zeroed (900 bytes?)?
|
||||
UgSaveData = new UgSaveData8b(this, 0x9A89C); // size: 0x27A0
|
||||
// 0x9D03C - GMS_DATA // size: 0x31304
|
||||
// 0xCE340 - PLAYER_NETWORK_DATA
|
||||
// 0x9D03C - GMS_DATA // size: 0x31304, (GMS_POINT_DATA[650], ushort, ushort, byte)?; substructure GMS_POINT_HISTORY_DATA[5]
|
||||
// 0xCE340 - PLAYER_NETWORK_DATA; bcatFlagArray byte[1300]
|
||||
// UnionSaveData
|
||||
// CON_PHOTO_LANG_DATA -- contest photo language data
|
||||
// ZUKAN_PERSONAL_RND_DATA
|
||||
// CON_PHOTO_EXT_DATA[]
|
||||
// CON_PHOTO_LANG_DATA -- contest photo language data; photo_data[5], photo_fx[5]
|
||||
// ZUKAN_PERSONAL_RND_DATA -- Spinda PID storage; uint[4] see, uint[4] get, uint[17] reserve
|
||||
// CON_PHOTO_EXT_DATA[5]
|
||||
// GMS_POINT_HISTORY_EXT_DATA[]
|
||||
// UgCountRecord
|
||||
// ReBuffnameData
|
||||
|
@ -66,12 +67,11 @@ namespace PKHeX.Core
|
|||
|
||||
// v1.1 additions
|
||||
// 0xE9828 -- RECORD_ADD_DATA: 0x30-sized[12] (0x120 bytes)
|
||||
// MysteryGiftSaveData
|
||||
// ZUKAN_PERSONAL_RND_DATA -- Spinda PID storage (17 * 2)
|
||||
// POKETCH_POKETORE_COUNT_ARRAY -- (u16 species, u16 unused, i32 count, i32 reserved, i32 reserved) = 0x10bytes
|
||||
// PLAYREPORT_DATA -- reporting player progress online?
|
||||
// MysteryGiftSaveData, RecvData[50], byte[0x100] receiveFlag, OneDayData[10], uint[66] reserve
|
||||
// POKETCH_POKETORE_COUNT_ARRAY -- (u16 species, u16 unused, i32 count, i32 reserved, i32 reserved)[3] = 0x10bytes
|
||||
// PLAYREPORT_DATA -- reporting player progress online? 248 bytes?
|
||||
// MT_DATA mtData; -- 0x400 bytes
|
||||
// DENDOU_SAVE_ADD -- language tracking of members (hall of fame?)
|
||||
// DENDOU_SAVE_ADD -- language tracking of members (hall of fame?); ADD_POKE_MEMBER[30], ADD_POKE[6]
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ namespace PKHeX.Core
|
|||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x5634);
|
||||
}
|
||||
|
||||
public float TimeScale
|
||||
public float TimeScale // default 1440.0f
|
||||
{
|
||||
get => BitConverter.ToSingle(Data, 0x5638);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x5638);
|
||||
|
|
|
@ -13,6 +13,15 @@ namespace PKHeX.Core
|
|||
public const int ItemSaveSize = 3000;
|
||||
|
||||
public MyItem8b(SAV8BS sav, int offset) : base(sav) => Offset = offset;
|
||||
|
||||
public void SetItemQuantity(ushort item, int quantity)
|
||||
{
|
||||
var ofs = InventoryPouch8b.GetItemOffset(item, Offset);
|
||||
var data = InventoryPouch8b.ReadItem(item, Data, Offset);
|
||||
data.Count = quantity;
|
||||
InventoryPouch8b.WriteItem(data, Data, ofs);
|
||||
}
|
||||
|
||||
public override IReadOnlyList<InventoryPouch> Inventory { get => ConvertToPouches(); set => LoadFromPouches(value); }
|
||||
|
||||
private IReadOnlyList<InventoryPouch> ConvertToPouches()
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace PKHeX.Core
|
|||
// int CookingCount;
|
||||
|
||||
// 0x640 bytes of data is for poffins
|
||||
public const int COUNT_POFFIN = 50;
|
||||
public const int COUNT_POFFIN = 50; // 100?
|
||||
public const int SIZE_POFFIN = 0x20;
|
||||
|
||||
public int CookingCount { get => BitConverter.ToInt32(Data, Offset + 0x640); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x640); }
|
||||
|
|
|
@ -9,12 +9,12 @@ namespace PKHeX.Core
|
|||
[TypeConverter(typeof(ExpandableObjectConverter))]
|
||||
public sealed class Poketch8b : SaveBlock
|
||||
{
|
||||
public const int APP_REGIST_MAX = 20;
|
||||
public const int POKETCH_MAP_MARK_MAX = 6;
|
||||
public const int POKETCH_DOTART_DATA_BYTESIZE = 192;
|
||||
public const int POKETCH_POKE_HISTORY_COUNT_MAX = 12;
|
||||
public const int APP_REGIST_MAX = 20; // bool array unlock flags
|
||||
public const int POKETCH_MAP_MARK_MAX = 6; // mark_map_pos[6]
|
||||
public const int POKETCH_DOTART_DATA_BYTESIZE = 192; // dotart data bytes
|
||||
public const int POKETCH_POKE_HISTORY_COUNT_MAX = 12; // poke_history[12]
|
||||
public const int POKETCH_PEDOMETER_MAX = 99999;
|
||||
public const int POKETCH_CALENDER_MONTH_MAX = 12;
|
||||
public const int POKETCH_CALENDER_MONTH_MAX = 12; // calendar markbit uint[12]
|
||||
|
||||
public Poketch8b(SAV8BS sav, int offset) : base(sav) => Offset = offset;
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ namespace PKHeX.Core
|
|||
{
|
||||
public const int COUNT_DIGPOINTS = 10;
|
||||
public const int COUNT_ENCOUNTERS = 15;
|
||||
public const int COUNT_FRIENDS = 50; // 100 total with Friends+Others, not sure if it's evenly split 50/50, or if this is actually correct.
|
||||
public const int COUNT_OTHERS = 50;
|
||||
public const int COUNT_FRIENDS = 100; // 100 total with Friends+Others, savedata ctor allocates 100 for FriendPlayerList
|
||||
public const int COUNT_OTHERS = 0; // unused
|
||||
public const int COUNT_TRAINERS = 100;
|
||||
|
||||
public const int SIZE_SECRETBASE = 0x14 + (MAX_STONE_STATUE * SIZE_STATUE) + 4; // 0x270
|
||||
|
@ -31,8 +31,8 @@ namespace PKHeX.Core
|
|||
// int ReturnUgZoneID; // 0x1528
|
||||
|
||||
// UGRecord ugRecord; (secret base, see below documentation), size 0x270
|
||||
// UgPlayerInfo[???] FriendPlayerList;
|
||||
// UgPlayerInfo[???] OtherPlayerList;
|
||||
// UgPlayerInfo[100] FriendPlayerList;
|
||||
// UgPlayerInfo[0] OtherPlayerList; // unused
|
||||
// byte[100] TalkedNPCsID;
|
||||
|
||||
private const int OFS_DIGPOINT = 0x24;
|
||||
|
@ -107,6 +107,21 @@ namespace PKHeX.Core
|
|||
public void ClearNPC() => GetTrainers().Fill(0);
|
||||
public void ClearNPC(int start, int count = COUNT_TRAINERS) => FillNPC(0, start, count);
|
||||
|
||||
public int TalkedNPC // Spiritomb Trainer Count (duplicates OK)
|
||||
{
|
||||
get
|
||||
{
|
||||
var tr = GetTrainers();
|
||||
int ctr = 0;
|
||||
foreach (var t in tr)
|
||||
{
|
||||
if (t != 0)
|
||||
ctr++;
|
||||
}
|
||||
return ctr;
|
||||
}
|
||||
}
|
||||
|
||||
public void FillNPC(byte value, int start = 0, int count = COUNT_TRAINERS)
|
||||
{
|
||||
if ((uint)start + (uint)count > COUNT_TRAINERS)
|
||||
|
|
|
@ -21,14 +21,10 @@ namespace PKHeX.Core
|
|||
foreach (var index in LegalItems)
|
||||
{
|
||||
var ofs = GetItemOffset(index, Offset);
|
||||
var count = BitConverter.ToInt32(data, ofs);
|
||||
if (count == 0)
|
||||
var item = ReadItem(index, data, ofs);
|
||||
if (item.Count == 0)
|
||||
continue;
|
||||
|
||||
bool isNew = BitConverter.ToInt32(data, ofs + 4) == 0;
|
||||
bool isFavorite = BitConverter.ToInt32(data, ofs + 0x8) == 1;
|
||||
// ushort sortOrder = BitConverter.ToUInt16(data, ofs + 0xE);
|
||||
Items[ctr++] = new InventoryItem { Index = index, Count = count, New = isNew, FreeSpace = isFavorite };
|
||||
Items[ctr++] = item;
|
||||
}
|
||||
|
||||
while (ctr != LegalItems.Length)
|
||||
|
@ -73,6 +69,15 @@ namespace PKHeX.Core
|
|||
|
||||
public static int GetItemOffset(ushort index, int baseOffset) => baseOffset + (SIZE_ITEM * index);
|
||||
|
||||
public static InventoryItem ReadItem(ushort index, byte[] data, int ofs)
|
||||
{
|
||||
var count = BitConverter.ToInt32(data, ofs);
|
||||
bool isNew = BitConverter.ToInt32(data, ofs + 4) == 0;
|
||||
bool isFavorite = BitConverter.ToInt32(data, ofs + 0x8) == 1;
|
||||
// ushort sortOrder = BitConverter.ToUInt16(data, ofs + 0xE);
|
||||
return new InventoryItem { Index = index, Count = count, New = isNew, FreeSpace = isFavorite };
|
||||
}
|
||||
|
||||
public static void WriteItem(InventoryItem item, byte[] data, int ofs)
|
||||
{
|
||||
BitConverter.GetBytes((uint)item.Count).CopyTo(data, ofs);
|
||||
|
|
Loading…
Add table
Reference in a new issue