Beispiel #1
0
        public void Parse(BinaryReader buffer, AKAOType type, long limit = long.MaxValue)
        {
            _type = type;
            if (buffer.BaseStream.Length < 4)
            {
                return;
            }

            if (_type == AKAOType.UNKNOWN)
            {
                // we must try to find the AKAO type
                byte[] header = buffer.ReadBytes(4);       // AKAO
                if (!CheckHeader(header))
                {
                    return;
                }
                ushort v1 = buffer.ReadUInt16(); // ID or type
                ushort v2 = buffer.ReadUInt16(); // File Length or empty
                byte   v3 = buffer.ReadByte();   // Type or empty
                byte   v4 = buffer.ReadByte();   // Type var or empty

                if (v2 + v3 + v4 == 0)
                {
                    if (v1 == 0)
                    {
                        _type = AKAOType.SAMPLE;
                    }
                    else
                    {
                        if (buffer.BaseStream.Position == 10)
                        {
                            // v1 is the sample collection ID in this case
                            _type = AKAOType.SOUND;
                        }
                        else
                        {
                            // E075.P have an AKAO PROG without v3 = 0xC8...
                            _type = AKAOType.PROG;
                        }
                    }
                }
                else if (v3 == 0xC8)
                {
                    _type = AKAOType.EFFECT;
                }
                else if (v2 > 0 && v2 == buffer.BaseStream.Length)
                {
                    _type = AKAOType.MUSIC;
                }

                buffer.BaseStream.Position -= 10;
            }


            switch (_type)
            {
            case AKAOType.MUSIC:
                //https://github.com/vgmtrans/vgmtrans/blob/master/src/main/formats/AkaoSeq.cpp
                // header datas
                byte[] header  = buffer.ReadBytes(4);   // AKAO
                ushort fileId  = buffer.ReadUInt16();
                ushort byteLen = buffer.ReadUInt16();
                ushort reverb  = buffer.ReadUInt16(); // 0x0500  | Just on case 0x0400 (MUSIC000.DAT), maybe it refer to the WAVE0005.DAT sample collection
                buffer.ReadBytes(6);                  // padding

                uint unk1      = buffer.ReadUInt32(); // never > 127, maybe a general volume ? or something like that
                uint sampleSet = buffer.ReadUInt32(); // ID of the WAVE*.DAT in the SOUND folder
                buffer.ReadBytes(8);                  // padding

                int   bnumt    = buffer.ReadInt32();
                uint  numTrack = ToolBox.GetNumPositiveBits(bnumt);
                short unk3     = buffer.ReadInt16(); // (0, -1, 255 or 16383) from MUSIC050 to MUSIC101 => unk3 != 0
                // when != 0 it seems like it's not a "music" but more like a sounds store for maps ambiance or monsters
                // when != 0, in most of case there is no instruments set nor a drum (excp 68, 69) and Unknowns AKAO events occur a lot.
                // in these cases you really feal that it doesn't really make sence to out a midi file and less a wav...
                // when != 0 => sampleSet 17 to 25
                // Case 255 (66 to 73, 82, 83, 96, 97)
                // Case 16383 (78 to 81, 88 to 91)
                // Case -1 all others from 50 to 101
                buffer.ReadBytes(10);                   // padding

                uint ptr1 = buffer.ReadUInt32() + 0x30; // instruments pointer
                uint ptr2 = buffer.ReadUInt32() + 0x34; // Drums pointer
                buffer.ReadBytes(8);                    // padding

                ushort jump        = buffer.ReadUInt16();
                long   basePtr     = buffer.BaseStream.Position;
                long   musInstrPtr = buffer.BaseStream.Position + jump - 2;


                if (true)
                {
                    Debug.Log(string.Concat("AKAO from : ", FileName, " FileSize = ", FileSize, "    |    reverb : ", reverb, " numTrack : ", numTrack, " sampleSet : ", sampleSet,
                                            "\r\ninstruments at : ", ptr1, "  Drums at : ", ptr2, "   musInstrPtr : ", musInstrPtr, "   |  unk1 : ", unk1, "   unk3 : ", unk3));
                }
                ushort[] tracksPtr = new ushort[numTrack];
                tracksPtr[0] = (ushort)musInstrPtr;

                for (uint i = 0; i < numTrack - 1; i++)
                {
                    tracksPtr[i + 1] = (ushort)((basePtr + i * 2) + buffer.ReadUInt16());
                }



                // music instuctions begin here, MIDI like format, we don't care yet, so let's jump



                uint instrCount = 0;
                // Instruments
                if (ptr1 > 0x30)
                {
                    buffer.BaseStream.Position = ptr1;
                    // Instruments Header always 0x20 ?
                    List <ushort> instrPtrs = new List <ushort>();
                    for (int i = 0; i < 0x10; i++)
                    {
                        ushort instrPtr = buffer.ReadUInt16();
                        if (instrPtr != 0xFFFF)
                        {
                            instrPtrs.Add(instrPtr);
                        }
                        else
                        {
                            // Padding
                        }
                    }

                    instrCount = (uint)instrPtrs.Count;
                    if (ptr2 > 0x34)
                    {
                        instrCount++;
                    }



                    if (UseDebug)
                    {
                        Debug.Log("Instruments number : " + instrCount);
                    }

                    instruments = new List <AKAOInstrument>();

                    for (int i = 0; i < instrPtrs.Count; i++)
                    {
                        AKAOInstrument instrument = new AKAOInstrument((uint)i, AKAOInstrument.InstrumentType.INSTR_MELODIC);
                        instrument.name = "Instrument #" + (ushort)i;
                        long instrStart = ptr1 + 0x20 + instrPtrs[i];
                        long instrEnd;
                        if (i < instrPtrs.Count - 1)
                        {
                            instrEnd = ptr1 + 0x20 + instrPtrs[i + 1];
                        }
                        else
                        {
                            if (ptr2 > 0x34)
                            {
                                instrEnd = ptr2;
                            }
                            else
                            {
                                instrEnd = byteLen;
                            }
                        }
                        int instrRegLoop = (int)(instrEnd - instrStart) / 0x08;
                        if (UseDebug)
                        {
                            Debug.Log(string.Concat("Instrument #", i, "   Regions count : ", instrRegLoop - 1));
                        }

                        instrument.regions = new AKAORegion[instrRegLoop - 1];     // -1 because the last 8 bytes are padding
                        for (int j = 0; j < instrRegLoop - 1; j++)
                        {
                            AKAORegion reg = new AKAORegion();
                            reg.FeedMelodic(buffer.ReadBytes(8));
                            instrument.regions[j] = reg;
                            if (UseDebug)
                            {
                                Debug.Log(reg.ToString());
                            }
                        }
                        buffer.ReadBytes(8);    // 0000 0000 0000 0000 padding

                        instruments.Add(instrument);
                    }
                }

                // Drum
                if (ptr2 > 0x34)
                {
                    if (buffer.BaseStream.Position != ptr2)
                    {
                        buffer.BaseStream.Position = ptr2;
                    }

                    // Special case when there is no melodic instruments
                    if (instruments == null)
                    {
                        instrCount++;
                        instruments = new List <AKAOInstrument>();
                    }

                    AKAOInstrument drum = new AKAOInstrument(instrCount - 1, AKAOInstrument.InstrumentType.INSTR_DRUM);
                    drum.name = "Drum";
                    int drumRegLoop = (int)(byteLen - ptr2) / 0x08;
                    if (UseDebug)
                    {
                        Debug.Log(string.Concat("Drum   Regions count : ", drumRegLoop - 1));
                    }

                    List <AKAORegion> dr = new List <AKAORegion>();
                    for (int j = 0; j < drumRegLoop - 1; j++)
                    {
                        byte[] b = buffer.ReadBytes(8);
                        if (b[0] == 0xFF && b[1] == 0xFF && b[2] == 0xFF && b[3] == 0xFF && b[4] == 0xFF && b[5] == 0xFF && b[6] == 0xFF && b[7] == 0xFF)
                        {
                            break;
                        }
                        if (b[0] > 0 && b[1] > 0 && b[6] > 0 && b[7] > 0)
                        {
                            AKAORegion dregion = new AKAORegion();
                            dregion.FeedDrum(b, j);
                            dr.Add(dregion);
                            if (UseDebug)
                            {
                                Debug.Log(dregion.ToString());
                            }
                        }
                    }

                    drum.regions = dr.ToArray();
                    instruments.Add(drum);
                }

                long end = 0;
                if (ptr1 > 0x30)
                {
                    end = ptr1;
                }
                else if (ptr2 > 0x34)
                {
                    end = ptr2;
                }
                else
                {
                    end = buffer.BaseStream.Length;
                }

                composer = new AKAOComposer(buffer, musInstrPtr, end, instrCount, numTrack, tracksPtr, FileName, true);


                // AKAO from : WAVE0000 startingArticulationId = 0
                // AKAO from : WAVE0005 startingArticulationId = 32
                // AKAO from : WAVE0032 startingArticulationId = 32
                // All other            startingArticulationId = 64
                // AKAO from : WAVE0200 startingArticulationId = 128

                // So we seek for the appropriate WAVE*.DAT in the SOUND folder
                string[] hash = FilePath.Split("/"[0]);
                hash[hash.Length - 2] = "SOUND";

                AKAO[] sampleCollections = new AKAO[3];

                // Program from 32 to 63
                hash[hash.Length - 1] = "WAVE0005.DAT";     // wave 005 or wave 032 ? (5 seems good)
                AKAO SampleColl32 = new AKAO();
                SampleColl32.UseDebug = UseDebug;
                SampleColl32.Parse(String.Join("/", hash), AKAO.SOUND);
                sampleCollections[0] = SampleColl32;

                string zz = "0";
                if (sampleSet < 100)
                {
                    zz += "0";
                }
                if (sampleSet < 10)
                {
                    zz += "0";
                }
                hash[hash.Length - 1] = "WAVE" + zz + sampleSet + ".DAT";
                string samplePath = String.Join("/", hash);
                bool   test       = File.Exists(samplePath);

                // Program from 64 to 95 or 127
                AKAO SampleColl64 = new AKAO();
                SampleColl64.UseDebug = UseDebug;
                SampleColl64.Parse(samplePath, AKAO.SOUND);
                sampleCollections[1] = SampleColl64;

                // Additionnal Collection, somztimes usefull for drum kit or A1 program change
                if (SampleColl64.articulations.Length < 64)
                {
                    hash[hash.Length - 1] = "WAVE0091.DAT";
                    AKAO addiColl = new AKAO();
                    addiColl.UseDebug = UseDebug;
                    addiColl.Parse(String.Join("/", hash), AKAO.SOUND);
                    sampleCollections[2] = addiColl;
                }

                if (composer.A1Calls.Count > 0)
                {
                    // we need to add new instruments with an unique region
                    foreach (uint iid in composer.A1Calls)
                    {
                        AKAOInstrument A1Instrument = new AKAOInstrument(iid);
                        A1Instrument.name    = "A1 Instrument #" + (ushort)iid;
                        A1Instrument.a1      = true;
                        A1Instrument.regions = new AKAORegion[1];
                        AKAORegion defaultRegion = new AKAORegion();
                        defaultRegion.articulationId = (byte)iid;
                        A1Instrument.regions[0]      = defaultRegion;
                        if (instruments == null)
                        {
                            instruments = new List <AKAOInstrument>();
                        }
                        instruments.Add(A1Instrument);
                    }
                }



                SF2 sf2 = null;
                if (bWAV || bSF2 || bDLS)
                {
                    sf2 = SoundFundry(this, sampleCollections);
                }
                if (bMID || bWAV)
                {
                    if (unk3 != 0)
                    {
                        bWAV = false;     // we don't want 1Gb crap .wav
                    }

                    composer.Synthetize(bMID, bWAV, sf2);
                }

                break;

            case AKAOType.SOUND:
                // Samples Collection

                // header datas
                header = buffer.ReadBytes(4); // AKAO
                ushort sampleId = buffer.ReadUInt16();
                buffer.ReadBytes(10);         // padding

                unk1 = buffer.ReadByte();     // almost always 0 (but one case 48 in WAVE0032)
                unk3 = buffer.ReadByte();     // almost always 81 (two cases 49 (WAVE0000, WAVE0005), one case 16 in WAVE0032, one case 177 in WAVE0200)
                buffer.ReadBytes(2);          // padding
                var sampleSize = buffer.ReadUInt32();
                startingArticulationId = buffer.ReadUInt32();
                var numArts = buffer.ReadUInt32();
                // mostly 32, sometimes 64, one case 48 (WAVE0071), one case 96 (WAVE0200)

                /* List of 64 arts
                 * WAVE0044
                 * WAVE0045
                 * WAVE0046
                 * WAVE0053
                 * WAVE0054
                 * WAVE0055
                 * WAVE0064
                 * WAVE0065
                 * WAVE0068
                 * WAVE0069
                 * WAVE0091
                 * WAVE0097
                 * WAVE0099
                 */

                buffer.ReadBytes(32);     // padding

                if (UseDebug)
                {
                    Debug.Log(string.Concat("AKAO from : ", FileName, " len = ", FileSize, "  ID : ", sampleId, " unk1 : ", unk1, " unk3 : ", unk3, " sampleSize : ", sampleSize, " stArtId : ", startingArticulationId, " numArts : ", numArts));
                }

                // Articulations section here
                articulations = new AKAOArticulation[numArts];
                for (uint i = 0; i < numArts; i++)
                {
                    AKAOArticulation arti = new AKAOArticulation(buffer, startingArticulationId + i);
                    articulations[i] = arti;
                    if (UseDebug)
                    {
                        //Debug.Log(arti.ToString());
                    }
                }

                // Samples section here
                ulong samStart = (ulong)buffer.BaseStream.Position;
                // First we need to determine the start and the end of the samples, 16 null bytes indicate a new sample, so lets find them.
                List <long> samPtr  = new List <long>();
                List <long> samEPtr = new List <long>();
                while (buffer.BaseStream.Position < buffer.BaseStream.Length)
                {
                    if (buffer.ReadUInt64() + buffer.ReadUInt64() == 0)
                    {
                        if (samPtr.Count > 0)
                        {
                            //samEPtr.Add(buffer.BaseStream.Position - 0x20);
                            samEPtr.Add(buffer.BaseStream.Position - 0x10);
                        }
                        samPtr.Add(buffer.BaseStream.Position - 0x10);
                        //samPtr.Add(buffer.BaseStream.Position);
                    }
                }
                samEPtr.Add(buffer.BaseStream.Length);

                // Let's loop again to get samples
                int numSam = samPtr.Count;
                samples = new AKAOSample[numSam];
                for (int i = 0; i < numSam; i++)
                {
                    buffer.BaseStream.Position = samPtr[i];
                    int        size = (int)(samEPtr[i] - samPtr[i]);
                    byte[]     dt   = buffer.ReadBytes(size);
                    AKAOSample sam  = new AKAOSample(string.Concat(FileName, " Sample #", (ushort)i), dt, (ulong)samPtr[i]);
                    sam.index  = i;
                    samples[i] = sam;

                    if (UseDebug && bWAV)
                    {
                        WAV wavSam = sam.ConvertToWAV();
                        wavSam.SetName(FileName + "_Sample_" + i);
                        ToolBox.DirExNorCreate(Application.dataPath + "/../Assets/Resources/Sounds/SampleColl/");
                        wavSam.WriteFile(Application.dataPath + "/../Assets/Resources/Sounds/SampleColl/" + FileName + "_Sample_" + i + ".wav", wavSam.Write());
                    }
                }
                // now to verify and associate each articulation with a sample index value
                // for every sample of every instrument, we add sample_section offset, because those values
                //  are relative to the beginning of the sample section
                for (uint i = 0; i < articulations.Length; i++)
                {
                    for (uint l = 0; l < samples.Length; l++)
                    {
                        //if (articulations[i].sampleOff + samStart + 0x10 == samples[l].offset)
                        if (articulations[i].sampleOff + samStart == samples[l].offset)
                        {
                            articulations[i].sampleNum = l;
                            articulations[i].sample    = samples[l];
                            samples[l].loopStart       = articulations[i].loopPt;

                            break;
                        }
                    }
                }
                break;

            case AKAOType.PROG:
                // unknown yet
                header = buffer.ReadBytes(4);    // AKAO
                ushort id = buffer.ReadUInt16();
                buffer.ReadUInt16();
                ushort tp = buffer.ReadUInt16();
                buffer.ReadUInt16();
                buffer.ReadUInt32();

                buffer.ReadUInt32();
                buffer.ReadUInt32();
                buffer.ReadUInt32();
                buffer.ReadUInt32();

                buffer.ReadUInt16();
                byteLen = buffer.ReadUInt16();

                //Debug.Log(string.Concat("AKAO PROG : id : ", id, "  tp : ", tp, "  byteLen : ", byteLen));

                //composer = new AKAOComposer(buffer, buffer.BaseStream.Position, limit, 0, 1, new ushort[] { (ushort)buffer.BaseStream.Position }, FileName, true);
                //composer.Synthetize(true, false);
                break;

            case AKAOType.EFFECT:
                //https://github.com/vgmtrans/vgmtrans/blob/akao-ps1/src/main/formats/AkaoSeq.cpp
                header   = buffer.ReadBytes(4);  // AKAO
                id       = buffer.ReadUInt16();
                byteLen  = buffer.ReadUInt16();
                reverb   = buffer.ReadUInt16();
                bnumt    = buffer.ReadInt32();
                numTrack = ToolBox.GetNumPositiveBits(bnumt);

                buffer.ReadBytes(6);

                Debug.Log(string.Concat("AKAO EFFECT : id : ", id, "  byteLen : ", byteLen, "  reverb : ", reverb, "  numTrack : ", numTrack));

                composer = new AKAOComposer(buffer, buffer.BaseStream.Position, limit, 0, 1, new ushort[] { (ushort)buffer.BaseStream.Position }, FileName, true);
                Debug.Log(string.Concat("composer.A1Calls.Count : ", composer.A1Calls.Count));

                composer.Synthetize(true, false);
                break;

            case AKAOType.SAMPLE:
                // similar to AKAOType.SOUND without articulations, we can output a WAV file
                // header datas
                header = buffer.ReadBytes(4); // AKAO
                buffer.ReadUInt16();
                buffer.ReadBytes(10);         // padding

                buffer.ReadUInt16();          //
                buffer.ReadBytes(2);          // padding
                buffer.ReadUInt32();
                buffer.ReadUInt32();
                buffer.ReadUInt32();

                buffer.ReadBytes(32);     // padding
                buffer.ReadBytes(16);     // sample padding

                AKAOSample sample = new AKAOSample(FileName, buffer.ReadBytes((int)(limit - buffer.BaseStream.Position)), (ulong)buffer.BaseStream.Position);
                WAV        nw     = sample.ConvertToWAV();
                nw.SetName(FileName);

                if (UseDebug && bWAV)
                {
                    ToolBox.DirExNorCreate(Application.dataPath + "/../Assets/Resources/Sounds/Effects/");
                    nw.WriteFile(Application.dataPath + "/../Assets/Resources/Sounds/Effects/" + FileName + ".wav", nw.Write());
                }
                break;
            }
        }
        public void Parse(BinaryReader buffer)
        {
            ptrRoomSection     = buffer.ReadUInt32();
            lenRoomSection     = buffer.ReadUInt32();
            ptrClearedSection  = buffer.ReadUInt32();
            lenClearedSection  = buffer.ReadUInt32();
            ptrScriptSection   = buffer.ReadUInt32();
            lenScriptSection   = buffer.ReadUInt32();
            ptrDoorSection     = buffer.ReadUInt32();
            lenDoorSection     = buffer.ReadUInt32();
            ptrEnemySection    = buffer.ReadUInt32();
            lenEnemySection    = buffer.ReadUInt32();
            ptrTreasureSection = buffer.ReadUInt32();
            lenTreasureSection = buffer.ReadUInt32();
            // Room sub sections
            lenGeometrySection       = buffer.ReadUInt32();
            lenCollisionSection      = buffer.ReadUInt32();
            lenSubSection03          = buffer.ReadUInt32();
            lenRoomDoorSection       = buffer.ReadUInt32();
            lenLightingSection       = buffer.ReadUInt32();
            lenSubSection06          = buffer.ReadUInt32();
            lenSubSection07          = buffer.ReadUInt32();
            lenSubSection08          = buffer.ReadUInt32();
            lenSubSection09          = buffer.ReadUInt32();
            lenSubSection0A          = buffer.ReadUInt32();
            lenSubSection0B          = buffer.ReadUInt32();
            lenTextureEffectsSection = buffer.ReadUInt32();
            lenSubSection0D          = buffer.ReadUInt32();
            lenSubSection0E          = buffer.ReadUInt32();
            lenSubSection0F          = buffer.ReadUInt32();
            lenSubSection10          = buffer.ReadUInt32();
            lenSubSection11          = buffer.ReadUInt32();
            lenSubSection12          = buffer.ReadUInt32();
            lenSubSection13          = buffer.ReadUInt32();
            lenAKAOSubSection        = buffer.ReadUInt32();
            lenSubSection15          = buffer.ReadUInt32();
            lenSubSection16          = buffer.ReadUInt32();
            lenSubSection17          = buffer.ReadUInt32();
            lenSubSection18          = buffer.ReadUInt32();


            if (UseDebug)
            {
                Debug.Log("MPD parse : " + filePath);
                Debug.Log("ptrRoomSection :" + ptrRoomSection + "  lenRoomSection : " + lenRoomSection);
                Debug.Log("ptrClearedSection :" + ptrClearedSection + "  lenClearedSection : " + lenClearedSection);
                Debug.Log("ptrScriptSection :" + ptrScriptSection + "  lenScriptSection : " + lenScriptSection);
                Debug.Log("ptrDoorSection :" + ptrDoorSection + "  lenDoorSection : " + lenDoorSection);
                Debug.Log("ptrEnemySection :" + ptrEnemySection + "  lenEnemySection : " + lenEnemySection);
                Debug.Log("ptrTreasureSection :" + ptrTreasureSection + "  lenTreasureSection : " + lenTreasureSection);
                Debug.Log("lenGeometrySection :" + lenGeometrySection);
                Debug.Log("lenCollisionSection :" + lenCollisionSection);
                Debug.Log("lenSubSection03 :" + lenSubSection03);
                Debug.Log("lenRoomDoorSection :" + lenRoomDoorSection);
                Debug.Log("lenLightingSection :" + lenLightingSection);
                Debug.Log("lenSubSection06 :" + lenSubSection06);
                Debug.Log("lenSubSection07 :" + lenSubSection07);
                Debug.Log("lenSubSection08 :" + lenSubSection08);
                Debug.Log("lenSubSection09 :" + lenSubSection09);
                Debug.Log("lenSubSection0A :" + lenSubSection0A);
                Debug.Log("lenSubSection0B :" + lenSubSection0B);
                Debug.Log("lenTextureEffectsSection :" + lenTextureEffectsSection);
                Debug.Log("lenSubSection0D :" + lenSubSection0D);
                Debug.Log("lenSubSection0E :" + lenSubSection0E);
                Debug.Log("lenSubSection0F :" + lenSubSection0F);
                Debug.Log("lenSubSection10 :" + lenSubSection10);
                Debug.Log("lenSubSection11 :" + lenSubSection11);
                Debug.Log("lenSubSection12 :" + lenSubSection12);
                Debug.Log("lenSubSection13 :" + lenSubSection13);
                Debug.Log("lenAKAOSubSection :" + lenAKAOSubSection);
                Debug.Log("lenSubSection15 :" + lenSubSection15);
                Debug.Log("lenSubSection16 :" + lenSubSection16);
                Debug.Log("lenSubSection17 :" + lenSubSection17);
                Debug.Log("lenSubSection18 :" + lenSubSection18);
            }

            // ROOM section
            if (UseDebug)
            {
                Debug.Log("ROOM section : " + buffer.BaseStream.Position);
            }
            // Geometry
            if (lenRoomSection > 4)
            {
                if (lenGeometrySection > 0)
                {
                    numGroups = buffer.ReadUInt32();
                    if (UseDebug)
                    {
                        Debug.Log("numGroups : " + numGroups);
                    }
                    groups = new MPDGroup[numGroups];
                    for (uint i = 0; i < numGroups; i++)
                    {
                        groups[i]        = new MPDGroup();
                        groups[i].header = buffer.ReadBytes(64);
                        if ((groups[i].header[1] & 0x08) > 0)
                        {
                            groups[i].scale = 1;
                        }
                    }
                    for (uint i = 0; i < numGroups; i++)
                    {
                        uint numTriangles = buffer.ReadUInt32();
                        uint numQuads     = buffer.ReadUInt32();
                        for (uint j = 0; j < numTriangles; j++)
                        {
                            MPDFace face = new MPDFace(groups[i], false);
                            face.feed(buffer);
                            MPDMesh m = groups[i].getMesh(face.textureId, face.clutId);
                            m.addFace(face);
                        }
                        for (uint j = 0; j < numQuads; j++)
                        {
                            MPDFace face = new MPDFace(groups[i], true);
                            face.feed(buffer);
                            MPDMesh m = groups[i].getMesh(face.textureId, face.clutId);
                            m.addFace(face);
                        }
                    }
                }

                // collision
                if (lenCollisionSection > 0)
                {
                    long collisionPtr = buffer.BaseStream.Position;
                    uint TyleWidth    = buffer.ReadUInt16();
                    uint TyleHeight   = buffer.ReadUInt16();
                    if (UseDebug)
                    {
                        Debug.Log("TyleWidth : " + TyleWidth + "  TyleHeight : " + TyleHeight);
                    }

                    uint   unk1          = buffer.ReadUInt16();
                    uint   unk2          = buffer.ReadUInt16();
                    uint[] FloorHeight   = new uint[TyleWidth * TyleHeight];
                    uint[] CeilingHeight = new uint[TyleWidth * TyleHeight];
                    uint[] Incline       = new uint[TyleWidth * TyleHeight];
                    //Debug.Log("Collision ptr : " + buffer.BaseStream.Position);
                    for (uint i = 0; i < TyleWidth * TyleHeight; i++)
                    {
                        FloorHeight[i] = buffer.ReadUInt16();
                        if (UseDebug)
                        {
                            //Debug.Log("FloorHeight[i] : " + FloorHeight[i]);
                        }
                    }

                    for (uint i = 0; i < TyleWidth * TyleHeight; i++)
                    {
                        CeilingHeight[i] = buffer.ReadUInt16();
                        if (UseDebug)
                        {
                            //Debug.Log("CeilingHeight[i] : " + CeilingHeight[i]);
                        }
                    }

                    for (uint i = 0; i < TyleWidth * TyleHeight / 2; i++)
                    {
                        byte b = buffer.ReadByte();
                        Incline[i * 2]     = (uint)b << 4;
                        Incline[i * 2 + 1] = (uint)b >> 4;
                    }
                    buffer.BaseStream.Position = collisionPtr + lenCollisionSection;
                }

                // section 3 ??
                //
                if (lenSubSection03 > 0)
                {
                    Debug.Log("lenSubSection03 ptr : " + buffer.BaseStream.Position + "   lenSubSection03 : " + lenSubSection03);
                    buffer.BaseStream.Position = buffer.BaseStream.Position + lenSubSection03;
                }

                // door section
                if (lenRoomDoorSection > 0)
                {
                    long doorPtr  = buffer.BaseStream.Position;
                    uint numDoors = lenRoomDoorSection / 0x0C;
                    doors = new MPDDoor[numDoors];
                    for (uint i = 0; i < numDoors; i++)
                    {
                        MPDDoor d = new MPDDoor();
                        d.destZone      = buffer.ReadByte();
                        d.destRoom      = buffer.ReadByte();
                        d.unkn          = buffer.ReadBytes(6);
                        d.idCurrentDoor = buffer.ReadUInt32();
                        doors[i]        = d;
                        if (UseDebug)
                        {
                            Debug.Log("MPDDoor # " + i + "  idCurrentDoor : " + d.idCurrentDoor + "  destZone : " + d.destZone + "  destRoom : " + d.destRoom);
                            Debug.Log(d.unkn[0] + ", " + d.unkn[1] + ", " + d.unkn[2] + ", " + d.unkn[3] + ", " + d.unkn[4] + ", " + d.unkn[5]);
                        }
                    }

                    buffer.BaseStream.Position = doorPtr + lenRoomDoorSection;
                }

                // lights section
                // http://www.psxdev.net/forum/viewtopic.php?f=51&t=3383
                if (lenLightingSection > 0)
                {
                    long lightPtr = buffer.BaseStream.Position;
                    if (UseDebug)
                    {
                        Debug.Log("lights ptr : " + lightPtr + "   lenLightingSection : " + lenLightingSection + "(" + (lightPtr + lenLightingSection) + ")");
                    }

                    Color32 mc        = new Color32(buffer.ReadByte(), buffer.ReadByte(), buffer.ReadByte(), buffer.ReadByte());
                    uint    numLights = buffer.ReadUInt32();
                    if (UseDebug)
                    {
                        Debug.Log("numLights : " + numLights + "  mainColor  :  " + mc.ToString());
                    }

                    buffer.ReadUInt32(); // padding

                    lights = new List <GameObject>();

                    string lightsDebug = "";
                    for (uint i = 0; i < numLights; i++)
                    {
                        string  lgtMat = "";
                        short[] matrix = new short[10];

                        byte[] hexa = buffer.ReadBytes(20);
                        buffer.BaseStream.Position -= 20;

                        for (uint j = 0; j < 10; j++)
                        {
                            matrix[j] = buffer.ReadInt16();
                            lgtMat   += (matrix[j]) + " | ";
                        }


                        byte[]  cols   = buffer.ReadBytes(12);
                        Color32 colorX = new Color32(cols[0], cols[1], cols[2], cols[3]);
                        Color32 colorY = new Color32(cols[4], cols[5], cols[6], cols[7]);
                        Color32 colorZ = new Color32(cols[8], cols[9], cols[10], cols[11]);

                        Color32 main = Color.black;
                        if (colorX.r != mc.r && colorX.g != mc.g && colorX.b != mc.b)
                        {
                            main = colorX;
                        }
                        if (colorY.r != mc.r && colorY.g != mc.g && colorY.b != mc.b)
                        {
                            main = colorY;
                        }
                        if (colorZ.r != mc.r && colorZ.g != mc.g && colorZ.b != mc.b)
                        {
                            main = colorZ;
                        }
                        main.a = 255;

                        lightsDebug += string.Concat("Light # ", i, "  :  ", BitConverter.ToString(hexa), "  ->  ", lgtMat, "  |  ", colorX, ", ", colorY, ", ", colorZ, "\r\n");
                        GameObject lgo       = new GameObject("Point Light");
                        Rect       lightRect = new Rect();
                        lightRect.xMin = -matrix[0] / 100;
                        lightRect.yMin = -matrix[1] / 100;
                        lightRect.xMax = -matrix[2] / 100;
                        lightRect.yMax = -matrix[3] / 100;
                        // i need to find a way to get Y axe
                        lgo.transform.position   = new Vector3(lightRect.center.x, 5f, lightRect.center.y);
                        lgo.transform.localScale = Vector3.one;
                        Light l = lgo.AddComponent <Light>();
                        l.name      = "l" + i;
                        l.type      = LightType.Point;
                        l.range     = Vector2.Distance(lightRect.center, lightRect.min);
                        l.intensity = 2f;
                        l.color     = main;
                        l.shadows   = LightShadows.Soft;
                        lights.Add(lgo);
                    }

                    if (UseDebug)
                    {
                        Debug.Log(lightsDebug);
                    }

                    if (UseDebug)
                    {
                        Debug.Log("end lights  :  " + buffer.BaseStream.Position);
                    }

                    buffer.BaseStream.Position = lightPtr + lenLightingSection;
                }

                if (lenSubSection06 > 0)
                {
                    Debug.Log("SubSection06 ptr : " + buffer.BaseStream.Position + "   lenSubSection06 : " + lenSubSection06);
                    buffer.BaseStream.Position = buffer.BaseStream.Position + lenSubSection06;
                }

                if (lenSubSection07 > 0)
                {
                    Debug.Log("SubSection07 ptr : " + buffer.BaseStream.Position + "   lenSubSection07 : " + lenSubSection07);
                    buffer.BaseStream.Position = buffer.BaseStream.Position + lenSubSection07;
                }

                if (lenSubSection08 > 0)
                {
                    Debug.Log("SubSection08 ptr : " + buffer.BaseStream.Position + "   lenSubSection08 : " + lenSubSection08);
                    buffer.BaseStream.Position = buffer.BaseStream.Position + lenSubSection08;
                }

                if (lenSubSection09 > 0)
                {
                    Debug.Log("SubSection09 ptr : " + buffer.BaseStream.Position + "   lenSubSection09 : " + lenSubSection09);
                    buffer.BaseStream.Position = buffer.BaseStream.Position + lenSubSection09;
                }

                if (lenSubSection0A > 0)
                {
                    Debug.Log("SubSection0A ptr : " + buffer.BaseStream.Position + "   lenSubSection0A : " + lenSubSection0A);
                    buffer.BaseStream.Position = buffer.BaseStream.Position + lenSubSection0A;
                }

                if (lenSubSection0B > 0)
                {
                    Debug.Log("SubSection0B ptr : " + buffer.BaseStream.Position + "   lenSubSection0B : " + lenSubSection0B);
                    buffer.BaseStream.Position = buffer.BaseStream.Position + lenSubSection0B;
                }

                if (lenTextureEffectsSection > 0)
                {
                    Debug.Log("TextureEffectsSection ptr : " + buffer.BaseStream.Position + "   lenTextureEffectsSection : " + lenTextureEffectsSection);
                    buffer.BaseStream.Position = buffer.BaseStream.Position + lenTextureEffectsSection;
                }

                if (lenSubSection0D > 0)
                {
                    Debug.Log("SubSection0D ptr : " + buffer.BaseStream.Position + "   lenSubSection0D : " + lenSubSection0D);
                    buffer.BaseStream.Position = buffer.BaseStream.Position + lenSubSection0D;
                }

                if (lenSubSection0E > 0)
                {
                    Debug.Log("SubSection0E ptr : " + buffer.BaseStream.Position + "   lenSubSection0E : " + lenSubSection0E);
                    buffer.BaseStream.Position = buffer.BaseStream.Position + lenSubSection0E;
                }

                if (lenSubSection0F > 0)
                {
                    Debug.Log("SubSection0F ptr : " + buffer.BaseStream.Position + "   lenSubSection0F : " + lenSubSection0F);
                    buffer.BaseStream.Position = buffer.BaseStream.Position + lenSubSection0F;
                }

                if (lenSubSection10 > 0)
                {
                    Debug.Log("SubSection10 ptr : " + buffer.BaseStream.Position + "   lenSubSection10 : " + lenSubSection10);
                    buffer.BaseStream.Position = buffer.BaseStream.Position + lenSubSection10;
                }

                if (lenSubSection11 > 0)
                {
                    Debug.Log("SubSection11 ptr : " + buffer.BaseStream.Position + "   lenSubSection11 : " + lenSubSection11);
                    buffer.BaseStream.Position = buffer.BaseStream.Position + lenSubSection11;
                }

                if (lenSubSection12 > 0)
                {
                    Debug.Log("SubSection12 ptr : " + buffer.BaseStream.Position + "   lenSubSection12 : " + lenSubSection12);
                    buffer.BaseStream.Position = buffer.BaseStream.Position + lenSubSection12;
                }

                if (lenSubSection13 > 0)
                {
                    Debug.Log("SubSection13 ptr : " + buffer.BaseStream.Position + "   lenSubSection13 : " + lenSubSection13);
                    buffer.BaseStream.Position = buffer.BaseStream.Position + lenSubSection13;
                }

                if (lenAKAOSubSection > 0)
                {
                    long akaoPtr = buffer.BaseStream.Position;
                    if (UseDebug)
                    {
                        Debug.Log("akaoPtr : " + akaoPtr + "   lenAKAOSubSection : " + lenAKAOSubSection + "(" + (akaoPtr + lenAKAOSubSection) + ")");
                    }

                    buffer.ReadUInt32(); // 0200 0000
                    buffer.ReadUInt32(); // 0000 0000
                    buffer.ReadUInt32(); // 0C00 0000


                    AKAO audio = new AKAO();
                    audio.FileName = FileName;
                    audio.UseDebug = true;
                    audio.Parse(buffer, AKAO.UNKNOWN, akaoPtr + lenAKAOSubSection);
                    buffer.BaseStream.Position = akaoPtr + lenAKAOSubSection;
                }

                if (lenSubSection15 > 0)
                {
                    Debug.Log("SubSection15 ptr : " + buffer.BaseStream.Position + "   lenSubSection15 : " + lenSubSection15);
                    buffer.BaseStream.Position = buffer.BaseStream.Position + lenSubSection15;
                }

                if (lenSubSection16 > 0)
                {
                    Debug.Log("SubSection16 ptr : " + buffer.BaseStream.Position + "   lenSubSection16 : " + lenSubSection16);
                    buffer.BaseStream.Position = buffer.BaseStream.Position + lenSubSection16;
                }

                if (lenSubSection17 > 0)
                {
                    Debug.Log("SubSection17 ptr : " + buffer.BaseStream.Position + "   lenSubSection17 : " + lenSubSection17);
                    buffer.BaseStream.Position = buffer.BaseStream.Position + lenSubSection17;
                }

                if (lenSubSection18 > 0)
                {
                    Debug.Log("SubSection18 ptr : " + buffer.BaseStream.Position + "   lenSubSection18 : " + lenSubSection18);
                    buffer.BaseStream.Position = buffer.BaseStream.Position + lenSubSection18;
                }
            }
            else
            {
                // No geometry :s
                _geom = false;
            }

            // Cleared section
            if (buffer.BaseStream.Position != ptrClearedSection)
            {
                buffer.BaseStream.Position = ptrClearedSection;
            }
            if (UseDebug)
            {
                Debug.Log("Cleared section : " + buffer.BaseStream.Position);
            }


            // Script section
            if (buffer.BaseStream.Position != ptrScriptSection)
            {
                buffer.BaseStream.Position = ptrScriptSection;
            }
            if (UseDebug)
            {
                Debug.Log("Script section : " + buffer.BaseStream.Position);
            }

            // See Opcode.cs


            // Door section

            if (buffer.BaseStream.Position != ptrDoorSection)
            {
                buffer.BaseStream.Position = ptrDoorSection;
            }
            if (UseDebug)
            {
                Debug.Log("Door section : " + buffer.BaseStream.Position);
            }
            if (lenDoorSection > 0)
            {
            }

            // Ennemy section
            if (buffer.BaseStream.Position != ptrEnemySection)
            {
                buffer.BaseStream.Position = ptrEnemySection;
            }
            if (UseDebug)
            {
                Debug.Log("Ennemy section : " + buffer.BaseStream.Position);
            }


            // Treasure section
            if (buffer.BaseStream.Position != ptrTreasureSection)
            {
                buffer.BaseStream.Position = ptrTreasureSection;
            }
            if (UseDebug)
            {
                Debug.Log("Treasure section : " + buffer.BaseStream.Position);
            }


            buffer.Close();
        }
Beispiel #3
0
        public void Parse(BinaryReader buffer)
        {
            byte[] header = buffer.ReadBytes(4);
            numBones     = buffer.ReadByte();
            numGroups    = buffer.ReadByte();
            numTriangles = buffer.ReadUInt16();
            numQuads     = buffer.ReadUInt16();
            numPolys     = buffer.ReadUInt16();
            numFaces     = numTriangles + numQuads + numPolys;
            byte[][] overlays = new byte[8][];
            for (int i = 0; i < 8; i++)
            {
                overlays[i] = buffer.ReadBytes(4);
            }

            buffer.ReadBytes(0x24); // Unknown
            buffer.ReadBytes(6);    // collision size and height (shape is a cylinder)
            buffer.ReadBytes(2);    // menu position Y
            buffer.ReadBytes(12);   // Unknown
            buffer.ReadBytes(2);    // Shadow radius
            buffer.ReadBytes(2);    // Shadow size increase rate
            buffer.ReadBytes(2);    // Shadow size decrease rate
            buffer.ReadBytes(4);    // Unknown
            buffer.ReadBytes(2);    // Menu scale
            buffer.ReadBytes(2);    // Unknown
            buffer.ReadBytes(2);    // Target sphere position Y
            buffer.ReadBytes(8);    // Unknown

            if (UseDebug)
            {
                Debug.Log(FileName);
                Debug.Log("numBones : " + numBones);
                Debug.Log("numGroups : " + numGroups);
                Debug.Log("numTriangles : " + numTriangles);
                Debug.Log("numQuads : " + numQuads);
                Debug.Log("numPolys : " + numPolys);
                Debug.Log("numFaces : " + numFaces);
            }

            // LBA XX_BTX.SEQ  (battle animations first one is actually XX_COM.SEQ)     certainly one weapon type for each file

            /*
             * LBA SEQ : 98646  OBJ\01_COM.SEQ
             * LBA SEQ : 0
             * LBA SEQ : 98599  OBJ\01_BT2.SEQ
             * LBA SEQ : 0
             * LBA SEQ : 98611  OBJ\01_BT4.SEQ
             * LBA SEQ : 0
             * LBA SEQ : 98623  OBJ\01_BT6.SEQ
             * LBA SEQ : 0
             * LBA SEQ : 0
             * LBA SEQ : 0
             * LBA SEQ : 98635  OBJ\01_BTA.SEQ
             * LBA SEQ : 0
             */
            for (int i = 0; i < 12; i++)
            {
                buffer.ReadUInt32();
            }

            for (int i = 0; i < 12; i++)
            {
                buffer.ReadBytes(2); // chain attack animation ID
            }

            for (int i = 0; i < 4; i++)
            {
                buffer.ReadBytes(4); // LBA XXSP0X.SEQ (special attack animations)
            }

            buffer.ReadBytes(0x20); // unknown (probably more LBA tables, there are also special attack ids stored here.)  file like 00BT1B00.SEQ (Battle Techniques)
            long dec      = buffer.BaseStream.Position + 4;
            long magicPtr = buffer.ReadUInt32() + dec;

            for (int i = 0; i < 0x18; i++)
            {
                buffer.ReadBytes(2); // unknown (noticeable effects when casting spell
            }

            long AKAOPtr   = buffer.ReadUInt32() + dec;
            long groupPtr  = buffer.ReadUInt32() + dec;
            long vertexPtr = buffer.ReadUInt32() + dec;
            long facePtr   = buffer.ReadUInt32() + dec;

            if (UseDebug)
            {
                Debug.Log("magicPtr : " + magicPtr);
                Debug.Log("AKAOPtr : " + AKAOPtr);
                Debug.Log("groupPtr : " + groupPtr);
                Debug.Log("vertexPtr : " + vertexPtr);
                Debug.Log("facePtr : " + facePtr);
            }

            // Bones section
            bones = new List <VSBone>();
            for (uint i = 0; i < numBones; i++)
            {
                VSBone bone = new VSBone();
                bone.index  = i;
                bone.name   = "bone_" + i;
                bone.length = buffer.ReadInt16();
                //Debug.LogWarning("bone  "+i+ " .length : "+ bone.length);
                buffer.ReadUInt16(); // always 0xFFFF
                bone.parentIndex = buffer.ReadByte();
                if (bone.parentIndex > numBones)
                {
                    bone.parentIndex = -1;
                }
                //Debug.LogWarning("bone.parentIndex : " + bone.parentIndex);
                // https://github.com/morris/vstools/blob/master/src/WEPBone.js
                byte[] offset = buffer.ReadBytes(3);
                bone.offset = new Vector3(offset[0], offset[1], offset[2]);
                bone.mode   = buffer.ReadByte();
                // 0 - 2 normal ?
                // 3 - 6 normal + roll 90 degrees
                // 7 - 255 absolute, different angles

                buffer.ReadBytes(7); // always 0000000
                bones.Add(bone);
            }

            // Group section
            if (buffer.BaseStream.Position != groupPtr)
            {
                if (UseDebug)
                {
                    Debug.Log(buffer.BaseStream.Position + " != " + groupPtr);
                    Debug.Log("le pointeur groupPtr n'est pas à la bonne place");
                }
                buffer.BaseStream.Position = groupPtr;
            }
            groups = new List <VSGroup>();
            for (uint i = 0; i < numGroups; i++)
            {
                VSGroup group = new VSGroup();
                group.boneIndex   = buffer.ReadInt16();
                group.numVertices = buffer.ReadUInt16();
                if (group.boneIndex != -1)
                {
                    group.bone = bones[group.boneIndex];
                }

                groups.Add(group);
            }

            // Vertices section
            if (buffer.BaseStream.Position != vertexPtr)
            {
                if (UseDebug)
                {
                    Debug.Log(buffer.BaseStream.Position + " != " + vertexPtr);
                    Debug.Log("le pointeur vertexPtr n'est pas à la bonne place");
                }
                buffer.BaseStream.Position = vertexPtr;
            }
            vertices = new List <VSVertex>();
            uint numVertices = groups[groups.Count - 1].numVertices;

            if (UseDebug)
            {
                Debug.Log("numVertices : " + numVertices);
            }

            int g = 0;

            for (uint i = 0; i < numVertices; i++)
            {
                if (i >= groups[g].numVertices)
                {
                    g++;
                }

                VSVertex vertex = new VSVertex();
                vertex.group = groups[g];
                vertex.bone  = vertex.group.bone;
                BoneWeight bw = new BoneWeight();
                bw.boneIndex0     = (int)vertex.group.bone.index;
                bw.weight0        = 1;
                vertex.boneWeight = bw;
                int x = buffer.ReadInt16();
                int y = buffer.ReadInt16();
                int z = buffer.ReadInt16();
                buffer.ReadInt16();
                vertex.position = -new Vector3(x, y, z) / 100;
                vertices.Add(vertex);
            }

            // Polygone section
            if (buffer.BaseStream.Position != facePtr)
            {
                if (UseDebug)
                {
                    Debug.Log(buffer.BaseStream.Position + " != " + facePtr);
                    Debug.Log("le pointeur facePtr n'est pas à la bonne place");
                }
                buffer.BaseStream.Position = facePtr;
            }

            faces = new List <VSFace>();

            if (excpFaces)
            {
                if (UseDebug)
                {
                    Debug.LogWarning("-------------   TRIANGLES    ----------------------");
                    Debug.LogWarning(buffer.BaseStream.Position);
                }
                for (uint i = 0; i < numTriangles; i++)
                {
                    faces.Add(ParseColoredFace(buffer, 3));
                }
                if (UseDebug)
                {
                    Debug.LogWarning("-------------   QUAD    ----------------------");
                    Debug.LogWarning(buffer.BaseStream.Position);
                }
                for (uint i = 0; i < numQuads; i++)
                {
                    faces.Add(ParseColoredFace(buffer, 4));
                }
                if (UseDebug)
                {
                    Debug.LogWarning("-------------   POLY    ----------------------");
                    Debug.LogWarning(buffer.BaseStream.Position);
                }
                for (uint i = 0; i < numPolys; i++)
                {
                    long   polyDec = buffer.BaseStream.Position;
                    byte[] bytes   = buffer.ReadBytes(24);
                    if (bytes[11] == 0x34)
                    {
                        // its a triangle
                        buffer.BaseStream.Position = polyDec;
                        faces.Add(ParseColoredFace(buffer, 3));
                    }
                    if (bytes[11] == 0x3C)
                    {
                        // its a quad
                        buffer.BaseStream.Position = polyDec;
                        faces.Add(ParseColoredFace(buffer, 4));
                    }
                }
            }
            else
            {
                for (uint i = 0; i < numFaces; i++)
                {
                    VSFace face    = new VSFace();
                    long   polyDec = buffer.BaseStream.Position;
                    // 4 bytes
                    face.type  = buffer.ReadByte();
                    face.size  = buffer.ReadByte();
                    face.side  = buffer.ReadByte();
                    face.alpha = buffer.ReadByte();

                    /*
                     * Triangles
                     * 24-10-04-00-C406-CC06-C806-08-78-05-6D-05-7C
                     * 24-10-04-00-D006-D806-D406-13-6D-0A-6D-0C-78
                     * 24-10-04-00-D406-E006-DC06-13-78-13-6D-0F-78
                     * 24-10-04-00-D406-D806-E006-0F-78-13-6D-0C-78
                     * */

                    // if (UseDebug)Debug.Log(string.Concat("#####   At : ", polyDec, " face# ", i, "   face.type : ", face.type, "   face.size : ", face.size, "   face.side : ", face.side, "   face.alpha : ", face.alpha));


                    uint[] table = new uint[256];
                    table[36] = 3;
                    table[44] = 4;

                    face.verticesCount = 0; // fallback
                    if (table[face.type] != 0)
                    {
                        face.verticesCount = table[face.type];
                    }
                    else
                    {
                        if (UseDebug)
                        {
                            Debug.LogError("####  Unknown face type !");
                        }
                    }

                    // 6 or 8 bytes
                    for (uint j = 0; j < face.verticesCount; j++)
                    {
                        int vId = buffer.ReadUInt16() / 4;
                        face.vertices.Add(vId);

                        // if (UseDebug) Debug.Log("vId : " + j + " - " + vId);
                    }

                    // 6 or 8 bytes
                    for (uint j = 0; j < face.verticesCount; j++)
                    {
                        int u = buffer.ReadByte();
                        int v = buffer.ReadByte();
                        face.uv.Add(new Vector2(u, v));
                        // if (UseDebug) Debug.Log("u : " + u + "    v : " + v);
                    }
                    faces.Add(face);
                }
            }

            // AKAO section
            if (buffer.BaseStream.Position != AKAOPtr)
            {
                if (UseDebug)
                {
                    Debug.LogWarning(buffer.BaseStream.Position + " != " + AKAOPtr + " le pointeur AKAOPtr n'est pas à la bonne place " + FileName);
                }

                buffer.BaseStream.Position = AKAOPtr;
            }


            uint akaoNum = buffer.ReadUInt32();

            if (UseDebug)
            {
                Debug.Log(string.Concat("akaoNum : ", akaoNum));
            }

            uint[] akaoFramesPtr = new uint[akaoNum];
            // one pointer for AKAO header, a second for AKAO datas
            for (uint j = 0; j < akaoNum; j++)
            {
                akaoFramesPtr[j] = buffer.ReadUInt32();
            }
            for (uint j = 0; j < akaoNum; j += 2)
            {
                long limit;
                if (j < akaoFramesPtr.Length - 1)
                {
                    limit = AKAOPtr + akaoFramesPtr[j + 1];
                    // somtimes there are empty ptrs at the begining so we skip
                    if (akaoFramesPtr[j + 1] > 0)
                    {
                        AKAO akao = new AKAO();
                        akao.FileName = string.Concat(FileName, "_Akao_", j);
                        akao.UseDebug = true;
                        akao.Parse(buffer, AKAO.UNKNOWN, limit);
                    }
                }
                else
                {
                    limit = magicPtr;
                    AKAO akao = new AKAO();
                    akao.FileName = string.Concat(FileName, "_Akao_", j);
                    akao.UseDebug = true;
                    akao.Parse(buffer, AKAO.UNKNOWN, limit);
                }
            }

            // Magic section
            if (buffer.BaseStream.Position != magicPtr)
            {
                if (UseDebug)
                {
                    Debug.LogWarning(buffer.BaseStream.Position + " != " + magicPtr + " le pointeur magicPtr n'est pas à la bonne place " + FileName);
                }

                buffer.BaseStream.Position = magicPtr;
            }
            long num       = buffer.ReadUInt32();
            long magicSize = buffer.ReadUInt32(); //size of magic effect section (doesnt include this 8 byte header)

            long num1 = buffer.ReadUInt32();
            long num2 = buffer.ReadUInt32();
            long num3 = buffer.ReadUInt32();

            if (UseDebug)
            {
                Debug.Log(string.Concat("Magic   num : ", num, "   magicSize : ", magicSize, "  num1 : " + num1, "  num2 : " + num2, "  num3 : " + num3));
            }
            if (buffer.BaseStream.Position + (magicSize - 12) < buffer.BaseStream.Length)
            {
                buffer.BaseStream.Position = buffer.BaseStream.Position + (magicSize - 12);
            }

            if (UseDebug)
            {
                Debug.Log(string.Concat("buffer.BaseStream.Position : ", buffer.BaseStream.Position, "   buffer.BaseStream.Length : ", buffer.BaseStream.Length));
            }

            if (buffer.BaseStream.Position + 8 < buffer.BaseStream.Length)
            {
                // Textures section
                tim          = new TIM();
                tim.FileName = FileName;
                tim.ParseSHP(buffer, excpFaces);
                texture = tim.DrawSHP(true);
            }

            //buffer.Close();
        }