Initial v1.7.0 Support (#445)

* Pre-patch preparations

* Update magic values

* Check formatting characters directly rather than string compare

"Brown".StartsWith("\u000e")
>true
what

let's be paranoid here, because .NET Core behaves differently from .NET framework.

* Update FileHashRevision.cs

Postbox with the massive decrease in size; likely the same mutation caused the other massive decreases.

* Dump item names

* Update flag definitions

* Update item info

* Add feathers to bug list

Might remove later.

* Update RecipeList.cs

* Update ItemRemakeUtil.cs

* Update stack details

* Update offsets

* Update MainSaveOffsets17.cs

* Update GameLists.cs
This commit is contained in:
Kurt 2021-01-27 20:04:51 -08:00 committed by GitHub
parent f427ca647e
commit 6c40e1c769
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 5886 additions and 2545 deletions

View File

@ -29,48 +29,22 @@ namespace NHSE.Core
public sealed class Aes128CounterMode : SymmetricAlgorithm
{
private readonly byte[] _counter;
private readonly AesManaged _aes;
private readonly AesManaged _aes = new() {Mode = CipherMode.ECB, Padding = PaddingMode.None};
public Aes128CounterMode(byte[] counter)
{
if (counter == null)
throw new ArgumentNullException(nameof(counter));
if (counter.Length != 16)
throw new ArgumentException($"Counter size must be same as block size (actual: {counter.Length}, expected: {16})");
_aes = new AesManaged
{
Mode = CipherMode.ECB,
Padding = PaddingMode.None
};
const int expect = 0x10;
if (counter.Length != expect)
throw new ArgumentException($"Counter size must be same as block size (actual: {counter.Length}, expected: {expect})");
_counter = counter;
}
public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] ignoredParameter)
{
return new CounterModeCryptoTransform(_aes, rgbKey, _counter);
}
public override ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] ignoredParameter) => new CounterModeCryptoTransform(_aes, rgbKey, _counter);
public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] ignoredParameter) => new CounterModeCryptoTransform(_aes, rgbKey, _counter);
public override ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] ignoredParameter)
{
return new CounterModeCryptoTransform(_aes, rgbKey, _counter);
}
public override void GenerateKey()
{
_aes.GenerateKey();
}
public override void GenerateIV()
{
// IV not needed in Counter Mode
}
protected override void Dispose(bool disposing)
{
_aes.Dispose();
}
public override void GenerateKey() => _aes.GenerateKey();
public override void GenerateIV() { /* IV not needed in Counter Mode */ }
protected override void Dispose(bool disposing) => _aes.Dispose();
}
public sealed class CounterModeCryptoTransform : ICryptoTransform
@ -82,19 +56,14 @@ public sealed class CounterModeCryptoTransform : ICryptoTransform
public CounterModeCryptoTransform(SymmetricAlgorithm symmetricAlgorithm, byte[] key, byte[] counter)
{
if (symmetricAlgorithm == null)
throw new ArgumentNullException(nameof(symmetricAlgorithm));
if (key == null)
throw new ArgumentNullException(nameof(key));
if (counter == null)
throw new ArgumentNullException(nameof(counter));
if (counter.Length != symmetricAlgorithm.BlockSize / 8)
throw new ArgumentException($"Counter size must be same as block size (actual: {counter.Length}, expected: {symmetricAlgorithm.BlockSize / 8})");
_symmetricAlgorithm = symmetricAlgorithm;
_encryptOutput = new byte[counter.Length];
_counter = counter;
var zeroIv = new byte[_symmetricAlgorithm.BlockSize / 8];
var zeroIv = new byte[counter.Length];
_counterEncryptor = symmetricAlgorithm.CreateEncryptor(key, zeroIv);
}
@ -107,40 +76,39 @@ public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int input
public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
{
var xm = _xorMask;
for (var i = 0; i < inputCount; i++)
{
if (NeedMoreXorMaskBytes()) EncryptCounterThenIncrement();
if (xm.Count == 0)
EncryptCounterThenIncrement();
var mask = _xorMask.Dequeue();
var mask = xm.Dequeue();
outputBuffer[outputOffset + i] = (byte)(inputBuffer[inputOffset + i] ^ mask);
}
return inputCount;
}
private bool NeedMoreXorMaskBytes()
{
return _xorMask.Count == 0;
}
private readonly byte[] _encryptOutput;
private void EncryptCounterThenIncrement()
{
var counterModeBlock = new byte[_symmetricAlgorithm.BlockSize / 8];
var counterModeBlock = _encryptOutput;
_counterEncryptor.TransformBlock(_counter, 0, _counter.Length, counterModeBlock, 0);
IncrementCounter();
var xm = _xorMask;
foreach (var b in counterModeBlock)
{
_xorMask.Enqueue(b);
}
xm.Enqueue(b);
}
private void IncrementCounter()
{
for (var i = _counter.Length - 1; i >= 0; i--)
var ctr = _counter;
for (var i = ctr.Length - 1; i >= 0; i--)
{
if (++_counter[i] != 0)
if (++ctr[i] != 0)
break;
}
}
@ -150,9 +118,6 @@ private void IncrementCounter()
public bool CanTransformMultipleBlocks => true;
public bool CanReuseTransform => false;
public void Dispose()
{
_counterEncryptor.Dispose();
}
public void Dispose() => _counterEncryptor.Dispose();
}
}

View File

@ -20,4 +20,4 @@ public CryptoFile(byte[] data, byte[] key, byte[] ctr)
public static bool operator ==(CryptoFile left, CryptoFile right) => left.Data == right.Data;
#endregion
}
}
}

View File

@ -6,16 +6,16 @@ public static class Encryption
{
private static byte[] GetParam(uint[] data, in int index)
{
var sead = new SEADRandom(data[data[index] & 0x7F]);
var rand = new XorShift128(data[data[index] & 0x7F]);
var prms = data[data[index + 1] & 0x7F] & 0x7F;
var rndRollCount = (prms & 0xF) + 1;
for (var i = 0; i < rndRollCount; i++)
sead.GetU64();
rand.GetU64();
var result = new byte[0x10];
for (var i = 0; i < result.Length; i++)
result[i] = (byte)(sead.GetU32() >> 24);
result[i] = (byte)(rand.GetU32() >> 24);
return result;
}
@ -47,7 +47,7 @@ public static void Decrypt(byte[] headerData, byte[] encData)
private static CryptoFile GenerateHeaderFile(uint seed, byte[] versionData)
{
// Generate 128 Random uints which will be used for params
var random = new SEADRandom(seed);
var random = new XorShift128(seed);
var encryptData = new uint[128];
for (var i = 0; i < encryptData.Length; i++)
encryptData[i] = random.GetU32();

View File

@ -3,19 +3,21 @@
namespace NHSE.Core
{
#pragma warning disable CA2237 // Mark ISerializable types with serializable
public sealed class FileHashInfo : Dictionary<uint, FileHashDetails>
#pragma warning restore CA2237 // Mark ISerializable types with serializable
public sealed class FileHashInfo
{
private readonly IReadOnlyDictionary<uint, FileHashDetails> List;
public FileHashInfo(IEnumerable<FileHashDetails> hashSets)
{
var list = new Dictionary<uint, FileHashDetails>();
foreach (var hashSet in hashSets)
this[hashSet.FileSize] = hashSet;
list[hashSet.FileSize] = hashSet;
List = list;
}
public FileHashDetails? GetFile(string nameData)
{
return this.FirstOrDefault(z => z.Value.FileName == nameData).Value;
return List.Values.FirstOrDefault(z => z.FileName == nameData);
}
}
}

View File

@ -5,17 +5,23 @@
/// </summary>
public static class FileHashRevision
{
private const string FN_MAIN = "main.dat";
private const string FN_PERSONAL = "personal.dat";
private const string FN_POSTBOX = "postbox.dat";
private const string FN_PHOTO = "photo_studio_island.dat";
private const string FN_PROFILE = "profile.dat";
#region REVISION 1.0.0
private const int MAIN_SAVE_SIZE = 0xAC0938;
private const int PERSONAL_SAVE_SIZE = 0x6BC50;
private const int POSTBOX_SAVE_SIZE = 0xB44580;
private const int PHOTO_STUDIO_ISLAND_SIZE = 0x263B4;
private const int PROFILE_SIZE = 0x69508;
internal const int REV_100_MAIN = 0xAC0938;
internal const int REV_100_PERSONAL = 0x6BC50;
internal const int REV_100_POSTBOX = 0xB44580;
internal const int REV_100_PHOTO = 0x263B4;
internal const int REV_100_PROFILE = 0x69508;
public static readonly FileHashInfo REV_100 = new(new FileHashDetails[]
{
new("main.dat", MAIN_SAVE_SIZE, new FileHashRegion[]
new(FN_MAIN, REV_100_MAIN, new FileHashRegion[]
{
new(0x000108, 0x1D6D4C),
new(0x1D6E58, 0x323384),
@ -37,20 +43,20 @@ public static class FileHashRevision
new(0x8223E0, 0x03607C),
new(0x858460, 0x2684D4)
}),
new("personal.dat", PERSONAL_SAVE_SIZE, new FileHashRegion[]
new(FN_PERSONAL, REV_100_PERSONAL, new FileHashRegion[]
{
new(0x00108, 0x35AC4),
new(0x35BD0, 0x3607C)
}),
new("postbox.dat", POSTBOX_SAVE_SIZE, new FileHashRegion[]
new(FN_POSTBOX, REV_100_POSTBOX, new FileHashRegion[]
{
new(0x000100, 0xB4447C)
}),
new("photo_studio_island.dat", PHOTO_STUDIO_ISLAND_SIZE, new FileHashRegion[]
new(FN_PHOTO, REV_100_PHOTO, new FileHashRegion[]
{
new(0x000100, 0x262B0)
}),
new("profile.dat", PROFILE_SIZE, new FileHashRegion[]
new(FN_PROFILE, REV_100_PROFILE, new FileHashRegion[]
{
new(0x000100, 0x69404)
}),
@ -60,15 +66,15 @@ public static class FileHashRevision
#region REVISION 1.1.0
private const int REV_110_MAIN_SAVE_SIZE = 0xAC2AA0;
private const int REV_110_PERSONAL_SAVE_SIZE = 0x6BED0;
private const int REV_110_POSTBOX_SAVE_SIZE = 0xB44590;
private const int REV_110_PHOTO_STUDIO_ISLAND_SIZE = 0x263C0;
private const int REV_110_PROFILE_SIZE = 0x69560;
internal const int REV_110_MAIN = 0xAC2AA0;
internal const int REV_110_PERSONAL = 0x6BED0;
internal const int REV_110_POSTBOX = 0xB44590;
internal const int REV_110_PHOTO = 0x263C0;
internal const int REV_110_PROFILE = 0x69560;
public static readonly FileHashInfo REV_110 = new(new FileHashDetails[]
{
new("main.dat", REV_110_MAIN_SAVE_SIZE, new FileHashRegion[]
new(FN_MAIN, REV_110_MAIN, new FileHashRegion[]
{
new(0x000110, 0x1D6D5C),
new(0x1D6E70, 0x323C0C),
@ -90,20 +96,20 @@ public static class FileHashRevision
new(0x823E40, 0x0362BC),
new(0x85A100, 0x26899C)
}),
new("personal.dat", REV_110_PERSONAL_SAVE_SIZE, new FileHashRegion[]
new(FN_PERSONAL, REV_110_PERSONAL, new FileHashRegion[]
{
new(0x00110, 0x35AFC),
new(0x35C10, 0x362BC)
}),
new("postbox.dat", REV_110_POSTBOX_SAVE_SIZE, new FileHashRegion[]
new(FN_POSTBOX, REV_110_POSTBOX, new FileHashRegion[]
{
new(0x000100, 0xB4448C)
}),
new("photo_studio_island.dat", REV_110_PHOTO_STUDIO_ISLAND_SIZE, new FileHashRegion[]
new(FN_PHOTO, REV_110_PHOTO, new FileHashRegion[]
{
new(0x000100, 0x262BC)
}),
new("profile.dat", REV_110_PROFILE_SIZE, new FileHashRegion[]
new(FN_PROFILE, REV_110_PROFILE, new FileHashRegion[]
{
new(0x000100, 0x6945C)
}),
@ -113,15 +119,15 @@ public static class FileHashRevision
#region REVISION 1.2.0
private const int REV_120_MAIN_SAVE_SIZE = 0xACECD0;
private const int REV_120_PERSONAL_SAVE_SIZE = 0x6D6C0;
private const int REV_120_POSTBOX_SAVE_SIZE = REV_110_POSTBOX_SAVE_SIZE;
private const int REV_120_PHOTO_STUDIO_ISLAND_SIZE = 0x2C9C0;
private const int REV_120_PROFILE_SIZE = REV_110_PROFILE_SIZE;
internal const int REV_120_MAIN = 0xACECD0;
internal const int REV_120_PERSONAL = 0x6D6C0;
internal const int REV_120_POSTBOX = REV_110_POSTBOX;
internal const int REV_120_PHOTO = 0x2C9C0;
internal const int REV_120_PROFILE = REV_110_PROFILE;
public static readonly FileHashInfo REV_120 = new(new FileHashDetails[]
{
new("main.dat", REV_120_MAIN_SAVE_SIZE, new FileHashRegion[]
new(FN_MAIN, REV_120_MAIN, new FileHashRegion[]
{
new(0x000110, 0x1D6D5C),
new(0x1D6E70, 0x323EBC),
@ -143,20 +149,20 @@ public static class FileHashRevision
new(0x82EAB0, 0x03787C),
new(0x866330, 0x26899C)
}),
new("personal.dat", REV_120_PERSONAL_SAVE_SIZE, new FileHashRegion[]
new(FN_PERSONAL, REV_120_PERSONAL, new FileHashRegion[]
{
new(0x00110, 0x35D2C),
new(0x35E40, 0x3787C)
}),
new("postbox.dat", REV_120_POSTBOX_SAVE_SIZE, new FileHashRegion[]
new(FN_POSTBOX, REV_120_POSTBOX, new FileHashRegion[]
{
new(0x000100, 0xB4448C)
}),
new("photo_studio_island.dat", REV_120_PHOTO_STUDIO_ISLAND_SIZE, new FileHashRegion[]
new(FN_PHOTO, REV_120_PHOTO, new FileHashRegion[]
{
new(0x000100, 0x2C8BC)
}),
new("profile.dat", REV_120_PROFILE_SIZE, new FileHashRegion[]
new(FN_PROFILE, REV_120_PROFILE, new FileHashRegion[]
{
new(0x000100, 0x6945C)
}),
@ -166,15 +172,15 @@ public static class FileHashRevision
#region REVISION 1.3.0
private const int REV_130_MAIN_SAVE_SIZE = 0xACED80;
private const int REV_130_PERSONAL_SAVE_SIZE = 0x6D6D0;
private const int REV_130_POSTBOX_SAVE_SIZE = REV_110_POSTBOX_SAVE_SIZE;
private const int REV_130_PHOTO_STUDIO_ISLAND_SIZE = REV_120_PHOTO_STUDIO_ISLAND_SIZE;
private const int REV_130_PROFILE_SIZE = REV_110_PROFILE_SIZE;
internal const int REV_130_MAIN = 0xACED80;
internal const int REV_130_PERSONAL = 0x6D6D0;
internal const int REV_130_POSTBOX = REV_110_POSTBOX;
internal const int REV_130_PHOTO = REV_120_PHOTO;
internal const int REV_130_PROFILE = REV_110_PROFILE;
public static readonly FileHashInfo REV_130 = new(new FileHashDetails[]
{
new("main.dat", REV_130_MAIN_SAVE_SIZE, new FileHashRegion[]
new(FN_MAIN, REV_130_MAIN, new FileHashRegion[]
{
new(0x000110, 0x1D6D5C),
new(0x1D6E70, 0x323EEC),
@ -196,20 +202,20 @@ public static class FileHashRevision
new(0x82EB50, 0x03788C),
new(0x8663E0, 0x26899C)
}),
new("personal.dat", REV_130_PERSONAL_SAVE_SIZE, new FileHashRegion[]
new(FN_PERSONAL, REV_130_PERSONAL, new FileHashRegion[]
{
new(0x00110, 0x35D2C),
new(0x35E40, 0x3788C)
}),
new("postbox.dat", REV_130_POSTBOX_SAVE_SIZE, new FileHashRegion[]
new(FN_POSTBOX, REV_130_POSTBOX, new FileHashRegion[]
{
new(0x000100, 0xB4448C)
}),
new("photo_studio_island.dat", REV_130_PHOTO_STUDIO_ISLAND_SIZE, new FileHashRegion[]
new(FN_PHOTO, REV_130_PHOTO, new FileHashRegion[]
{
new(0x000100, 0x2C8BC)
}),
new("profile.dat", REV_130_PROFILE_SIZE, new FileHashRegion[]
new(FN_PROFILE, REV_130_PROFILE, new FileHashRegion[]
{
new(0x000100, 0x6945C)
}),
@ -219,15 +225,15 @@ public static class FileHashRevision
#region REVISION 1.4.0
private const int REV_140_MAIN_SAVE_SIZE = 0xB05790;
private const int REV_140_PERSONAL_SAVE_SIZE = 0x74420;
private const int REV_140_POSTBOX_SAVE_SIZE = REV_110_POSTBOX_SAVE_SIZE;
private const int REV_140_PHOTO_STUDIO_ISLAND_SIZE = REV_120_PHOTO_STUDIO_ISLAND_SIZE;
private const int REV_140_PROFILE_SIZE = REV_110_PROFILE_SIZE;
internal const int REV_140_MAIN = 0xB05790;
internal const int REV_140_PERSONAL = 0x74420;
internal const int REV_140_POSTBOX = REV_110_POSTBOX;
internal const int REV_140_PHOTO = REV_120_PHOTO;
internal const int REV_140_PROFILE = REV_110_PROFILE;
public static readonly FileHashInfo REV_140 = new(new FileHashDetails[]
{
new("main.dat", REV_140_MAIN_SAVE_SIZE, new FileHashRegion[]
new(FN_MAIN, REV_140_MAIN, new FileHashRegion[]
{
new(0x000110, 0x1d6d5c),
new(0x1d6e70, 0x323f2c),
@ -249,20 +255,20 @@ public static class FileHashRevision
new(0x85e8c0, 0x03e5dc),
new(0x89cea0, 0x2688ec)
}),
new("personal.dat", REV_140_PERSONAL_SAVE_SIZE, new FileHashRegion[]
new(FN_PERSONAL, REV_140_PERSONAL, new FileHashRegion[]
{
new(0x00110, 0x35D2C),
new(0x35E40, 0x3E5DC)
}),
new("postbox.dat", REV_140_POSTBOX_SAVE_SIZE, new FileHashRegion[]
new(FN_POSTBOX, REV_140_POSTBOX, new FileHashRegion[]
{
new(0x000100, 0xB4448C)
}),
new("photo_studio_island.dat", REV_140_PHOTO_STUDIO_ISLAND_SIZE, new FileHashRegion[]
new(FN_PHOTO, REV_140_PHOTO, new FileHashRegion[]
{
new(0x000100, 0x2C8BC)
}),
new("profile.dat", REV_140_PROFILE_SIZE, new FileHashRegion[]
new(FN_PROFILE, REV_140_PROFILE, new FileHashRegion[]
{
new(0x000100, 0x6945C)
}),
@ -272,15 +278,15 @@ public static class FileHashRevision
#region REVISION 1.5.0
private const int REV_150_MAIN_SAVE_SIZE = 0xB20750;
private const int REV_150_PERSONAL_SAVE_SIZE = 0x76390;
private const int REV_150_POSTBOX_SAVE_SIZE = REV_110_POSTBOX_SAVE_SIZE;
private const int REV_150_PHOTO_STUDIO_ISLAND_SIZE = REV_120_PHOTO_STUDIO_ISLAND_SIZE;
private const int REV_150_PROFILE_SIZE = REV_110_PROFILE_SIZE;
internal const int REV_150_MAIN = 0xB20750;
internal const int REV_150_PERSONAL = 0x76390;
internal const int REV_150_POSTBOX = REV_110_POSTBOX;
internal const int REV_150_PHOTO = REV_120_PHOTO;
internal const int REV_150_PROFILE = REV_110_PROFILE;
public static readonly FileHashInfo REV_150 = new(new FileHashDetails[]
{
new("main.dat", REV_150_MAIN_SAVE_SIZE, new FileHashRegion[]
new(FN_MAIN, REV_150_MAIN, new FileHashRegion[]
{
new(0x000110, 0x1e215c),
new(0x1e2270, 0x323f6c),
@ -302,20 +308,20 @@ public static class FileHashRevision
new(0x878520, 0x03f93c),
new(0x8b7e60, 0x2688ec)
}),
new("personal.dat", REV_150_PERSONAL_SAVE_SIZE, new FileHashRegion[]
new(FN_PERSONAL, REV_150_PERSONAL, new FileHashRegion[]
{
new(0x00110, 0x3693c),
new(0x36a50, 0x3f93c)
}),
new("postbox.dat", REV_150_POSTBOX_SAVE_SIZE, new FileHashRegion[]
new(FN_POSTBOX, REV_150_POSTBOX, new FileHashRegion[]
{
new(0x000100, 0xB4448C)
}),
new("photo_studio_island.dat", REV_150_PHOTO_STUDIO_ISLAND_SIZE, new FileHashRegion[]
new(FN_PHOTO, REV_150_PHOTO, new FileHashRegion[]
{
new(0x000100, 0x2C8BC)
}),
new("profile.dat", REV_150_PROFILE_SIZE, new FileHashRegion[]
new(FN_PROFILE, REV_150_PROFILE, new FileHashRegion[]
{
new(0x000100, 0x6945C)
}),
@ -325,15 +331,15 @@ public static class FileHashRevision
#region REVISION 1.6.0
private const int REV_160_MAIN_SAVE_SIZE = 0xB258E0;
private const int REV_160_PERSONAL_SAVE_SIZE = 0x76CF0;
private const int REV_160_POSTBOX_SAVE_SIZE = REV_110_POSTBOX_SAVE_SIZE;
private const int REV_160_PHOTO_STUDIO_ISLAND_SIZE = REV_120_PHOTO_STUDIO_ISLAND_SIZE;
private const int REV_160_PROFILE_SIZE = REV_110_PROFILE_SIZE;
internal const int REV_160_MAIN = 0xB258E0;
internal const int REV_160_PERSONAL = 0x76CF0;
internal const int REV_160_POSTBOX = REV_110_POSTBOX;
internal const int REV_160_PHOTO = REV_120_PHOTO;
internal const int REV_160_PROFILE = REV_110_PROFILE;
public static readonly FileHashInfo REV_160 = new(new FileHashDetails[]
{
new("main.dat", REV_160_MAIN_SAVE_SIZE, new FileHashRegion[]
new(FN_MAIN, REV_160_MAIN, new FileHashRegion[]
{
new(0x000110, 0x1e215c),
new(0x1e2270, 0x32403c),
@ -355,20 +361,73 @@ public static class FileHashRevision
new(0x87c790, 0x04029c),
new(0x8bca30, 0x268eac)
}),
new("personal.dat", REV_160_PERSONAL_SAVE_SIZE, new FileHashRegion[]
new(FN_PERSONAL, REV_160_PERSONAL, new FileHashRegion[]
{
new(0x00110, 0x3693c),
new(0x36a50, 0x4029c)
}),
new("postbox.dat", REV_160_POSTBOX_SAVE_SIZE, new FileHashRegion[]
new(FN_POSTBOX, REV_160_POSTBOX, new FileHashRegion[]
{
new(0x000100, 0xB4448C)
}),
new("photo_studio_island.dat", REV_160_PHOTO_STUDIO_ISLAND_SIZE, new FileHashRegion[]
new(FN_PHOTO, REV_160_PHOTO, new FileHashRegion[]
{
new(0x000100, 0x2C8BC)
}),
new("profile.dat", REV_160_PROFILE_SIZE, new FileHashRegion[]
new(FN_PROFILE, REV_160_PROFILE, new FileHashRegion[]
{
new(0x000100, 0x6945C)
}),
});
#endregion
#region REVISION 1.7.0
internal const int REV_170_MAIN = 0x849C30; // reduced size
internal const int REV_170_PERSONAL = 0x64140; // reduced size
internal const int REV_170_POSTBOX = 0x47430; // reduced size
internal const int REV_170_PHOTO = REV_120_PHOTO;
internal const int REV_170_PROFILE = REV_110_PROFILE;
public static readonly FileHashInfo REV_170 = new(new FileHashDetails[]
{
new(FN_MAIN, REV_170_MAIN, new FileHashRegion[]
{
new(0x000110, 0x1e215c),
new(0x1e2270, 0x3221fc),
new(0x504580, 0x03693c),
new(0x53aec0, 0x02d6ec),
new(0x5686c0, 0x03693c),
new(0x59f000, 0x02d6ec),
new(0x5cc800, 0x03693c),
new(0x603140, 0x02d6ec),
new(0x630940, 0x03693c),
new(0x667280, 0x02d6ec),
new(0x694a80, 0x03693c),
new(0x6cb3c0, 0x02d6ec),
new(0x6f8bc0, 0x03693c),
new(0x72f500, 0x02d6ec),
new(0x75cd00, 0x03693c),
new(0x793640, 0x02d6ec),
new(0x7c0e40, 0x03693c),
new(0x7f7780, 0x02d6ec),
new(0x824e70, 0x024dbc),
}),
new(FN_PERSONAL, REV_170_PERSONAL, new FileHashRegion[]
{
new(0x00110, 0x3693c),
new(0x36a50, 0x2d6ec),
}),
new(FN_POSTBOX, REV_170_POSTBOX, new FileHashRegion[]
{
new(0x000100, 0x4732c)
}),
new(FN_PHOTO, REV_170_PHOTO, new FileHashRegion[]
{
new(0x000100, 0x2C8BC)
}),
new(FN_PROFILE, REV_170_PROFILE, new FileHashRegion[]
{
new(0x000100, 0x6945C)
}),

File diff suppressed because it is too large Load Diff

View File

@ -2610,7 +2610,7 @@ wooden simple bed
ribbon (Green)
ribbon (Red)
star bopper (Yellow)
Festivale accessory (Blue)
mountain bike
ladder
@ -3539,14 +3539,14 @@ pinafore (Dark blue)
chima jeogori (Vermilion)
snowflake
large snowflake
red feather
blue feather
green feather
purple feather
rainbow feather
beak (Yellow)
handlebar mustache (Hair Color)
bamboo shelf
@ -5131,7 +5131,7 @@ top hat (Black)
samurai shirt (Red)
sleeveless silk dress (Red)
sleeved apron (Pink)
ogre costume (Blue)
thief's costume (Black)
astro dress (Blue)
explorer's hat (Camel)
@ -5343,7 +5343,7 @@ dance warm-up pants (Black)
square mailbox
wooden mailbox
large mailbox
horned-ogre mask (Blue)
gold helmet (Gold)
@ -8647,8 +8647,8 @@ full-body tights (Gold)
full-body tights (Silver)
wrestling singlet (Blue)
wrestling singlet (Green)
ogre costume (Red)
ogre costume (Green)
instant-muscles suit (Green)
instant-muscles suit (Light blue)
instant-muscles suit (Orange)
@ -9730,9 +9730,9 @@ corduroy pants (Light gray)
corduroy pants (Black)
Festivale accessory (Red)
Festivale accessory (Purple)
Festivale accessory (Green)
@ -10909,7 +10909,7 @@ attus robe (Blue)
bingata dress (Yellow)
plushie-muffler coat (Orange)
painter's coverall (Beige)
Festivale tank dress (Blue)
tubeteika (Red)
matanpushi (Blue)
@ -11884,8 +11884,8 @@ veil (Pink)
veil (Yellow)
alpinist hat (Blue)
alpinist hat (Red)
horned-ogre mask (Red)
horned-ogre mask (Green)
bun wig (Blue)
bun wig (Mustard)
bun wig (White)
@ -12021,9 +12021,9 @@ knapsack (Black)
plushie-muffler coat (Pink)
painter's coverall (Green)
painter's coverall (White)
Festivale tank dress (Red)
Festivale tank dress (Purple)
Festivale tank dress (Green)
@ -13486,7 +13486,7 @@ berliner
chocolate heart
zodiac ox figurine
magic-academy robe (Purple)
@ -13765,18 +13765,18 @@ Hip Reaction Collection
Top 6 Stylish Hairstyles
Festivale garland
Festivale parasol
Festivale float
Festivale balloon lamp
Festivale stall
Festivale drum
Festivale stage
Festivale confetti machine
Festivale lamp
Festivale flag
fish meunière
gratin
clam chowder
@ -13865,7 +13865,7 @@ Jingle's photo
Resetti model
someone's gift
@ -13902,17 +13902,17 @@ someone's gift
football rug
okame mask (White)
football cheer megaphone
bean-tossing kit
@ -13929,3 +13929,351 @@ someone's gift
set of stockings
lucky red envelope
bokjumeoni lucky pouch
maracas
fiery cheer megaphone
starry cheer megaphone
glittery cheer megaphone
Festivale costume (Blue)
heart-shaped bouquet
Viva Festivale Reaction Set
Lunar New Year decoration
lucky money
sebaetdon
Festivale costume (Red)
Festivale costume (Purple)
Festivale costume (Green)
mermaid fence

View File

@ -2610,7 +2610,7 @@ cama individual de madera
lazo (Verde)
lazo (Rojo)
diadema estrellas (Amarillo)
tocado de Carnaval (Azul)
bici de montaña
escalera de mano
@ -3539,14 +3539,14 @@ mandil añejo (Azul oscuro)
vestido coreano (Bermellón)
copo de nieve
copo de nieve XL
pluma roja
pluma azul
pluma verde
pluma morada
pluma arcoíris
pico (Amarillo)
bigote inglés (Color del pelo)
estante de bambú
@ -4665,7 +4665,7 @@ eustenopteron
acantostega
juramaia
antifaz de carnaval (Púrpura)
antifaz baile de máscaras (Púrpura)
top largo (Blanco)
montura de madera (Marrón)
@ -5131,7 +5131,7 @@ sombrero de copa (Negro)
coraza de samurái (Rojo)
vestido de seda sin mangas (Rojo)
delantal con protectores (Rosa)
disfraz de ogro (Azul)
disfraz de maleante (Negro)
vestido corto futurista (Azul)
sombrero de exploración (Pardo)
@ -5343,7 +5343,7 @@ pantalón compañía de baile (Negro)
buzón cuadrado
buzón de madera
buzón para paquetes
careta de ogro (Azul)
yelmo dorado (Dorado)
@ -8647,8 +8647,8 @@ traje térmico (Dorado)
traje térmico (Plateado)
maillot de lucha deportiva (Azul)
maillot de lucha deportiva (Verde)
disfraz de ogro (Rojo)
disfraz de ogro (Verde)
disfraz de musculitos (Verde)
disfraz de musculitos (Celeste)
disfraz de musculitos (Naranja)
@ -9730,9 +9730,9 @@ pantalón de pana (Gris claro)
pantalón de pana (Negro)
tocado de Carnaval (Rojo)
tocado de Carnaval (Púrpura)
tocado de Carnaval (Verde)
@ -10909,7 +10909,7 @@ kimono ainu (Azul)
kimono bingata (Amarillo)
abrigo con chal de peluche (Naranja)
mono de trabajo de pintor (Beis)
vestido de Carnaval (Azul)
tubeteika (Rojo)
matanpushi (Azul)
@ -11159,11 +11159,11 @@ antifaz para dormir (Naranja)
antifaz para dormir (Rojo)
máscara de gas (Verde bosque)
antifaz de carnaval (Negro)
antifaz de carnaval (Azul)
antifaz de carnaval (Rojo)
antifaz de carnaval (Verde)
antifaz de carnaval (Dorado)
antifaz baile de máscaras (Negro)
antifaz baile de máscaras (Azul)
antifaz baile de máscaras (Rojo)
antifaz baile de máscaras (Verde)
antifaz baile de máscaras (Dorado)
careta de bufón (Rojo)
careta de bufón (Verde)
careta de bufón (Azul)
@ -11884,8 +11884,8 @@ velo princesa desierto (Rosa)
velo princesa desierto (Amarillo)
sombrero tirolés (Azul)
sombrero tirolés (Rojo)
careta de ogro (Rojo)
careta de ogro (Verde)
moño (Azul)
moño (Mostaza)
moño (Blanco)
@ -12021,9 +12021,9 @@ mochila saco (Negro)
abrigo con chal de peluche (Rosa)
mono de trabajo de pintor (Verde)
mono de trabajo de pintor (Blanco)
vestido de Carnaval (Rojo)
vestido de Carnaval (Púrpura)
vestido de Carnaval (Verde)
@ -13486,7 +13486,7 @@ plato de berlinesas
caja bombones Enamorados
figura zodiacal de buey
túnica escuela de magia (Púrpura)
@ -13765,18 +13765,18 @@ Emociones y actividades
6 peinados revolucionarios
guirnalda de Carnaval
parasol de Carnaval
carroza de Carnaval
lámpara globo de Carnaval
tenderete de Carnaval
tambor de Carnaval
escenario de Carnaval
cañón de confeti Carnaval
lamparita de Carnaval
estandarte de Carnaval
pescado a la molinera
gratinado
sopa de almejas
@ -13865,7 +13865,7 @@ foto de Renato
mini Rese T. Ado
regalo de alguien
@ -13902,17 +13902,17 @@ regalo de alguien
alfombra final deportiva
máscara de Okame (Blanco)
megáfono fútbol americano
caja habichuelas para lanzar
@ -13929,3 +13929,351 @@ regalo de alguien
lote de calcetines de pared
sobre rojo de la suerte
bolsita de la suerte
par de maracas
megáfono ánimo encendido
megáfono de las estrellas
megáfono deslumbrante
traje de Carnaval (Azul)
ramo de flores Enamorados
Set de emociones Carnaval
adorno Año Nuevo Lunar
aguinaldo Año Nuevo Lunar
aguinaldo de Seollal
traje de Carnaval (Rojo)
traje de Carnaval (Púrpura)
traje de Carnaval (Verde)
valla sirena

View File

@ -2610,7 +2610,7 @@ lit en bois
nœud à cheveux (Vert)
nœud à cheveux (Rouge)
serre-tête étoiles (Jaune)
coiffe de carnaval (Bleu)
VTT
échelle
@ -3539,14 +3539,14 @@ robe tablier (Bleu foncé)
chima chogori (Vermillon)
flocon de neige
grand flocon de neige
plume rouge
plume bleue
plume verte
plume violette
plume irisée
bec (Jaune)
moustache en guidon (Couleur de cheveux)
étagère en bambou
@ -5131,7 +5131,7 @@ haut-de-forme (Noir)
cuirasse de samouraï (Rouge)
qipao sans manches (Rouge)
tablier avec manches (Rose)
costume d'ogre (Bleu)
costume de cambrioleur (Noir)
robe astro (Bleu)
chapeau aventure (Sable)
@ -5343,7 +5343,7 @@ pantalon équipe de danse (Noir)
b.a.l. rectangulaire
boîte aux lettres en bois
grande boîte aux lettres
masque d'ogre cornu (Bleu)
casque en or (Or)
@ -8647,8 +8647,8 @@ collant intégral (Or)
collant intégral (Argent)
combinaison de lutte (Bleu)
combinaison de lutte (Vert)
costume d'ogre (Rouge)
costume d'ogre (Vert)
costume effet gonflette (Vert)
costume effet gonflette (Bleu clair)
costume effet gonflette (Orange)
@ -9730,9 +9730,9 @@ pantalon en velours côtelé (Gris clair)
pantalon en velours côtelé (Noir)
coiffe de carnaval (Rouge)
coiffe de carnaval (Violet)
coiffe de carnaval (Vert)
@ -10909,7 +10909,7 @@ robe attus (Bleu)
robe bingata (Jaune)
caban à écharpe en peluche (Orange)
combinaison de peintre (Beige)
robe d'été carnaval (Bleu)
tubeteika (Rouge)
matanpushi (Bleu)
@ -11884,8 +11884,8 @@ voile princesse du désert (Rose)
voile princesse du désert (Jaune)
chapeau tyrolien (Bleu)
chapeau tyrolien (Rouge)
masque d'ogre cornu (Rouge)
masque d'ogre cornu (Vert)
perruque beignet (Bleu)
perruque beignet (Jaune moutarde)
perruque beignet (Blanc)
@ -12021,9 +12021,9 @@ sac à dos à cordon (Noir)
caban à écharpe en peluche (Rose)
combinaison de peintre (Vert)
combinaison de peintre (Blanc)
robe d'été carnaval (Rouge)
robe d'été carnaval (Violet)
robe d'été carnaval (Vert)
@ -13486,7 +13486,7 @@ beignet
cœur en chocolat
figurine année du buffle
robe école de magie (Violet)
@ -13765,18 +13765,18 @@ Mimiques sans micmacs
6 coiffures qui décoiffent
guirlande de carnaval
parasol de carnaval
char de carnaval
lampe ballon carnaval
stand de carnaval
tambour de carnaval
scène de carnaval
canon à confettis carnaval
lampe carnaval
drapeau de carnaval
poisson meunière
gratin
potée de palourdes
@ -13816,7 +13816,7 @@ salade Olivier
plat à gratin jour du partage
plat à gratin fête du partage
décor de blé du partage
service fête du partage
@ -13865,7 +13865,7 @@ photo de Rodolphe
figurine de Resetti
cadeau de quelqu'un
@ -13902,17 +13902,17 @@ cadeau de quelqu'un
tapis football américain
masque okame (Blanc)
mégaphone de supporter
kit de lancer de haricots
@ -13929,3 +13929,351 @@ cadeau de quelqu'un
lot de chaussettes déco
hóngbāo porte chance
bokjumeoni porte chance
paire de maracas
még. de supporter flammes
még. de supporter étoiles
még. de supporter pailleté
costume de carnaval (Bleu)
bouquet en forme de cœur
lot de mimiques de carnaval
déco de nouvel an lunaire
argent porte chance
sebaetdon
costume de carnaval (Rouge)
costume de carnaval (Violet)
costume de carnaval (Vert)
clôture sirène

View File

@ -2610,7 +2610,7 @@ letto singolo di legno
fiocco (Verde)
fiocco (Rosso)
paio antenne stelle (Giallo)
copricapo Carnevale (Blu)
mountain bike
scala a pioli
@ -2769,7 +2769,7 @@ legno morbido
legno normale
legno duro
scacchiera
stufetta bianca cilindrica
stufetta cilindrica
violino di lusso
@ -3422,7 +3422,7 @@ uniforme da pompiere (Nero)
costume da anfibio (Verde)
costume da tartaruga (Verde)
costume da kappa (Verde)
@ -3539,14 +3539,14 @@ vestito grembiulone (Blu scuro)
vestito coreano (Vermiglio)
fiocco di neve
fiocco di neve grande
piuma rossa
piuma blu
piuma verde
piuma viola
piuma arcobaleno
becco (Giallo)
baffo a manubrio (Colore dei capelli)
scaffale di bambù
@ -5131,7 +5131,7 @@ cilindro (Nero)
armatura da samurai (Rosso)
vestito di seta smanicato (Rosso)
grembiule con maniche (Rosa)
costume da orco (Blu)
costume da ladro (Nero)
vestito futuristico (Blu)
cappello da esploratore (Cammello)
@ -5329,7 +5329,7 @@ passamontagna (Verde)
copricapo scheletro (Bianco)
cappellino basso di lana (Verde)
cappello da orso (Marrone)
cappello da tartaruga (Verde)
cappello da kappa (Verde)
cappello da capitano (Bianco)
berretto da dandy (Cammello)
elmo medievale (Grigio)
@ -5343,7 +5343,7 @@ pantalone della tuta danza (Nero)
cassetta posta cubica
cassetta posta di legno
cassetta posta grande
maschera da orco (Blu)
elmo d'oro (Dorato)
@ -8647,8 +8647,8 @@ tuta aderente (Dorato)
tuta aderente (Argentato)
tuta da wrestling (Blu)
tuta da wrestling (Verde)
costume da orco (Rosso)
costume da orco (Verde)
costume muscoloso (Verde)
costume muscoloso (Blu chiaro)
costume muscoloso (Arancio)
@ -9632,7 +9632,7 @@ costume da orso (Blu)
costume da anfibio (Blu)
costume da anfibio (Rosso)
costume da anfibio (Giallo)
costume da tartaruga (Rosa)
costume da kappa (Rosa)
costume da montone (Rosa)
costume da montone (Blu chiaro)
costume da montone (Marrone)
@ -9730,9 +9730,9 @@ pantalone di velluto a coste (Grigio chiaro)
pantalone di velluto a coste (Nero)
copricapo Carnevale (Rosso)
copricapo Carnevale (Viola)
copricapo Carnevale (Verde)
@ -10909,7 +10909,7 @@ kimono ainu (Blu)
kimono bingata (Giallo)
cappotto e sciarpa imbottita (Arancio)
tuta da pittore (Beige)
scamiciato Carnevale (Blu)
tubeteika (Rosso)
matanpushi (Blu)
@ -11694,7 +11694,7 @@ paio di stivaletti pon-pon (Verde)
paio di stivaletti pon-pon (Blu)
paio di stivaletti pon-pon (Nero)
cappello da tartaruga (Rosa)
cappello da kappa (Rosa)
cappello da rana (Blu)
cappello da rana (Rosso)
cappello da rana (Giallo)
@ -11884,8 +11884,8 @@ velo da mille e una notte (Rosa)
velo da mille e una notte (Giallo)
cappello tirolese (Blu)
cappello tirolese (Rosso)
maschera da orco (Rosso)
maschera da orco (Verde)
parrucca con chignon (Blu)
parrucca con chignon (Senape)
parrucca con chignon (Bianco)
@ -12021,9 +12021,9 @@ sacca morbida (Nero)
cappotto e sciarpa imbottita (Rosa)
tuta da pittore (Verde)
tuta da pittore (Bianco)
scamiciato Carnevale (Rosso)
scamiciato Carnevale (Viola)
scamiciato Carnevale (Verde)
@ -13486,7 +13486,7 @@ piatto di krapfen
ciocco-cuore
statuetta del segno del bue
vestito da scuola di magia (Viola)
@ -13765,18 +13765,18 @@ Collezione Gran Emozione
I migliori 6 tagli top
festone Carnevale
parasole Carnevale
carro Carnevale
globo luminoso Carnevale
bancarella Carnevale
tamburo Carnevale
palcoscenico Carnevale
lanciacoriandoli Carnevale
lampada Carnevale
stendardo Carnevale
pesce alla mugnaia
sformato
zuppa di vongole
@ -13865,7 +13865,7 @@ foto di Jingle
modellino di Resetti
regalo da qualcuno
@ -13902,17 +13902,17 @@ regalo da qualcuno
tappeto football
maschera da Okame (Bianco)
megafono fan football
set con fagioli da lanciare
@ -13929,3 +13929,351 @@ regalo da qualcuno
set di calze per regali
busta della fortuna rossa
sacchettino bokjumeoni
paio di maracas
megafono fan con fiamme
megafono fan con stelle
megafono fan luccicante
costume Carnevale (Blu)
bouquet a cuore
Set di emozioni Carnevale
decoraz. Capodanno lunare
denaro della fortuna
sebaetdon
costume Carnevale (Rosso)
costume Carnevale (Viola)
costume Carnevale (Verde)
recinzione sirena

View File

@ -2610,7 +2610,7 @@ DIYさぎょうだい
リボン (グリーン)
リボン (レッド)
ひかるスターアクセサリー (イエロー)
カーニバルなかみかざり (ブルー)
マウンテンバイク
はしご
@ -3539,14 +3539,14 @@ DIYさぎょうだい
チマチョゴリ (しゅいろ)
ゆきのけっしょう
ゆきのだいけっしょう
あかいはね
あおいはね
みどりのはね
むらさきのはね
にじいろのはね
くちばし (イエロー)
カイゼルひげ (ヘアカラー)
たけのシェルフ
@ -5131,7 +5131,7 @@ TOYなスクリーン
かっちゅう (あか)
チャイナドレス (レッド)
うでカバーつきエプロン (ピンク)
オニのふく (ブルー)
かいとうのふく (ブラック)
スペースワンピース (ブルー)
たんけんぼう (キャメル)
@ -5343,7 +5343,7 @@ HMD (ホワイト)
しかくいポスト
きのポスト
おおきなポスト
オニのおめん (ブルー)
ゴールデンアーマーヘルメット (ゴールド)
@ -8647,8 +8647,8 @@ No.1のふく (レッド)
ぜんしんタイツ (シルバー)
レスリングのユニフォーム (ブルー)
レスリングのユニフォーム (グリーン)
オニのふく (レッド)
オニのふく (グリーン)
マッスルスーツ (グリーン)
マッスルスーツ (ライトブルー)
マッスルスーツ (オレンジ)
@ -9730,9 +9730,9 @@ No.1のふく (レッド)
コーデュロイボトム (ブラック)
カーニバルなかみかざり (レッド)
カーニバルなかみかざり (パープル)
カーニバルなかみかざり (グリーン)
@ -10909,7 +10909,7 @@ DJ K.Kのポスター
びんがたいしょう (イエロー)
ぬいぐるみマフラーつきコート (オレンジ)
ペイントつなぎ (ベージュ)
カーニバルなワンピース (ブルー)
ウズベクなぼうし (レッド)
マタンプシ (ブルー)
@ -11884,8 +11884,8 @@ DJ K.Kのポスター
ベール (イエロー)
チロリアンハット (ブルー)
チロリアンハット (レッド)
オニのおめん (レッド)
オニのおめん (グリーン)
おだんごあたま (ブルー)
おだんごあたま (マスタード)
おだんごあたま (ホワイト)
@ -12021,9 +12021,9 @@ DJ K.Kのポスター
ぬいぐるみマフラーつきコート (ピンク)
ペイントつなぎ (グリーン)
ペイントつなぎ (ホワイト)
カーニバルなワンピース (レッド)
カーニバルなワンピース (パープル)
カーニバルなワンピース (グリーン)
@ -13486,7 +13486,7 @@ Nintendo Switch
ハートのチョコレート
うしのおきもの
まほうスクールのローブ (パープル)
@ -13765,18 +13765,18 @@ Nintendo Switch
もっとヘアアレンジ×6
カーニバルなガーランド
カーニバルなパラソル
カーニバルなフロート
カーニバルなバルーンランプ
カーニバルなやたい
カーニバルなパーカッション
カーニバルなステージ
カーニバルなかみふぶきマシン
カーニバルなランプ
カーニバルなフラッグ
サカナのムニエル
グラタン
クラムチャウダー
@ -13865,7 +13865,7 @@ Nintendo Switch
グラウンドホッグのもけい
だれかのプレゼント
@ -13902,17 +13902,17 @@ Nintendo Switch
アメフトのラグ
おかめのおめん (ホワイト)
おうえんメガホン・アメフト
まめまきセット
@ -13929,3 +13929,351 @@ Nintendo Switch
かべかけソックス
しゅんせつのおとしだま
ソルラルのおとしだま
マラカス
おうえんメガホン・ファイアー
おうえんメガホン・スター
おうえんメガホン・グリッター
カーニバルなコスチューム (ブルー)
ハートのバラブーケ
ビバ!カーニバルリアクション
しゅんせつのドアかざり
しゅんせつのおとしだま
ソルラルのおとしだま
カーニバルなコスチューム (レッド)
カーニバルなコスチューム (パープル)
カーニバルなコスチューム (グリーン)
マーメイドなさく

View File

@ -2610,7 +2610,7 @@ K.K.디스코
리본 (그린)
리본 (레드)
빛나는 별 액세서리 (옐로)
카니발 머리 장식 (블루)
마운틴 바이크
사다리
@ -3539,14 +3539,14 @@ K.K.디스코
치마 한복 (주홍색)
눈의 결정
커다란 눈의 결정
빨간색 깃털
파란색 깃털
초록색 깃털
보라색 깃털
무지개 깃털
부리 (옐로)
콧수염 (헤어 컬러)
대나무 쉘프
@ -4509,7 +4509,7 @@ MA-1 (카키)
생일 선글라스 (옐로)
루돌프 의상 (브라운)
순록 의상 (브라운)
팩 (화이트)
코믹한 안경 (브라운)
자전거 경주복 하의 (블루×레드)
@ -4564,7 +4564,7 @@ MA-1 (카키)
펑크 스타일 의상 (블랙)
가죽 트렌치코트 (블랙)
루돌프 스웨터 (그린)
순록 스웨터 (그린)
매듭 와이셔츠 (블루)
@ -5131,7 +5131,7 @@ TOY 파티션
일본 무사 갑옷 (빨간색)
차이나 드레스 (레드)
팔토시와 앞치마 (핑크)
도깨비 옷 (블루)
괴도 옷 (블랙)
우주 원피스 (블루)
탐험 모자 (캐멀)
@ -5343,7 +5343,7 @@ HMD (화이트)
사각 우편함
나무 우편함
커다란 우편함
도깨비 가면 (블루)
골든 아머 헬멧 (골드)
@ -5444,7 +5444,7 @@ HMD (화이트)
풀페이스 헬멧 (레드)
치마요무늬 양말 (옐로)
루돌프 모자 (브라운)
순록 모자 (브라운)
황소 두개골 (화이트)
하운드투스 치마 (레드)
쉐비 스커트 (베이지)
@ -7738,8 +7738,8 @@ Nook Inc. 러그
스노 스웨터 (블루)
스노 스웨터 (블랙)
루돌프 스웨터 (브라운)
루돌프 스웨터 (레드)
순록 스웨터 (브라운)
순록 스웨터 (레드)
아가일 스웨터 (그레이)
아가일 스웨터 (머스터드)
아가일 스웨터 (블랙)
@ -8647,8 +8647,8 @@ MA-1 (브라운)
전신 타이츠 (실버)
레슬링 유니폼 (블루)
레슬링 유니폼 (그린)
도깨비 옷 (레드)
도깨비 옷 (그린)
근육 슈트 (그린)
근육 슈트 (라이트 블루)
근육 슈트 (오렌지)
@ -9730,9 +9730,9 @@ Nook Inc. 안대 (그린)
코듀로이 바지 (블랙)
카니발 머리 장식 (레드)
카니발 머리 장식 (퍼플)
카니발 머리 장식 (그린)
@ -10909,7 +10909,7 @@ DJ K.K.의 포스터
빈가타 의상 (옐로)
인형 머플러 코트 (오렌지)
페인트 점프 수트 (베이지)
카니발 원피스 (블루)
우즈베키스탄풍 모자 (레드)
아이누족 두건 (블루)
@ -11884,8 +11884,8 @@ MA-1 스커트 (브라운)
베일 (옐로)
알프스풍 모자 (블루)
알프스풍 모자 (레드)
도깨비 가면 (레드)
도깨비 가면 (그린)
양갈래 머리 (블루)
양갈래 머리 (머스터드)
양갈래 머리 (화이트)
@ -12021,9 +12021,9 @@ MA-1 스커트 (브라운)
인형 머플러 코트 (핑크)
페인트 점프 수트 (그린)
페인트 점프 수트 (화이트)
카니발 원피스 (레드)
카니발 원피스 (퍼플)
카니발 원피스 (그린)
@ -13486,7 +13486,7 @@ RC 헬리콥터
하트 초콜릿
소띠 장식품
마법 학교 로브 (퍼플)
@ -13765,18 +13765,18 @@ RC 헬리콥터
조금 더! 헤어스타일×6
카니발 가랜드
카니발 파라솔
카니발 플로트
카니발 풍선 램프
카니발 가판대
카니발 퍼커션
카니발 스테이지
카니발 꽃가루 머신
카니발 램프
카니발 플래그
생선 뫼니에르
그라탱
클램 차우더
@ -13865,7 +13865,7 @@ RC 헬리콥터
그라운드호그 모형
누군가의 선물
@ -13902,17 +13902,17 @@ RC 헬리콥터
미식축구 러그
복을 부르는 가면 (화이트)
미식축구 응원 메가폰
콩 뿌리기 세트
@ -13929,3 +13929,351 @@ RC 헬리콥터
벽걸이 양말
춘절 세뱃돈
설날 세뱃돈
마라카스
파이어 응원 메가폰
스타 응원 메가폰
글리터 응원 메가폰
카니발 의상 (블루)
하트 장미 꽃다발
비바! 카니발 리액션
춘절 복 장식
춘절 세뱃돈
설날 세뱃돈
카니발 의상 (레드)
카니발 의상 (퍼플)
카니발 의상 (그린)
머메이드 울타리

View File

@ -2610,7 +2610,7 @@ K.K.迪斯科
蝴蝶结 (绿色)
蝴蝶结 (红色)
发光星星头饰 (黄色)
狂欢节发饰 (蓝色)
登山车
梯子
@ -3539,14 +3539,14 @@ Polo衫 (海军蓝)
韩服裙 (朱红色)
雪花
大雪花
红色羽毛
蓝色羽毛
绿色羽毛
紫色羽毛
彩虹羽毛
鸭嘴道具 (黄色)
八字翘胡 (发色)
竹制博古架
@ -5131,7 +5131,7 @@ TOY屏风
盔甲 (红色)
旗袍 (红色)
连袖套围裙 (粉红)
鬼怪服 (蓝色)
怪盗服 (黑色)
未来感连身裙 (蓝色)
探险帽 (驼色)
@ -5343,7 +5343,7 @@ TOY屏风
方形信箱
木信箱
大信箱
鬼面具 (蓝色)
金甲头盔 (金色)
@ -8647,8 +8647,8 @@ MA-1飞行外套 (棕色)
全身紧身衣 (银色)
摔角手制服 (蓝色)
摔角手制服 (绿色)
鬼怪服 (红色)
鬼怪服 (绿色)
肌肉装 (绿色)
肌肉装 (浅蓝色)
肌肉装 (橘色)
@ -9730,9 +9730,9 @@ Nook Inc.眼罩 (绿色)
灯芯绒裤 (黑色)
狂欢节发饰 (红色)
狂欢节发饰 (紫色)
狂欢节发饰 (绿色)
@ -10909,7 +10909,7 @@ DJ KK的海报
红型染服装 (黄色)
玩偶围巾大衣 (橘色)
彩绘连体服 (米色)
狂欢节连身裙 (蓝色)
乌兹别克帽 (红色)
阿伊努头巾 (蓝色)
@ -11884,8 +11884,8 @@ MA-1防风裙 (棕色)
面纱 (黄色)
提洛尔帽子 (蓝色)
提洛尔帽子 (红色)
鬼面具 (红色)
鬼面具 (绿色)
双丸子头 (蓝色)
双丸子头 (芥末黄)
双丸子头 (白色)
@ -12021,9 +12021,9 @@ MA-1防风裙 (棕色)
玩偶围巾大衣 (粉红)
彩绘连体服 (绿色)
彩绘连体服 (白色)
狂欢节连身裙 (红色)
狂欢节连身裙 (紫色)
狂欢节连身裙 (绿色)
@ -13486,7 +13486,7 @@ Ring-Con
心形巧克力
牛摆饰
魔法学校长袍 (紫色)
@ -13765,18 +13765,18 @@ Ring-Con
更多发型×6
狂欢节挂饰
狂欢节阳伞
狂欢节花车
狂欢节气球灯
狂欢节小吃摊
狂欢节打击乐器
狂欢节舞台
狂欢节撒纸片机
狂欢节灯
狂欢节旗子
法式煎鱼排
奶汁烤菜
蛤蜊浓汤
@ -13865,7 +13865,7 @@ Ring-Con
土拨鼠模型
某人的礼物
@ -13902,17 +13902,17 @@ Ring-Con
美式足球地毯
阿龟面具 (白色)
助威扩音器·美式足球
撒豆组合
@ -13929,3 +13929,351 @@ Ring-Con
壁挂式袜子
春节红包
韩国新年红包
沙锤
助威扩音器·火焰
助威扩音器·星星
助威扩音器·闪亮
狂欢节服装 (蓝色)
心形玫瑰花束
欢乐!狂欢节反应
春节门饰
春节红包
韩国新年红包
狂欢节服装 (红色)
狂欢节服装 (紫色)
狂欢节服装 (绿色)
人鱼栅栏

View File

@ -2610,7 +2610,7 @@ K.K.迪斯可
蝴蝶結 (綠色)
蝴蝶結 (紅色)
發光星星頭飾 (黃色)
狂歡節髮飾 (藍色)
登山車
梯子
@ -3539,14 +3539,14 @@ Polo衫 (海軍藍)
韓服裙 (朱紅色)
雪花
大雪花
紅色羽毛
藍色羽毛
綠色羽毛
紫色羽毛
彩虹羽毛
鴨嘴道具 (黃色)
八字翹鬍 (頭髮顏色)
竹製多寶架
@ -5131,7 +5131,7 @@ TOY屏風
盔甲 (紅色)
旗袍 (紅色)
圍裙連袖套 (粉紅色)
鬼怪服 (藍色)
怪盜服 (黑色)
太空連身裙 (藍色)
探險帽 (駝色)
@ -5343,7 +5343,7 @@ TOY屏風
四角型郵筒
木郵筒
大郵筒
鬼面具 (藍色)
金頭盔 (金色)
@ -8647,8 +8647,8 @@ MA-1飛行外套 (棕色)
全身緊身衣 (銀色)
摔角制服 (藍色)
摔角制服 (綠色)
鬼怪服 (紅色)
鬼怪服 (綠色)
肌肉裝 (綠色)
肌肉裝 (淺藍色)
肌肉裝 (橘色)
@ -9730,9 +9730,9 @@ Nook Inc.眼罩 (綠色)
燈芯絨褲 (黑色)
狂歡節髮飾 (紅色)
狂歡節髮飾 (紫色)
狂歡節髮飾 (綠色)
@ -10909,7 +10909,7 @@ DJ KK的海報
沖繩傳統服裝 (黃色)
玩偶圍巾大衣 (橘色)
油漆連身工作服 (米色)
狂歡節連身裙 (藍色)
烏茲別克帽子 (紅色)
阿伊努族頭巾 (藍色)
@ -11884,8 +11884,8 @@ MA-1防風裙 (棕色)
面紗 (黃色)
提洛爾帽子 (藍色)
提洛爾帽子 (紅色)
鬼面具 (紅色)
鬼面具 (綠色)
丸子頭 (藍色)
丸子頭 (芥末黃)
丸子頭 (白色)
@ -12021,9 +12021,9 @@ MA-1防風裙 (棕色)
玩偶圍巾大衣 (粉紅色)
油漆連身工作服 (綠色)
油漆連身工作服 (白色)
狂歡節連身裙 (紅色)
狂歡節連身裙 (紫色)
狂歡節連身裙 (綠色)
@ -13486,7 +13486,7 @@ Ring-Con
愛心巧克力
牛擺飾
魔法學校長袍 (紫色)
@ -13765,18 +13765,18 @@ Ring-Con
更多頭髮造型×6
狂歡節掛旗
狂歡節陽傘
狂歡節花車
狂歡節氣球燈
狂歡節路邊攤
狂歡節打擊樂器
狂歡節舞台
狂歡節撒紙片機
狂歡節燈
狂歡節旗子
法式煎魚排
焗烤
蛤蜊巧達湯
@ -13865,7 +13865,7 @@ Ring-Con
土撥鼠模型
某人的禮物
@ -13902,17 +13902,17 @@ Ring-Con
美式足球地毯
阿龜面具 (白色)
加油大聲公‧美式足球
撒豆組合
@ -13929,3 +13929,351 @@ Ring-Con
壁掛式襪子
春節紅包
韓國新年紅包
沙錘
加油大聲公‧火焰
加油大聲公‧星星
加油大聲公‧閃亮
狂歡節服裝 (藍色)
愛心玫瑰花束
歡樂!狂歡節表情
春節門飾
春節紅包
韓國新年紅包
狂歡節服裝 (紅色)
狂歡節服裝 (紫色)
狂歡節服裝 (綠色)
人魚柵欄

View File

@ -1,5 +1,4 @@
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices;
// ReSharper disable NonReadonlyMemberInGetHashCode
namespace NHSE.Core
@ -7,65 +6,16 @@ namespace NHSE.Core
/// <summary>
/// Metadata stored in a file's Header, indicating the revision information.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public class FileHeaderInfo : IEquatable<FileHeaderInfo>
[StructLayout(LayoutKind.Explicit)]
public sealed record FileHeaderInfo
{
public const int SIZE = 0x40;
/* 0x00 */ public uint Major;
/* 0x04 */ public uint Minor;
/* 0x08 */ public ushort Unk1;
/* 0x0A */ public ushort HeaderRevision;
/* 0x0C */ public ushort Unk2;
/* 0x0E */ public ushort SaveRevision;
public override string ToString() => $"Major = 0x{Major:X}, Minor = 0x{Minor:X}, HeaderRevision = {HeaderRevision}, Unk1 = {Unk1}, SaveRevision = {SaveRevision}, Unk2 = {Unk2}";
public bool Equals(FileHeaderInfo? other)
{
if (other is null)
return false;
if (ReferenceEquals(this, other))
return true;
if (Major != other.Major)
return false;
if (Minor != other.Minor)
return false;
if (Unk1 != other.Unk1)
return false;
if (HeaderRevision != other.HeaderRevision)
return false;
if (Unk2 != other.Unk2)
return false;
if (SaveRevision != other.SaveRevision)
return false;
return true;
}
public override bool Equals(object? obj)
{
if (obj is null)
return false;
if (ReferenceEquals(this, obj))
return true;
if (obj.GetType() != GetType())
return false;
return Equals((FileHeaderInfo) obj);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = (int) Major;
hashCode = (hashCode * 397) ^ (int) Minor;
hashCode = (hashCode * 397) ^ Unk1.GetHashCode();
hashCode = (hashCode * 397) ^ HeaderRevision.GetHashCode();
hashCode = (hashCode * 397) ^ Unk2.GetHashCode();
hashCode = (hashCode * 397) ^ SaveRevision.GetHashCode();
return hashCode;
}
}
[field: FieldOffset(0x00)] public uint Major { get; init; }
[field: FieldOffset(0x04)] public uint Minor { get; init; }
[field: FieldOffset(0x08)] public ushort Unk1 { get; init; }
[field: FieldOffset(0x0A)] public ushort HeaderRevision { get; init; }
[field: FieldOffset(0x0C)] public ushort Unk2 { get; init; }
[field: FieldOffset(0x0E)] public ushort SaveRevision { get; init; }
}
}
}

View File

@ -66,6 +66,8 @@ public bool ValidateSizes()
var sizes = RevisionChecker.SizeInfo[info];
if (Main.Data.Length != sizes.Main)
return false;
// Each player present in the savedata must have been migrated to this revision.
foreach (var p in Players)
{
if (p.Personal.Data.Length != sizes.Personal)

View File

@ -15,17 +15,28 @@ public sealed class Player : IEnumerable<EncryptedFilePair>
public readonly PostBox PostBox;
public readonly Profile Profile;
/// <summary>
/// Directory Name where the player data was loaded from. Not the full path.
/// </summary>
public readonly string DirectoryName;
#region Override Implementations
public IEnumerator<EncryptedFilePair> GetEnumerator() => new EncryptedFilePair[] {Personal, Photo, PostBox, Profile}.AsEnumerable().GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public override string ToString() => Personal.PlayerName;
#endregion
/// <summary>
/// Imports Player data from the requested <see cref="folder"/>.
/// </summary>
/// <param name="folder">Folder that contains the Player Villager sub-folders.</param>
/// <returns>Player object array loaded from the <see cref="folder"/>.</returns>
public static Player[] ReadMany(string folder)
{
var dirs = Directory.GetDirectories(folder, "Villager*", SearchOption.TopDirectoryOnly);
var result = new Player[dirs.Length];
for (int i = 0; i <result.Length; i++)
for (int i = 0; i < result.Length; i++)
result[i] = new Player(dirs[i]);
return result;
}
@ -40,4 +51,4 @@ private Player(string folder)
Profile = new Profile(folder);
}
}
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using static NHSE.Core.FileHashRevision;
namespace NHSE.Core
{
@ -8,36 +9,40 @@ namespace NHSE.Core
/// </summary>
public static class RevisionChecker
{
// Patches where the sizes of individual files changed
/// <summary>
/// Unique save file size list by patch.
/// </summary>
private static readonly SaveFileSizes[] SizesByRevision =
{
new(0xAC0938, 0x6BC50, 0x263B4, 0xB44580, 0x69508), // 1.0.0
new(0xAC2AA0, 0x6BED0, 0x263C0, 0xB44590, 0x69560), // 1.1.0
new(0xACECD0, 0x6D6C0, 0x2C9C0, 0xB44590, 0x69560), // 1.2.0
new(0xACED80, 0x6D6D0, 0x2C9C0, 0xB44590, 0x69560), // 1.3.0
new(0xB05790, 0x74420, 0x2C9C0, 0xB44590, 0x69560), // 1.4.0
new(0xB20750, 0x76390, 0x2C9C0, 0xB44590, 0x69560), // 1.5.0
new(0xB258E0, 0x76CF0, 0x2C9C0, 0xB44590, 0x69560), // 1.6.0
new(REV_100_MAIN, REV_100_PERSONAL, REV_100_PHOTO, REV_100_POSTBOX, REV_100_PROFILE), // 1.0.0
new(REV_110_MAIN, REV_110_PERSONAL, REV_110_PHOTO, REV_110_POSTBOX, REV_110_PROFILE), // 1.1.0
new(REV_120_MAIN, REV_120_PERSONAL, REV_120_PHOTO, REV_120_POSTBOX, REV_120_PROFILE), // 1.2.0
new(REV_130_MAIN, REV_130_PERSONAL, REV_130_PHOTO, REV_130_POSTBOX, REV_130_PROFILE), // 1.3.0
new(REV_140_MAIN, REV_140_PERSONAL, REV_140_PHOTO, REV_140_POSTBOX, REV_140_PROFILE), // 1.4.0
new(REV_150_MAIN, REV_150_PERSONAL, REV_150_PHOTO, REV_150_POSTBOX, REV_150_PROFILE), // 1.5.0
new(REV_160_MAIN, REV_160_PERSONAL, REV_160_PHOTO, REV_160_POSTBOX, REV_160_PROFILE), // 1.6.0
new(REV_170_MAIN, REV_170_PERSONAL, REV_170_PHOTO, REV_170_POSTBOX, REV_170_PROFILE), // 1.7.0
};
private static readonly FileHeaderInfo[] RevisionInfo =
{
new() { Major = 0x67, Minor = 0x6F, HeaderRevision = 0, Unk1 = 2, SaveRevision = 0, Unk2 = 2 }, // 1.0.0
new() { Major = 0x6D, Minor = 0x78, HeaderRevision = 0, Unk1 = 2, SaveRevision = 1, Unk2 = 2 }, // 1.1.0
new() { Major = 0x6D, Minor = 0x78, HeaderRevision = 0, Unk1 = 2, SaveRevision = 2, Unk2 = 2 }, // 1.1.1
new() { Major = 0x6D, Minor = 0x78, HeaderRevision = 0, Unk1 = 2, SaveRevision = 3, Unk2 = 2 }, // 1.1.2
new() { Major = 0x6D, Minor = 0x78, HeaderRevision = 0, Unk1 = 2, SaveRevision = 4, Unk2 = 2 }, // 1.1.3
new() { Major = 0x6D, Minor = 0x78, HeaderRevision = 0, Unk1 = 2, SaveRevision = 5, Unk2 = 2 }, // 1.1.4
new() { Major = 0x20006, Minor = 0x20008, HeaderRevision = 0, Unk1 = 2, SaveRevision = 6, Unk2 = 2 }, // 1.2.0
new() { Major = 0x20006, Minor = 0x20008, HeaderRevision = 0, Unk1 = 2, SaveRevision = 7, Unk2 = 2 }, // 1.2.1
new() { Major = 0x40002, Minor = 0x40008, HeaderRevision = 0, Unk1 = 2, SaveRevision = 8, Unk2 = 2 }, // 1.3.0
new() { Major = 0x40002, Minor = 0x40008, HeaderRevision = 0, Unk1 = 2, SaveRevision = 9, Unk2 = 2 }, // 1.3.1
new() { Major = 0x00067, Minor = 0x0006F, HeaderRevision = 0, Unk1 = 2, SaveRevision = 00, Unk2 = 2 }, // 1.0.0
new() { Major = 0x0006D, Minor = 0x00078, HeaderRevision = 0, Unk1 = 2, SaveRevision = 01, Unk2 = 2 }, // 1.1.0
new() { Major = 0x0006D, Minor = 0x00078, HeaderRevision = 0, Unk1 = 2, SaveRevision = 02, Unk2 = 2 }, // 1.1.1
new() { Major = 0x0006D, Minor = 0x00078, HeaderRevision = 0, Unk1 = 2, SaveRevision = 03, Unk2 = 2 }, // 1.1.2
new() { Major = 0x0006D, Minor = 0x00078, HeaderRevision = 0, Unk1 = 2, SaveRevision = 04, Unk2 = 2 }, // 1.1.3
new() { Major = 0x0006D, Minor = 0x00078, HeaderRevision = 0, Unk1 = 2, SaveRevision = 05, Unk2 = 2 }, // 1.1.4
new() { Major = 0x20006, Minor = 0x20008, HeaderRevision = 0, Unk1 = 2, SaveRevision = 06, Unk2 = 2 }, // 1.2.0
new() { Major = 0x20006, Minor = 0x20008, HeaderRevision = 0, Unk1 = 2, SaveRevision = 07, Unk2 = 2 }, // 1.2.1
new() { Major = 0x40002, Minor = 0x40008, HeaderRevision = 0, Unk1 = 2, SaveRevision = 08, Unk2 = 2 }, // 1.3.0
new() { Major = 0x40002, Minor = 0x40008, HeaderRevision = 0, Unk1 = 2, SaveRevision = 09, Unk2 = 2 }, // 1.3.1
new() { Major = 0x50001, Minor = 0x5000B, HeaderRevision = 0, Unk1 = 2, SaveRevision = 10, Unk2 = 2 }, // 1.4.0
new() { Major = 0x50001, Minor = 0x5000B, HeaderRevision = 0, Unk1 = 2, SaveRevision = 11, Unk2 = 2 }, // 1.4.1
new() { Major = 0x50001, Minor = 0x5000B, HeaderRevision = 0, Unk1 = 2, SaveRevision = 12, Unk2 = 2 }, // 1.4.2
new() { Major = 0x60001, Minor = 0x6000C, HeaderRevision = 0, Unk1 = 2, SaveRevision = 13, Unk2 = 2 }, // 1.5.0
new() { Major = 0x60001, Minor = 0x6000C, HeaderRevision = 0, Unk1 = 2, SaveRevision = 14, Unk2 = 2 }, // 1.5.1
new() { Major = 0x70001, Minor = 0x70006, HeaderRevision = 0, Unk1 = 2, SaveRevision = 15, Unk2 = 2 }, // 1.6.0
new() { Major = 0x74001, Minor = 0x74005, HeaderRevision = 0, Unk1 = 2, SaveRevision = 16, Unk2 = 2 }, // 1.7.0
};
public static readonly IReadOnlyList<SaveFileSizes> SizeInfo = new[]
@ -58,26 +63,28 @@ public static class RevisionChecker
SizesByRevision[5], // 1.5.0
SizesByRevision[5], // 1.5.1
SizesByRevision[6], // 1.6.0
SizesByRevision[7], // 1.7.0
};
public static readonly IReadOnlyList<FileHashInfo> HashInfo = new[]
{
FileHashRevision.REV_100, // 1.0.0
FileHashRevision.REV_110, // 1.1.0
FileHashRevision.REV_110, // 1.1.1
FileHashRevision.REV_110, // 1.1.2
FileHashRevision.REV_110, // 1.1.3
FileHashRevision.REV_110, // 1.1.4
FileHashRevision.REV_120, // 1.2.0
FileHashRevision.REV_120, // 1.2.1
FileHashRevision.REV_130, // 1.3.0
FileHashRevision.REV_130, // 1.3.1
FileHashRevision.REV_140, // 1.4.0
FileHashRevision.REV_140, // 1.4.1
FileHashRevision.REV_140, // 1.4.2
FileHashRevision.REV_150, // 1.5.0
FileHashRevision.REV_150, // 1.5.1
FileHashRevision.REV_160, // 1.6.0
REV_100, // 1.0.0
REV_110, // 1.1.0
REV_110, // 1.1.1
REV_110, // 1.1.2
REV_110, // 1.1.3
REV_110, // 1.1.4
REV_120, // 1.2.0
REV_120, // 1.2.1
REV_130, // 1.3.0
REV_130, // 1.3.1
REV_140, // 1.4.0
REV_140, // 1.4.1
REV_140, // 1.4.2
REV_150, // 1.5.0
REV_150, // 1.5.1
REV_160, // 1.6.0
REV_170, // 1.7.0
};
public static bool IsRevisionKnown(this FileHeaderInfo info) => info.GetKnownRevisionIndex() >= 0;

View File

@ -68,6 +68,7 @@ public static MainSaveOffsets GetOffsets(FileHeaderInfo Info)
13 => new MainSaveOffsets15(),
14 => new MainSaveOffsets15(),
15 => new MainSaveOffsets16(),
16 => new MainSaveOffsets17(),
_ => throw new IndexOutOfRangeException("Unknown revision!" + Environment.NewLine + Info),
};
}

View File

@ -0,0 +1,53 @@
namespace NHSE.Core
{
/// <summary>
/// <inheritdoc cref="MainSaveOffsets"/>
/// </summary>
public class MainSaveOffsets17 : MainSaveOffsets
{
#region GSaveLand
public const int GSaveLandStart = 0x110;
public override int Animal => GSaveLandStart + 0x10;
public override int LandMyDesign => GSaveLandStart + 0x1e2600;
public override int PatternsPRO => LandMyDesign + (PatternCount * DesignPattern.SIZE);
public override int PatternFlag => PatternsPRO + (PatternCount * DesignPatternPRO.SIZE);
public override int PatternTailor => PatternFlag + DesignPattern.SIZE;
public const int GSaveWeather = GSaveLandStart + 0x1e23B0;
public override int WeatherArea => GSaveWeather + 0x14; // Hemisphere
public override int WeatherRandSeed => GSaveWeather + 0x18;
public override int EventFlagLand => GSaveLandStart + 0x20a408;
// GSaveMainField
public const int GSaveMainFieldStart = GSaveLandStart + 0x20ac08;
public override int FieldItem => GSaveMainFieldStart + 0x00000;
public override int LandMakingMap => GSaveMainFieldStart + 0xAAA00;
public override int MainFieldStructure => GSaveMainFieldStart + 0xCF600;
public override int OutsideField => GSaveMainFieldStart + 0xCF998;
public override int MyDesignMap => GSaveMainFieldStart + 0xCFA34;
public override int PlayerHouseList => GSaveLandStart + 0x2e5634;
public override int NpcHouseList => GSaveLandStart + 0x417634;
public const int GSaveShop = GSaveLandStart + 0x41887c;
public override int ShopKabu => GSaveShop + 0x2cb0; // part of shop; tailor increased size
public override int Museum => GSaveLandStart + 0x41bba0;
public override int Visitor => GSaveLandStart + 0x41efa4;
public override int SaveFg => GSaveLandStart + 0x41f1d4;
public override int BulletinBoard => GSaveLandStart + 0x41fb18;
public override int AirportThemeColor => GSaveLandStart + 0x500720;
#endregion
#region GSaveLandOther
public const int GSaveLandOtherStart = 0x504470;
public override int LostItemBox => GSaveLandOtherStart + 0x340680;
public override int LastSavedTime => GSaveLandOtherStart + 0x344f18;
#endregion
public override int VillagerSize => Villager2.SIZE;
public override IVillager ReadVillager(byte[] data) => new Villager2(data);
}
}

View File

@ -60,6 +60,7 @@ public static PersonalOffsets GetOffsets(FileHeaderInfo Info)
13 => new PersonalOffsets15(),
14 => new PersonalOffsets15(),
15 => new PersonalOffsets16(),
16 => new PersonalOffsets17(),
_ => throw new IndexOutOfRangeException("Unknown revision!" + Environment.NewLine + Info),
};
}

View File

@ -0,0 +1,47 @@
namespace NHSE.Core
{
/// <summary>
/// <inheritdoc cref="PersonalOffsets"/>
/// </summary>
public sealed class PersonalOffsets17 : PersonalOffsets
{
private const int Player = 0x110;
public override int PersonalId => Player + 0xAFA8;
public override int EventFlagsPlayer => Player + 0xAFE0;
private const int GSaveLifeSupport = Player + 0xBFE0;
public override int CountAchievement => GSaveLifeSupport + 0xE98; // CountAchievement
public override int NowPoint => GSaveLifeSupport + 0x5498; // Nook Miles
public override int TotalPoint => NowPoint + 8; // Total Nook Miles Earned
public override int Birthday => Player + 0x1228c;
public override int ProfileMain => Player + 0x122a0;
public override int ProfilePhoto => ProfileMain + 0x14;
public override int ProfileBirthday => ProfileMain + 0x23058;
public override int ProfileFruit => ProfileMain + 0x2305C;
public override int ProfileTimestamp => ProfileMain + 0x230CC;
public override int ProfileIsMakeVillage => ProfileMain + 0x230D0;
// end player
private const int PlayerOther = 0x36a50;
public override int Pockets1 => PlayerOther + 0x10;
public override int Pockets2 => Pockets1 + (8 * Pockets1Count) + 0x18;
public override int Wallet => Pockets2 + (8 * Pockets2Count) + 0x18;
public override int ItemChest => PlayerOther + 0x18C;
public override int ItemCollectBit => PlayerOther + 0xA058;
public override int ItemRemakeCollectBit => PlayerOther + 0xA7AC;
public override int Manpu => PlayerOther + 0xAF7C;
public override int Bank => PlayerOther + 0x22594;
public override int Recipes => Bank + 0x10;
public override int MaxRecipeID => 0x308;
public override int MaxRemakeBitFlag => 0x7D0 * 32;
public override IReactionStore ReadReactions(byte[] data) => data.Slice(Manpu, GSavePlayerManpu15.SIZE).ToStructure<GSavePlayerManpu15>();
public override void SetReactions(byte[] data, IReactionStore value) => ((GSavePlayerManpu15)value).ToBytes().CopyTo(data, Manpu);
}
}

View File

@ -93,6 +93,9 @@ public static bool TryGetMaxStackCount(ushort id, out ushort max)
{Kind_HandheldPennant, 00001},
{Kind_BigbagPresent, 00001},
{Kind_JuiceFuzzyapple, 00001},
{Kind_Megaphone, 00001},
{Kind_SoySet, 00001},
{Kind_MaracasCarnival, 00001},
{Kind_TreeSeedling, 00010},
{Kind_Tree, 00001},
{Kind_BushSeedling, 00010},
@ -147,6 +150,7 @@ public static bool TryGetMaxStackCount(ushort id, out ushort max)
{Kind_DIYRecipe, 00001},
{Kind_MessageBottle, 00001},
{Kind_WrappingPaper, 00010},
{Kind_Otoshidama, 00010},
{Kind_HousingKit, 00001},
{Kind_HousingKitRcoQuest, 00001},
{Kind_HousingKitBirdge, 00001},
@ -170,6 +174,8 @@ public static bool TryGetMaxStackCount(ushort id, out ushort max)
{Kind_LoveCrystal, 00030},
{Kind_Candy, 00030},
{Kind_HarvestDish, 00001},
{Kind_Feather, 00003},
{Kind_RainbowFeather, 00001},
{Kind_Giftbox, 00001},
{Kind_PinataStick, 00001},
{Kind_NpcOutfit, 00001},
@ -189,6 +195,7 @@ public static bool TryGetMaxStackCount(ushort id, out ushort max)
{Kind_EventObjFtr, 00001},
{Kind_NnpcRoomMarker, 00001},
{Kind_PhotoStudioList, 00001},
{Kind_DummyWrappingOtoshidama, 00001},
};
/// <summary>

View File

@ -47,8 +47,10 @@ public enum ItemKind : byte
Kind_DummyPresentbox,
Kind_DummyRecipe,
Kind_DummyWrapping,
Kind_DummyWrappingOtoshidama,
Kind_EasterEgg,
Kind_EventObjFtr,
Kind_Feather,
Kind_Fence,
Kind_FierworkHand,
Kind_FireworkM,
@ -83,7 +85,9 @@ public enum ItemKind : byte
Kind_LostQuest,
Kind_LostQuestDust,
Kind_LoveCrystal,
Kind_MaracasCarnival,
Kind_Medicine,
Kind_Megaphone,
Kind_MessageBottle,
Kind_MilePlaneTicket,
Kind_Money,
@ -97,6 +101,7 @@ public enum ItemKind : byte
Kind_NpcOutfit,
Kind_Ocarina,
Kind_Ore,
Kind_Otoshidama,
Kind_Panflute,
Kind_Partyhorn,
Kind_PartyPopper,
@ -110,6 +115,7 @@ public enum ItemKind : byte
Kind_Poster,
Kind_QuestChristmasPresentbox,
Kind_QuestWrapping,
Kind_RainbowFeather,
Kind_RiverMaker,
Kind_RollanTicket,
Kind_RoomFloor,
@ -128,6 +134,7 @@ public enum ItemKind : byte
Kind_SmartPhone,
Kind_SnowCrystal,
Kind_Socks,
Kind_SoySet,
Kind_StarPiece,
Kind_StickLight,
Kind_TailorTicket,
@ -150,8 +157,8 @@ public enum ItemKind : byte
Kind_Windmill,
Kind_WoodenStickTool,
Kind_WrappingPaper,
Kind_YutaroWisp,
Kind_XmasDeco,
Kind_YutaroWisp,
Onepiece_Dress,
Onepiece_Long,
Onepiece_Middle,

View File

@ -5,6 +5,18 @@ namespace NHSE.Core
/// </summary>
public enum ItemMenuIconType : ushort
{
_0x096F00E1,
_0x1178E84F,
_0x2B925207,
_0x3CD47393,
_0x599D99CA,
_0x5A07F70B,
_0x5E0B9075,
_0x631DD141,
_0x6C26EAB8,
_0x8CC66ACC,
_0xD4295E14,
_0xE3CF868D,
Akoyagai,
Amaebi,
Anemone0,

View File

@ -8,6 +8,7 @@ namespace NHSE.Core
public class ItemRemakeInfo
{
public const int BodyColorCountMax = 8;
public const int NoColor = (int)ItemCustomColor.None; // 14
public readonly short Index;
public readonly ushort ItemUniqueID;
@ -38,8 +39,8 @@ public ItemRemakeInfo(short index, ushort id, sbyte count, byte[] bc0, byte[] bc
private const string Invalid = nameof(Invalid);
public bool HasBodyColor(int variant) => ReBodyPatternColors0[variant] != 14 || ReBodyPatternColors1[variant] != 14;
public bool HasFabricColor(int variant) => ReFabricPatternColors0[variant] != 14 || ReFabricPatternColors1[variant] != 14;
public bool HasBodyColor(int variant) => ReBodyPatternColors0[variant] != NoColor || ReBodyPatternColors1[variant] != NoColor;
public bool HasFabricColor(int variant) => ReFabricPatternColors0[variant] != NoColor || ReFabricPatternColors1[variant] != NoColor;
public string GetBodyDescription(int colorIndex, IRemakeString str)
{

View File

@ -363,14 +363,14 @@ public static class ItemRemakeInfoData
{0512, new ItemRemakeInfo(0512, 04017, 3, new byte[] {11, 07, 09, 10, 14, 14, 14, 14}, new byte[] {10, 07, 09, 10, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shower set
{0513, new ItemRemakeInfo(0513, 04104, 5, new byte[] {10, 10, 10, 10, 10, 10, 14, 14}, new byte[] {10, 06, 08, 01, 07, 09, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // frying pan
{0515, new ItemRemakeInfo(0515, 04137, 6, new byte[] {01, 04, 07, 06, 02, 08, 10, 14}, new byte[] {12, 12, 12, 12, 12, 12, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // diner chair
{0516, new ItemRemakeInfo(0516, 04138, 6, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 04, 07, 05, 02, 12, 10, 14}, false)}, // diner counter chair
{0516, new ItemRemakeInfo(0516, 04138, 6, new byte[] {11, 11, 11, 11, 11, 11, 11, 14}, new byte[] {01, 04, 07, 06, 02, 08, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 04, 07, 05, 02, 12, 10, 14}, false)}, // diner counter chair
{0517, new ItemRemakeInfo(0517, 04139, 6, new byte[] {01, 04, 07, 06, 02, 08, 10, 14}, new byte[] {11, 11, 11, 11, 11, 11, 11, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // diner counter table
{0518, new ItemRemakeInfo(0518, 04140, 5, new byte[] {01, 06, 07, 12, 10, 09, 14, 14}, new byte[] {01, 06, 07, 12, 10, 09, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 06, 07, 14, 14, 14, 14, 14}, false)}, // retro gas pump
{0519, new ItemRemakeInfo(0519, 04141, 6, new byte[] {01, 04, 07, 06, 02, 08, 10, 14}, new byte[] {12, 12, 12, 12, 12, 12, 12, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // diner sofa
{0520, new ItemRemakeInfo(0520, 04142, 6, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 04, 07, 05, 02, 12, 10, 14}, false)}, // diner dining table
{0520, new ItemRemakeInfo(0520, 04142, 6, new byte[] {11, 11, 11, 11, 11, 11, 11, 14}, new byte[] {01, 04, 07, 06, 02, 08, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 04, 07, 05, 02, 12, 10, 14}, false)}, // diner dining table
{0521, new ItemRemakeInfo(0521, 04143, 4, new byte[] {04, 07, 01, 02, 01, 14, 14, 14}, new byte[] {01, 00, 06, 03, 04, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // diner neon sign
{0522, new ItemRemakeInfo(0522, 04144, 6, new byte[] {01, 04, 07, 06, 02, 12, 03, 14}, new byte[] {01, 04, 07, 06, 02, 12, 03, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {13, 04, 10, 14, 14, 14, 14, 14}, false)}, // diner neon clock
{0523, new ItemRemakeInfo(0523, 04441, 6, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 04, 07, 05, 02, 12, 10, 14}, false)}, // diner mini table
{0523, new ItemRemakeInfo(0523, 04441, 6, new byte[] {11, 11, 11, 11, 11, 11, 11, 14}, new byte[] {01, 04, 07, 06, 02, 08, 10, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {01, 04, 07, 05, 02, 12, 10, 14}, false)}, // diner mini table
{0524, new ItemRemakeInfo(0524, 03406, 4, new byte[] {08, 12, 01, 04, 07, 14, 14, 14}, new byte[] {08, 12, 06, 10, 09, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // beekeeper's hive
{0525, new ItemRemakeInfo(0525, 04023, 2, new byte[] {01, 09, 11, 14, 14, 14, 14, 14}, new byte[] {11, 12, 04, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // pants press
{0526, new ItemRemakeInfo(0526, 01161, 3, new byte[] {00, 11, 12, 12, 14, 14, 14, 14}, new byte[] {11, 11, 11, 11, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cream and sugar
@ -487,7 +487,7 @@ public static class ItemRemakeInfoData
{0671, new ItemRemakeInfo(0671, 07143, 5, new byte[] {13, 12, 12, 12, 01, 05, 14, 14}, new byte[] {13, 13, 08, 13, 03, 06, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Mom's candle set
{0672, new ItemRemakeInfo(0672, 07146, 5, new byte[] {13, 01, 13, 12, 13, 09, 14, 14}, new byte[] {12, 12, 12, 02, 04, 10, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Mom's homemade cake
{0673, new ItemRemakeInfo(0673, 07139, 7, new byte[] {13, 13, 12, 13, 13, 13, 13, 13}, new byte[] {09, 08, 10, 07, 07, 12, 07, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Mom's art
{0674, new ItemRemakeInfo(0674, 07135, 7, new byte[] {12, 00, 01, 02, 00, 04, 05, 06}, new byte[] {12, 00, 01, 02, 00, 04, 05, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // floor light
{0674, new ItemRemakeInfo(0674, 07135, 7, new byte[] {12, 00, 01, 02, 03, 04, 05, 06}, new byte[] {12, 00, 01, 02, 03, 04, 05, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // floor light
{0675, new ItemRemakeInfo(0675, 07136, 4, new byte[] {12, 10, 01, 05, 02, 14, 14, 14}, new byte[] {06, 06, 06, 06, 06, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // cat grass
{0676, new ItemRemakeInfo(0676, 07148, 3, new byte[] {01, 04, 07, 00, 14, 14, 14, 14}, new byte[] {12, 12, 12, 12, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // life ring
{0680, new ItemRemakeInfo(0680, 07189, 7, new byte[] {10, 10, 10, 10, 10, 10, 10, 10}, new byte[] {12, 07, 00, 01, 02, 03, 04, 06}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // studio spotlight
@ -616,7 +616,7 @@ public static class ItemRemakeInfoData
{0843, new ItemRemakeInfo(0843, 05309, 7, new byte[] {02, 11, 10, 04, 06, 00, 01, 03}, new byte[] {12, 05, 12, 05, 06, 00, 01, 03}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // heart doorplate
{0844, new ItemRemakeInfo(0844, 05716, 7, new byte[] {08, 05, 10, 00, 09, 12, 05, 02}, new byte[] {09, 00, 08, 08, 08, 00, 04, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // paw-print doorplate
{0845, new ItemRemakeInfo(0845, 04738, 1, new byte[] {08, 12, 14, 14, 14, 14, 14, 14}, new byte[] {09, 01, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // skull doorplate
{0846, new ItemRemakeInfo(0846, 05717, 5, new byte[] {11, 07, 11, 01, 11, 14, 14, 14}, new byte[] {10, 11, 04, 12, 06, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // crest doorplate
{0846, new ItemRemakeInfo(0846, 05717, 5, new byte[] {11, 07, 11, 01, 11, 13, 14, 14}, new byte[] {10, 11, 04, 12, 06, 12, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // crest doorplate
{0847, new ItemRemakeInfo(0847, 05719, 1, new byte[] {11, 04, 14, 14, 14, 14, 14, 14}, new byte[] {08, 08, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fossil doorplate
{0848, new ItemRemakeInfo(0848, 04764, 7, new byte[] {05, 01, 00, 07, 06, 03, 10, 11}, new byte[] {12, 12, 12, 12, 12, 12, 12, 12}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // fish doorplate
{0849, new ItemRemakeInfo(0849, 04752, 7, new byte[] {10, 12, 04, 11, 08, 07, 00, 09}, new byte[] {10, 12, 04, 11, 08, 07, 00, 09}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // iron doorplate
@ -661,7 +661,7 @@ public static class ItemRemakeInfoData
{0895, new ItemRemakeInfo(0895, 12207, 2, new byte[] {01, 11, 04, 14, 14, 14, 14, 14}, new byte[] {11, 11, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // arcade seat
{0896, new ItemRemakeInfo(0896, 07259, 3, new byte[] {06, 07, 02, 04, 14, 14, 14, 14}, new byte[] {00, 06, 02, 04, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // palm-tree lamp
{0897, new ItemRemakeInfo(0897, 11942, 1, new byte[] {13, 13, 14, 14, 14, 14, 14, 14}, new byte[] {01, 12, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // street piano
{0899, new ItemRemakeInfo(0899, 00667, 1, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shaved-ice maker
{0899, new ItemRemakeInfo(0899, 00667, 1, new byte[] {05, 12, 14, 14, 14, 14, 14, 14}, new byte[] {04, 05, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // shaved-ice maker
{0901, new ItemRemakeInfo(0901, 12332, 2, new byte[] {08, 00, 12, 14, 14, 14, 14, 14}, new byte[] {10, 06, 11, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // natural square table
{0920, new ItemRemakeInfo(0920, 12373, 5, new byte[] {01, 06, 11, 13, 00, 10, 14, 14}, new byte[] {12, 07, 11, 12, 00, 01, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Pocket vintage camper
{0921, new ItemRemakeInfo(0921, 12372, 5, new byte[] {07, 01, 06, 13, 11, 00, 14, 14}, new byte[] {01, 10, 06, 13, 13, 13, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Pocket modern camper
@ -705,10 +705,21 @@ public static class ItemRemakeInfoData
{1295, new ItemRemakeInfo(1295, 13447, 1, new byte[] {12, 11, 14, 14, 14, 14, 14, 14}, new byte[] {12, 11, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Turkey Day garden stand
{1296, new ItemRemakeInfo(1296, 13448, 1, new byte[] {12, 11, 14, 14, 14, 14, 14, 14}, new byte[] {00, 06, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Turkey Day hearth
{1297, new ItemRemakeInfo(1297, 13453, 1, new byte[] {09, 08, 14, 14, 14, 14, 14, 14}, new byte[] {12, 06, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Turkey Day table
{1495, new ItemRemakeInfo(1495, 13767, 4, new byte[] {06, 01, 04, 03, 13, 14, 14, 14}, new byte[] {07, 00, 05, 02, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Festivale garland
{1496, new ItemRemakeInfo(1496, 13776, 4, new byte[] {06, 01, 04, 03, 13, 14, 14, 14}, new byte[] {07, 00, 05, 02, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Festivale confetti machine
{1497, new ItemRemakeInfo(1497, 13775, 4, new byte[] {06, 01, 04, 03, 13, 14, 14, 14}, new byte[] {07, 00, 12, 02, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Festivale stage
{1498, new ItemRemakeInfo(1498, 13774, 4, new byte[] {06, 01, 04, 03, 13, 14, 14, 14}, new byte[] {09, 09, 12, 02, 08, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Festivale drum
{1500, new ItemRemakeInfo(1500, 13770, 4, new byte[] {06, 01, 04, 03, 13, 14, 14, 14}, new byte[] {07, 00, 05, 02, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Festivale parasol
{1501, new ItemRemakeInfo(1501, 13772, 4, new byte[] {06, 01, 04, 03, 13, 14, 14, 14}, new byte[] {07, 00, 12, 02, 13, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Festivale balloon lamp
{1504, new ItemRemakeInfo(1504, 13773, 4, new byte[] {06, 01, 04, 03, 13, 14, 14, 14}, new byte[] {07, 00, 05, 02, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Festivale stall
{1505, new ItemRemakeInfo(1505, 13777, 4, new byte[] {06, 01, 04, 03, 13, 14, 14, 14}, new byte[] {07, 00, 05, 02, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Festivale lamp
{1506, new ItemRemakeInfo(1506, 13778, 4, new byte[] {06, 01, 04, 03, 13, 14, 14, 14}, new byte[] {08, 09, 12, 02, 12, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Festivale flag
{1508, new ItemRemakeInfo(1508, 13820, 1, new byte[] {00, 06, 14, 14, 14, 14, 14, 14}, new byte[] {12, 12, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Turkey Day table setting
{1509, new ItemRemakeInfo(1509, 13818, 1, new byte[] {12, 06, 14, 14, 14, 14, 14, 14}, new byte[] {00, 06, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Turkey Day casserole
{1510, new ItemRemakeInfo(1510, 13819, 1, new byte[] {09, 07, 14, 14, 14, 14, 14, 14}, new byte[] {08, 06, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // Turkey Day wheat decor
{1516, new ItemRemakeInfo(1516, 13488, 3, new byte[] {09, 10, 12, 02, 14, 14, 14, 14}, new byte[] {01, 07, 04, 05, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // chocolate heart
{1524, new ItemRemakeInfo(1524, 13930, 5, new byte[] {13, 02, 04, 11, 01, 11, 14, 14}, new byte[] {13, 12, 05, 04, 12, 08, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // set of stockings
{1546, new ItemRemakeInfo(1546, 14029, 5, new byte[] {01, 02, 07, 03, 12, 10, 14, 14}, new byte[] {12, 12, 00, 12, 06, 11, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, new byte[] {14, 14, 14, 14, 14, 14, 14, 14}, false)}, // heart-shaped bouquet
};
}
}

View File

@ -1109,11 +1109,22 @@ public static class ItemRemakeUtil
{13449, 1293}, // Turkey Day decorations
{13450, 1292}, // Turkey Day chair
{13453, 1297}, // Turkey Day table
{13488, 1516}, // chocolate heart
{13767, 1495}, // Festivale garland
{13770, 1500}, // Festivale parasol
{13772, 1501}, // Festivale balloon lamp
{13773, 1504}, // Festivale stall
{13774, 1498}, // Festivale drum
{13775, 1497}, // Festivale stage
{13776, 1496}, // Festivale confetti machine
{13777, 1505}, // Festivale lamp
{13778, 1506}, // Festivale flag
{13818, 1509}, // Turkey Day casserole
{13819, 1510}, // Turkey Day wheat decor
{13820, 1508}, // Turkey Day table setting
{13862, 0652}, // Jingle's photo
{13930, 1524}, // set of stockings
{14029, 1546}, // heart-shaped bouquet
};
}
}

View File

@ -642,7 +642,9 @@ public static class RecipeList
{0x2EE, 13244}, // gift pile
{0x2EF, 13792}, // festive wrapping paper
{0x2F0, 13603}, // falling-snow wall
{0x2F3, 03548}, // rainbow feather
{0x2F5, 12217}, // summer-shell rug
{0x308, 14278}, // mermaid fence
};
}
}

View File

@ -323,7 +323,6 @@ public EventFlagLand(short init, short max, ushort index, string name)
{0x160, new EventFlagLand(0 , 1 , 0352, "FoxPreVisitAlreadyBuyToday" )}, // つねきち|今日誰かが事前来訪中に美術品を買った
{0x161, new EventFlagLand(0 , 1 , 0353, "RcoHasResolvedMoveKitBug" )}, // いせつキットバグを解消したか
{0x162, new EventFlagLand(0 , 1 , 0354, "TapDreamEnable" )}, // ゆめみ|ゆめみ機能解禁か?
{0x164, new EventFlagLand(0 , 1 , 0356, "MyDesignPro2" )}, // 追加型マイデザインPro解禁
{0x165, new EventFlagLand(0 , 1 , 0357, "GulBVisitEnable" )}, // 海賊ジョニーが来訪する条件を満たしたか
{0x167, new EventFlagLand(0 , 9999 , 0359, "FireworksAddBbsYear" )}, // 花火大会予告の掲示板書き込みをした年
{0x16A, new EventFlagLand(0 , 1 , 0362, "EnableMyDream" )}, // ゆめみ|現在、自分の島の夢を提供中か?
@ -361,12 +360,21 @@ public EventFlagLand(short init, short max, ushort index, string name)
{0x18F, new EventFlagLand(0 , 1 , 0399, "TkkFirstLiveNow" )}, // とたけけ|初ライブステージか?
{0x190, new EventFlagLand(0 , 1 , 0400, "ChristmasFtrFirstRound" )}, // クリスマスおもちゃ家具の商品抽選が1巡したか
{0x191, new EventFlagLand(0 , 9999 , 0401, "HarvestFestivalAddBbsYear" )}, // ハーベストフェスティバル予告の掲示板書き込みをした年
{0x192, new EventFlagLand(0 , 1 , 0402, "GrowUpAfterPatch1_7" )}, // 1.7適用して成長処理をした
{0x193, new EventFlagLand(0 , 9999 , 0403, "XmasEveAddBbsYear" )}, // クリスマス予告の掲示板書き込みをした年
{0x194, new EventFlagLand(0 , 1 , 0404, "BCAT_EventFlag_005" )}, // クリスマス準備期間解禁
{0x195, new EventFlagLand(0 , -1 , 0405, "RandomKey5" )}, // ランダムキーe
{0x196, new EventFlagLand(0 , 1 , 0406, "ShopSocksFlag" )}, // かべかけソックス当選済み
{0x197, new EventFlagLand(0 , -1 , 0407, "ShopHeartChocoSelect" )}, // ハートのチョコレート抽選済みカラバリ
{0x198, new EventFlagLand(0 , -1 , 0408, "ShopHeartFlowerSelect" )}, // ハートのバラブーケ抽選済みカラバリ
{0x199, new EventFlagLand(0 , -1 , 0409, "RandomKey6" )}, // ランダムキーf
{0x19A, new EventFlagLand(0 , -1 , 0410, "RandomKey7" )}, // ランダムキーg
{0x19C, new EventFlagLand(0 , 1 , 0412, "BCAT_EventFlag_006" )}, // クリスマスイブ解禁
{0x19D, new EventFlagLand(0 , 1 , 0413, "BCAT_EventFlag_007" )}, // カーニバル本番、バレンタイン本番解禁
{0x1A3, new EventFlagLand(0 , 9999 , 0419, "ValentineAddBbsYear" )}, // バレンタイン予告の掲示板書き込みをした年
{0x1A4, new EventFlagLand(0 , 9999 , 0420, "CarnivalAddBbsYear" )}, // カーニバル予告の掲示板書き込みをした年
{0x1A5, new EventFlagLand(0 , 1 , 0421, "CarnivalNpcFeatherColorDecided" )}, // カーニバルNPCが欲しがる羽の色決定済み
{0x1A6, new EventFlagLand(0 , 1 , 0422, "CarnivalEventPlazaNpcWander" )}, // カーニバル広場行動NPCがぶらつくか
};
private const string Unknown = "???";

View File

@ -28,7 +28,6 @@ public EventFlagPlayer(short init, short max, ushort index, string name)
{0x009, new EventFlagPlayer(0 , 1 , 0009, "JohnnyQuestFinishFlag" )}, // ジョニークエスト完了フラグ(海賊ジョニーは別フラグ)
{0x00A, new EventFlagPlayer(0 , 8 , 0010, "JonnyTalkCount" )}, // 寝ているジョニーに話しかけた回数(海賊ジョニー共用)
{0x00B, new EventFlagPlayer(0 , 1 , 0011, "HasPlayedTreasureHunt" )}, // 宝探しクエストをした事がある
{0x00C, new EventFlagPlayer(0 , 1 , 0012, "HasPlayedHideAndSeek" )}, // かくれんぼクエストをした事がある
{0x00D, new EventFlagPlayer(0 , 1 , 0013, "ShizueCmnExplanationTowntune" )}, // しずえ|メロ説明聞いたか?
{0x00E, new EventFlagPlayer(0 , 1 , 0014, "ShizueCmnExplanationTownflag" )}, // しずえ|村の旗説明聞いたか?
{0x00F, new EventFlagPlayer(0 , 1 , 0015, "ShizueCmnExplanationComplaint" )}, // しずえ|『村民のこと』の説明聞いたか?
@ -946,7 +945,6 @@ public EventFlagPlayer(short init, short max, ushort index, string name)
{0x47B, new EventFlagPlayer(0 , 1 , 1147, "NpcHalloweenTrickFlag" )}, // ハロウィン|今日イタズラされた?
{0x47C, new EventFlagPlayer(0 , 1 , 1148, "TapFirstDreamIn" )}, // ゆめみ|夢の中に入ったことがある?
{0x47D, new EventFlagPlayer(0 , 1 , 1149, "TapFirstCheckMydesingShowcase" )}, // ゆめみ|夢の中のマイデザインショーケース端末にアクセスしたことがある?
{0x47E, new EventFlagPlayer(0 , 1 , 1150, "SeekingQuestFirst" )}, // かくれんぼ|かくれんをした事がある
{0x47F, new EventFlagPlayer(0 , 1 , 1151, "SpecialMakeChanged" )}, // プレイヤが特殊メイクに変更した
{0x480, new EventFlagPlayer(0 , 1 , 1152, "TalkMakeTodayAnyone" )}, // 今日誰かにメイク会話を聞いたか
{0x481, new EventFlagPlayer(0 , 1 , 1153, "RcmExplainCandyFlag" )}, // まめきち/ハロウィン|今年アメの説明聞いた?
@ -1032,6 +1030,7 @@ public EventFlagPlayer(short init, short max, ushort index, string name)
{0x4E5, new EventFlagPlayer(0 , 10 , 1253, "SantaMissionNpcIndex3" )}, // クリスマスサンタミッションでお返しをくれるNPC3
{0x4E6, new EventFlagPlayer(0 , 1 , 1254, "ReceiveLeaveTapLetter" )}, // ゆめみ|おまかせ解禁の手紙を受け取った
{0x4E7, new EventFlagPlayer(0 , 1 , 1255, "RcmExplainToy" )}, // クリスマス|おもちゃ家具陳列の案内を受けた?
{0x4E8, new EventFlagPlayer(0 , 1 , 1256, "PckTalkTodayFlag" )}, // カーニバル/べルリーナ|今日すでに会話した?
{0x4E9, new EventFlagPlayer(0 , 9999, 1257, "ChristmasWreathGetYear" )}, // クリスマスクリスマスリースをNPCから貰った年
{0x4EA, new EventFlagPlayer(0 , 9 , 1258, "TukSecretRewardType" )}, // ハーベスト|フランクリンの隠し食材報酬抽選結果
{0x4EE, new EventFlagPlayer(0 , 1 , 1262, "TapUpdatedDreamFirstTalk" )}, // ゆめみ|初回会話を1.6.0以降に行った?
@ -1039,6 +1038,7 @@ public EventFlagPlayer(short init, short max, ushort index, string name)
{0x4F1, new EventFlagPlayer(0 , 1 , 1265, "CheckHarvestFtrInStore" )}, // ハーベスト|ハーベスト家具をお店でチェックしたことがあるか?
{0x4F2, new EventFlagPlayer(0 , 9999, 1266, "ChristmasPresentYear" )}, // クリスマス|自宅プレゼントをもらった年
{0x4F3, new EventFlagPlayer(0 , 2 , 1267, "InputApproachBanCount" )}, // アプローチ|入力系アプローチ禁止カウント
{0x4F4, new EventFlagPlayer(0 , 1 , 1268, "PckLookChatFlag" )}, // カーニバル/べルリーナ|カーニバル装備の雑談した?
{0x4F5, new EventFlagPlayer(0 , 1 , 1269, "TukCancel1stRequest" )}, // ハーベスト|フランクリン1品目で「大変ですね」を選択した
{0x4F6, new EventFlagPlayer(0 , 1 , 1270, "ChristmasWrappingGiftFlag" )}, // クリスマス|プレゼント交換初回でラッピングもらった?
{0x4F8, new EventFlagPlayer(0 , 1 , 1272, "HarvestRefuseGiveHQFood1" )}, // ハーベスト|料理1の隠し食材を渡すのを拒んだ
@ -1050,18 +1050,46 @@ public EventFlagPlayer(short init, short max, ushort index, string name)
{0x4FE, new EventFlagPlayer(0 , 2 , 1278, "HarvestGetHint3" )}, // ハーベスト|料理3の隠し食材ヒント聞いた
{0x4FF, new EventFlagPlayer(0 , 2 , 1279, "HarvestGetHint4" )}, // ハーベスト|料理4の隠し食材ヒント聞いた
{0x500, new EventFlagPlayer(0 , 1 , 1280, "ChristmasWrappingPresentFlag" )}, // クリスマス|ラッピングを誰かくれようとしたか?
{0x501, new EventFlagPlayer(0 , 1 , 1281, "PckRecipeFlag" )}, // カーニバル/べルリーナ|にじいろのはねのレシピもらった?
{0x502, new EventFlagPlayer(0 , 1 , 1282, "RcoStorageExpansionReserved" )}, // たぬきち|収納の拡張を予約している
{0x503, new EventFlagPlayer(0 , 1 , 1283, "RcoStorageExpansionLevel" )}, // たぬきち|収納の拡張段階
{0x504, new EventFlagPlayer(0 , 1 , 1284, "PlayerMovingReservedStorageExpand" )}, // たぬきち|収納の拡張申し込み当日にPだけ引越しした
{0x505, new EventFlagPlayer(0 , 1 , 1285, "MailSend_NoticeStorageExpansion" )}, // たぬきち|収納の拡張のお知らせ手紙の判定処理したか?
{0x506, new EventFlagPlayer(0 , 1 , 1286, "RcoStandbyNoticeStorageExpansion" )}, // たぬきち|収納の拡張について強制会話するか?
{0x507, new EventFlagPlayer(0 , 1 , 1287, "ChristmasWreathNoGetFlag" )}, // クリスマス|このNPCからリース受け取り損ねた
{0x508, new EventFlagPlayer(0 , 3 , 1288, "PckGetItem" )}, // カーニバル/べルリーナ|報酬アイテムは?
{0x50A, new EventFlagPlayer(0 , 1 , 1290, "GetCarnivalLight" )}, // カーニバル/べルリーナ|カーニバルなライトもらった?
{0x50B, new EventFlagPlayer(0 , 1 , 1291, "GetCarnivalFoodStand" )}, // カーニバル/べルリーナ|カーニバルな屋台もらった?
{0x50C, new EventFlagPlayer(0 , 1 , 1292, "GetCarnivalstage" )}, // カーニバル/べルリーナ|カーニバルなステージもらった?
{0x50D, new EventFlagPlayer(0 , 1 , 1293, "GetCarnivalConfettiMachine" )}, // カーニバル/べルリーナ|カーニバルなかみふぶきマシンもらった?
{0x50E, new EventFlagPlayer(0 , 1 , 1294, "GetCarnivalPercussion" )}, // カーニバル/べルリーナ|カーニバルなパーカッションもらった?
{0x50F, new EventFlagPlayer(0 , 1 , 1295, "GetCarnivalBalloonLight" )}, // カーニバル/べルリーナ|カーニバルバルーンライトもらった?
{0x510, new EventFlagPlayer(0 , 1 , 1296, "GetCarnivalUmbrellas" )}, // カーニバル/べルリーナ|カーニバルなパラソルもらった?
{0x511, new EventFlagPlayer(0 , 1 , 1297, "GetCarnivalFlag" )}, // カーニバル/べルリーナ|カーニバルなフラッグもらった?
{0x512, new EventFlagPlayer(0 , 1 , 1298, "GetCarnivalGarland" )}, // カーニバル/べルリーナ|カーニバルなガーランドもらった?
{0x513, new EventFlagPlayer(0 , 1 , 1299, "GetCarnivalFloat" )}, // カーニバル/べルリーナ|カーニバルなフロートもらった?
{0x515, new EventFlagPlayer(0 , 10 , 1301, "PckGiveFurnitureCount" )}, // カーニバル/べルリーナ|家具をもらった回数
{0x518, new EventFlagPlayer(0 , 1 , 1304, "SloExplainPumpkinColorFlag" )}, // レイジ|かぼちゃの苗説明聞いたことある?
{0x519, new EventFlagPlayer(0 , 1 , 1305, "SloExplainAddPumpkinFlag" )}, // レイジ|かぼちゃの苗販売開始の説明聞いた?
{0x51B, new EventFlagPlayer(0 , 1 , 1307, "TukSecretRewardType3rd" )}, // ハーベスト|フランクリンの隠し食材報酬抽選結果(3回目)
{0x51C, new EventFlagPlayer(0 , 1 , 1308, "PckTalkBeforeFlag" )}, // カーニバル/べルリーナ|面識ある?
{0x51D, new EventFlagPlayer(0 , 1 , 1309, "SendNNPCConversationPlayReport" )}, // 会話のフリのプレイレポートがその日送信されたか
{0x51F, new EventFlagPlayer(0 , 8 , 1311, "ChristmasPrevPresentItemType" )}, // クリスマス直前にNPCにもらったアイテムの種類
{0x520, new EventFlagPlayer(0 , 1 , 1312, "ValentineLetterFlag" )}, // バレンタイン|手紙送った?
{0x522, new EventFlagPlayer(0 , 1 , 1314, "AnnounceChristmasEve" )}, // クリスマス|当日に島内放送で告知した?
{0x526, new EventFlagPlayer(0 , 511 , 1318, "GetCarnivalFurniture" )}, // カーニバル/ベルリーナ|どのカーニバル家具をもらったか?
{0x52C, new EventFlagPlayer(0 , 9999, 1324, "LastPlayValentineYear" )}, // バレンタイン|最後に遊んだバレンタインの年
{0x52D, new EventFlagPlayer(0 , 1 , 1325, "PckRecipeTalkFlag" )}, // カーニバル/べルリーナ|にじいろのはねのレシピもらう会話した?
{0x530, new EventFlagPlayer(0 , 1 , 1328, "BuyReactionBook17" )}, // カーニバル用リアクション本を購入した
{0x531, new EventFlagPlayer(0 , 511 , 1329, "GetCarnivalFurnitureRed" )}, // カーニバル/ベルリーナ|どの赤色カーニバル家具をもらったか?
{0x532, new EventFlagPlayer(0 , 511 , 1330, "GetCarnivalFurnitureBlue" )}, // カーニバル/ベルリーナ|どの青色カーニバル家具をもらったか?
{0x533, new EventFlagPlayer(0 , 511 , 1331, "GetCarnivalFurnitureGreen" )}, // カーニバル/ベルリーナ|どの緑色カーニバル家具をもらったか?
{0x534, new EventFlagPlayer(0 , 511 , 1332, "GetCarnivalFurniturePurple" )}, // カーニバル/ベルリーナ|どの紫色カーニバル家具をもらったか?
{0x535, new EventFlagPlayer(0 , 511 , 1333, "GetCarnivalFurnitureRainbow" )}, // カーニバル/ベルリーナ|どの虹色カーニバル家具をもらったか?
{0x536, new EventFlagPlayer(0 , 1 , 1334, "PckColorLotteryFlag" )}, // カーニバル/ベルリーナ|色ごとにカーニバル家具の抽選をするか?
{0x537, new EventFlagPlayer(0 , 1 , 1335, "RcmChkReactionBook" )}, // カーニバル用リアクション本をチェックした
{0x538, new EventFlagPlayer(0 , 1 , 1336, "RcmChkCarnivalFtr" )}, // まめきち|カーニバル家具チェックした?
{0x539, new EventFlagPlayer(0 , 1 , 1337, "AnnounceCarnival" )}, // カーニバル|当日に島内放送で告知した?
};
private const string Unknown = "???";

View File

@ -69,6 +69,11 @@ public EventFlagVillager(short v1, short v2, ushort index, string name)
{0x039, new EventFlagVillager(0 , 2 , 0057, "HarvestGiveHint2" )}, // ハーベスト2品目の隠し食材ヒント出したら1か2をセット
{0x03A, new EventFlagVillager(0 , 2 , 0058, "HarvestGiveHint3" )}, // ハーベスト3品目の隠し食材ヒント出したら1か2をセット
{0x03B, new EventFlagVillager(0 , 2 , 0059, "HarvestGiveHint4" )}, // ハーベスト4品目の隠し食材ヒント出したら1か2をセット
{0x03D, new EventFlagVillager(0 , 3 , 0061, "CarnivalFeatherColor" )}, // カーニバル|欲しがる羽の色
{0x03E, new EventFlagVillager(0 , 10 , 0062, "DisplayValentinePresent" )}, // バレンタインデー|飾られるブーケの種類
{0x040, new EventFlagVillager(0 , 1 , 0064, "HarvestDemoEndWait" )}, // ハーベスト|デモ終了待機中か?
{0x041, new EventFlagVillager(0 , 1 , 0065, "WoreNewYearHat" )}, // カウントダウン|ニューイヤーハットを被った
{0x042, new EventFlagVillager(0 , 1 , 0066, "HarvestDemoStateNow" )}, // ハーベスト|デモ参加状態か?
};
private const string Unknown = "???";

View File

@ -31,7 +31,7 @@ public EventFlagVillagerMemoryPlayer(byte init, byte max, ushort index, string n
{0x08, new EventFlagVillagerMemoryPlayer(0 , 7 , 008, "VisitCount" )}, // そのプレイヤーの家に行った回数
{0x09, new EventFlagVillagerMemoryPlayer(0 , 7 , 009, "VisitedCount" )}, // そのプレイヤーが家に来た回数
{0x0A, new EventFlagVillagerMemoryPlayer(25, 255, 010, "Friendship" )}, // 親密度
{0x0B, new EventFlagVillagerMemoryPlayer(0 , 7 , 011, "TalkCountToday" )}, // 今日の会話回数(通算)
{0x0B, new EventFlagVillagerMemoryPlayer(0 , 9 , 011, "TalkCountToday" )}, // 今日の会話回数(通算)
{0x0C, new EventFlagVillagerMemoryPlayer(0 , 7 , 012, "TalkCountInNpcHouseToday" )}, // 今日NPCの家での会話回数
{0x0D, new EventFlagVillagerMemoryPlayer(0 , 1 , 013, "HasAcquaintanceship" )}, // 面識ありか
{0x0E, new EventFlagVillagerMemoryPlayer(0 , 1 , 014, "SitBenchFlag" )}, // NPCをベンチに座らせる
@ -151,7 +151,6 @@ public EventFlagVillagerMemoryPlayer(byte init, byte max, ushort index, string n
{0x83, new EventFlagVillagerMemoryPlayer(0 , 1 , 131, "FireworksGetItemFlag" )}, // 花火大会|このNPCからリアクション会話で花火を受け取った
{0x84, new EventFlagVillagerMemoryPlayer(0 , 1 , 132, "HaloweenTalkThisSceneFalg" )}, // ハロウィン|このシーンで会話した?
{0x85, new EventFlagVillagerMemoryPlayer(0 , 1 , 133, "HaloweenGetCandyThisSceneFalg" )}, // ハロウィン|このシーンでアメもらった?
{0x86, new EventFlagVillagerMemoryPlayer(0 , 1 , 134, "FollowQuestAfter" )}, // 追従|追従クエスト後か?
{0x88, new EventFlagVillagerMemoryPlayer(0 , 1 , 136, "HalloweenLastNotGetFlag" )}, // ハロウィン|最後の会話で報酬アイテムもらえなかった?
{0x89, new EventFlagVillagerMemoryPlayer(0 , 16 , 137, "HalloweenLastNotGetItem" )}, // ハロウィン|最後の会話でもらえなかった報酬アイテム
{0x8A, new EventFlagVillagerMemoryPlayer(0 , 1 , 138, "HarvestItemExchangeToday" )}, // ハーベスト|物々交換を1度でも行ったか?
@ -167,6 +166,11 @@ public EventFlagVillagerMemoryPlayer(byte init, byte max, ushort index, string n
{0x94, new EventFlagVillagerMemoryPlayer(0 , 8 , 148, "ChristmasSantaPresentItemType" )}, // クリスマス|サンタミッションであげたプレゼントの種類
{0x95, new EventFlagVillagerMemoryPlayer(0 , 8 , 149, "ChristmasExchangeRemakeId" )}, // クリスマスプレゼント交換であげたプレゼントのリメイクID
{0x96, new EventFlagVillagerMemoryPlayer(0 , 8 , 150, "ChristmasSantaPresentRemakeId" )}, // クリスマスサンタミッションであげたプレゼントのリメイクID
{0x97, new EventFlagVillagerMemoryPlayer(0 , 1 , 151, "CarnvalTalkWithoutFeatherFlag" )}, // 一般NPC/カーニバル|はねを持たずに会話した?
{0x98, new EventFlagVillagerMemoryPlayer(0 , 1 , 152, "CarnvalExchangeFeatherFlag" )}, // 一般NPC/カーニバル|このNPCとはね交換した
{0x99, new EventFlagVillagerMemoryPlayer(0 , 1 , 153, "CarnvalTalkOutdoorFlag" )}, // 一般NPC/カーニバル|今日屋外で会話した?
{0x9A, new EventFlagVillagerMemoryPlayer(0 , 1 , 154, "CarnvalExchangeFeatherTalkFlag" )}, // 一般NPC/カーニバル|このNPCとはね交換の会話をした
{0x9B, new EventFlagVillagerMemoryPlayer(0 , 1 , 155, "ValentinePresentFlag" )}, // バレンタイン|バレンタインのプレゼント渡した?
};
private const string Unknown = "???";

View File

@ -1,50 +0,0 @@
namespace NHSE.Core
{
/// <summary>
/// SEAD likely stands for Software Entertainment Analysis & Development
/// </summary>
internal sealed class SEADRandom
{
private readonly uint[] state = new uint[4];
public SEADRandom(uint seedOne, uint seedTwo, uint seedThree, uint seedFour)
{
state[0] = seedOne;
state[1] = seedTwo;
state[2] = seedThree;
state[3] = seedFour;
}
public SEADRandom(uint seed)
{
for (int i = 0; i < 4; i++)
{
state[i] = (uint)((0x6C078965 * (seed ^ (seed >> 30))) + i + 1);
seed = state[i];
}
}
public uint GetU32()
{
uint v1 = state[0] ^ (state[0] << 11);
state[0] = state[1];
state[1] = state[2];
state[2] = state[3];
return state[3] = v1 ^ (v1 >> 8) ^ state[3] ^ (state[3] >> 19);
}
public ulong GetU64()
{
uint v1 = state[0] ^ (state[0] << 11);
uint v2 = state[1];
uint v3 = v1 ^ (v1 >> 8) ^ state[3];
state[0] = state[2];
state[1] = state[3];
state[2] = v3 ^ (state[3] >> 19);
state[3] = v2 ^ (v2 << 11) ^ ((v2 ^ (v2 << 11)) >> 8) ^ state[2] ^ (v3 >> 19);
return ((ulong)state[2] << 32) | state[3];
}
}
}

View File

@ -0,0 +1,38 @@
namespace NHSE.Core
{
/// <summary>
/// Xorshift128 RNG Implementation (xor128)
/// <see href="https://en.wikipedia.org/wiki/Xorshift#Example_implementation"/>
/// </summary>
internal ref struct XorShift128
{
private uint a, b, c, d;
private const int Mersenne = 0x6C078965;
/// <summary>
/// Initialize the generator from a seed.
/// </summary>
/// <param name="seed">Ticks, usually.</param>
public XorShift128(uint seed)
{
// Unrolled Mersenne Twister initialization loop
a = (Mersenne * (seed ^ (seed >> 30))) + 1;
b = (Mersenne * ( a ^ ( a >> 30))) + 2;
c = (Mersenne * ( b ^ ( b >> 30))) + 3;
d = (Mersenne * ( c ^ ( c >> 30))) + 4;
}
public uint GetU32()
{
uint t = a;
a = b;
b = c;
c = d;
t ^= t << 11;
t ^= t >> 8;
return d = t ^ d ^ (d >> 19);
}
public ulong GetU64() => ((ulong)GetU32() << 32) | GetU32();
}
}

View File

@ -0,0 +1,36 @@
#if !NET5
#pragma warning disable
// ReSharper disable once UnusedType.Global
namespace System.Runtime.CompilerServices
{
using Diagnostics;
using Diagnostics.CodeAnalysis;
/// <summary>
/// Reserved to be used by the compiler for tracking metadata.
/// This class should not be used by developers in source code.
/// </summary>
[ExcludeFromCodeCoverage, DebuggerNonUserCode]
internal static class IsExternalInit
{
}
}
namespace System.Diagnostics.CodeAnalysis
{
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
internal sealed class NotNullWhenAttribute : Attribute
{
/// <summary>Initializes the attribute with the specified return value condition.</summary>
/// <param name="returnValue">
/// The return value condition. If the method returns this value, the associated parameter will not be null.
/// </param>
public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue;
/// <summary>Gets the return value condition.</summary>
public bool ReturnValue { get; }
}
}
#pragma warning restore
#endif

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
@ -193,12 +194,14 @@ private static (string Label, string Text) GetCleanLabelText(MSBTLabel lbl, ILis
var label = lbl.Name;
var index = (int)lbl.Index;
var text = txt[index].ToString(Encoding.Unicode);
if (text.StartsWith("\u000e")) // string formatting present; discard formatting!
var bytes = txt[index];
var text = bytes.ToString(Encoding.Unicode);
var raw = text.ToCharArray();
int format = Array.FindIndex(raw, z => z == '\u000e');
if (format == 0) // string formatting present; discard formatting!
text = text.Substring(6);
const char germanJunk = '\u000e';
int junk = text.IndexOf(germanJunk);
int junk = Array.FindIndex(text.ToCharArray(), z => z == '\u000e');
if (junk != -1) // string formatting present; discard formatting! (german)
text = text.Substring(0, junk);

View File

@ -12,7 +12,7 @@ public static class GameMSBTDumperNHSE
/// <summary>
/// NHSE language code -> Game Language identifier
/// </summary>
private static readonly IReadOnlyDictionary<string, string> Languages = new Dictionary<string, string>
public static readonly IReadOnlyDictionary<string, string> Languages = new Dictionary<string, string>
{
{"en", "USen"},
{"jp", "JPja"},
@ -25,11 +25,7 @@ public static class GameMSBTDumperNHSE
{"ko", "KRko"},
};
public static void Dump(
string repoPath = @"C:\Users\Kurt\Documents\GitHub",
string messageStringPath = @"D:\Kurt\Desktop\v16\",
string unpackedMessageFormat = @"Message\String_{0}.sarc"
)
public static void Dump(string repoPath, string messageStringPath, string unpackedMessageFormat)
{
string corePath = Path.Combine(repoPath, @"NHSE\NHSE.Core\Resources\text\");
string folder = Path.Combine(messageStringPath, unpackedMessageFormat);

View File

@ -1,38 +1,30 @@
using System.Collections.Generic;
using System.IO;
using System.IO;
using NHSE.Parsing;
using Xunit;
using static NHSE.Parsing.GameMSBTDumperNHSE;
namespace NHSE.Tests
{
public static class DumpTests
{
private const string ver = "v16";
private const string RepoPath = @"C:\Users\Kurt\Documents\GitHub";
private const string PatchDumpPath = @"D:\Kurt\Desktop\" + PatchFolderName;
private const string PatchFolderName = "v17";
private const string MessageDumpFormat = @"\Message\String_{0}";
[Fact]
public static void DumpBCSV()
{
var folder = $@"D:\Kurt\Desktop\{ver}\bcsv";
const string folder = PatchDumpPath + @"\bcsv";
GameBCSVDumper.UpdateDumps(folder, folder, true);
}
[Fact]
public static void DumpMSBT()
{
const string cs = @"C:\Users\Kurt\Documents\GitHub\NHSE\NHSE.Core\Resources\text\";
string folder = $@"D:\Kurt\Desktop\{ver}\Message\String_{{0}}.sarc";
var langs = new Dictionary<string, string>
{
{"en", "USen"},
{"jp", "JPja"},
{"zhs", "CNzh"},
{"zht", "TWzh"},
{"de", "EUde"},
{"fr", "EUfr"},
{"it", "EUit"},
{"es", "EUes"},
{"ko", "KRko"},
};
const string cs = RepoPath + @"\NHSE\NHSE.Core\Resources\text\";
const string folder = PatchDumpPath + MessageDumpFormat;
var langs = Languages;
foreach (var (code, langName) in langs)
{