/// <summary> /// Loads a game info from the stream at the specified offset /// </summary> /// <param name="stream">Stream.</param> /// <param name="offset">Offset.</param> /// <returns>The game information at the specified offset</returns> /// <remarks>This method has only been tested with the US version of the games</remarks> public static GameInfo Load(Stream stream, int offset) { GameInfo info = new GameInfo(); byte[] versionBytes = new byte[1]; byte[] gameIdBytes = new byte[2]; byte[] heroBytes = new byte[5]; byte[] kidBytes = new byte[5]; byte[] behaviorBytes = new byte[1]; byte[] animalBytes = new byte[1]; byte[] linkedBytes = new byte[1]; byte[] heroQuestBytes = new byte[1]; byte[] beatenBytes = new byte[1]; byte[] ringBytes = new byte[8]; stream.Seek(offset, SeekOrigin.Begin); stream.Read(versionBytes, 0, 1); // The version is represented by the char values '1' or '2' if (versionBytes[0] != 49 && versionBytes[0] != 50) return null; stream.Seek(96, SeekOrigin.Begin); stream.Read(gameIdBytes, 0, 2); stream.Read(heroBytes, 0, 5); stream.Seek(2, SeekOrigin.Current); stream.Read(kidBytes, 0, 5); stream.Seek(1, SeekOrigin.Current); stream.Read(behaviorBytes, 0, 1); stream.Seek(2, SeekOrigin.Current); stream.Read(animalBytes, 0, 1); // These are mostly just a guess stream.Read(linkedBytes, 0, 1); stream.Read(heroQuestBytes, 0, 1); stream.Read(beatenBytes, 0, 1); stream.Seek(5, SeekOrigin.Current); stream.Read(ringBytes, 0, 8); // The save files use the values 11, 12, and 13 for the animal friends. Interestingly, // the bit value before the animal in the secrets is always set to 1. Perhaps these // are the actual values. info.Game = versionBytes[0] == 49 ? Game.Seasons : Game.Ages; info.GameID = BitConverter.ToInt16(gameIdBytes, 0); info.Hero = System.Text.Encoding.ASCII.GetString(heroBytes); info.Child = System.Text.Encoding.ASCII.GetString(kidBytes); info.Animal = (Animal)(animalBytes[0] & 7); info.IsLinkedGame = linkedBytes[0] == 0; info.IsHeroQuest = heroQuestBytes[0] == 0; info.Rings = (Rings)BitConverter.ToUInt64(ringBytes, 0); return info; }
/// <summary> /// Converts the provided dictionary into an object of the specified type. /// </summary> /// <param name="dictionary">An <see cref="T:System.Collections.Generic.IDictionary`2" /> instance of property data stored as name/value pairs.</param> /// <param name="type">The type of the resulting object.</param> /// <param name="serializer">The <see cref="T:System.Web.Script.Serialization.JavaScriptSerializer" /> instance.</param> /// <returns> /// The deserialized object. /// </returns> /// <exception cref="ArgumentNullException">dictionary</exception> public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) { if (dictionary == null) throw new ArgumentNullException("dictionary"); if (type != typeof(GameInfo)) return null; GameInfo info = new GameInfo(); info.Hero = dictionary.ReadValue<string>("Hero"); info.Child = dictionary.ReadValue<string>("Child"); info.IsHeroQuest = dictionary.ReadValue<bool>("IsHeroQuest"); info.IsLinkedGame = dictionary.ReadValue<bool>("IsLinkedGame"); info.GameID = dictionary.ReadValue<short>("GameID"); info.Rings = (Rings)dictionary.ReadValue<long>("Rings"); info.Game = dictionary.ReadValue<Game>("Game"); info.Animal = dictionary.ReadValue<Animal>("Animal"); info.Behavior = dictionary.ReadValue<ChildBehavior>("Behavior"); return info; }
/// <summary> /// Initializes a new instance of the <see cref="GameSecret"/> class from the /// specified game <paramref name="info"/>. /// </summary> /// <param name="info">The game information.</param> public GameSecret(GameInfo info) : base() { Load(info); }
/// <summary> /// Updates the game information. /// </summary> /// <param name="info">The information.</param> /// <example> /// <code language="C#"> /// GameSecret secret = new GameSecret() /// { /// TargetGame = Game.Ages, /// GameID = 14129, /// Hero = "Link", /// Child = "Pip", /// Animal = Animal.Dimitri, /// Behavior = ChildBehavior.BouncyD, /// IsLinkedGame = true, /// IsHeroQuest = false /// }; /// GameInfo info = new GameInfo(); /// secret.UpdateGameInfo(info); /// </code> /// </example> public void UpdateGameInfo(GameInfo info) { info.GameID = GameID; info.Game = TargetGame; info.Hero = Hero; info.Child = Child; info.Animal = Animal; info.Behavior = Behavior; info.IsLinkedGame = IsLinkedGame; info.IsHeroQuest = IsHeroQuest; }
/// <summary> /// Loads in data from the specified game info /// </summary> /// <param name="info">The game info</param> /// <example> /// <code language="C#"> /// GameInfo info = new GameInfo() /// { /// Game = Game.Ages, /// GameID = 14129, /// Hero = "Link", /// Child = "Pip", /// Animal = Animal.Dimitri, /// Behavior = ChildBehavior.BouncyD, /// IsLinkedGame = true, /// IsHeroQuest = false /// }; /// GameSecret secret = new GameSecret(); /// secret.Load(info); /// </code> /// </example> public override void Load(GameInfo info) { GameID = info.GameID; TargetGame = info.Game; Hero = info.Hero; Child = info.Child; Animal = info.Animal; Behavior = info.Behavior; IsLinkedGame = info.IsLinkedGame; IsHeroQuest = info.IsHeroQuest; }
/// <summary> /// Initializes a new instance of the <see cref="MemorySecret"/> class. /// </summary> /// <param name="info">The game information.</param> /// <param name="memory">The memory.</param> /// <param name="isReturnSecret">if set to <c>true</c> [is return secret].</param> public MemorySecret(GameInfo info, Memory memory, bool isReturnSecret) : this(info.Game, info.GameID, memory, isReturnSecret) { }
/// <summary> /// Initializes a new instance of the <see cref="RingSecret"/> class from the /// specified game <paramref name="info"/>. /// </summary> /// <param name="info">The game information.</param> public RingSecret(GameInfo info) { Load(info); }
/// <summary> /// Loads in data from the specified game info /// </summary> /// <param name="info">The game info</param> /// <remarks> /// Because <see cref="GameInfo"/> does not contain information about /// memories, only the properties <see cref="TargetGame"/> and /// <see cref="Secret.GameID"/> will be populated by this method. /// </remarks> /// <example> /// <code language="C#"> /// GameInfo info = new GameInfo() /// { /// Game = Game.Ages, /// GameID = 14129 /// }; /// MemorySecret secret = new MemorySecret(); /// secret.Load(info); /// </code> /// </example> public override void Load(GameInfo info) { TargetGame = info.Game; GameID = info.GameID; }
/// <summary> /// Updates the <see cref="GameInfo.Rings"/> property with the rings in this secret /// </summary> /// <param name="info">The information.</param> /// <param name="appendRings"> /// If true, this will add the rings contained in the secret to the /// existings Rings. If false, it will overwrite them. /// </param> /// <exception cref="InvalidSecretException"> /// The Game IDs of the secret and game info do not match. /// </exception> /// <example> /// <code language="C#"> /// RingSecret secret = new RingSecret() /// { /// GameID = 14129, /// Rings = -9222246136947933182 /// }; /// GameInfo info = new GameInfo() { GameID = 14129 }; /// bool appendRings = true; /// secret.UpdateGameInfo(info, appendRings); /// </code> /// </example> public void UpdateGameInfo(GameInfo info, bool appendRings) { if(info.GameID != GameID) throw new InvalidSecretException("The Game IDs of the secret and game info do not match."); info.Rings = Rings | (appendRings ? info.Rings : Rings.None); }
/// <summary> /// Loads in data from the specified game info /// </summary> /// <param name="info">The game info</param> /// <example> /// <code language="C#"> /// GameInfo info = new GameInfo() /// { /// GameID = 14129, /// Rings = Rings.PowerRingL1 | Rings.DoubleEdgeRing | Rings.ProtectionRing /// }; /// RingSecret secret = new RingSecret(); /// secret.Load(info); /// </code> /// </example> public override void Load(GameInfo info) { GameID = info.GameID; Rings = info.Rings; }
/// <summary> /// Loads in data from the specified game info /// </summary> /// <param name="info">The game info</param> public abstract void Load(GameInfo info);