/// <summary> /// Constructs a list of mini-animations from a file stream, starting with the beginning pointer table. /// </summary> /// <param name="stream">Stream to read from, starting with a pointer table to sub-mini anims.</param> public MiniAnimGroup(Stream stream) { Pointer = stream.Position; int firstAnimPointer = int.MaxValue; while (stream.Position < firstAnimPointer + Pointer) { int animationPointer = BNSAFile.ReadIntegerFromStream(stream); firstAnimPointer = Math.Min(firstAnimPointer, animationPointer); //should only be triggered by the first pointer as it goes ascending. long nextPosition = stream.Position; stream.Seek(Pointer + animationPointer, SeekOrigin.Begin); //Move cursor to start of minianim MiniAnim animation = new MiniAnim(stream, Pointer); IsValid &= animation.IsValid; if (!IsValid) { break; //Invalid data, stop caring and exit. } MiniAnimations.Add(animation); if (nextPosition < firstAnimPointer + Pointer) { //Read the next 4 bytes in the pointer table as its a new pointer stream.Seek(nextPosition, SeekOrigin.Begin); } } }
/// <summary> /// Changes binary file pointers and indexes to object references from the parsed BNSA file. /// This calls ResolveReferences() on each frame in the animation /// </summary> internal void ResolveReferences(BNSAFile parsedBNSA) { int i = 0; foreach (Frame frame in Frames) { Console.WriteLine("--Resolving Frame " + i + " references"); frame.ResolveReferences(parsedBNSA); i++; } }
internal void ResolveReferences(BNSAFile parsedBNSA, Frame owningFrame) { int i = 0; foreach (MiniFrame miniFrame in MiniFrames) { //Console.WriteLine("--Resolving Frame " + i + " references"); miniFrame.ResolveReferences(parsedBNSA, owningFrame); i++; } }
/// <summary> /// Maps the OAM Data List Index to the proper data list object /// </summary> /// <param name="parsedBNSA">Parsed BNSA File to link against</param> internal void ResolveReferences(BNSAFile parsedBNSA, Frame frame) { Console.Write("Resolving OAMIndex " + OAMDataListIndex); ResolvedOAMDataList = frame.ResolvedOAMDataListGroup.OAMDataLists[OAMDataListIndex]; if (ResolvedOAMDataList == null) { Console.WriteLine("... Failed to resolve: " + OAMDataListIndex); } else { Console.WriteLine("... OK"); } }
public Tileset(Stream stream, int index) { Pointer = stream.Position; Index = index; Console.WriteLine("Reading Tileset at 0x" + Pointer.ToString("X2")); BitmapSize = BNSAFile.ReadIntegerFromStream(stream); BitmapData = new byte[BitmapSize]; stream.Read(BitmapData, 0, BitmapSize); //Copy Export Memory stream.Seek(Pointer, SeekOrigin.Begin); Memory = new byte[BitmapSize + 4]; stream.Read(Memory, 0, BitmapSize + 4); }
/// <summary> /// Creates a new frame from the next 0x20 bytes of the given stream. /// </summary> /// <param name="stream">Stream to read a frame from</param> public Frame(Stream stream) { Pointer = stream.Position; TilesetPointer = BNSAFile.ReadIntegerFromStream(stream) + 0x4; PalettePointer = BNSAFile.ReadIntegerFromStream(stream) + 0x4; MiniAnimationPointer = BNSAFile.ReadIntegerFromStream(stream) + 0x4; OAMDataListPointer = BNSAFile.ReadIntegerFromStream(stream) + 0x4; FrameDelay = (byte)stream.ReadByte(); stream.ReadByte(); //constant 00? Flags = (byte)stream.ReadByte(); stream.ReadByte(); //constant 00 ? //Convenience Booleans EndFrame = (Flags & 0x80) != 0; Loops = (Flags & 0x40) != 0; //Copy Memory for Export stream.Seek(Pointer, SeekOrigin.Begin); Memory = new byte[20]; stream.Read(Memory, 0, 20); }
/// <summary> /// Animation Object, created from a pointer in the BNSA archive. The passed in stream will be used to load data. The stream position will be modified, so save it before you call this. /// </summary> /// <param name="bnsa">BNSA Object. Will be used so the probably palette pointer can be updated.</param> /// <param name="ptr">Pointer (from start of file) to the animation data.</param> /// <param name="stream">Stream to read read from</param> public Animation(BNSAFile bnsa, int ptr, Stream stream) { Pointer = ptr; Pointer += 4; //Skip Header Console.WriteLine("Animation Pointer 0x" + Pointer.ToString("X8")); //"X8" = 8 byte hex output stream.Seek(Pointer, SeekOrigin.Begin); Frames = new List <Frame>(); int frameindex = 0; while (true) { //Read Frame Until Stop or Loop at Pos + 0x12 Console.WriteLine("--Reading Frame " + frameindex + " at 0x" + stream.Position.ToString("X2")); Frame frame = new Frame(stream); bnsa.ProbablyPaletteStartPointer = Math.Min(bnsa.ProbablyPaletteStartPointer, frame.PalettePointer); //Find first Palette Pointer Frames.Add(frame); if (frame.EndFrame) //End of animation indicator { break; } frameindex++; } }
public OAMDataListGroup(Stream stream, int index) { Index = index; Pointer = stream.Position; Console.WriteLine("--Reading OAM Data List Pointer Table (Group) at 0x" + stream.Position.ToString("X2")); int firstOAMEntryPointer = int.MaxValue; while (stream.Position < firstOAMEntryPointer + Pointer) { int oamDataEntryPointer = BNSAFile.ReadIntegerFromStream(stream); firstOAMEntryPointer = Math.Min(firstOAMEntryPointer, oamDataEntryPointer); //should only be triggered by the first pointer as it goes ascending. long nextPosition = stream.Position; //Address of next pointer in the list stream.Seek(oamDataEntryPointer + Pointer, SeekOrigin.Begin); OAMDataList oamDataList = new OAMDataList(stream); OAMDataLists.Add(oamDataList); if (nextPosition < firstOAMEntryPointer + Pointer) { //Read the next 4 bytes in the pointer table as its a new pointer stream.Seek(nextPosition, SeekOrigin.Begin); } } }
/// <summary> /// Converts pointers to references to other parsed BNSA objects. This allows us to export references rather than hard coded values for easy recompilation and editing of the outputted XML. /// </summary> /// <param name="parsedBNSA">BNSA File that has been parsed</param> public void ResolveReferences(BNSAFile parsedBNSA) { //foreach (Palette palette in parsedBNSA.Palettes) //{ // if (palette.Pointer == PalettePointer) // { // ResolvedPalette = palette; // break; // } //} foreach (Tileset tileset in parsedBNSA.Tilesets) { if (tileset.Pointer == TilesetPointer) { ResolvedTileset = tileset; break; } } foreach (OAMDataListGroup oamDataList in parsedBNSA.OAMDataListGroups) { if (oamDataList.Pointer == OAMDataListPointer) { ResolvedOAMDataListGroup = oamDataList; break; } } foreach (MiniAnimGroup minianimgroup in parsedBNSA.MiniAnimGroups) { if (minianimgroup.Pointer == MiniAnimationPointer) { ResolvedMiniAnimGroup = minianimgroup; ResolvedMiniAnimGroup.ResolveReferences(parsedBNSA, this); break; } } //if (ResolvedPalette != null) //{ // Console.WriteLine("----Resolved Palette Reference"); //} //else //{ // Console.WriteLine("----/!\\ Failed to Resolve Palette: 0x"+PalettePointer.ToString("X2")); //} if (ResolvedTileset != null) { Console.WriteLine("----Resolved Tileset Reference"); } else { Console.WriteLine("----/!\\ Failed to Resolve Tileset Pointer 0x" + TilesetPointer.ToString("X2")); throw new Exception("Failed to resolve mini-animation object."); } if (ResolvedMiniAnimGroup != null) { Console.WriteLine("----Resolved MiniAnim Reference"); } else { Console.WriteLine("----/!\\ Failed to Resolve MiniAnim 0x" + MiniAnimationPointer.ToString("X2")); throw new Exception("Failed to resolve mini-animation object."); } if (ResolvedOAMDataListGroup != null) { Console.WriteLine("----Resolved OAM Data List Reference"); } else { Console.WriteLine("----/!\\ Failed to Resolve OAM Data List 0x" + OAMDataListPointer.ToString("X2")); throw new Exception("Failed to resolve mini-animation object."); } //foreach (MiniAnim tileset in parsedBNSA.MiniAnimGroups) //{ // if (minianim.Pointer == TilesetPointer) // { // ResolvedMiniAnim = tileset; // break; // } //} }