public void Write(byte[] New_Pattern_Data) { if (Save_File.Save_Generation == SaveGeneration.GCN) { int PatternNameSize = Save_File.Save_Type == SaveType.Animal_Crossing ? 0x10 : 0x0A; Save_File.Write(Offset, ACString.GetBytes(Name, PatternNameSize)); Save_File.Write(Offset + PatternNameSize, Palette); Save_File.Write(Offset + 0x20, New_Pattern_Data); } else if (Save_File.Save_Type == SaveType.Wild_World) { Save_File.Write(Offset, New_Pattern_Data); // TODO: Town Name & Creator Name (Also for City Folk, New Leaf) Save_File.Write(Offset + 0x216, ACString.GetBytes(Name, 0x10)); Save_File.Write(Offset + 0x226, (byte)(((Palette & 0x0F) << 4) | (Concept & 0x0F))); } else if (Save_File.Save_Type == SaveType.City_Folk) { Save_File.Write(Offset, New_Pattern_Data); Save_File.Write(Offset + 0x84C, ACString.GetBytes(Name, 0x20)); Save_File.Write(Offset + 0x86F, Palette); } else if (Save_File.Save_Generation == SaveGeneration.N3DS) { Save_File.Write(Offset, ACString.GetBytes(Name, 0x2A)); Save_File.Write(Offset + 0x6C, New_Pattern_Data); // TODO: Write Palette (since it's customizable) } }
public Messageboard_Post(int offset) { Post = DataConverter.ReadString(offset, 0xC0); Post_String = Post.Clean(); Post_Date = new ACDate(DataConverter.ReadDataRaw(offset + 0xC0, 8)); //MessageBox.Show(string.Format("{0}\n\nPosted at:\n{1}", Post_String, Post_Date.Date_Time_String)); }
public House(int offset) { Offset = offset; Owning_Player_Name = DataConverter.ReadString(offset, 8).Trim(); Town_Name = DataConverter.ReadString(offset + 8, 8).Trim(); Player_ID = DataConverter.ReadUInt(offset + 0x10); Last_Entry_Date = new ACDate(DataConverter.ReadDataRaw(offset + 0x1C, 4)); Last_Upgrade_Date = new ACDate(DataConverter.ReadDataRaw(offset + 0x26, 4), true); //Garbage here House_Number = (byte)((offset - 0x9CE8) / 0x26B0); for (int i = 0; i < 3; i++) { Rooms[i] = new Room(DataConverter.ReadUShortArray(offset + 0x38 + i * 0x8A8, 0x454), i); } for (int i = 0; i < 10; i++) { Mailbox[i] = new Mail(offset + 0x1A30 + i * 0x12A); } for (int i = 0; i < 4; i++) { int local_Offset = offset + 0x25D4 + i * 0x8; Gyroid_Storage[i] = new Gyroid_Item(DataConverter.ReadUShort(local_Offset), DataConverter.ReadUInt(local_Offset + 4), DataConverter.ReadByte(local_Offset + 3)); } Gyroid_Message = DataConverter.ReadString(offset + 0x25F4, 0x80); Cockroach_Count = DataConverter.ReadByte(offset + 0x2648); //MessageBox.Show(Gyroid_Message.Clean()); }
public void Write(int offset, dynamic data, bool reversed = false, int stringLength = 0) { Type Data_Type = data.GetType(); NewMainForm.Debug_Manager.WriteLine(string.Format("Writing Data{2} of type {0} to offset {1}", Data_Type.Name, "0x" + offset.ToString("X"), //recasting a value shows it as original type? Data_Type.IsArray ? "" : " with value 0x" + (data.ToString("X"))), DebugLevel.Debug); if (!Data_Type.IsArray) { if (Data_Type == typeof(byte)) { Working_Save_Data[offset] = (byte)data; } else if (Data_Type == typeof(string)) { byte[] String_Byte_Buff = ACString.GetBytes((string)data, stringLength); Buffer.BlockCopy(String_Byte_Buff, 0, Working_Save_Data, offset, String_Byte_Buff.Length); } else { byte[] Byte_Array = BitConverter.GetBytes(data); if (reversed) { Array.Reverse(Byte_Array); } Buffer.BlockCopy(Byte_Array, 0, Working_Save_Data, offset, Byte_Array.Length); } } else { dynamic Data_Array = data; if (Data_Type == typeof(byte[])) { for (int i = 0; i < Data_Array.Length; i++) { Working_Save_Data[offset + i] = Data_Array[i]; } } else { int Data_Size = Marshal.SizeOf(Data_Array[0]); for (int i = 0; i < Data_Array.Length; i++) { byte[] Byte_Array = BitConverter.GetBytes(Data_Array[i]); if (reversed) { Array.Reverse(Byte_Array); } Byte_Array.CopyTo(Working_Save_Data, offset + i * Data_Size); } } } }
public override void Write() { SaveFile.Write(Offset, ACString.GetBytes(PlayerName, 8)); SaveFile.Write(Offset + 8, ACString.GetBytes(PlayerTownName, 8)); SaveFile.Write(Offset + 0x10, PlayerId, true); SaveFile.Write(Offset + 0x12, PlayerTownId, true); // Met Date SaveFile.Write(Offset + 0x1C, ACString.GetBytes(MetTownName, 8)); SaveFile.Write(Offset + 0x24, MetTownId, true); // Unknown 1 SaveFile.Write(Offset + 0x30, Friendship); SaveFile.Write(Offset + 0x31, Flags); // Letter Data }
public static void WriteString(int offset, string str, int maxSize) { byte[] strBytes = new byte[maxSize]; byte[] ACStringBytes = ACString.GetBytes(str, maxSize); if (ACStringBytes.Length <= maxSize) { ACStringBytes.CopyTo(strBytes, 0); if (str.Length < maxSize) { for (int i = (str.Length); i <= maxSize - 1; i++) { strBytes[i] = 0x20; } } //strBytes.CopyTo(MainForm.SaveBuffer, offset); } }
public Mail(int offset, bool Player_Mail = false) { this.Player_Mail = Player_Mail; Offset = Player_Mail ? offset : offset - 0x2A; if (Player_Mail) { Reciepiant_Name = DataConverter.ReadString(Offset, 8).Trim(); Reciepiant_Town_Name = DataConverter.ReadString(Offset + 8, 8).Trim(); Reciepiant_ID = DataConverter.ReadUInt(Offset + 0x10); Sender_Name = DataConverter.ReadString(Offset + 0x16, 8).Trim(); Sender_Town_Name = DataConverter.ReadString(Offset + 0x1E, 8).Trim(); Sender_ID = DataConverter.ReadUInt(Offset + 0x26); } Event_Flag = DataConverter.ReadByte(Offset + 0x2A); Unknown_1 = DataConverter.ReadByte(Offset + 0x2B); Present = new Item(DataConverter.ReadUShort(Offset + 0x2C)); Read = DataConverter.ReadByte(Offset + 0x2E); Unknown_2 = DataConverter.ReadByte(Offset + 0x2F); Sender_Type = DataConverter.ReadByte(Offset + 0x30); Stationary_Type = new Item((ushort)((0x20 << 8) + DataConverter.ReadByte(Offset + 0x31))); Message_Data = DataConverter.ReadString(Offset + 0x32, 0xF8); Message = Message_Data.Clean(); }
public void Write() { Type PlayerSaveInfoType = typeof(PlayerSaveInfo); Type PlayerDataType = typeof(PlayerData); foreach (var Field in PlayerSaveInfoType.GetFields(BindingFlags.Public | BindingFlags.Instance)) { if (Field.GetValue(Offsets) != null && !Field.Name.Contains("Count") && !Field.Name.Contains("Size")) { if (PlayerDataType.GetField(Field.Name) != null) { if (Field.FieldType == typeof(int) && (int)Field.GetValue(Offsets) != -1) { Type FieldType = typeof(PlayerData).GetField(Field.Name).FieldType; int DataOffset = Offset + (int)Field.GetValue(Offsets); //MessageBox.Show("Field Name: " + Field.Name + " | Data Offset: " + DataOffset.ToString("X")); if (Field.Name == "TownPassCardImage" && (SaveData.Save_Type == SaveType.New_Leaf || SaveData.Save_Type == SaveType.Welcome_Amiibo)) { SaveData.Write(DataOffset, Data.TownPassCardData); } else if (FieldType == typeof(string)) { SaveData.Write(DataOffset, ACString.GetBytes((string)PlayerDataType.GetField(Field.Name).GetValue(Data), (int)PlayerSaveInfoType.GetField(Field.Name + "Size").GetValue(Offsets))); } else if (FieldType == typeof(byte)) { if (SaveData.Save_Type == SaveType.Wild_World) { if (Field.Name == "HairColor") { byte Condensed_Data = (byte)(Data.HairColor & 0x0F); //Remove upper nibble just incase Condensed_Data += (byte)((Data.Tan & 0x0F) << 4); //Add in tan to the byte SaveData.Write(DataOffset, Condensed_Data); //MessageBox.Show("HairColor: " + Condensed_Data.ToString("X2")); } else if (Field.Name == "HairType") { byte Condensed_Data = (byte)(Data.FaceType & 0x0F); Condensed_Data += (byte)((Data.HairType & 0x0F) << 4); SaveData.Write(DataOffset, Condensed_Data); //MessageBox.Show("HairType: " + Condensed_Data.ToString("X2")); } else { SaveData.Write(DataOffset, (byte)PlayerDataType.GetField(Field.Name).GetValue(Data)); //MessageBox.Show("Hello! " + Field.Name + " Offset: " + DataOffset.ToString("X")); } } else if (SaveData.Save_Type == SaveType.City_Folk) { if (Field.Name == "Tan") { byte Shifted_Data = (byte)(Data.Tan << 1); //ACToolkit does this SaveData.Write(DataOffset, Shifted_Data); } else if (Field.Name == "FaceType") { SaveData.Write(DataOffset, (byte)(Data.EyeColor + Data.FaceType)); } else { SaveData.Write(DataOffset, (byte)PlayerDataType.GetField(Field.Name).GetValue(Data)); } } else { SaveData.Write(DataOffset, (byte)PlayerDataType.GetField(Field.Name).GetValue(Data)); } } else if (FieldType == typeof(ushort) || FieldType == typeof(uint)) { SaveData.Write(DataOffset, (dynamic)PlayerDataType.GetField(Field.Name).GetValue(Data), SaveData.Is_Big_Endian); } else if (FieldType == typeof(Inventory)) { if (SaveData.Save_Type == SaveType.New_Leaf || SaveData.Save_Type == SaveType.Welcome_Amiibo) { uint[] Items = new uint[Offsets.PocketsCount]; for (int i = 0; i < Items.Length; i++) { Items[i] = ItemData.EncodeItem(Data.Pockets.Items[i]); } SaveData.Write(DataOffset, Items); } else { ushort[] Items = new ushort[Offsets.PocketsCount]; for (int i = 0; i < Items.Length; i++) { Items[i] = Data.Pockets.Items[i].ItemID; } SaveData.Write(DataOffset, Items, SaveData.Is_Big_Endian); } } else if (FieldType == typeof(NL_Int32)) { if (SaveData.Save_Type == SaveType.New_Leaf || SaveData.Save_Type == SaveType.Welcome_Amiibo) { NL_Int32 Encrypted_Int = (NL_Int32)PlayerDataType.GetField(Field.Name).GetValue(Data); SaveData.Write(DataOffset, Encrypted_Int.Int_1); SaveData.Write(DataOffset + 4, Encrypted_Int.Int_2); } } } } } } }
public void Write() { var SaveData = MainForm.Save_File; var Offsets = HouseInfo.GetHouseOffsets(SaveData.Save_Type); // Set House TownID & Name if (Offsets.Owning_Player_Name != -1 && Owner != null && Offsets.Town_ID != -1) { Data.Town_ID = SaveData.ReadUInt16(SaveData.Save_Data_Start_Offset + MainForm.Current_Save_Info.Save_Offsets.Town_ID, SaveData.Is_Big_Endian); // Might not be UInt16 in all games } if (Offsets.Owning_Player_Name != -1 && Owner != null && Offsets.Town_Name != -1) { Data.Town_Name = SaveData.ReadString(SaveData.Save_Data_Start_Offset + MainForm.Current_Save_Info.Save_Offsets.Town_Name, MainForm.Current_Save_Info.Save_Offsets.Town_NameSize); } if (Offsets.Owning_Player_Name != -1 && Owner != null) { Data.Owning_Player_Name = Owner.Data.Name; } if (Offsets.Owning_Player_ID != -1 && Owner != null) { Data.Owning_Player_ID = Owner.Data.Identifier; } Type HouseOffsetData = typeof(HouseOffsets); Type HouseDataType = typeof(HouseData); foreach (var Field in HouseOffsetData.GetFields(BindingFlags.Public | BindingFlags.Instance)) { if (Field.GetValue(Offsets) != null && !Field.Name.Contains("Count") && !Field.Name.Contains("Size")) { if (HouseDataType.GetField(Field.Name) != null) { if (Field.FieldType == typeof(int) && (int)Field.GetValue(Offsets) != -1) { Type FieldType = HouseDataType.GetField(Field.Name).FieldType; int DataOffset = Offset + (int)Field.GetValue(Offsets); //MessageBox.Show("Field Name: " + Field.Name + " | Data Offset: " + DataOffset.ToString("X")); if (FieldType == typeof(string)) { SaveData.Write(DataOffset, ACString.GetBytes((string)HouseDataType.GetField(Field.Name).GetValue(Data), (int)HouseOffsetData.GetField(Field.Name + "Size").GetValue(Offsets))); } else if (FieldType == typeof(byte)) { SaveData.Write(DataOffset, (byte)HouseDataType.GetField(Field.Name).GetValue(Data)); } else if (FieldType == typeof(byte[])) { SaveData.Write(DataOffset, (byte[])HouseDataType.GetField(Field.Name).GetValue(Data)); } else if (FieldType == typeof(ushort)) { SaveData.Write(DataOffset, (ushort)HouseDataType.GetField(Field.Name).GetValue(Data), SaveData.Is_Big_Endian); } else if (FieldType == typeof(Item)) { if (SaveData.Save_Generation == SaveGeneration.N3DS) { SaveData.Write(DataOffset, ItemData.EncodeItem((Item)HouseDataType.GetField(Field.Name).GetValue(Data)), SaveData.Is_Big_Endian); } else { SaveData.Write(DataOffset, ((Item)HouseDataType.GetField(Field.Name).GetValue(Data)).ItemID, SaveData.Is_Big_Endian); } } } } } } foreach (Room r in Data.Rooms) { r.Write(); } }
public void Write() { // Set Villager TownID & Name if (Offsets.Town_ID != -1) { Data.Town_ID = SaveData.ReadUInt16(SaveData.Save_Data_Start_Offset + NewMainForm.Current_Save_Info.Save_Offsets.Town_ID, SaveData.Is_Big_Endian); // Might not be UInt16 in all games } if (Offsets.Town_Name != -1) { Data.Town_Name = SaveData.ReadString(SaveData.Save_Data_Start_Offset + NewMainForm.Current_Save_Info.Save_Offsets.Town_Name, NewMainForm.Current_Save_Info.Save_Offsets.Town_NameSize); } //MessageBox.Show(string.Format("Writing Villager #{0} with data offset of 0x{1}", Index, Offset.ToString("X"))); Type VillagerOffsetData = typeof(VillagerOffsets); Type VillagerDataType = typeof(VillagerDataStruct); foreach (var Field in VillagerOffsetData.GetFields(BindingFlags.Public | BindingFlags.Instance)) { if (Field.GetValue(Offsets) != null && !Field.Name.Contains("Count") && !Field.Name.Contains("Size")) { if (VillagerDataType.GetField(Field.Name) != null) { if (Field.FieldType == typeof(int) && (int)Field.GetValue(Offsets) != -1) { Type FieldType = VillagerDataType.GetField(Field.Name).FieldType; int DataOffset = Offset + (int)Field.GetValue(Offsets); //MessageBox.Show("Field Name: " + Field.Name + " | Data Offset: " + DataOffset.ToString("X")); if (Field.Name == "Villager_ID") { if (SaveData.Save_Type == SaveType.Wild_World) { SaveData.Write(DataOffset, Convert.ToByte(VillagerDataType.GetField(Field.Name).GetValue(Data))); } else //Might not encompass City Folk { SaveData.Write(DataOffset, (ushort)VillagerDataType.GetField(Field.Name).GetValue(Data), SaveData.Is_Big_Endian); } } else if (FieldType == typeof(string) && SaveData.Game_System != SaveGeneration.N3DS) // Temp 3DS exclusion { SaveData.Write(DataOffset, ACString.GetBytes((string)VillagerDataType.GetField(Field.Name).GetValue(Data), (int)VillagerOffsetData.GetField(Field.Name + "Size").GetValue(Offsets))); } else if (FieldType == typeof(byte)) { SaveData.Write(DataOffset, (byte)VillagerDataType.GetField(Field.Name).GetValue(Data)); } else if (FieldType == typeof(byte[])) { SaveData.Write(DataOffset, (byte[])VillagerDataType.GetField(Field.Name).GetValue(Data)); } else if (FieldType == typeof(ushort)) { SaveData.Write(DataOffset, (ushort)VillagerDataType.GetField(Field.Name).GetValue(Data), SaveData.Is_Big_Endian); } else if (FieldType == typeof(Item)) { if (SaveData.Save_Type == SaveType.New_Leaf || SaveData.Save_Type == SaveType.Welcome_Amiibo) { SaveData.Write(DataOffset, ItemData.EncodeItem((Item)VillagerDataType.GetField(Field.Name).GetValue(Data)), SaveData.Is_Big_Endian); } else { SaveData.Write(DataOffset, ((Item)VillagerDataType.GetField(Field.Name).GetValue(Data)).ItemID, SaveData.Is_Big_Endian); } } } } } } // Special case here, since Villager_Data_Start + 0xC is always the same as the villager's ID. (Lower byte) // TODO: Add check to see if the villager is an islander. If they are, use 0xFF instead. if (SaveData.Save_Type == SaveType.Animal_Crossing) { SaveData.Write(Offset + 0xC, (byte)Data.Villager_ID); } // TODO: Add House Coordinate Saving/Updating (Also automatic placing/removing??) for the GC version }