private static ChrAnimationTable LoadOneAnimation(MetroidRom rom, LevelIndex level, ref int frameIndex) { ChrAnimationTable result = new ChrAnimationTable(); if (isTerminator(rom, frameIndex)) { return(null); } bool lastFrame = false; while (!lastFrame) { ChrAnimationFrame?loadedFrame = LoadOneFrame(rom, frameIndex, out lastFrame); // If we fail to load a frame, that means there is an erroneous condition and this animation is invalid. if (loadedFrame == null) { return(null); } result.Frames.Add(loadedFrame.Value); frameIndex++; } return(result); }
/// <summary> /// Loads animation data/frames for the specified level. /// </summary> /// <param name="level">The level to load data for</param> /// <param name="lastFrame">The index of the first frame after the current area's frame data, or FF to leave unspecified. If an FF terminator is encountered in frame data, parsing will stop sooner.</param> /// <returns></returns> private static ChrAnimationLevelData LoadAnimationsForLevel(MetroidRom rom, LevelIndex level, int lastFrame) { ChrAnimationLevelData data = new ChrAnimationLevelData(level); // CHR usage table has been repurposed in MMC3 ROMs (hence accessor names don't match usage) data.SprBank0 = rom.ChrUsage.GetSprPage(level); data.SprBank1 = rom.ChrUsage.GetBgLastPage(level); // First frame index int frameIndex = rom.ChrUsage.GetBgFirstPage(level); bool keepGoing = true; while (keepGoing && frameIndex < lastFrame && frameIndex < 0xFF) { ChrAnimationTable loadedAnimation = LoadOneAnimation(rom, level, ref frameIndex); if (loadedAnimation == null) { if (data.Animations.Count == 0) { loadedAnimation = new ChrAnimationTable(); ChrAnimationFrame frame = new ChrAnimationFrame(); frame.FrameTime = 1; loadedAnimation.Frames.Add(frame); } else { return(data); } } data.Animations.Add(loadedAnimation); } return(data); }