public void FillTextureBlock(Texture2D tex, int blockX, int blockY, int relX, int relY, byte[] imageBuffer, int imageBufferOffset, IList<ARGB1555Color> pal, int paletteInd, bool flipX, bool flipY)
        {
            var offset1 = imageBufferOffset;
            var offset2 = imageBufferOffset + 16;

            for (int y = 0; y < 8; y++)
            {
                for (int x = 0; x < 8; x++)
                {
                    int actualX = blockX + relX * 8 + (flipX ? (8 - x - 1) : x);
                    int actualY = blockY + relY * 8 + (flipY ? (8 - y - 1) : y);

                    int off = y * 8 + (8 - x - 1);

                    var bit0 = BitHelpers.ExtractBits(imageBuffer[offset1 + ((off / 8) * 2)], 1, off % 8);
                    var bit1 = BitHelpers.ExtractBits(imageBuffer[offset1 + ((off / 8) * 2 + 1)], 1, off % 8);
                    var bit2 = BitHelpers.ExtractBits(imageBuffer[offset2 + ((off / 8) * 2)], 1, off % 8);
                    var bit3 = BitHelpers.ExtractBits(imageBuffer[offset2 + ((off / 8) * 2 + 1)], 1, off % 8);

                    int b = 0;

                    b = BitHelpers.SetBits(b, bit0, 1, 0);
                    b = BitHelpers.SetBits(b, bit1, 1, 1);
                    b = BitHelpers.SetBits(b, bit2, 1, 2);
                    b = BitHelpers.SetBits(b, bit3, 1, 3);
                    
                    Color c = pal[paletteInd * 0x10 + b].GetColor();

                    if (b != 0)
                        c = new Color(c.r, c.g, c.b, 1f);

                    tex.SetPixel(actualX, actualY, c);
                }
            }
        }
Beispiel #2
0
            private void Insert(HuffmanCode <T> code)
            {
                Node currentNode = root;

                for (int bitIndex = code.Length - 1; bitIndex >= 0; bitIndex--)
                {
                    int bit = BitHelpers.ExtractBits(code.Code, 1, bitIndex);

                    if (bit == 1)
                    {
                        if (currentNode.Node1 == null)
                        {
                            currentNode.Node1 = new Node();
                        }
                        currentNode = currentNode.Node1;
                    }
                    else
                    {
                        if (currentNode.Node0 == null)
                        {
                            currentNode.Node0 = new Node();
                        }
                        currentNode = currentNode.Node0;
                    }
                }
                currentNode.Value = code.Value;
            }
Beispiel #3
0
 /// <summary>
 /// Handles the data serialization
 /// </summary>
 /// <param name="s">The serializer object</param>
 public override void SerializeImpl(SerializerObject s)
 {
     Flags = s.Serialize <byte>(Flags, name: nameof(Flags));
     if (BitHelpers.ExtractBits(Flags, 1, 7) == 1)
     {
         if (BitHelpers.ExtractBits(Flags, 1, 0) == 1)
         {
             Note = s.Serialize <byte>(Note, name: nameof(Note));
         }
         if (BitHelpers.ExtractBits(Flags, 1, 1) == 1)
         {
             Instrument = s.Serialize <byte>(Instrument, name: nameof(Instrument));
         }
         if (BitHelpers.ExtractBits(Flags, 1, 2) == 1)
         {
             VolumeColumnByte = s.Serialize <byte>(VolumeColumnByte, name: nameof(VolumeColumnByte));
         }
         if (BitHelpers.ExtractBits(Flags, 1, 3) == 1)
         {
             EffectType = s.Serialize <byte>(EffectType, name: nameof(EffectType));
         }
         if (BitHelpers.ExtractBits(Flags, 1, 4) == 1)
         {
             EffectParameter = s.Serialize <byte>(EffectParameter, name: nameof(EffectParameter));
         }
     }
     else
     {
         Note             = Flags;
         Instrument       = s.Serialize <byte>(Instrument, name: nameof(Instrument));
         VolumeColumnByte = s.Serialize <byte>(VolumeColumnByte, name: nameof(VolumeColumnByte));
         EffectType       = s.Serialize <byte>(EffectType, name: nameof(EffectType));
         EffectParameter  = s.Serialize <byte>(EffectParameter, name: nameof(EffectParameter));
     }
 }
Beispiel #4
0
        public override void SerializeBlock(SerializerObject s)
        {
            if (s.GameSettings.GBA_IsMilan && s.GameSettings.EngineVersion != EngineVersion.GBA_TomClancysRainbowSixRogueSpear)
            {
                // Copied from function at 0x080087e4 in The Mummy (US)

                // Serialize header
                s.DoAt(ShanghaiOffsetTable.GetPointer(0), () =>
                {
                    Milan_Ushort_00 = s.Serialize <ushort>(Milan_Ushort_00, name: nameof(Milan_Ushort_00));
                    Milan_Ushort_02 = s.Serialize <ushort>(Milan_Ushort_02, name: nameof(Milan_Ushort_02));
                });

                // Go to palette data
                s.Goto(ShanghaiOffsetTable.GetPointer(1));

                if (Milan_Palettes == null)
                {
                    Milan_Palettes = new Dictionary <int, RGBA5551Color[]>();

                    if (Milan_Ushort_00 == 0)
                    {
                        var palIndex = 0;

                        do
                        {
                            if (BitHelpers.ExtractBits(Milan_Ushort_02, 1, palIndex) == 1)
                            {
                                var pal = s.SerializeObjectArray <RGBA5551Color>(default, 0x10, name: $"Palette[{palIndex}]");
        public override void SerializeImpl(SerializerObject s)
        {
            Byte_00    = s.Serialize <byte>(Byte_00, name: nameof(Byte_00));
            Byte_01    = s.Serialize <byte>(Byte_01, name: nameof(Byte_01));
            YPosition  = s.Serialize <short>(YPosition, name: nameof(YPosition));
            XPosition  = s.Serialize <short>(XPosition, name: nameof(XPosition));
            ImageIndex = s.Serialize <ushort>(ImageIndex, name: nameof(ImageIndex));


            IsFlippedHorizontally = BitHelpers.ExtractBits(Byte_00, 1, 6) == 1;
            IsFlippedVertically   = BitHelpers.ExtractBits(Byte_00, 1, 7) == 1;
            SpriteShape           = (Shape)BitHelpers.ExtractBits(Byte_01, 2, 2);
            SpriteSize            = BitHelpers.ExtractBits(Byte_01, 2, 0);


            // Calculate size
            XSize = 1;
            YSize = 1;
            switch (SpriteShape)
            {
            case Shape.Square:
                XSize = 1 << SpriteSize;
                YSize = XSize;
                break;

            case Shape.Wide:
                switch (SpriteSize)
                {
                case 0: XSize = 2; YSize = 1; break;

                case 1: XSize = 4; YSize = 1; break;

                case 2: XSize = 4; YSize = 2; break;

                case 3: XSize = 8; YSize = 4; break;
                }
                break;

            case Shape.Tall:
                switch (SpriteSize)
                {
                case 0: XSize = 1; YSize = 2; break;

                case 1: XSize = 1; YSize = 4; break;

                case 2: XSize = 2; YSize = 4; break;

                case 3: XSize = 4; YSize = 8; break;
                }
                break;
            }
        }
        public override async UniTask ExportMenuSpritesAsync(GameSettings settings, string outputPath, bool exportAnimFrames)
        {
            using (var menuContext = new Context(settings))
            {
                using (var bigRayContext = new Context(settings))
                {
                    await LoadFilesAsync(menuContext);
                    await LoadFilesAsync(bigRayContext);

                    // Read the allfix & font files for the menu
                    await LoadExtraFile(menuContext, GetAllfixFilePath(menuContext.Settings), false);

                    var fix = FileFactory.Read <R1_PS1_AllfixFile>(GetAllfixFilePath(menuContext.Settings), menuContext);
                    await LoadExtraFile(menuContext, GetFontFilePath(menuContext.Settings), false);

                    // Correct font palette
                    if (settings.EngineVersion == EngineVersion.R1_PS1_JP)
                    {
                        foreach (R1_PS1_FontData font in fix.AllfixData.FontData)
                        {
                            foreach (R1_ImageDescriptor imgDescr in font.ImageDescriptors)
                            {
                                var paletteInfo = imgDescr.PaletteInfo;
                                paletteInfo          = (ushort)BitHelpers.SetBits(paletteInfo, 509, 10, 6);
                                imgDescr.PaletteInfo = paletteInfo;
                            }
                        }
                    }
                    else
                    {
                        foreach (R1_PS1_FontData font in fix.AllfixData.FontData)
                        {
                            foreach (R1_ImageDescriptor imgDescr in font.ImageDescriptors)
                            {
                                var paletteInfo = imgDescr.PaletteInfo;
                                paletteInfo          = (ushort)BitHelpers.SetBits(paletteInfo, 492, 10, 6);
                                imgDescr.PaletteInfo = paletteInfo;
                            }
                        }
                    }

                    // Read the BigRay file
                    await LoadExtraFile(bigRayContext, GetBigRayFilePath(bigRayContext.Settings), false);

                    var br = bigRayContext.FileExists(GetBigRayFilePath(bigRayContext.Settings)) ? FileFactory.Read <R1_PS1_BigRayFile>(GetBigRayFilePath(bigRayContext.Settings), bigRayContext) : null;

                    // Export
                    await ExportMenuSpritesAsync(menuContext, bigRayContext, outputPath, exportAnimFrames, fix.AllfixData.FontData, fix.AllfixData.WldObj, br?.BigRayData);
                }
            }
        }
Beispiel #7
0
 public XM_PatternRow(
     byte?note             = null,
     byte?instrument       = null,
     byte?volumeColumnByte = null,
     byte?effectType       = null,
     byte?effectParameter  = null)
 {
     if (!(instrument.HasValue || volumeColumnByte.HasValue || effectType.HasValue || effectParameter.HasValue))
     {
         if (note.HasValue)
         {
             Flags = note.Value;
             Note  = note.Value;
         }
         Size = 1;
     }
     else
     {
         Size = 1;
         if (note.HasValue)
         {
             Flags = (byte)BitHelpers.SetBits(Flags, 1, 1, 0);
             Note  = note.Value;
             Size++;
         }
         if (instrument.HasValue)
         {
             Flags      = (byte)BitHelpers.SetBits(Flags, 1, 1, 1);
             Instrument = instrument.Value;
             Size++;
         }
         if (volumeColumnByte.HasValue)
         {
             Flags            = (byte)BitHelpers.SetBits(Flags, 1, 1, 2);
             VolumeColumnByte = volumeColumnByte.Value;
             Size++;
         }
         if (effectType.HasValue)
         {
             Flags      = (byte)BitHelpers.SetBits(Flags, 1, 1, 3);
             EffectType = effectType.Value;
             Size++;
         }
         if (effectParameter.HasValue)
         {
             Flags           = (byte)BitHelpers.SetBits(Flags, 1, 1, 4);
             EffectParameter = effectParameter.Value;
             Size++;
         }
     }
 }
Beispiel #8
0
        void ExportVignette(GBC_PalmOS_Vignette vignette, string outputPath)
        {
            if (vignette == null)
            {
                throw new Exception("Not a vignette");
            }
            if (vignette.Width > 0x1000 || vignette.Height > 0x1000 || vignette.Width == 0 || vignette.Height == 0)
            {
                throw new Exception("Not a vignette");
            }
            int w = (int)vignette.Width;
            int h = (int)vignette.Height;

            var palette = vignette.BPP == 8 ? Util.CreateDummyPalette(256, firstTransparent: false) : Util.CreateDummyPalette(16, firstTransparent: false).Reverse().ToArray();

            Texture2D tex = TextureHelpers.CreateTexture2D(w, h);

            for (int y = 0; y < h; y++)
            {
                for (int x = 0; x < w; x++)
                {
                    int ind = y * w + x;
                    if (vignette.BPP == 16)
                    {
                        BaseColor col = vignette.DataPPC[ind];
                        tex.SetPixel(x, h - 1 - y, col.GetColor());
                    }
                    else if (vignette.BPP == 8)
                    {
                        int col = vignette.Data[ind];
                        tex.SetPixel(x, h - 1 - y, palette[col].GetColor());
                    }
                    else
                    {
                        int col = vignette.Data[ind / 2];
                        if (ind % 2 == 0)
                        {
                            col = BitHelpers.ExtractBits(col, 4, 4);
                        }
                        else
                        {
                            col = BitHelpers.ExtractBits(col, 4, 0);
                        }
                        tex.SetPixel(x, h - 1 - y, palette[col].GetColor());
                    }
                }
            }
            tex.Apply();
            Util.ByteArrayToFile(outputPath, tex.EncodeToPNG());
        }
Beispiel #9
0
        public void DecompressBlock_Bits(byte[] compressed, byte[] decompressed, ref int inPos, ref int outPos, ref int toDecompress)
        {
            uint commandOffset = (uint)(compressed[inPos] | (compressed[inPos + 1] << 8));
            uint endOffset     = (uint)(compressed[inPos + 2] | (compressed[inPos + 3] << 8));

            inPos += 4;
            int  curCommandOffset = 0;
            byte curCommand       = 0;
            uint startOffset      = (uint)inPos;
            uint curOffset        = 0;
            int  curCommandBit    = 0;

            void GetNewCommandBit(int bytesLeft)
            {
                if (curCommandBit == 0)
                {
                    curCommandBit = 7;
                    if (bytesLeft > 0)
                    {
                        curCommand = compressed[startOffset + commandOffset + curCommandOffset++];
                    }
                }
                else
                {
                    curCommandBit--;
                }
            }

            GetNewCommandBit(toDecompress);
            while (toDecompress > 0)
            {
                if (BitHelpers.ExtractBits(curCommand, 1, curCommandBit) == 1)
                {
                    curOffset += 2;
                }
                byte bVar1 = compressed[startOffset + curOffset + 1];
                if (bVar1 == 0)
                {
                    decompressed[outPos++] = compressed[startOffset + curOffset];
                    toDecompress--;
                    curOffset = 0;
                }
                else
                {
                    curOffset += (uint)bVar1 * 2;
                }
                GetNewCommandBit(toDecompress);
            }
            inPos = compressed.Length;
        }
Beispiel #10
0
        public override void SerializeBlock(SerializerObject s)
        {
            Flags = s.Serialize <byte>(Flags, name: nameof(Flags));

            if (!s.GameSettings.GBA_IsMilan)
            {
                Byte_01             = s.Serialize <byte>(Byte_01, name: nameof(Byte_01));
                AffineMatricesIndex = s.Serialize <byte>((byte)AffineMatricesIndex, name: nameof(AffineMatricesIndex));
                Byte_03             = s.Serialize <byte>(Byte_03, name: nameof(Byte_03));
                FrameCount          = (byte)BitHelpers.ExtractBits(Byte_03, 6, 0);

                LayersPerFrame = s.SerializeArray <byte>(LayersPerFrame, FrameCount, name: nameof(LayersPerFrame));

                s.Align();

                if (Layers == null)
                {
                    Layers = new GBA_AnimationChannel[FrameCount][];
                }

                for (int i = 0; i < FrameCount; i++)
                {
                    Layers[i] = s.SerializeObjectArray <GBA_AnimationChannel>(Layers[i], LayersPerFrame[i], name: $"{nameof(Layers)}[{i}]");
                }
            }
            else
            {
                FrameCount          = s.Serialize <byte>(FrameCount, name: nameof(FrameCount));
                Milan_Ushort_02     = s.Serialize <ushort>(Milan_Ushort_02, name: nameof(Milan_Ushort_02));
                AffineMatricesIndex = s.Serialize <ushort>(AffineMatricesIndex, name: nameof(AffineMatricesIndex));
                Milan_Int_06        = s.Serialize <int>(Milan_Int_06, name: nameof(Milan_Int_06));

                var offsetBase = s.CurrentPointer;

                Milan_LayerOffsets = s.SerializeArray <ushort>(Milan_LayerOffsets, FrameCount + 1, name: nameof(Milan_LayerOffsets)); // +1 since last offset is the end

                if (Layers == null)
                {
                    Layers = new GBA_AnimationChannel[FrameCount][];
                }

                for (int i = 0; i < FrameCount; i++)
                {
                    Layers[i] = s.DoAt(offsetBase + Milan_LayerOffsets[i], () => s.SerializeObjectArray <GBA_AnimationChannel>(Layers[i], (Milan_LayerOffsets[i + 1] - Milan_LayerOffsets[i]) / 6, name: $"{nameof(Layers)}[{i}]"));
                }

                s.Goto(offsetBase + Milan_LayerOffsets.LastOrDefault());
            }
        }
Beispiel #11
0
 public void DecompressBlock_Shorts(byte[] compressed, byte[] decompressed, ref int inPos, ref int outPos, ref int toDecompress)
 {
     using (Reader reader = new Reader(new MemoryStream(compressed))) {
         reader.BaseStream.Position = inPos;
         using (Writer writer = new Writer(new MemoryStream())) {
             while (toDecompress > 0)
             {
                 ushort cmd     = reader.ReadUInt16();
                 ushort toWrite = (ushort)BitHelpers.ExtractBits(cmd, 14, 0);
                 bool   flag14  = BitHelpers.ExtractBits(cmd, 1, 14) == 1;
                 bool   flag15  = BitHelpers.ExtractBits(cmd, 1, 15) == 1;
                 if (!flag15)
                 {
                     if (flag14)
                     {
                         writer.Write(toWrite);
                         toDecompress -= 2;
                     }
                     writer.Write(toWrite);
                     toDecompress -= 2;
                 }
                 else
                 {
                     if (!flag14)
                     {
                         byte count = reader.ReadByte();
                         for (int i = 0; i < count; i++)
                         {
                             writer.Write(toWrite);
                         }
                         toDecompress -= 2 * count;
                     }
                     else
                     {
                         writer.Write(toWrite);
                         writer.Write(toWrite);
                         writer.Write(toWrite);
                         toDecompress -= 6;
                     }
                 }
             }
             writer.BaseStream.Position = 0;
             byte[] decompressed2 = (writer.BaseStream as MemoryStream).ToArray();
             Array.Copy(decompressed2, 0, decompressed, outPos, decompressed2.Length);
             outPos += decompressed2.Length;
         }
         inPos = (int)reader.BaseStream.Position;
     }
 }
Beispiel #12
0
 public void DecompressBlock_Window(byte[] compressed, byte[] decompressed, ref int inPos, ref int outPos, ref int toDecompress)
 {
     while (toDecompress > 0)
     {
         byte cmd = compressed[inPos++];
         if (BitHelpers.ExtractBits(cmd, 1, 7) == 0)
         {
             if (cmd == 0 || 8 < cmd)
             {
                 //UnityEngine.Debug.Log($"1: td{toDecompress}: ip{inPos}, op{outPos}, cmd{cmd}");
                 decompressed[outPos++] = cmd;
                 toDecompress--;
             }
             else
             {
                 //UnityEngine.Debug.Log($"2: td{toDecompress}: ip{inPos}, op{outPos}, cmd{cmd}");
                 for (int i = 0; i < cmd; i++)
                 {
                     decompressed[outPos++] = compressed[inPos++];
                 }
                 toDecompress -= cmd;
             }
         }
         else
         {
             if (cmd < 0xc0)
             {
                 int bits     = (cmd << 8) | compressed[inPos++];
                 int count    = BitHelpers.ExtractBits(bits, 4, 0) + 3;
                 int lookBack = BitHelpers.ExtractBits(bits, 10, 4) + 1;
                 //UnityEngine.Debug.Log($"window lookback: td{toDecompress}: ip{inPos}, op{outPos}, lb{lookBack}, c{count}");
                 for (int i = 0; i < count; i++)
                 {
                     decompressed[outPos] = decompressed[outPos - lookBack];
                     outPos++;
                 }
                 toDecompress -= count;
             }
             else
             {
                 //UnityEngine.Debug.Log($"3: td{toDecompress}: ip{inPos}, op{outPos}, cmd{cmd}");
                 decompressed[outPos++] = 0x20;
                 decompressed[outPos++] = (byte)((cmd & 0x3f) + 0x41);
                 toDecompress          -= 2;
             }
         }
     }
 }
Beispiel #13
0
 public void DecompressBlock_Buffer(byte[] compressed, byte[] decompressed, ref int inPos, ref int outPos, ref int toDecompress)
 {
     while (toDecompress > 0)
     {
         int blockSz = Math.Min(0x800, toDecompress);
         // Fill temp buffer
         ushort[] buffer = new ushort[0x100];
         for (int i = 0; i < buffer.Length; i++)
         {
             buffer[i] = (ushort)i;
         }
         byte fillBufferCount = compressed[inPos++];
         for (int i = 0; i < fillBufferCount; i++)
         {
             byte location = compressed[inPos++];
             byte msb      = compressed[inPos++];
             byte lsb      = compressed[inPos++];
             buffer[location] = (ushort)((msb << 8) | lsb);
         }
         int          curSz  = 0;
         Stack <byte> puVar6 = new Stack <byte>();
         //UnityEngine.Debug.Log($"1: td{toDecompress}: ip{inPos}, op{outPos}");
         while (curSz != blockSz)
         {
             uint unk = compressed[inPos++];
             //UnityEngine.Debug.Log($"2: td{toDecompress}: ip{inPos}, op{outPos}, unk{unk}");
             while (true)
             {
                 while (buffer[unk] != unk)
                 {
                     ushort buf = buffer[unk];
                     unk = (uint)BitHelpers.ExtractBits(buf, 8, 0);
                     puVar6.Push((byte)BitHelpers.ExtractBits(buf, 8, 8));
                 }
                 decompressed[outPos++] = (byte)unk;
                 //UnityEngine.Debug.Log($"3: td{toDecompress}: ip{inPos}, op{outPos}, unk{unk}");
                 curSz++;
                 if (puVar6.Count == 0)
                 {
                     break;
                 }
                 unk = puVar6.Pop();
             }
         }
         toDecompress -= blockSz;
     }
 }
Beispiel #14
0
        public override void SerializeOffsetData(SerializerObject s)
        {
            Palette = s.DoAt(OffsetTable.GetPointer(Index_Palette), () => s.SerializeObject <GBA_SpritePalette>(Palette, name: nameof(Palette)));

            if (!s.GameSettings.GBA_IsMilan)
            {
                TileSet = s.DoAt(OffsetTable.GetPointer(Index_TileSet), () => s.SerializeObject <GBA_SpriteTileSet>(TileSet, onPreSerialize: x =>
                {
                    if (s.GameSettings.EngineVersion == EngineVersion.GBA_Sabrina)
                    {
                        x.IsDataCompressed = BitHelpers.ExtractBits(Byte_04, 1, 5) == 0;
                    }
                }, name: nameof(TileSet)));
            }
            else
            {
                Milan_TileKit = s.DoAt(OffsetTable.GetPointer(Index_TileSet), () => s.SerializeObject <GBA_TileKit>(Milan_TileKit, name: nameof(Milan_TileKit)));
            }

            if (Animations == null)
            {
                Animations = new GBA_Animation[AnimationsCount];
            }

            for (int i = 0; i < Animations.Length; i++)
            {
                Animations[i] = s.DoAt(OffsetTable.GetPointer(AnimationIndexTable[i]), () => s.SerializeObject <GBA_Animation>(Animations[i], name: $"{nameof(Animations)}[{i}]"));
            }

            for (int i = 0; i < Animations.Length; i++)
            {
                if (Animations[i] == null)
                {
                    continue;
                }
                int matrixIndex = Animations[i].AffineMatricesIndex;
                if (matrixIndex != 0)
                {
                    Matrices[matrixIndex] = s.DoAt(OffsetTable.GetPointer(matrixIndex),
                                                   () => s.SerializeObject <GBA_AffineMatrixList>(
                                                       Matrices.ContainsKey(matrixIndex) ? Matrices[matrixIndex] : null,
                                                       onPreSerialize: ml => ml.FrameCount = Animations[i].FrameCount,
                                                       name: $"{nameof(Matrices)}[{matrixIndex}]"));
                }
            }
        }
Beispiel #15
0
        public override void SerializeBitValues <T>(Action <SerializeBits> serializeFunc)
        {
            int    valueInt  = 0;
            int    pos       = 0;
            string logPrefix = LogPrefix;

            // Set bits
            serializeFunc((v, length, name) => {
                valueInt = BitHelpers.SetBits(valueInt, v, length, pos);
                if (Settings.Log)
                {
                    Context.Log.Log(logPrefix + $"  ({typeof(T)}) {name ?? "<no name>"}: {v}");
                }
                pos += length;
                return(v);
            });

            // Serialize value
            Serialize <T>((T)Convert.ChangeType(valueInt, typeof(T)), name: "Value");
        }
Beispiel #16
0
        public void DecompressString(Reader reader, byte[] outBuffer)
        {
            byte bits      = 0;
            int  curBit    = -1;
            int  curHelper = 0;
            int  outPos    = 0;

            while (outPos < outBuffer.Length)
            {
                if (curBit < 0)
                {
                    bits    = reader.ReadByte();
                    curBit += 8;
                }
                if (BitHelpers.ExtractBits(bits, 1, curBit) == 0)
                {
                    if (BitHelpers.ExtractBits(Helpers[curHelper].b0, 1, 0) == 1)
                    {
                        outBuffer[outPos++] = (byte)(Helpers[curHelper].b1);
                        curHelper           = 0;
                    }
                    else
                    {
                        curHelper = Helpers[curHelper].b1;
                    }
                }
                else
                {
                    if (BitHelpers.ExtractBits(Helpers[curHelper].b0, 1, 1) == 1)
                    {
                        outBuffer[outPos++] = (byte)(Helpers[curHelper].b2);
                        curHelper           = 0;
                    }
                    else
                    {
                        curHelper = Helpers[curHelper].b2;
                    }
                }
                curBit--;
            }
        }
                    public void DecompressString(byte[] compressed, Writer writer)
                    {
                        byte bits      = 0;
                        int  curBit    = -1;
                        int  curHelper = 0;
                        int  inPos     = 0;

                        while (true)
                        {
                            if (curBit < 0)
                            {
                                if (inPos >= compressed.Length)
                                {
                                    break;
                                }
                                bits    = compressed[inPos++];
                                curBit += 8;
                            }
                            if (BitHelpers.ExtractBits(bits, 1, curBit) == 0)
                            {
                                curHelper = Helpers[curHelper].Left;
                                if (Helpers[curHelper].IsLeaf)
                                {
                                    writer.Write(Helpers[curHelper].Value);
                                    curHelper = 0;
                                }
                            }
                            else
                            {
                                curHelper = Helpers[curHelper].Right;
                                if (Helpers[curHelper].IsLeaf)
                                {
                                    writer.Write(Helpers[curHelper].Value);
                                    curHelper = 0;
                                }
                            }
                            curBit--;
                        }
                    }
        private Stream XORStream(Stream s)
        {
            byte compr_incremental_xor = 0x57;

            var    decompressedStream = new MemoryStream();
            Reader reader             = new Reader(s, isLittleEndian: true); // No using, because we don't want to close the stream

            byte bytes_in_window = reader.ReadByte();

            bytes_in_window ^= 0x53;
            decompressedStream.WriteByte(bytes_in_window);

            uint decompressedSize = reader.ReadUInt32();

            decompressedSize ^= 0x54555657;
            decompressedStream.Write(BitConverter.GetBytes(decompressedSize), 0, 4);
            while (s.Position < s.Length)
            {
                byte b   = reader.ReadByte();
                byte xor = 0;
                // Bit reverse
                for (int i = 0; i < 8; i++)
                {
                    xor = (byte)BitHelpers.SetBits(xor, BitHelpers.ExtractBits(compr_incremental_xor, 1, i), 1, 7 - i);
                }
                b = (byte)(b ^ (xor ^ 0xB9));
                if (compr_incremental_xor == 0xFF)
                {
                    compr_incremental_xor = 0x0;
                }
                else
                {
                    compr_incremental_xor++;
                }
                decompressedStream.WriteByte(b);
            }
            decompressedStream.Position = 0;
            return(decompressedStream);
        }
Beispiel #19
0
        /// <summary>
        /// Handles the data serialization
        /// </summary>
        /// <param name="s">The serializer object</param>
        public override void SerializeImpl(SerializerObject s)
        {
            SampleLength       = s.Serialize <uint>(SampleLength, name: nameof(SampleLength));
            SampleLoopStart    = s.Serialize <uint>(SampleLoopStart, name: nameof(SampleLoopStart));
            SampleLoopLength   = s.Serialize <uint>(SampleLoopLength, name: nameof(SampleLoopLength));
            Volume             = s.Serialize <byte>(Volume, name: nameof(Volume));
            FineTune           = s.Serialize <sbyte>(FineTune, name: nameof(FineTune));
            Type               = s.Serialize <byte>(Type, name: nameof(Type));
            Panning            = s.Serialize <byte>(Panning, name: nameof(Panning));
            RelativeNoteNumber = s.Serialize <sbyte>(RelativeNoteNumber, name: nameof(RelativeNoteNumber));
            DataType           = s.Serialize <byte>(DataType, name: nameof(DataType));
            SampleName         = s.SerializeString(SampleName, 22, Encoding.ASCII, name: nameof(SampleName));

            if (BitHelpers.ExtractBits(Type, 1, 4) == 1)
            {
                SampleData16 = s.SerializeArray <short>(SampleData16, SampleLength / 2, name: nameof(SampleData16));
            }
            else
            {
                SampleData8 = s.SerializeArray <sbyte>(SampleData8, SampleLength, name: nameof(SampleData8));
            }
        }
Beispiel #20
0
        public override void SerializeBlock(SerializerObject s)
        {
            if (s.GameSettings.EngineVersion == EngineVersion.GBA_BatmanVengeance)
            {
                if (StructType != Type.Collision)
                {
                    Unk_02 = s.Serialize <byte>(Unk_02, name: nameof(Unk_02));
                    Unk_03 = s.Serialize <byte>(Unk_03, name: nameof(Unk_03));

                    LayerID      = s.Serialize <byte>(LayerID, name: nameof(LayerID));
                    ClusterIndex = s.Serialize <byte>(ClusterIndex, name: nameof(ClusterIndex));
                    // TODO: figure out what this is. One of these
                    UnkBytes = s.SerializeArray <byte>(UnkBytes, 5, name: nameof(UnkBytes));
                    ShouldSetBGAlphaBlending = s.Serialize <bool>(ShouldSetBGAlphaBlending, name: nameof(ShouldSetBGAlphaBlending));
                    Unk_0E    = s.Serialize <byte>(Unk_0E, name: nameof(Unk_0E));
                    ColorMode = s.Serialize <GBA_ColorMode>(ColorMode, name: nameof(ColorMode));
                }
            }
            else if (s.GameSettings.GBA_IsMilan)
            {
                ColorMode = GBA_ColorMode.Color4bpp;

                // Serialize cluster
                Cluster = s.DoAt(ShanghaiOffsetTable.GetPointer(0), () => s.SerializeObject <GBA_Cluster>(Cluster, name: nameof(Cluster)));

                IStreamEncoder encoder = null;

                switch (Cluster.Milan_MapCompressionType)
                {
                case GBA_Cluster.Milan_CompressionType.Collision_RL:
                case GBA_Cluster.Milan_CompressionType.Map_RL:
                    encoder = new GBA_RLEEncoder();
                    break;

                case GBA_Cluster.Milan_CompressionType.Collsiion_LZSS:
                case GBA_Cluster.Milan_CompressionType.Map_LZSS:
                    encoder = new GBA_LZSSEncoder();
                    break;
                }

                // Go to the map data
                s.Goto(ShanghaiOffsetTable.GetPointer(2));

                if (StructType == Type.Layer2D)
                {
                    s.DoEncodedIf(encoder, encoder != null, () => Shanghai_MapIndices_16 = s.SerializeArray <ushort>(Shanghai_MapIndices_16, ((Width + Width % 2) * (Height + Height % 2)) / 4, name: nameof(Shanghai_MapIndices_16)));

                    var end = s.CurrentPointer;

                    // Go to the map tiles
                    s.Goto(ShanghaiOffsetTable.GetPointer(1));

                    s.DoEncodedIf(encoder, encoder != null, () => Shanghai_MapTiles = s.SerializeObjectArray <MapTile>(Shanghai_MapTiles, (Shanghai_MapIndices_16.Max(x => BitHelpers.ExtractBits(x, 12, 0)) + 1) * 4, name: nameof(Shanghai_MapTiles)));

                    s.Goto(end);
                }
                else // Collision
                {
                    s.DoEncodedIf(encoder, encoder != null, () => SerializeTileMap(s));
                }

                s.Align();

                // Return to avoid serializing the map tile array normally
                return;
            }
            else if (s.GameSettings.GBA_IsShanghai)
            {
                ColorMode    = GBA_ColorMode.Color4bpp;
                IsCompressed = false;

                if (StructType == Type.Layer2D)
                {
                    // Serialize cluster
                    Cluster = s.DoAt(ShanghaiOffsetTable.GetPointer(0), () => s.SerializeObject <GBA_Cluster>(Cluster, name: nameof(Cluster)));

                    // Go to the map data
                    s.Goto(ShanghaiOffsetTable.GetPointer(2));

                    // If the map tile size is not 0 the map is split into a 32x8 index array and 8x8 map tiles
                    if (Cluster.Shanghai_MapTileSize != 0)
                    {
                        var indexArrayLength = Mathf.CeilToInt(Width / 4f) * Height;

                        // The tile size is either 1 or 2 bytes
                        if (Cluster.Shanghai_MapTileSize == 1)
                        {
                            Shanghai_MapIndices_8 = s.SerializeArray <byte>(Shanghai_MapIndices_8, indexArrayLength, name: nameof(Shanghai_MapIndices_8));
                        }
                        else
                        {
                            Shanghai_MapIndices_16 = s.SerializeArray <ushort>(Shanghai_MapIndices_16, indexArrayLength, name: nameof(Shanghai_MapIndices_16));
                        }

                        var indexArray = Cluster.Shanghai_MapTileSize == 1 ? Shanghai_MapIndices_8.Select(x => (ushort)x).ToArray() : Shanghai_MapIndices_16;

                        Shanghai_MapTiles = s.SerializeObjectArray <MapTile>(Shanghai_MapTiles, (indexArray.Max() + 1) * 4, name: nameof(Shanghai_MapTiles));

                        // Return to avoid serializing the map tile array normally
                        return;
                    }
                }
                else
                {
                    // Go to the collision data
                    s.Goto(ShanghaiOffsetTable.GetPointer(0));

                    // Serialize header properties
                    Shanghai_CollisionValue1 = s.Serialize <ushort>(Shanghai_CollisionValue1, name: nameof(Shanghai_CollisionValue1));
                    Width  = s.Serialize <ushort>(Width, name: nameof(Width));
                    Height = s.Serialize <ushort>(Height, name: nameof(Height));
                    Shanghai_CollisionValue2 = s.Serialize <ushort>(Shanghai_CollisionValue2, name: nameof(Shanghai_CollisionValue2));
                }
            }
            else
            {
                StructType = s.Serialize <Type>(StructType, name: nameof(StructType));

                if (StructType != Type.TextLayerMode7)
                {
                    IsCompressed = s.Serialize <bool>(IsCompressed, name: nameof(IsCompressed));
                }
                else
                {
                    Unk_01 = s.Serialize <bool>(Unk_01, name: nameof(Unk_01));
                }

                Unk_02 = s.Serialize <byte>(Unk_02, name: nameof(Unk_02));
                Unk_03 = s.Serialize <byte>(Unk_03, name: nameof(Unk_03));

                Width  = s.Serialize <ushort>(Width, name: nameof(Width));
                Height = s.Serialize <ushort>(Height, name: nameof(Height));

                switch (StructType)
                {
                case Type.TextLayerMode7:
                    LayerID = s.Serialize <byte>(LayerID, name: nameof(LayerID));
                    ShouldSetBGAlphaBlending = s.Serialize <bool>(ShouldSetBGAlphaBlending, name: nameof(ShouldSetBGAlphaBlending));
                    AlphaBlending_Coeff      = s.Serialize <sbyte>(AlphaBlending_Coeff, name: nameof(AlphaBlending_Coeff));
                    UnkBytes  = s.SerializeArray <byte>(UnkBytes, 0x14, name: nameof(UnkBytes));
                    ColorMode = s.Serialize <GBA_ColorMode>(ColorMode, name: nameof(ColorMode));
                    // 21 bytes
                    // Prio is 0x1D
                    // ColorMode is 0x1F
                    // Width & height seems duplicates again (is it actually width and height?)

                    break;

                case Type.RotscaleLayerMode7:
                    LayerID = s.Serialize <byte>(LayerID, name: nameof(LayerID));
                    ShouldSetBGAlphaBlending = s.Serialize <bool>(ShouldSetBGAlphaBlending, name: nameof(ShouldSetBGAlphaBlending));
                    AlphaBlending_Coeff      = s.Serialize <sbyte>(AlphaBlending_Coeff, name: nameof(AlphaBlending_Coeff));
                    // The game hard-codes the color mode
                    ColorMode = GBA_ColorMode.Color8bpp;

                    Unk_0C   = s.Serialize <byte>(Unk_0C, name: nameof(Unk_0C));
                    Unk_0D   = s.Serialize <byte>(Unk_0D, name: nameof(Unk_0D));
                    Unk_0E   = s.Serialize <byte>(Unk_0E, name: nameof(Unk_0E));
                    Unk_0F   = s.Serialize <byte>(Unk_0F, name: nameof(Unk_0F));
                    Mode7_10 = s.Serialize <byte>(Mode7_10, name: nameof(Mode7_10));
                    Mode7_11 = s.Serialize <byte>(Mode7_11, name: nameof(Mode7_11));
                    Mode7_12 = s.Serialize <byte>(Mode7_12, name: nameof(Mode7_12));
                    Mode7_13 = s.Serialize <byte>(Mode7_13, name: nameof(Mode7_13));
                    Mode7_14 = s.Serialize <byte>(Mode7_14, name: nameof(Mode7_14));
                    break;

                case Type.SplinterCellZoom:
                    if (LayerID < 2)
                    {
                        Unk_0C = s.Serialize <byte>(Unk_0C, name: nameof(Unk_0C));
                        Unk_0D = s.Serialize <byte>(Unk_0D, name: nameof(Unk_0D));
                        Unk_0E = s.Serialize <byte>(Unk_0E, name: nameof(Unk_0E));
                        Unk_0F = s.Serialize <byte>(Unk_0F, name: nameof(Unk_0F));
                        if (s.GameSettings.EngineVersion == EngineVersion.GBA_SplinterCell_NGage)
                        {
                            ColorMode = GBA_ColorMode.Color8bpp;
                        }
                        else
                        {
                            ColorMode = GBA_ColorMode.Color4bpp;
                        }
                    }
                    else
                    {
                        ColorMode = GBA_ColorMode.Color8bpp;
                    }
                    UsesTileKitDirectly = true;
                    break;

                case Type.PoP:
                    Unk_0C    = s.Serialize <byte>(Unk_0C, name: nameof(Unk_0C));
                    Unk_0D    = s.Serialize <byte>(Unk_0D, name: nameof(Unk_0D));
                    Unk_0E    = s.Serialize <byte>(Unk_0E, name: nameof(Unk_0E));
                    Unk_0F    = s.Serialize <byte>(Unk_0F, name: nameof(Unk_0F));
                    ColorMode = GBA_ColorMode.Color8bpp;
                    break;

                case Type.Layer2D:
                    LayerID                  = s.Serialize <byte>(LayerID, name: nameof(LayerID));
                    ClusterIndex             = s.Serialize <byte>(ClusterIndex, name: nameof(ClusterIndex));
                    ShouldSetBGAlphaBlending = s.Serialize <bool>(ShouldSetBGAlphaBlending, name: nameof(ShouldSetBGAlphaBlending));
                    AlphaBlending_Coeff      = s.Serialize <sbyte>(AlphaBlending_Coeff, name: nameof(AlphaBlending_Coeff));

                    UsesTileKitDirectly = s.Serialize <bool>(UsesTileKitDirectly, name: nameof(UsesTileKitDirectly));
                    ColorMode           = s.Serialize <GBA_ColorMode>(ColorMode, name: nameof(ColorMode));
                    TileKitIndex        = s.Serialize <byte>(TileKitIndex, name: nameof(TileKitIndex));
                    Unk_0F = s.Serialize <byte>(Unk_0F, name: nameof(Unk_0F));
                    break;
                }
            }

            if (StructType != Type.TextLayerMode7)
            {
                if (!IsCompressed)
                {
                    SerializeTileMap(s);
                }
                else if (s.GameSettings.EngineVersion >= EngineVersion.GBA_PrinceOfPersia && StructType != Type.PoP)
                {
                    s.DoEncoded(new GBA_Huffman4Encoder(), () => s.DoEncoded(new GBA_LZSSEncoder(), () => SerializeTileMap(s)));
                }
                else
                {
                    s.DoEncoded(new GBA_LZSSEncoder(), () => SerializeTileMap(s));
                }
                s.Align();
            }
        }
        private Track CreateTrack(R1Jaguar_MusicDescriptor jagFile)
        {
            Track t = new Track();
            TempoChangeBuilder b = new TempoChangeBuilder();

            b.Tempo = 22000;
            b.Build();
            t.Insert(0, b.Result);
            ChannelMessageBuilder builder          = new ChannelMessageBuilder();
            Dictionary <int, int> curNoteOnChannel = new Dictionary <int, int>();
            int timeScale = 1;

            for (int i = 0; i < jagFile.MusicData.Length; i++)
            {
                R1Jaguar_MusicData e = jagFile.MusicData[i];
                if (e.Time != int.MaxValue)
                {
                    int channelByte = BitHelpers.ExtractBits(e.Command, 8, 24);
                    if (channelByte == 0x7F)                       // special point in the song
                    {
                        int idByte = BitHelpers.ExtractBits(e.Command, 8, 0);
                        if (idByte == 0xFF && i >= jagFile.MusicData.Length - 2)                           // End point
                        {
                            t.EndOfTrackOffset = e.Time / timeScale;
                            break;
                        }
                        else
                        {
                            // Loop point, or command to return to loop point
                        }
                    }
                    else
                    {
                        int channel = BitHelpers.ExtractBits(e.Command, 4, 26);
                        int command = BitHelpers.ExtractBits(e.Command, 1, 31);
                        if (command == 1)
                        {
                            // Note off
                            if (curNoteOnChannel.ContainsKey(channel))
                            {
                                builder.Command = ChannelCommand.NoteOff;
                                int note = curNoteOnChannel.TryGetValue(channel, out int val) ? val : 0;
                                if (note >= 128)
                                {
                                    builder.MidiChannel = 9;
                                    builder.Data1       = note - 128;
                                }
                                else
                                {
                                    builder.MidiChannel = channel;
                                    builder.Data1       = note;
                                }
                                builder.Data2 = 127;
                                builder.Build();
                                t.Insert(e.Time / timeScale, builder.Result);
                            }

                            // Program change
                            int instrument = BitHelpers.ExtractBits(e.Command, 5, 21);
                            if (PercussionInstruments[instrument] != Percussion.None)
                            {
                                builder.MidiChannel = 9;
                            }
                            else
                            {
                                builder.MidiChannel = channel;
                                builder.Command     = ChannelCommand.ProgramChange;
                                builder.Data1       = GeneralMidiInstruments[instrument] == Instrument.None ? 0 : (int)GeneralMidiInstruments[instrument];
                                if (GeneralMidiInstruments[instrument] == Instrument.Sitar)
                                {
                                    Controller.print("unknown @ " + jagFile.MusicDataPointer);
                                }
                                builder.Build();
                                t.Insert(e.Time / timeScale, builder.Result);
                            }

                            // Note on
                            builder.Command = ChannelCommand.NoteOn;
                            int freq = BitHelpers.ExtractBits(e.Command, 13, 8);
                            int vel  = BitHelpers.ExtractBits(e.Command, 7, 0);
                            //bool hasVelocity = BitHelpers.ExtractBits(e.Command, 1, 7) == 1;
                            builder.Data1 = GetMidiPitch(freq, 349f);
                            //builder.Data2 = UnityEngine.Mathf.RoundToInt(127f * (vel / 7f));
                            float velf = ((vel + 1) / 128f); // hack
                            int   veli = Mathf.RoundToInt(velf * 127f);

                            /*if (!hasVelocity) {
                             *  veli = 127;
                             * }*/
                            if (PercussionInstruments[instrument] != Percussion.None)
                            {
                                builder.Data1             = (int)PercussionInstruments[instrument];
                                builder.Data2             = PercussionInstruments[instrument] == Percussion.None ? 0 : veli;
                                curNoteOnChannel[channel] = builder.Data1 + 128;
                            }
                            else
                            {
                                builder.Data2             = GeneralMidiInstruments[instrument] == Instrument.None ? 0 : veli;
                                curNoteOnChannel[channel] = builder.Data1;
                            }
                            builder.Build();
                            t.Insert(e.Time / timeScale, builder.Result);
                        }
                        else
                        {
                            builder.Command = ChannelCommand.NoteOff;
                            int note = curNoteOnChannel.TryGetValue(channel, out int val) ? val : 0;
                            if (note >= 128)
                            {
                                builder.MidiChannel = 9;
                                builder.Data1       = note - 128;
                            }
                            else
                            {
                                builder.MidiChannel = channel;
                                builder.Data1       = note;
                            }
                            builder.Data2 = 127;
                            curNoteOnChannel.Remove(channel);

                            builder.Build();
                            t.Insert(e.Time / timeScale, builder.Result);
                        }
                    }
                }
            }
            return(t);
        }
Beispiel #22
0
        /// <summary>
        /// Handles the data serialization
        /// </summary>
        /// <param name="s">The serializer object</param>
        public override void SerializeImpl(SerializerObject s)
        {
            if (s.GameSettings.GameModeSelection == GameModeSelection.MapperPC || s.GameSettings.EngineVersion == EngineVersion.R1_GBA || s.GameSettings.EngineVersion == EngineVersion.R1_DSi)
            {
                TileMapY      = s.Serialize <ushort>(TileMapY, name: nameof(TileMapY));
                TileMapX      = 0;
                CollisionType = (byte)s.Serialize <ushort>((ushort)CollisionType, name: nameof(CollisionType));
            }
            else if (s.GameSettings.EngineVersion == EngineVersion.R1_PC || s.GameSettings.EngineVersion == EngineVersion.R1_PC_Kit || s.GameSettings.EngineVersion == EngineVersion.R1_PC_Edu || s.GameSettings.EngineVersion == EngineVersion.R1_PS1_Edu || s.GameSettings.EngineVersion == EngineVersion.R1_PocketPC)
            {
                TileMapY            = s.Serialize <ushort>(TileMapY, name: nameof(TileMapY));
                TileMapX            = 0;
                CollisionType       = s.Serialize <byte>(CollisionType, name: nameof(CollisionType));
                PC_Unk1             = s.Serialize <byte>(PC_Unk1, name: nameof(PC_Unk1));
                PC_TransparencyMode = s.Serialize <R1_PC_MapTileTransparencyMode>(PC_TransparencyMode, name: nameof(PC_TransparencyMode));
                PC_Unk2             = s.Serialize <byte>(PC_Unk2, name: nameof(PC_Unk2));
            }
            else if (s.GameSettings.EngineVersion == EngineVersion.R1_PS1_JPDemoVol3 || s.GameSettings.EngineVersion == EngineVersion.R1_PS1_JPDemoVol6)
            {
                s.SerializeBitValues <int>(bitFunc =>
                {
                    TileMapX      = (ushort)bitFunc(TileMapX, 10, name: nameof(TileMapX));
                    TileMapY      = (ushort)bitFunc(TileMapY, 6, name: nameof(TileMapY));
                    CollisionType = (byte)bitFunc(CollisionType, 8, name: nameof(CollisionType));
                });
            }
            else if (s.GameSettings.EngineVersion == EngineVersion.R1_Saturn)
            {
                s.SerializeBitValues <ushort>(bitFunc =>
                {
                    TileMapX = (ushort)bitFunc(TileMapX, 4, name: nameof(TileMapX));
                    TileMapY = (ushort)bitFunc(TileMapY, 12, name: nameof(TileMapY));
                });

                CollisionType = s.Serialize <byte>(CollisionType, name: nameof(CollisionType));
                s.Serialize <byte>(0, name: "Padding");
            }
            else if (s.GameSettings.MajorEngineVersion == MajorEngineVersion.Rayman1_Jaguar)
            {
                s.SerializeBitValues <ushort>(bitFunc =>
                {
                    TileMapY      = (ushort)bitFunc(TileMapY, 12, name: nameof(TileMapY));
                    CollisionType = (byte)bitFunc(CollisionType, 4, name: nameof(CollisionType));
                });

                TileMapX = 0;
            }
            else if (s.GameSettings.MajorEngineVersion == MajorEngineVersion.SNES)
            {
                s.SerializeBitValues <ushort>(bitFunc =>
                {
                    TileMapY       = (ushort)bitFunc(TileMapY, 10, name: nameof(TileMapY));
                    HorizontalFlip = bitFunc(HorizontalFlip ? 1 : 0, 1, name: nameof(HorizontalFlip)) == 1;
                    VerticalFlip   = bitFunc(VerticalFlip ? 1 : 0, 1, name: nameof(VerticalFlip)) == 1;
                    CollisionType  = (byte)bitFunc(CollisionType, 4, name: nameof(CollisionType));
                });

                TileMapX = 0;
            }
            else if (s.GameSettings.MajorEngineVersion == MajorEngineVersion.GBA)
            {
                // TODO: Use SerializeBitValues

                if ((GBATileType == GBA_TileType.BGTile || GBATileType == GBA_TileType.FGTile) &&
                    s.GameSettings.EngineVersion != EngineVersion.GBA_SplinterCell_NGage &&
                    s.GameSettings.EngineVersion != EngineVersion.GBA_BatmanVengeance)
                {
                    int numBits = Is8Bpp ? 9 : 10;

                    if (s.GameSettings.EngineVersion <= EngineVersion.GBA_BatmanVengeance)
                    {
                        numBits = 8;
                    }/*else if(s.GameSettings.EngineVersion >= EngineVersion.GBA_StarWarsTrilogy) {
                      * numBits = Is8Bpp ? 9 : 10;
                      * } else if (s.GameSettings.EngineVersion >= EngineVersion.GBA_SplinterCell) {
                      * numBits = 9;
                      * if (GBATileType == GBA_TileType.FGTile) numBits = 10;
                      * }*/

                    ushort value = 0;

                    value = (ushort)BitHelpers.SetBits(value, TileMapY, numBits, 0);
                    //value = (ushort)BitHelpers.SetBits(value, VerticalFlip ? 1 : 0, 1, numBits);
                    value = (ushort)BitHelpers.SetBits(value, HorizontalFlip ? 1 : 0, 1, numBits);
                    value = (ushort)BitHelpers.SetBits(value, PaletteIndex, 4, 12);

                    value = s.Serialize <ushort>(value, name: nameof(value));

                    TileMapY = (ushort)BitHelpers.ExtractBits(value, numBits, 0);
                    TileMapX = 0;
                    if (Is8Bpp)
                    {
                        IsFirstBlock = BitHelpers.ExtractBits(value, 1, 9) == 1;
                    }
                    HorizontalFlip = BitHelpers.ExtractBits(value, 1, 10) == 1;
                    VerticalFlip   = BitHelpers.ExtractBits(value, 1, 11) == 1;
                    PaletteIndex   = (byte)BitHelpers.ExtractBits(value, 4, 12);

                    s.Log($"{nameof(TileMapY)}: {TileMapY}");
                    s.Log($"{nameof(HorizontalFlip)}: {HorizontalFlip}");
                    s.Log($"{nameof(IsFirstBlock)}: {IsFirstBlock}");
                    s.Log($"{nameof(PaletteIndex)}: {PaletteIndex}");
                }
                else if (GBATileType == GBA_TileType.Mode7Tile)
                {
                    ushort value = 0;

                    value = (ushort)BitHelpers.SetBits(value, TileMapY, 9, 0);
                    //value = (ushort)BitHelpers.SetBits(value, VerticalFlip ? 1 : 0, 1, numBits);
                    value = (ushort)BitHelpers.SetBits(value, HorizontalFlip ? 1 : 0, 1, 9);

                    value = s.Serialize <ushort>(value, name: nameof(value));

                    TileMapY       = (ushort)BitHelpers.ExtractBits(value, 9, 0);
                    TileMapX       = 0;
                    IsFirstBlock   = BitHelpers.ExtractBits(value, 1, 9) == 1;
                    HorizontalFlip = BitHelpers.ExtractBits(value, 1, 10) == 1;
                    VerticalFlip   = BitHelpers.ExtractBits(value, 1, 11) == 1;

                    s.Log($"{nameof(TileMapY)}: {TileMapY}");
                    s.Log($"{nameof(HorizontalFlip)}: {HorizontalFlip}");
                    s.Log($"{nameof(IsFirstBlock)}: {IsFirstBlock}");
                }
                else
                {
                    int numBits = Is8Bpp ? 14 : 11;

                    if (s.GameSettings.EngineVersion <= EngineVersion.GBA_BatmanVengeance)
                    {
                        numBits = 10;
                    }
                    else if (s.GameSettings.EngineVersion == EngineVersion.GBA_SplinterCell_NGage)
                    {
                        numBits = Is8Bpp ? 14 : 12;
                    }
                    else if (s.GameSettings.EngineVersion >= EngineVersion.GBA_SplinterCell)
                    {
                        numBits = Is8Bpp ? 14 : 12;
                    }

                    ushort value = 0;

                    value = (ushort)BitHelpers.SetBits(value, TileMapY, numBits, 0);
                    value = (ushort)BitHelpers.SetBits(value, HorizontalFlip ? 1 : 0, 1, numBits);
                    value = (ushort)BitHelpers.SetBits(value, PaletteIndex, 4, 12);

                    value = s.Serialize <ushort>(value, name: nameof(value));

                    TileMapY = (ushort)BitHelpers.ExtractBits(value, numBits, 0);
                    if (s.GameSettings.EngineVersion == EngineVersion.GBA_SplinterCell_NGage && Is8Bpp)
                    {
                        TileMapY = (ushort)BitHelpers.ExtractBits(value, numBits - 1, 0);
                    }
                    TileMapX       = 0;
                    HorizontalFlip = BitHelpers.ExtractBits(value, 1, numBits) == 1;
                    if (s.GameSettings.EngineVersion == EngineVersion.GBA_BatmanVengeance)
                    {
                        VerticalFlip = BitHelpers.ExtractBits(value, 1, numBits + 1) == 1;
                    }
                    if (!Is8Bpp)
                    {
                        if (s.GameSettings.EngineVersion >= EngineVersion.GBA_SplinterCell)
                        {
                            PaletteIndex = (byte)BitHelpers.ExtractBits(value, 3, 13);
                        }
                        else
                        {
                            PaletteIndex = (byte)BitHelpers.ExtractBits(value, 4, 12);
                        }

                        if (s.GameSettings.EngineVersion == EngineVersion.GBA_SplinterCell)
                        {
                            PaletteIndex += 8;
                        }
                    }
                    else if (s.GameSettings.EngineVersion != EngineVersion.GBA_BatmanVengeance)
                    {
                        VerticalFlip = BitHelpers.ExtractBits(value, 1, numBits + 1) == 1;
                    }

                    s.Log($"{nameof(TileMapY)}: {TileMapY}");
                    s.Log($"{nameof(HorizontalFlip)}: {HorizontalFlip}");
                    s.Log($"{nameof(PaletteIndex)}: {PaletteIndex}");
                }
            }
            else if (s.GameSettings.EngineVersion == EngineVersion.R1_PS1 || s.GameSettings.EngineVersion == EngineVersion.R2_PS1)
            {
                s.SerializeBitValues <ushort>(bitFunc =>
                {
                    TileMapX      = (ushort)bitFunc(TileMapX, 4, name: nameof(TileMapX));
                    TileMapY      = (ushort)bitFunc(TileMapY, 6, name: nameof(TileMapY));
                    CollisionType = (byte)bitFunc(CollisionType, 6, name: nameof(CollisionType));
                });
            }
            else if (s.GameSettings.EngineVersion == EngineVersion.R1_PS1_JP)
            {
                s.SerializeBitValues <ushort>(bitFunc =>
                {
                    TileMapX      = (ushort)bitFunc(TileMapX, 9, name: nameof(TileMapX));
                    CollisionType = (byte)bitFunc(CollisionType, 7, name: nameof(CollisionType));
                });
            }
            else if (s.GameSettings.MajorEngineVersion == MajorEngineVersion.GBARRR)
            {
                if (GBARRRType == GBARRR_MapBlock.MapType.Collision)
                {
                    CollisionType = s.Serialize <byte>(CollisionType, name: nameof(CollisionType));
                }
                else if (GBARRRType == GBARRR_MapBlock.MapType.Tiles)
                {
                    TileMapY = s.Serialize <ushort>(TileMapY, name: nameof(TileMapY));
                }
                else if (GBARRRType == GBARRR_MapBlock.MapType.Foreground)
                {
                    s.SerializeBitValues <ushort>(bitFunc =>
                    {
                        TileMapY       = (ushort)bitFunc(TileMapY, 10, name: nameof(TileMapY));
                        HorizontalFlip = bitFunc(HorizontalFlip ? 1 : 0, 1, name: nameof(HorizontalFlip)) == 1;
                        VerticalFlip   = bitFunc(VerticalFlip ? 1 : 0, 1, name: nameof(VerticalFlip)) == 1;
                        PaletteIndex   = (byte)bitFunc(PaletteIndex, 4, name: nameof(PaletteIndex));
                        //Unk = (byte)bitFunc(Unk, 4, name: nameof(Unk));
                    });
                }
                else if (GBARRRType == GBARRR_MapBlock.MapType.Menu)
                {
                    s.SerializeBitValues <ushort>(bitFunc =>
                    {
                        TileMapY       = (ushort)bitFunc(TileMapY, 8, name: nameof(TileMapY));
                        GBARRR_MenuUnk = (byte)bitFunc(GBARRR_MenuUnk, 2, name: nameof(GBARRR_MenuUnk));
                        HorizontalFlip = bitFunc(HorizontalFlip ? 1 : 0, 1, name: nameof(HorizontalFlip)) == 1;
                        VerticalFlip   = bitFunc(VerticalFlip ? 1 : 0, 1, name: nameof(VerticalFlip)) == 1;
                        PaletteIndex   = (byte)bitFunc(PaletteIndex, 4, name: nameof(PaletteIndex));
                        //Unk = (byte)bitFunc(Unk, 4, name: nameof(Unk));
                    });
                }
                else if (GBARRRType == GBARRR_MapBlock.MapType.Mode7Tiles)
                {
                    TileMapY = s.Serialize <byte>((byte)TileMapY, name: nameof(TileMapY));
                }
            }
        }
Beispiel #23
0
 public override void SerializeImpl(SerializerObject s)
 {
     TrackLength      = s.Serialize <ushort>(TrackLength, name: nameof(TrackLength));
     TrackBlocks      = s.SerializeObjectArray <TrackBlock>(TrackBlocks, TrackLength, name: nameof(TrackBlocks));
     Structs12Count   = s.Serialize <byte>(Structs12Count, name: nameof(Structs12Count));
     BM_Byte0         = s.Serialize <byte>(BM_Byte0, name: nameof(BM_Byte0));
     BM_Bool1         = s.Serialize <bool>(BM_Bool1, name: nameof(BM_Bool1));
     BM_Byte2         = s.Serialize <byte>(BM_Byte2, name: nameof(BM_Byte2));
     BM_Byte3         = s.Serialize <byte>(BM_Byte3, name: nameof(BM_Byte3));
     MapSpriteMapping = s.SerializeObjectArray <TrackMapping>(MapSpriteMapping, TrackLength - 1, name: nameof(MapSpriteMapping));
     if (s.GameSettings.GameModeSelection == GameModeSelection.RaymanKartMobile_320x240)
     {
         RoadTextureID_0 = s.Serialize <byte>(RoadTextureID_0, name: nameof(RoadTextureID_0));
         RoadTextureID_1 = s.Serialize <byte>(RoadTextureID_1, name: nameof(RoadTextureID_1));
     }
     aW             = s.Serialize <byte>(aW, name: nameof(aW));
     aUCount        = s.Serialize <byte>(aUCount, name: nameof(aUCount));
     bB             = s.Serialize <byte>(bB, name: nameof(bB));
     Color_bC       = s.SerializeObject <RGB888Color>(Color_bC, name: nameof(Color_bC));
     Color_bD_Road1 = s.SerializeObject <RGB888Color>(Color_bD_Road1, name: nameof(Color_bD_Road1));
     Color_bA       = s.SerializeObject <RGB888Color>(Color_bA, name: nameof(Color_bA));
     Color_bE_Road2 = s.SerializeObject <RGB888Color>(Color_bE_Road2, name: nameof(Color_bE_Road2));
     Color_bF       = s.SerializeObject <RGB888Color>(Color_bF, name: nameof(Color_bF));
     bG             = s.Serialize <short>(bG, name: nameof(bG));
     aU_2           = s.Serialize <short>(aU_2, name: nameof(aU_2));
     N  = s.Serialize <byte>(N, name: nameof(N));
     gF = s.Serialize <byte>(gF, name: nameof(gF));
     bp = s.Serialize <bool>(bp, name: nameof(bp));
     bJ = s.Serialize <short>(bJ, name: nameof(bJ));
     bK = s.Serialize <short>(bK, name: nameof(bK));
     Color_afterbK_0 = s.SerializeObject <RGB888Color>(Color_afterbK_0, name: nameof(Color_afterbK_0));
     Color_afterbK_1 = s.SerializeObject <RGB888Color>(Color_afterbK_1, name: nameof(Color_afterbK_1));
     bL = s.Serialize <byte>(bL, name: nameof(bL));
     Color_bH_TunnelDark  = s.SerializeObject <RGB888Color>(Color_bH_TunnelDark, name: nameof(Color_bH_TunnelDark));
     Color_bI_TunnelLight = s.SerializeObject <RGB888Color>(Color_bI_TunnelLight, name: nameof(Color_bI_TunnelLight));
     byte_afterBI         = s.Serialize <byte>(byte_afterBI, name: nameof(byte_afterBI));
     if (BitHelpers.ExtractBits(aW, 1, 2) == 1)
     {
         Color_dj_BridgeDark  = s.SerializeObject <RGB888Color>(Color_dj_BridgeDark, name: nameof(Color_dj_BridgeDark));
         Color_dk_BridgeLight = s.SerializeObject <RGB888Color>(Color_dk_BridgeLight, name: nameof(Color_dk_BridgeLight));
         dl = s.Serialize <byte>(dl, name: nameof(dl));
         dm = s.Serialize <byte>(dm, name: nameof(dm));
     }
     if (s.GameSettings.GameModeSelection != GameModeSelection.RaymanKartMobile_320x240)
     {
         Color_dq = s.SerializeObject <RGB888Color>(Color_dq, name: nameof(Color_dq));
         Color_dr = s.SerializeObject <RGB888Color>(Color_dr, name: nameof(Color_dr));
         Color_ds = s.SerializeObject <RGB888Color>(Color_ds, name: nameof(Color_ds));
         Color_dt = s.SerializeObject <RGB888Color>(Color_dt, name: nameof(Color_dt));
         Color_du = s.SerializeObject <RGB888Color>(Color_du, name: nameof(Color_du));
         dx       = s.Serialize <short>(dx, name: nameof(dx));
         dw       = s.Serialize <short>(dw, name: nameof(dw));
         dv       = s.Serialize <short>(dv, name: nameof(dv));
     }
     Structs1Count              = s.Serialize <ushort>(Structs1Count, name: nameof(Structs1Count));
     Structs1                   = s.SerializeObjectArray <Struct1>(Structs1, Structs1Count, name: nameof(Structs1));
     Structs2Count              = s.Serialize <byte>(Structs2Count, name: nameof(Structs2Count));
     Structs2                   = s.SerializeObjectArray <Struct2>(Structs2, Structs2Count, name: nameof(Structs2));
     BackgroundLayers           = s.SerializeObjectArray <BackgroundLayer>(BackgroundLayers, aUCount, name: nameof(BackgroundLayers));
     bs_Struct0_BackgroundIndex = s.SerializeArraySize <byte[], byte>(bs_Struct0_BackgroundIndex, name: nameof(bs_Struct0_BackgroundIndex));
     for (int i = 0; i < bs_Struct0_BackgroundIndex.Length; i++)
     {
         bs_Struct0_BackgroundIndex[i] = s.SerializeArray <byte>(bs_Struct0_BackgroundIndex[i], TrackLength, name: $"{nameof(bs_Struct0_BackgroundIndex)}[{i}]");
     }
     Structs4Count     = s.Serialize <byte>(Structs4Count, name: nameof(Structs4Count));
     Structs4          = s.SerializeObjectArray <Struct4>(Structs4, Structs4Count, name: nameof(Structs4));
     Structs5Count     = s.Serialize <byte>(Structs5Count, name: nameof(Structs5Count));
     Structs5          = s.SerializeObjectArray <Struct5>(Structs5, Structs5Count, name: nameof(Structs5));
     Structs6Count     = s.Serialize <ushort>(Structs6Count, name: nameof(Structs6Count));
     Structs6          = s.SerializeObjectArray <Struct6>(Structs6, Structs6Count, name: nameof(Structs6));
     Structs7Count     = s.Serialize <ushort>(Structs7Count, name: nameof(Structs7Count));
     Structs7          = s.SerializeObjectArray <Struct7>(Structs7, Structs7Count, name: nameof(Structs7));
     TrackObjectsCount = s.Serialize <ushort>(TrackObjectsCount, name: nameof(TrackObjectsCount));
     TrackObjects      = s.SerializeObjectArray <TrackObject>(TrackObjects, TrackObjectsCount, name: nameof(TrackObjects));
     cF = s.Serialize <ushort>(cF, name: nameof(cF));
     TrackObjectInstances = s.SerializeObjectArray <TrackObjectInstance>(TrackObjectInstances, cF, name: nameof(TrackObjectInstances));
     if (cF > 0)
     {
         TrackObjectCollections = s.SerializeObjectArray <TrackObjectCollection>(TrackObjectCollections, TrackLength, name: nameof(TrackObjectCollections));
     }
     Structs11Count = s.Serialize <byte>(Structs11Count, name: nameof(Structs11Count));
     Types          = s.SerializeObjectArray <Type>(Types, Structs11Count, name: nameof(Types));
     Structs12      = s.SerializeObjectArray <Struct12>(Structs12, Structs12Count, name: nameof(Structs12));
 }
        public override void SerializeImpl(SerializerObject s)
        {
            Attr0 = s.Serialize <ushort>(Attr0, name: nameof(Attr0));
            if (IsEndAttribute)
            {
                return;
            }

            // Parse
            Attr1 = s.Serialize <ushort>(Attr1, name: nameof(Attr1));
            Attr2 = s.Serialize <ushort>(Attr2, name: nameof(Attr2));

            // Attr0
            YPosition = (short)BitHelpers.ExtractBits(Attr0, 8, 0);
            if (YPosition >= 128)
            {
                YPosition -= 256;
            }


            TransformMode = (AffineObjectMode)BitHelpers.ExtractBits(Attr0, 2, 8);
            RenderMode    = (GfxMode)BitHelpers.ExtractBits(Attr0, 2, 10);
            Mosaic        = BitHelpers.ExtractBits(Attr0, 1, 12) == 1;
            Color         = (GBA_ColorMode)BitHelpers.ExtractBits(Attr0, 1, 13);
            SpriteShape   = (Shape)BitHelpers.ExtractBits(Attr0, 2, 14);

            // Attr1
            XPosition = (short)BitHelpers.ExtractBits(Attr1, 9, 0);
            bool bit9 = false, bit10 = false, bit11 = false;

            //if (XPosition >= 256) XPosition -= 512;
            if (XPosition >= 128)
            {
                XPosition -= 256;
            }
            if (TransformMode == AffineObjectMode.Affine || TransformMode == AffineObjectMode.AffineDouble)
            {
                AffineMatrixIndex = BitHelpers.ExtractBits(Attr1, 5, 9);
            }
            else
            {
                bit9  = BitHelpers.ExtractBits(Attr1, 1, 9) == 1;
                bit10 = BitHelpers.ExtractBits(Attr1, 1, 10) == 1;
                bit11 = BitHelpers.ExtractBits(Attr1, 1, 11) == 1;
                IsFlippedHorizontally = BitHelpers.ExtractBits(Attr1, 1, 12) == 1;
                IsFlippedVertically   = BitHelpers.ExtractBits(Attr1, 1, 13) == 1;
            }
            SpriteSize = BitHelpers.ExtractBits(Attr1, 2, 14);

            ImageIndex   = (short)BitHelpers.ExtractBits(Attr2, 10, 0);
            Priority     = BitHelpers.ExtractBits(Attr2, 2, 10);
            PaletteIndex = BitHelpers.ExtractBits(Attr2, 4, 12);

            s.Log($"{nameof(XPosition)}: {XPosition}");
            s.Log($"{nameof(YPosition)}: {YPosition}");
            s.Log($"{nameof(TransformMode)}: {TransformMode}");
            s.Log($"{nameof(RenderMode)}: {RenderMode}");
            s.Log($"{nameof(Color)}: {Color}");
            s.Log($"{nameof(Mosaic)}: {Mosaic}");
            s.Log($"{nameof(SpriteShape)}: {SpriteShape}");
            s.Log($"{nameof(SpriteSize)}: {SpriteSize}");

            s.Log($"{nameof(ImageIndex)}: {ImageIndex}");
            s.Log($"{nameof(Priority)}: {Priority}");
            s.Log($"{nameof(PaletteIndex)}: {PaletteIndex}");
            if (TransformMode == AffineObjectMode.Affine || TransformMode == AffineObjectMode.AffineDouble)
            {
                s.Log($"{nameof(AffineMatrixIndex)}: {AffineMatrixIndex}");
            }
            else
            {
                s.Log($"{nameof(IsFlippedHorizontally)}: {IsFlippedHorizontally}");
                s.Log($"{nameof(IsFlippedVertically)}: {IsFlippedVertically}");
            }
            if (bit9)
            {
                s.Log("BIT9");
            }
            if (bit10)
            {
                s.Log("BIT10");
            }
            if (bit11)
            {
                s.Log("BIT11");
            }

            // Calculate size
            XSize = 1;
            YSize = 1;
            switch (SpriteShape)
            {
            case Shape.Square:
                XSize = 1 << SpriteSize;
                YSize = XSize;
                break;

            case Shape.Wide:
                switch (SpriteSize)
                {
                case 0: XSize = 2; YSize = 1; break;

                case 1: XSize = 4; YSize = 1; break;

                case 2: XSize = 4; YSize = 2; break;

                case 3: XSize = 8; YSize = 4; break;
                }
                break;

            case Shape.Tall:
                switch (SpriteSize)
                {
                case 0: XSize = 1; YSize = 2; break;

                case 1: XSize = 1; YSize = 4; break;

                case 2: XSize = 2; YSize = 4; break;

                case 3: XSize = 4; YSize = 8; break;
                }
                break;
            }
        }
Beispiel #25
0
        public byte[] ReadBlock(Reader reader, int decompressedBlockSize)
        {
            reader.Align(4);
            bool log = false;
            //bool log = true;
            string logOffset      = $"{reader.BaseStream.Position:X8}";
            ushort head           = reader.ReadUInt16();
            byte   unk0           = reader.ReadByte();
            byte   unk1           = reader.ReadByte();
            int    compressedSize = reader.ReadInt32();

            byte cmd = (byte)BitHelpers.ExtractBits(head, 7, 0);
            int  byte2UpperNibble = BitHelpers.ExtractBits(head, 4, 12);
            int  byte2LowerNibble = BitHelpers.ExtractBits(head, 4, 8);
            uint local_2c         = 0;

            if (byte2UpperNibble > 4)
            {
                throw new NotImplementedException();
            }
            if (byte2UpperNibble == 5)
            {
                local_2c        = reader.ReadUInt32();
                compressedSize -= 4;
            }
            byte[] compressed   = reader.ReadBytes(compressedSize);
            int    inPos        = 0;
            int    outPos       = 0;
            int    toDecompress = decompressedBlockSize;

            byte[] decompressed = new byte[decompressedBlockSize];

            if (log)
            {
                Util.ByteArrayToFile(LevelEditorData.MainContext.BasePath + $"blocks/{logOffset}_{cmd}-{byte2LowerNibble}-{byte2UpperNibble}_compressed.bin", compressed);
            }
            try {
                switch (cmd)
                {
                case 0:
                    // Uncompressed
                    DecompressBlock_Copy(compressed, decompressed, ref inPos, ref outPos, ref toDecompress);
                    break;

                case 1:
                    // RLE
                    DecompressBlock_RLE(compressed, decompressed, ref inPos, ref outPos, ref toDecompress);
                    break;

                case 2:
                    // Shorts
                    DecompressBlock_Shorts(compressed, decompressed, ref inPos, ref outPos, ref toDecompress);
                    break;

                case 3:
                    // Bits
                    DecompressBlock_Bits(compressed, decompressed, ref inPos, ref outPos, ref toDecompress);
                    break;

                case 4:
                    // Window
                    DecompressBlock_Window(compressed, decompressed, ref inPos, ref outPos, ref toDecompress);
                    break;

                case 5:
                    // Block
                    DecompressBlock_Buffer(compressed, decompressed, ref inPos, ref outPos, ref toDecompress);
                    break;
                }
                if (log)
                {
                    Util.ByteArrayToFile(LevelEditorData.MainContext.BasePath + $"blocks/{logOffset}_{cmd}-{byte2LowerNibble}-{byte2UpperNibble}_after_1.bin", decompressed);
                }
                switch (byte2LowerNibble)
                {
                case 1:
                    DecodeBlock_Sum_Byte(decompressed, 0, decompressed.Length);
                    break;

                case 2:
                    DecodeBlock_Sum_Short(decompressed, 0, decompressed.Length);
                    break;

                case 3:
                    DecodeBlock_Copy(decompressed, 0, decompressed.Length);
                    break;

                case 4:
                    DecodeBlock_Buffer(decompressed, 0, decompressed.Length);
                    break;
                }
                if (log)
                {
                    Util.ByteArrayToFile(LevelEditorData.MainContext.BasePath + $"blocks/{logOffset}_{cmd}-{byte2LowerNibble}-{byte2UpperNibble}_after_2.bin", decompressed);
                }
                switch (byte2UpperNibble)
                {
                case 1:
                    DecodeBlock_Sum_Byte(decompressed, 0, decompressed.Length);
                    break;

                case 2:
                    DecodeBlock_Sum_Short(decompressed, 0, decompressed.Length);
                    break;

                case 3:
                    DecodeBlock_Copy(decompressed, 0, decompressed.Length);
                    break;

                case 4:
                    DecodeBlock_Buffer(decompressed, 0, decompressed.Length);
                    break;

                case 5:
                case 6:
                case 7:
                    throw new NotImplementedException();
                    //break;
                }
                if (log)
                {
                    Util.ByteArrayToFile(LevelEditorData.MainContext.BasePath + $"blocks/{logOffset}_{cmd}-{byte2LowerNibble}-{byte2UpperNibble}_after_3.bin", decompressed);
                }
            } catch (Exception ex) {
                if (log)
                {
                    Util.ByteArrayToFile(LevelEditorData.MainContext.BasePath + $"blocks/{logOffset}_{cmd}-{byte2LowerNibble}-{byte2UpperNibble}_crashedBlock.bin", decompressed);
                }
                throw new Exception($"{cmd}:{byte2LowerNibble}:{byte2UpperNibble} - {ex.Message}", ex);
            }

            return(decompressed);
        }
        public override void SerializeImpl(SerializerObject s)
        {
            var manager = (R1_PS1BaseManager)s.GameSettings.GetGameManager;

            if (manager.TypeZDCOffset != null)
            {
                TypeZDC = s.DoAt(new Pointer(manager.TypeZDCOffset.Value, Offset.file), () => s.SerializeObjectArray <R1_ZDCEntry>(TypeZDC, manager.TypeZDCCount, name: nameof(TypeZDC)));
            }

            if (manager.ZDCDataOffset != null)
            {
                ZDCData = s.DoAt(new Pointer(manager.ZDCDataOffset.Value, Offset.file), () => s.SerializeObjectArray <R1_ZDCData>(ZDCData, manager.ZDCDataCount, name: nameof(ZDCData)));
            }

            if (manager.EventFlagsOffset != null)
            {
                if (s.GameSettings.EngineVersion == EngineVersion.R1_Saturn)
                {
                    EventFlags = s.DoAt(new Pointer(manager.EventFlagsOffset.Value, Offset.file),
                                        () => s.SerializeArray <int>(EventFlags?.Select(x => BitHelpers.ReverseBits((int)x)).ToArray(), manager.EventFlagsCount, name: nameof(EventFlags))).Select(BitHelpers.ReverseBits).Select(x => (R1_EventFlags)x).ToArray();
                }
                else
                {
                    EventFlags = s.DoAt(new Pointer(manager.EventFlagsOffset.Value, Offset.file),
                                        () => s.SerializeArray <R1_EventFlags>(EventFlags, manager.EventFlagsCount, name: nameof(EventFlags)));
                }
            }

            if (manager.WorldInfoOffset != null)
            {
                WorldInfo = s.DoAt(new Pointer(manager.WorldInfoOffset.Value, Offset.file), () => s.SerializeObjectArray <R1_WorldMapInfo>(WorldInfo, 24, name: nameof(WorldInfo)));
            }

            if (manager.LevelBackgroundIndexTableOffset != null)
            {
                if (LevelBackgroundIndexTable == null)
                {
                    LevelBackgroundIndexTable = new byte[6][];
                }

                s.DoAt(new Pointer(manager.LevelBackgroundIndexTableOffset.Value, Offset.file), () =>
                {
                    for (int i = 0; i < LevelBackgroundIndexTable.Length; i++)
                    {
                        LevelBackgroundIndexTable[i] = s.SerializeArray <byte>(LevelBackgroundIndexTable[i], 30, name: $"{nameof(LevelBackgroundIndexTable)}[{i}]");
                    }
                });
            }

            var fileTableInfos = manager.FileTableInfos;

            if (FileTable == null)
            {
                FileTable = new R1_PS1_FileTableEntry[fileTableInfos.Sum(x => x.Count)];
            }

            var index = 0;

            foreach (var info in fileTableInfos)
            {
                s.DoAt(new Pointer(info.Offset, Offset.file), () =>
                {
                    for (int i = 0; i < info.Count; i++)
                    {
                        FileTable[index] = s.SerializeObject <R1_PS1_FileTableEntry>(FileTable[index], name: $"{nameof(FileTable)}_{info.FileType}[{i}]");
                        index++;
                    }
                });
            }

            if (s.GameSettings.EngineVersion == EngineVersion.R1_Saturn)
            {
                var saturnManager = (R1_Saturn_Manager)manager;

                Saturn_Palettes = s.DoAt(new Pointer(saturnManager.GetPalOffset, Offset.file), () => s.SerializeObjectArray <RGBA5551Color>(Saturn_Palettes, 25 * 256 * 2, name: nameof(Saturn_Palettes)));

                if (Saturn_FNDFileTable == null)
                {
                    Saturn_FNDFileTable = new string[6][];
                }

                s.DoAt(new Pointer(saturnManager.GetFndFileTableOffset, Offset.file), () =>
                {
                    for (int i = 0; i < Saturn_FNDFileTable.Length; i++)
                    {
                        Saturn_FNDFileTable[i] = s.SerializeStringArray(Saturn_FNDFileTable[i], 10, 12, name: $"{nameof(Saturn_FNDFileTable)}[{i}]");
                    }
                });

                if (Saturn_FNDSPFileTable == null)
                {
                    Saturn_FNDSPFileTable = new string[6][];
                }

                s.DoAt(new Pointer(saturnManager.GetFndSPFileTableOffset, Offset.file), () =>
                {
                    for (int i = 0; i < Saturn_FNDSPFileTable.Length; i++)
                    {
                        Saturn_FNDSPFileTable[i] = s.SerializeStringArray(Saturn_FNDSPFileTable[i], 5, 12, name: $"{nameof(Saturn_FNDSPFileTable)}[{i}]");
                    }
                });

                if (Saturn_FNDIndexTable == null)
                {
                    Saturn_FNDIndexTable = new byte[7][];
                }

                s.DoAt(new Pointer(saturnManager.GetFndIndexTableOffset, Offset.file), () =>
                {
                    for (int i = 0; i < Saturn_FNDIndexTable.Length; i++)
                    {
                        Saturn_FNDIndexTable[i] = s.SerializeArray <byte>(Saturn_FNDIndexTable[i], 25, name: $"{nameof(Saturn_FNDIndexTable)}[{i}]");
                    }
                });
            }
        }
Beispiel #27
0
        /// <summary>
        /// Gets the sprite texture for an event
        /// </summary>
        /// <param name="context">The context</param>
        /// <param name="imgBuffer">The image buffer, if available</param>
        /// <param name="s">The image descriptor to use</param>
        /// <returns>The texture</returns>
        public override Texture2D GetSpriteTexture(Context context, byte[] imgBuffer, R1_ImageDescriptor img)
        {
            if (img.ImageType != 2 && img.ImageType != 3)
            {
                return(null);
            }
            if (img.Unknown2 == 0)
            {
                return(null);
            }
            ImageBuffer buf = context.GetStoredObject <ImageBuffer>("vram");

            // Get the image properties
            var width  = img.Width;
            var height = img.Height;
            var offset = img.ImageBufferOffset;

            Texture2D tex = TextureHelpers.CreateTexture2D(width, height);

            var palette       = FileFactory.Read <R1_PS1_Executable>(ExeFilePath, context).Saturn_Palettes;
            var paletteOffset = img.PaletteInfo;

            var isBigRay = img.Offset.file.filePath == GetBigRayFilePath();
            var isFont   = context.GetStoredObject <R1_PS1_FontData[]>("Font")?.SelectMany(x => x.ImageDescriptors).Contains(img) == true;

            //paletteOffset = (ushort)(256 * (img.Unknown2 >> 4));
            if (img.ImageType == 3)
            {
                //paletteOffset = 20 * 256;
                paletteOffset = isBigRay ? (ushort)(21 * 256) : isFont ? (ushort)(19 * 256) : (ushort)((GetPaletteIndex(context) * 256));
            }
            else
            {
                paletteOffset = isBigRay ? (ushort)(21 * 256) : isFont ? (ushort)(19 * 256) : (ushort)((GetPaletteIndex(context) * 256) + ((img.PaletteInfo >> 8)) * 16);
                //paletteOffset = (ushort)((GetPaletteIndex(context) * 256) + ((img.Unknown2 >> 4) - 1) * 16);
                //paletteOffset = (ushort)(19 * 256 + ((img.Unknown2 >> 4) - 1) * 16);
            }

            // Set every pixel
            if (img.ImageType == 3)
            {
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        var paletteIndex = buf.GetPixel8((uint)(offset + width * y + x));

                        // Set the pixel
                        var color = palette[paletteOffset + paletteIndex].GetColor();
                        if (paletteIndex == 0)
                        {
                            color = new Color(color.r, color.g, color.b, 0f);
                        }
                        else
                        {
                            color = new Color(color.r, color.g, color.b, 1f);
                        }
                        tex.SetPixel(x, height - 1 - y, color);
                    }
                }
            }
            else if (img.ImageType == 2)
            {
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        var paletteIndex = buf.GetPixel8((uint)(offset + (width * y + x) / 2));
                        if (x % 2 == 0)
                        {
                            paletteIndex = (byte)BitHelpers.ExtractBits(paletteIndex, 4, 4);
                        }
                        else
                        {
                            paletteIndex = (byte)BitHelpers.ExtractBits(paletteIndex, 4, 0);
                        }

                        // Set the pixel
                        var color = palette[paletteOffset + paletteIndex].GetColor();
                        if (paletteIndex == 0)
                        {
                            color = new Color(color.r, color.g, color.b, 0f);
                        }
                        else
                        {
                            color = new Color(color.r, color.g, color.b, 1f);
                        }
                        tex.SetPixel(x, height - 1 - y, color);
                    }
                }
            }


            //tex.SetPixels(Enumerable.Repeat(Color.blue, tex.width * tex.height).ToArray());
            tex.Apply();

            return(tex);
        }
Beispiel #28
0
        public override void SerializeImpl(SerializerObject s)
        {
            Attr0 = s.Serialize <ushort>(Attr0, name: nameof(Attr0));

            // Parse
            if ((Attr0 & BOX_FLAG) == 0x800)
            {
                ChannelType = Type.Unknown8;
            }
            if ((Attr0 & BOX_FLAG) == 0xC00)
            {
                ChannelType = Type.UnknownC;
            }
            if ((Attr0 & BOX_FLAG) == 0x1000)
            {
                ChannelType = Type.AttackBox;
            }
            if ((Attr0 & BOX_FLAG) == 0x1400)
            {
                ChannelType = Type.VulnerabilityBox;
            }

            if (ChannelType == Type.Sprite)
            {
                Attr1 = s.Serialize <ushort>(Attr1, name: nameof(Attr1));
                Attr2 = s.Serialize <ushort>(Attr2, name: nameof(Attr2));
                if (Attr0 == 0 && Attr1 == 0 && Attr2 == 0)
                {
                    ChannelType = Type.Null;
                    return;
                }
                // Attr0
                YPosition = (short)BitHelpers.ExtractBits(Attr0, 8, 0);

                /*if (s.GameSettings.Game == Game.GBA_Rayman3) {
                 *  if (YPosition >= 96) YPosition -= 256; // Hack. Since usually more of the top sprite is visible, this is more likely.
                 * } else {
                 *  if (YPosition >= 128) YPosition -= 256;
                 * }*/
                if (YPosition >= 128)
                {
                    YPosition -= 256;
                }
                TransformMode = (AffineObjectMode)BitHelpers.ExtractBits(Attr0, 2, 8);
                RenderMode    = (GfxMode)BitHelpers.ExtractBits(Attr0, 2, 10);
                //Controller.print(BitHelpers.ExtractBits(Attr0, 2, 10));
                Color       = (GBA_ColorMode)BitHelpers.ExtractBits(Attr0, 1, 13);
                SpriteShape = (Shape)BitHelpers.ExtractBits(Attr0, 2, 14);

                // Attr1
                XPosition = (short)BitHelpers.ExtractBits(Attr1, 9, 0);
                bool bit9 = false, bit10 = false, bit11 = false;
                if (XPosition >= 256)
                {
                    XPosition -= 512;
                }
                if (TransformMode == AffineObjectMode.Affine || TransformMode == AffineObjectMode.AffineDouble)
                {
                    AffineMatrixIndex = BitHelpers.ExtractBits(Attr1, 5, 9);
                }
                else
                {
                    bit9  = BitHelpers.ExtractBits(Attr1, 1, 9) == 1;
                    bit10 = BitHelpers.ExtractBits(Attr1, 1, 10) == 1;
                    bit11 = BitHelpers.ExtractBits(Attr1, 1, 11) == 1;
                    IsFlippedHorizontally = BitHelpers.ExtractBits(Attr1, 1, 12) == 1;
                    IsFlippedVertically   = BitHelpers.ExtractBits(Attr1, 1, 13) == 1;
                }
                SpriteSize = BitHelpers.ExtractBits(Attr1, 2, 14);

                if (s.GameSettings.EngineVersion == EngineVersion.GBA_Sabrina)
                {
                    ImageIndex   = (ushort)BitHelpers.ExtractBits(Attr2, 12, 0);
                    PaletteIndex = BitHelpers.ExtractBits(Attr2, 3, 12); // another flag at byte 0xF?
                }
                else if (s.GameSettings.EngineVersion == EngineVersion.GBA_BatmanRiseOfSinTzu)
                {
                    ImageIndex   = (ushort)BitHelpers.ExtractBits(Attr2, 15, 0);
                    PaletteIndex = BitHelpers.ExtractBits(Attr2, 1, 15); // another flag at byte 0xF?
                }
                else if (s.GameSettings.EngineVersion == EngineVersion.GBA_StarWarsTrilogy)
                {
                    ImageIndex   = (ushort)BitHelpers.ExtractBits(Attr2, 14, 0);
                    PaletteIndex = BitHelpers.ExtractBits(Attr2, 1, 14); // another flag at byte 0xF?
                }
                else if (s.GameSettings.EngineVersion >= EngineVersion.GBA_SplinterCell)
                {
                    ImageIndex   = (ushort)BitHelpers.ExtractBits(Attr2, 14, 0);
                    PaletteIndex = BitHelpers.ExtractBits(Attr2, 2, 14); // another flag at byte 0xF?
                }
                else if (s.GameSettings.GBA_IsMilan)
                {
                    ImageIndex = Attr2;
                }
                else
                {
                    ImageIndex   = (ushort)BitHelpers.ExtractBits(Attr2, 11, 0);
                    Priority     = BitHelpers.ExtractBits(Attr2, 1, 11);
                    PaletteIndex = BitHelpers.ExtractBits(Attr2, 3, 12); // another flag at byte 0xF?
                }
                bool paletteFlag = BitHelpers.ExtractBits(Attr2, 1, 15) == 1;

                s.Log($"{nameof(XPosition)}: {XPosition}");
                s.Log($"{nameof(YPosition)}: {YPosition}");
                s.Log($"{nameof(TransformMode)}: {TransformMode}");
                s.Log($"{nameof(RenderMode)}: {RenderMode}");
                s.Log($"{nameof(Color)}: {Color}");
                s.Log($"{nameof(SpriteShape)}: {SpriteShape}");
                s.Log($"{nameof(SpriteSize)}: {SpriteSize}");

                s.Log($"{nameof(ImageIndex)}: {ImageIndex}");
                s.Log($"{nameof(Priority)}: {Priority}");
                s.Log($"{nameof(PaletteIndex)}: {PaletteIndex}");
                s.Log($"{nameof(paletteFlag)}: {paletteFlag}");
                if (TransformMode == AffineObjectMode.Affine || TransformMode == AffineObjectMode.AffineDouble)
                {
                    s.Log($"{nameof(AffineMatrixIndex)}: {AffineMatrixIndex}");
                }
                else
                {
                    s.Log($"{nameof(IsFlippedHorizontally)}: {IsFlippedHorizontally}");
                    s.Log($"{nameof(IsFlippedVertically)}: {IsFlippedVertically}");
                }
                if (bit9)
                {
                    s.Log("BIT9");
                }
                if (bit10)
                {
                    s.Log("BIT10");
                }
                if (bit11)
                {
                    s.Log("BIT11");
                }

                // Calculate size
                XSize = 1;
                YSize = 1;
                switch (SpriteShape)
                {
                case Shape.Square:
                    XSize = 1 << SpriteSize;
                    YSize = XSize;
                    break;

                case Shape.Wide:
                    switch (SpriteSize)
                    {
                    case 0: XSize = 2; YSize = 1; break;

                    case 1: XSize = 4; YSize = 1; break;

                    case 2: XSize = 4; YSize = 2; break;

                    case 3: XSize = 8; YSize = 4; break;
                    }
                    break;

                case Shape.Tall:
                    switch (SpriteSize)
                    {
                    case 0: XSize = 1; YSize = 2; break;

                    case 1: XSize = 1; YSize = 4; break;

                    case 2: XSize = 2; YSize = 4; break;

                    case 3: XSize = 4; YSize = 8; break;
                    }
                    break;
                }
            }
            else if (ChannelType == Type.Unknown8)
            {
                Unknown8 = s.Serialize <int>(Unknown8, name: nameof(Unknown8));
            }
            else if (ChannelType == Type.UnknownC)
            {
                UnknownC = s.Serialize <int>(UnknownC, name: nameof(UnknownC));
            }
            else
            {
                s.Log($"{nameof(ChannelType)}: {ChannelType}");
                Box_MinY = s.Serialize <sbyte>(Box_MinY, name: nameof(Box_MinY));
                Box_MaxY = s.Serialize <sbyte>(Box_MaxY, name: nameof(Box_MaxY));
                Box_MinX = s.Serialize <sbyte>(Box_MinX, name: nameof(Box_MinX));
                Box_MaxX = s.Serialize <sbyte>(Box_MaxX, name: nameof(Box_MaxX));
            }
        }
        public Stream EncodeStream(Stream s)
        {
            var memStream = new MemoryStream();

            Reader reader = new Reader(s);

            using (Stream temp = new MemoryStream()) {
                using (Writer writer = new Writer(temp)) {
                    byte[] compr_big_window = new byte[256 * 8];
                    for (int i = 0; i < 256; i++)
                    {
                        for (int j = 0; j < 8; j++)
                        {
                            compr_big_window[i * 8 + j] = (byte)i;
                        }
                    }
                    byte[] compr_window = new byte[8];
                    for (int j = 0; j < 8; j++)
                    {
                        compr_window[j] = 0;
                    }
                    writer.Write((byte)0); // checksum
                    writer.Write((uint)0); // size

                    uint startPos = (uint)reader.BaseStream.Position;
                    writer.BeginCalculateChecksum(new Checksum8Calculator());
                    bool isFinished = false;
                    while (!isFinished)
                    {
                        uint num_bytesToCompress = 0;
                        for (int i = 0; i < 8; i++)
                        {
                            if (reader.BaseStream.Position >= reader.BaseStream.Length)
                            {
                                break;
                            }
                            num_bytesToCompress++;
                            byte b = reader.ReadByte();
                            compr_window[i] = b;
                        }
                        if (num_bytesToCompress > 0)
                        {
                            int maxOccurrencesInBigWindow = -1;
                            int bestBigWindowI            = 0;
                            for (int i = 0; i < 256; i++)
                            {
                                int occurrencesInBigWindow = 0;
                                for (int j = 0; j < num_bytesToCompress; j++)
                                {
                                    if (compr_big_window[i * 8 + j] == compr_window[j])
                                    {
                                        occurrencesInBigWindow++;
                                    }
                                }
                                if (occurrencesInBigWindow > maxOccurrencesInBigWindow)
                                {
                                    maxOccurrencesInBigWindow = occurrencesInBigWindow;
                                    bestBigWindowI            = i;
                                    if (occurrencesInBigWindow == num_bytesToCompress)
                                    {
                                        break;
                                    }
                                }
                            }
                            writer.Write((byte)bestBigWindowI);
                            byte windowUpdateBitArray = 0;
                            for (int i = 0; i < Math.Min(8, num_bytesToCompress); i++)
                            {
                                if (compr_big_window[bestBigWindowI * 8 + i] != compr_window[i])
                                {
                                    windowUpdateBitArray = (byte)BitHelpers.SetBits(windowUpdateBitArray, 1, 1, i);
                                }
                            }
                            writer.Write(windowUpdateBitArray);
                            for (int i = 0; i < 8; i++)
                            {
                                if (windowUpdateBitArray % 2 == 1)
                                {
                                    writer.Write((byte)compr_window[i]);
                                }
                                windowUpdateBitArray /= 2;
                            }
                            if (num_bytesToCompress >= 8)
                            {
                                for (int i = 0; i < 8; i++)
                                {
                                    compr_big_window[bestBigWindowI * 8 + i] = compr_window[i];
                                }
                            }
                            else
                            {
                                writer.Write((byte)num_bytesToCompress);
                                isFinished = true;
                            }
                        }
                        else
                        {
                            isFinished = true;
                        }
                    }
                    byte checksum         = writer.EndCalculateChecksum <byte>();
                    uint decompressedSize = (uint)reader.BaseStream.Position - startPos;
                    writer.BaseStream.Position = 0;
                    writer.Write((byte)checksum);
                    writer.Write((uint)decompressedSize);
                    writer.BaseStream.Position = 0;
                    using (Stream xor = XORStream(writer.BaseStream)) {
                        xor.CopyTo(memStream);
                    }
                }
            }

            memStream.Position = 0;
            return(memStream);
        }
        public override Unity_ObjGraphics GetCommonDesign(GBA_ActorGraphicData graphicData)
        {
            // Create the design
            var des = new Unity_ObjGraphics {
                Sprites    = new List <Sprite>(),
                Animations = new List <Unity_ObjAnimation>(),
            };

            if (graphicData == null)
            {
                return(des);
            }

            var       tileMap     = graphicData.SpriteGroup_BatmanVengeance.TileMap;
            var       pal         = graphicData.SpriteGroup_BatmanVengeance.Palette.Palette;
            const int tileWidth   = 8;
            const int tileSize    = (tileWidth * tileWidth) / 2;
            var       numPalettes = graphicData.SpriteGroup_BatmanVengeance.Palette.Palette.Length / 16;

            // Add sprites for each palette
            for (int palIndex = 0; palIndex < numPalettes; palIndex++)
            {
                for (int i = 0; i < tileMap.TileMapLength; i++)
                {
                    var tex = TextureHelpers.CreateTexture2D(CellSize, CellSize);

                    for (int y = 0; y < tileWidth; y++)
                    {
                        for (int x = 0; x < tileWidth; x++)
                        {
                            int index = (i * tileSize) + ((y * tileWidth + x) / 2);

                            var b = tileMap.TileMap[index];
                            var v = BitHelpers.ExtractBits(b, 4, x % 2 == 0 ? 0 : 4);

                            Color c = pal[palIndex * 16 + v].GetColor();

                            if (v != 0)
                            {
                                c = new Color(c.r, c.g, c.b, 1f);
                            }

                            tex.SetPixel(x, (tileWidth - 1 - y), c);
                        }
                    }

                    tex.Apply();
                    des.Sprites.Add(tex.CreateSprite());
                }
            }

            Unity_ObjAnimationPart[] GetPartsForLayer(GBA_BatmanVengeance_SpriteGroup s, GBA_BatmanVengeance_Animation a, int frame, GBA_BatmanVengeance_AnimationChannel l)
            {
                /*if (l.TransformMode == GBA_AnimationLayer.AffineObjectMode.Hide
                || l.RenderMode == GBA_AnimationLayer.GfxMode.Window
                || l.RenderMode == GBA_AnimationLayer.GfxMode.Regular
                || l.Mosaic) return new Unity_ObjAnimationPart[0];
                || if (l.Color == GBA_AnimationLayer.ColorMode.Color8bpp) {
                ||  Debug.LogWarning("Animation Layer @ " + l.Offset + " has 8bpp color mode, which is currently not supported.");
                ||  return new Unity_ObjAnimationPart[0];
                || }*/
                Unity_ObjAnimationPart[] parts = new Unity_ObjAnimationPart[l.XSize * l.YSize];
                if (l.ImageIndex > graphicData.SpriteGroup_BatmanVengeance.TileMap.TileMapLength)
                {
                    Controller.print("Image index too high: " + graphicData.Offset + " - " + l.Offset);
                }
                if (l.PaletteIndex > graphicData.SpriteGroup_BatmanVengeance.Palette.Palette.Length / 16)
                {
                    Controller.print("Palette index too high: " + graphicData.Offset + " - " + l.Offset + " - " + l.PaletteIndex + " - " + (graphicData.SpriteGroup_BatmanVengeance.Palette.Palette.Length / 16));
                }
                float   rot = 0;    // l.GetRotation(a, s, frame);
                Vector2?scl = null; // l.GetScale(a, s, frame);

                for (int y = 0; y < l.YSize; y++)
                {
                    for (int x = 0; x < l.XSize; x++)
                    {
                        parts[y * l.XSize + x] = new Unity_ObjAnimationPart {
                            ImageIndex            = tileMap.TileMapLength * l.PaletteIndex + (l.ImageIndex + y * l.XSize + x),
                            IsFlippedHorizontally = l.IsFlippedHorizontally,
                            IsFlippedVertically   = l.IsFlippedVertically,
                            XPosition             = (l.XPosition + (l.IsFlippedHorizontally ? (l.XSize - 1 - x) : x) * CellSize),
                            YPosition             = (l.YPosition + (l.IsFlippedVertically ? (l.YSize - 1 - y) : y) * CellSize),
                            Rotation         = rot,
                            Scale            = scl,
                            TransformOriginX = (l.XPosition + l.XSize * CellSize / 2f),
                            TransformOriginY = (l.YPosition + l.YSize * CellSize / 2f)
                        };
                    }
                }
                return(parts);
            }

            // Add first animation for now
            foreach (var a in graphicData.SpriteGroup_BatmanVengeance.Animations)
            {
                var unityAnim = new Unity_ObjAnimation();
                var frames    = new List <Unity_ObjAnimationFrame>();
                for (int i = 0; i < a.FrameCount; i++)
                {
                    frames.Add(new Unity_ObjAnimationFrame(a.Frames[i].Layers /*.OrderByDescending(l => l.Priority)*/.SelectMany(l => GetPartsForLayer(graphicData.SpriteGroup_BatmanVengeance, a, i, l)).Reverse().ToArray()));
                }
                unityAnim.Frames    = frames.ToArray();
                unityAnim.AnimSpeed = 1;
                des.Animations.Add(unityAnim);
            }

            return(des);
        }