public void InitializeAppData(AmiiboTag tag) { this.ThrowOnInvalidAppId(tag); var game = new MonsterHunterStories(tag.AppData); game.PublisherTag.CopyFrom(Encoding.ASCII.GetBytes("155260401735857398289")); }
internal static void ThrowOnInvalidAppId(this IAppDataInitializer game, AmiiboTag tag) { if (tag == null || !tag.HasAppData || tag.AmiiboSettings.AmiiboAppData.AppID != game.GetAppID()) { throw new InvalidOperationException("The provided tag has not the correct app data. Maybe initialize it to this game before."); } }
public void InitializeAppData(AmiiboTag tag) { this.ThrowOnInvalidAppId(tag); var game = new MarioTennis(tag.AppData); game.AppData.CopyFrom(new byte[0x0B]); // TODO: Use for-loop and create extension method }
public static void EncryptNtag(string savePath, AmiiboTag amiibo) { const string missingSavePath = "Missing save path"; const string missingAmibo = "Can't encrypt amiibo if no amiibo was given, DUH!"; if (string.IsNullOrEmpty(savePath)) { Console.WriteLine(missingSavePath); ActionOutput?.Invoke(null, new ActionOutputEventArgs(false, missingSavePath)); return; } if (amiibo == null) { Console.WriteLine(missingAmibo); ActionOutput?.Invoke(null, new ActionOutputEventArgs(false, missingAmibo)); return; } try { byte[] encryptedNtagData = amiibo.EncryptWithKeys(); File.WriteAllBytes(savePath, encryptedNtagData); } catch (Exception ex) { string errorEncrypting = $"Error while encrypting {amiibo.Amiibo?.AmiiboSetName}"; ActionOutput?.Invoke(null, new ActionOutputEventArgs(false, errorEncrypting + Environment.NewLine + Environment.NewLine + ex.Message)); Console.WriteLine(errorEncrypting); Console.WriteLine(ex.Message); } }
public static AmiiboTag LoadAndDecryptNtag(string amiiboPath) { var amiiboFileNotFound = $"{amiiboPath} not found!"; if (!File.Exists(amiiboPath)) { Console.WriteLine(amiiboFileNotFound); ActionOutput?.Invoke(null, new ActionOutputEventArgs(false, amiiboFileNotFound)); return(null); } byte[] encryptedNtagData = File.ReadAllBytes(amiiboPath); try { return(AmiiboTag.DecryptWithKeys(encryptedNtagData)); } catch (Exception ex) { string errorDecrypting = $"Error while decrypting {amiiboPath}"; ActionOutput?.Invoke(null, new ActionOutputEventArgs(false, errorDecrypting + Environment.NewLine + Environment.NewLine + ex.Message)); Console.WriteLine(errorDecrypting); Console.WriteLine(ex.Message); } return(null); }
public void InitializeAppData(AmiiboTag tag) { this.ThrowOnInvalidAppId(tag); var game = new Pikmin(tag.AppData); game.AppData.CopyFrom(new byte[0x0C]); // TODO: Use for-loop and create extension method game.Constant = 1; }
public void InitializeAppData(AmiiboTag tag) { this.ThrowOnInvalidAppId(tag); var game = new MarioSportsSuperstar(tag.AppData); game.AppData.CopyFrom(new byte[0xD8]); // TODO: Use for-loop and create extension method game.IsSuperstar = true; }
public void InitializeAppData(AmiiboTag tag) { this.ThrowOnInvalidAppId(tag); var game = new ZeldaTwilightPrincess(tag.AppData); game.AppData.CopyFrom(new byte[0x34]); // TODO: Use for-loop and create extension method // TODO: how is OwnerTag calculated? Based on settings-CRC32? // TODO: how is ConsoleTag calculated? Based on settings-CRC32? game.QuickStartSlotNr = 0xFF; }
public void InitializeAppData(AmiiboTag tag) { this.ThrowOnInvalidAppId(tag); var game = new ChibiRoboZipLash(tag.AppData); game.AppData.CopyFrom(new byte[0x0C]); // TODO: Use for-loop and create extension method game.Constant = 3; // TODO: how is OwnerTag calculated? Based on settings-CRC32? game.OwnerTag.CopyFrom(new byte[] { 0x9e, 0x3b, 0x9d, 0xbf }); }
public void InitializeAppData(AmiiboTag tag) { this.ThrowOnInvalidAppId(tag); var game = new MarioLuigiSuperstarSaga(tag.AppData); game.AppData.CopyFrom(new byte[0x20]); // TODO: Use for-loop and create extension method game.PublisherTag.CopyFrom(Encoding.ASCII.GetBytes("REMILLI")); // TODO: how is OwnerTag calculated? Based on settings-CRC32? game.SaveTag.CopyFrom(new byte[] { 0x3d, 0x0d, 0x2f, 0xc9 }); if (CHARACTER_CHECK_MAP.TryGetValue(tag.Amiibo.CharacterId, out CharacterCheckValue tmpCharCheck)) { game.CharacterCheck = tmpCharCheck; } }
static byte[] GenerateBin(params byte[] identificationBlock) { if (identificationBlock.Length != 8) { throw new ArgumentException("Invalid identification block length"); } var decrypted = new byte[540]; tagHeader.CopyTo(decrypted, 0); identificationBlock.CopyTo(decrypted, 84); GetRandomBytes(32).CopyTo(decrypted, 96); tagFooter.CopyTo(decrypted, 520); var tag = AmiiboTag.FromNtagData(decrypted); return(tag.EncryptWithKeys().Take(540).ToArray()); }
private static void GenerateNewAmiiboFiles(AmiiboTag amiibo, uint amount, string amiiboPath, string output) { Console.WriteLine("Generating and saving modified Amiibos"); for (int i = 0; i < amount; i++) { var fileName = Path.GetFileNameWithoutExtension(amiiboPath) + AmiiboSNHelper.FileNameExtension + i + AmiiboSNHelper.FileType; var savePath = Path.Combine(output, fileName); Console.WriteLine($">> Creating Amiibo {savePath}"); amiibo.UID = AmiiboSNHelper.CustomRandomizeSerial(); if (!amiibo.IsUidValid()) { Console.WriteLine($">> Invalid UID for Amiibo Nr {i}"); } else { AmiiboSNHelper.EncryptNtag(savePath, amiibo); } } }
static int Main(string[] args) { try { p.Parse(args); } catch (OptionException e) { Console.Write("amiitool: "); Console.WriteLine(e.Message); Console.WriteLine("Try `amiitool --help' for more information."); return(1); } if (showHelp || !(doEncrypt ^ doDecrypt) || keyFile == null) { ShowHelp(); return(1); } AmiiboKeys amiiboKeys = AmiiboKeys.LoadKeys(keyFile); if (amiiboKeys == null) { Console.Error.WriteLine("Could not load keys from \"{0}\"", keyFile); return(5); } byte[] original = new byte[NTAG215_SIZE]; byte[] modified = new byte[NtagHelpers.NFC3D_AMIIBO_SIZE]; Stream file; try { file = File.OpenRead(inputFile); } catch (Exception ex) { Console.Error.WriteLine("Could not open input file: {0}", ex.Message); return(3); } int readBytes = 0; try { using (var reader = new BinaryReader(file)) { readBytes = reader.Read(original, 0, original.Length); if (readBytes < NtagHelpers.NFC3D_AMIIBO_SIZE) { throw new Exception("Wrong length"); } } } catch (Exception ex) { Console.Error.WriteLine("Could not read from input: {0}", ex.Message); return(3); } if (doEncrypt) { amiiboKeys.Pack(original, modified); } else { if (!amiiboKeys.Unpack(original, modified)) { Console.Error.WriteLine("!!! WARNING !!!: Tag signature was NOT valid"); if (!deactivateSignatureCheck) { return(6); } } var amiiboTag1 = AmiiboTag.FromInternalTag(modified); var amiiboTag2 = AmiiboTag.FromInternalTag(NtagHelpers.GetInternalTag(original)); } file = Console.OpenStandardOutput(); if (outputFile != null) { try { file = File.OpenWrite(outputFile); } catch (Exception ex) { Console.Error.WriteLine("Could not open output file: {0}", ex.Message); return(4); } } try { using (var writer = new BinaryWriter(file)) { writer.Write(modified, 0, modified.Length); if (readBytes > modified.Length) { writer.Write(original, modified.Length, readBytes - modified.Length); } } } catch (Exception ex) { Console.Error.WriteLine("CouldCould not write to output: {0}", ex.Message); return(3); } return(0); }
public static bool EqualAmiiboTag(AmiiboTag at1, AmiiboTag at2) => StructuralComparisons.StructuralEqualityComparer.Equals(at1.UID, at2.UID) && at1.HasAppData == at2.HasAppData && at1.HasUserData == at2.HasUserData && at1.WriteCounter == at2.WriteCounter;
// Since the Amiibo was already loaded once, we can reload it instantly. If it fails. the user f****d someting up ¯\_(ツ)_/¯ public void ReloadAmiibo() => this.AmiiboTag = AmiiboTag.DecryptWithKeys(File.ReadAllBytes(this.FilePath));
public AmiiboTagWrapper(string filePath, AmiiboTag amiibo) { this.FilePath = filePath; this.AmiiboTag = amiibo; }