Exemplo n.º 1
0
    public static CraClip Import(string bankName, uint animNameCRC, string clipNaming = null)
    {
        CraClip clip;

        uint animID = HashUtils.GetCRC(bankName) * animNameCRC;

        if (ClipDB.TryGetValue(animID, out clip))
        {
            return(clip);
        }

        AnimationBank bank = Con.Get <AnimationBank>(bankName);

        if (bank == null)
        {
            Debug.LogError($"Cannot find AnimationBank '{bankName}'!");
            return(null);
        }

        if (!bank.GetAnimationMetadata(animNameCRC, out int numFrames, out int numBones))
        {
            //Debug.LogError($"Cannot find Animation '{animNameCRC}' in AnimationBank '{bankName}'!");
            return(null);
        }

        clip      = new CraClip();
        clip.Name = string.IsNullOrEmpty(clipNaming) ? animNameCRC.ToString() : clipNaming;

        uint dummyroot = HashUtils.GetCRC("dummyroot");

        uint[]         boneCRCs = bank.GetBoneCRCs();
        List <CraBone> bones    = new List <CraBone>();

        for (int i = 0; i < boneCRCs.Length; ++i)
        {
            // no root motion
            if (boneCRCs[i] == dummyroot)
            {
                continue;
            }

            CraBone bone = new CraBone();
            bone.BoneHash = (int)boneCRCs[i];
            bone.Curve    = new CraTransformCurve();

            for (uint j = 0; j < 7; ++j)
            {
                if (!bank.GetCurve(animNameCRC, boneCRCs[i], j, out ushort[] indices, out float[] values))
Exemplo n.º 2
0
        async Task LoadDreamcast()
        {
            textures = new TextureInfo[0];

            loadingState = "Loading fixed memory";
            await WaitIfNecessary();

            files_array[Mem.Fix].GotoHeader();
            Reader  reader        = files_array[Mem.Fix].reader;
            Pointer off_base_fix  = Pointer.Current(reader);
            uint    base_language = reader.ReadUInt32(); //Pointer off_language = Pointer.Read(reader);

            reader.ReadUInt32();
            uint num_text_language = reader.ReadUInt32();

            reader.ReadUInt16();
            reader.ReadUInt16();
            reader.ReadUInt32(); // base
            Pointer off_text_general = Pointer.Read(reader);

            localization = FromOffsetOrRead <LocalizationStructure>(reader, off_text_general);
            Pointer off_inputStructure = Pointer.Read(reader);

            Pointer.DoAt(ref reader, off_inputStructure, () => {
                inputStruct = InputStructure.Read(reader, off_inputStructure);
                foreach (EntryAction ea in inputStruct.entryActions)
                {
                    print(ea.ToString());
                }
            });

            await WaitIfNecessary();

            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            reader.ReadUInt32();
            reader.ReadUInt32();
            reader.ReadUInt32();
            reader.ReadUInt32();
            reader.ReadUInt32();
            reader.ReadUInt32();
            reader.ReadUInt32();
            reader.ReadUInt32();
            reader.ReadUInt32();
            reader.ReadUInt32();
            Pointer.Read(reader);
            Pointer off_levelNames = Pointer.Read(reader);
            Pointer off_languages  = Pointer.Read(reader);
            uint    num_levelNames = reader.ReadUInt32();
            uint    num_languages  = reader.ReadUInt32();

            reader.ReadUInt32(); // same as num_levelNames
            Pointer.DoAt(ref reader, off_levelNames, () => {
                lvlNames = new string[num_levelNames];
                for (uint i = 0; i < num_levelNames; i++)
                {
                    lvlNames[i] = reader.ReadString(0x1E);
                }
            });
            Pointer.DoAt(ref reader, off_languages, () => {
                ReadLanguages(reader, off_languages, num_languages);
            });
            if (languages != null && localization != null)
            {
                for (int i = 0; i < num_languages; i++)
                {
                    loadingState = "Loading text files: " + (i + 1) + "/" + num_languages;
                    string langFilePath = gameDataBinFolder + "TEXTS/" + languages[i].ToUpper() + ".LNG";
                    await PrepareFile(langFilePath);

                    files_array[2] = new DCDAT(languages[i], langFilePath, 2);
                    ((DCDAT)files_array[2]).SetHeaderOffset(base_language);
                    files_array[2].GotoHeader();
                    localization.ReadLanguageTableDreamcast(files_array[2].reader, i, (ushort)num_text_language);
                    files_array[2].Dispose();
                }
            }

            loadingState = "Loading fixed textures";
            await WaitIfNecessary();

            Pointer off_events_fix   = Pointer.Read(reader);
            uint    num_events_fix   = reader.ReadUInt32();
            uint    num_textures_fix = reader.ReadUInt32();
            Pointer off_textures_fix = Pointer.Read(reader);

            Pointer.DoAt(ref reader, off_textures_fix, () => {
                Array.Resize(ref textures, (int)num_textures_fix);
                for (uint i = 0; i < num_textures_fix; i++)
                {
                    Pointer off_texture = Pointer.Read(reader);
                    textures[i]         = null;
                    Pointer.DoAt(ref reader, off_texture, () => {
                        textures[i] = TextureInfo.Read(reader, off_texture);
                    });
                }
                TEX tex = new TEX(texPaths[0]);
                for (uint i = 0; i < num_textures_fix; i++)
                {
                    if (textures[i] != null && tex.Count > i)
                    {
                        textures[i].Texture = tex.textures[i];
                    }
                }
            });
            loadingState = "Loading level memory";
            await WaitIfNecessary();

            files_array[Mem.Lvl].GotoHeader();
            reader = files_array[Mem.Lvl].reader;

            // Animation stuff
            Pointer off_animationBank = Pointer.Current(reader);

            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            reader.ReadUInt32();
            Pointer.Read(reader);

            // Globals
            globals.off_actualWorld          = Pointer.Read(reader);
            globals.off_dynamicWorld         = Pointer.Read(reader);
            globals.off_inactiveDynamicWorld = Pointer.Read(reader);
            globals.off_fatherSector         = Pointer.Read(reader);
            reader.ReadUInt32();
            Pointer off_always = Pointer.Read(reader);

            Pointer.DoAt(ref reader, off_always, () => {
                globals.num_always      = reader.ReadUInt32();
                globals.spawnablePersos = LinkedList <Perso> .ReadHeader(reader, Pointer.Current(reader), LinkedList.Type.Double);
                globals.spawnablePersos.FillPointers(reader, globals.spawnablePersos.off_tail, globals.spawnablePersos.offset);
                globals.off_always_reusableSO = Pointer.Read(reader); // There are (num_always) empty SuperObjects starting with this one.
            });
            Pointer.Read(reader);
            Pointer off_objectTypes = Pointer.Read(reader);

            Pointer.DoAt(ref reader, off_objectTypes, () => {
                // Fill in pointers for the object type tables and read them
                objectTypes = new ObjectType[3][];
                for (uint i = 0; i < 3; i++)
                {
                    Pointer off_names_header = Pointer.Current(reader);
                    Pointer off_names_first  = Pointer.Read(reader);
                    Pointer off_names_last   = Pointer.Read(reader);
                    uint num_names           = reader.ReadUInt32();

                    FillLinkedListPointers(reader, off_names_last, off_names_header);
                    ReadObjectNamesTable(reader, off_names_first, num_names, i);
                }
            });
            Pointer.Read(reader);
            Pointer off_mainChar = Pointer.Read(reader);

            reader.ReadUInt32();
            uint    num_persoInFixPointers = reader.ReadUInt32();
            Pointer off_persoInFixPointers = Pointer.Read(reader);

            //Pointer[] persoInFixPointers = new Pointer[num_persoInFixPointers];
            Pointer.DoAt(ref reader, off_persoInFixPointers, () => {
                for (int i = 0; i < num_persoInFixPointers; i++)
                {
                    Pointer off_perso        = Pointer.Read(reader);
                    Pointer off_so           = Pointer.Read(reader);
                    byte[] unk               = reader.ReadBytes(4);
                    Pointer off_matrix       = Pointer.Current(reader); // It's better to change the pointer instead of the data as that is reused in some places
                    byte[] matrixData        = reader.ReadBytes(0x68);
                    byte[] soFlags           = reader.ReadBytes(4);
                    byte[] brothersAndParent = reader.ReadBytes(12);

                    Pointer.DoAt(ref reader, off_perso, () => {
                        reader.ReadUInt32();
                        Pointer off_stdGame = Pointer.Read(reader);
                        if (off_stdGame != null && off_so != null)
                        {
                            ((DCDAT)off_stdGame.file).OverwriteData(off_stdGame.FileOffset + 0xC, off_so.offset);
                        }
                    });
                    if (off_so != null)
                    {
                        ((DCDAT)off_so.file).OverwriteData(off_so.FileOffset + 0x14, brothersAndParent);
                        ((DCDAT)off_so.file).OverwriteData(off_so.FileOffset + 0x20, off_matrix.offset);
                        ((DCDAT)off_so.file).OverwriteData(off_so.FileOffset + 0x30, soFlags);
                    }
                }
            });

            await WaitIfNecessary();

            Pointer.Read(reader);                        // contains a pointer to the camera SO
            Pointer off_cameras  = Pointer.Read(reader); // Double linkedlist of cameras
            Pointer off_families = Pointer.Read(reader);

            Pointer.DoAt(ref reader, off_families, () => {
                families = LinkedList <Family> .ReadHeader(reader, Pointer.Current(reader), type: LinkedList.Type.Double);
                families.FillPointers(reader, families.off_tail, families.off_head);
            });
            Pointer.Read(reader); // At this pointer: a double linkedlist of fix perso's with headers (soptr, next, prev, hdr)
            Pointer.Read(reader); // Rayman
            reader.ReadUInt32();
            Pointer.Read(reader); // Camera
            reader.ReadUInt32();
            reader.ReadUInt32();

            loadingState = "Loading level textures";
            await WaitIfNecessary();

            uint    num_textures_lvl   = reader.ReadUInt32();
            uint    num_textures_total = num_textures_fix + num_textures_lvl;
            Pointer off_textures_lvl   = Pointer.Read(reader);

            Pointer.DoAt(ref reader, off_textures_lvl, () => {
                Array.Resize(ref textures, (int)num_textures_total);
                for (uint i = num_textures_fix; i < num_textures_total; i++)
                {
                    Pointer off_texture = Pointer.Read(reader);
                    textures[i]         = null;
                    Pointer.DoAt(ref reader, off_texture, () => {
                        textures[i] = TextureInfo.Read(reader, off_texture);
                    });
                }
                TEX tex = new TEX(texPaths[1]);
                for (uint i = 0; i < num_textures_lvl; i++)
                {
                    if (textures[num_textures_fix + i] != null && tex.Count > i)
                    {
                        textures[num_textures_fix + i].Texture = tex.textures[i];
                    }
                }
            });

            loadingState = "Loading families";
            await WaitIfNecessary();

            ReadFamilies(reader);
            loadingState = "Loading animation banks";
            await WaitIfNecessary();

            Pointer.DoAt(ref reader, off_animationBank, () => {
                animationBanks    = new AnimationBank[2];
                animationBanks[0] = AnimationBank.ReadDreamcast(reader, off_animationBank, off_events_fix, num_events_fix);
                animationBanks[1] = animationBanks[0];
            });
            loadingState = "Loading superobject hierarchy";
            await WaitIfNecessary();

            ReadSuperObjects(reader);
            loadingState = "Loading always structure";
            await WaitIfNecessary();

            ReadAlways(reader);
            loadingState = "Filling in cross-references";
            await WaitIfNecessary();

            ReadCrossReferences(reader);
            loadingState = "Loading behavior copies";
            await WaitIfNecessary();

            ReadBehaviorCopies(reader);
            await WaitIfNecessary();

            /*print("Sectors: " + sectors.Count);
             * for (int i = 0; i < sectors.Count; i++) {
             *      print("Sector " + i + "\t" + sectors[i].persos.Count + "\t" + sectors[i].staticLights.Count);
             * }
             * print("Persos: " + persos.Count);
             * print("World: " + superObjects.Count(so => so.type == SuperObject.Type.World));
             * print("IPOs: " + superObjects.Count(so => so.type == SuperObject.Type.IPO || so.type == SuperObject.Type.IPO_2));
             * print("POs: " + superObjects.Count(so => so.type == SuperObject.Type.PO));
             * print("SOs: " + superObjects.Count);
             * print("Families: " + families.Count);
             * print("Always: " + globals.num_always + " - Spawnables: " + globals.spawnablePersos.Count);*/

            // Parse transformation matrices and other settings for fix characters

            /*if (off_mainChar != null && off_matrix_mainChar != null) {
             * SuperObject so = SuperObject.FromOffset(off_mainChar);
             * Pointer.DoAt(ref reader, off_matrix_mainChar, () => {
             * reader.ReadUInt32();
             * reader.ReadUInt32();
             * reader.ReadUInt32();
             * reader.ReadUInt32();
             * reader.ReadUInt32();
             * reader.ReadUInt32();
             * reader.ReadUInt32();
             * reader.ReadUInt32();
             * reader.ReadUInt32();
             * Pointer off_matrix = Pointer.Current(reader);
             * Matrix mat = Matrix.Read(reader, off_matrix);
             * if (so != null) {
             * so.off_matrix = off_matrix;
             * so.matrix = mat;
             * if (so.Gao != null) {
             *  so.Gao.transform.localPosition = mat.GetPosition(convertAxes: true);
             *  so.Gao.transform.localRotation = mat.GetRotation(convertAxes: true);
             *  so.Gao.transform.localScale = mat.GetScale(convertAxes: true);
             * }
             * }
             * });
             * }*/
        }
Exemplo n.º 3
0
        async UniTask LoadLVLSNA()
        {
            loadingState = "Loading level memory";
            await WaitIfNecessary();

            Reader  reader = files_array[Mem.Lvl].reader;
            Pointer off_current;
            SNA     sna = (SNA)files_array[Mem.Lvl];

            // First read GPT
            files_array[Mem.Lvl].GotoHeader();
            reader = files_array[Mem.Lvl].reader;
            print("LVL GPT offset: " + Pointer.Current(reader));

            if (Settings.s.engineVersion == Settings.EngineVersion.Montreal)
            {
                // SDA

                /*sna.GotoSDA();
                 * print(Pointer.Current(reader));
                 * reader.ReadUInt32();
                 * reader.ReadUInt32(); // same as next
                 * uint num_strings = reader.ReadUInt32();
                 * uint indexOfTextGlobal = reader.ReadUInt32(); // dword_6EEE78
                 * uint dword_83EC58 = reader.ReadUInt32();
                 * print(num_strings + " - " + Pointer.Current(reader));
                 *
                 * // DLG
                 * sna.GotoDLG();
                 * Pointer off_strings = Pointer.Read(reader);
                 * for (int i = 0; i < num_strings; i++) {
                 *  Pointer.Read(reader);
                 * }
                 * reader.ReadUInt32();*/

                // GPT
                sna.GotoHeader();
                if (Settings.s.game != Settings.Game.PlaymobilLaura)
                {
                    Pointer.Read(reader); // sound related
                }
                Pointer.Read(reader);
                Pointer.Read(reader);
                reader.ReadUInt32();
            }
            if (Settings.s.engineVersion != Settings.EngineVersion.Montreal)
            {
                loadingState = "Reading settings for persos in fix";
                await WaitIfNecessary();

                // Fill in fix -> lvl pointers for perso's in fix
                uint      num_persoInFixPointers = reader.ReadUInt32();
                Pointer[] persoInFixPointers     = new Pointer[num_persoInFixPointers];
                for (int i = 0; i < num_persoInFixPointers; i++)
                {
                    Pointer off_perso = Pointer.Read(reader);
                    if (off_perso != null)
                    {
                        off_current = Pointer.Goto(ref reader, off_perso);
                        reader.ReadUInt32();
                        Pointer off_stdGame = Pointer.Read(reader);
                        if (off_stdGame != null)
                        {
                            if (Settings.s.engineVersion > Settings.EngineVersion.TT)
                            {
                                Pointer.Goto(ref reader, off_stdGame);
                                reader.ReadUInt32(); // type 0
                                reader.ReadUInt32(); // type 1
                                reader.ReadUInt32(); // type 2
                                Pointer off_superObject = Pointer.Read(reader);
                                Pointer.Goto(ref reader, off_current);
                                if (off_superObject == null)
                                {
                                    continue;
                                }
                            }
                            else
                            {
                                Pointer.Goto(ref reader, off_current);
                            }
                            // First read everything from the GPT
                            Pointer off_newSuperObject = null, off_nextBrother = null, off_prevBrother = null, off_father = null;
                            byte[]  matrixData = null, floatData = null, renderBits = null;
                            if (Settings.s.engineVersion > Settings.EngineVersion.TT)
                            {
                                off_newSuperObject = Pointer.Read(reader);
                                matrixData         = reader.ReadBytes(0x58);
                                renderBits         = reader.ReadBytes(4);
                                floatData          = reader.ReadBytes(4);
                                off_nextBrother    = Pointer.Read(reader);
                                off_prevBrother    = Pointer.Read(reader);
                                off_father         = Pointer.Read(reader);
                            }
                            else
                            {
                                matrixData         = reader.ReadBytes(0x58);
                                off_newSuperObject = Pointer.Read(reader);
                                Pointer.DoAt(ref reader, off_stdGame + 0xC, () => {
                                    ((SNA)off_stdGame.file).AddPointer(off_stdGame.offset + 0xC, off_newSuperObject);
                                });
                            }

                            // Then fill everything in
                            off_current = Pointer.Goto(ref reader, off_newSuperObject);
                            uint    newSOtype             = reader.ReadUInt32();
                            Pointer off_newSOengineObject = Pointer.Read(reader);
                            if (SuperObject.GetSOType(newSOtype) == SuperObject.Type.Perso)
                            {
                                persoInFixPointers[i] = off_newSOengineObject;
                                Pointer.Goto(ref reader, off_newSOengineObject);
                                Pointer off_p3dData = Pointer.Read(reader);
                                if (Settings.s.game == Settings.Game.R2Demo)
                                {
                                    ((SNA)off_p3dData.file).OverwriteData(off_p3dData.FileOffset + 0x1C, matrixData);
                                }
                                else
                                {
                                    ((SNA)off_p3dData.file).OverwriteData(off_p3dData.FileOffset + 0x18, matrixData);
                                }

                                if (Settings.s.engineVersion > Settings.EngineVersion.TT)
                                {
                                    FileWithPointers file = off_newSuperObject.file;
                                    file.AddPointer(off_newSuperObject.FileOffset + 0x14, off_nextBrother);
                                    file.AddPointer(off_newSuperObject.FileOffset + 0x18, off_prevBrother);
                                    file.AddPointer(off_newSuperObject.FileOffset + 0x1C, off_father);
                                    ((SNA)file).OverwriteData(off_newSuperObject.FileOffset + 0x30, renderBits);
                                    ((SNA)file).OverwriteData(off_newSuperObject.FileOffset + 0x38, floatData);
                                }
                            }
                            else
                            {
                                persoInFixPointers[i] = null;
                            }
                        }
                        Pointer.Goto(ref reader, off_current);
                    }
                }
            }
            loadingState = "Loading globals";
            await WaitIfNecessary();

            if (Settings.s.engineVersion > Settings.EngineVersion.Montreal)
            {
                globals.off_actualWorld          = Pointer.Read(reader);
                globals.off_dynamicWorld         = Pointer.Read(reader);
                globals.off_inactiveDynamicWorld = Pointer.Read(reader);
                globals.off_fatherSector         = Pointer.Read(reader);
                globals.off_firstSubMapPosition  = Pointer.Read(reader);
            }
            else
            {
                globals.off_actualWorld  = Pointer.Read(reader);
                globals.off_dynamicWorld = Pointer.Read(reader);
                globals.off_fatherSector = Pointer.Read(reader);
                uint soundEventIndex = reader.ReadUInt32(); // In Montreal version this is a pointer, also sound event related
                if (Settings.s.game == Settings.Game.PlaymobilLaura)
                {
                    Pointer.Read(reader);
                }
            }

            globals.num_always      = reader.ReadUInt32();
            globals.spawnablePersos = LinkedList <Perso> .ReadHeader(reader, Pointer.Current(reader), LinkedList.Type.Double);

            globals.off_always_reusableSO = Pointer.Read(reader); // There are (num_always) empty SuperObjects starting with this one.
            if (Settings.s.engineVersion > Settings.EngineVersion.Montreal)
            {
                globals.off_always_reusableUnknown1 = Pointer.Read(reader); // (num_always) * 0x2c blocks
                globals.off_always_reusableUnknown2 = Pointer.Read(reader); // (num_always) * 0x4 blocks
            }
            else
            {
                reader.ReadUInt32(); // 0x6F. In Montreal version this is a pointer to a pointer table for always
                globals.spawnablePersos.FillPointers(reader, globals.spawnablePersos.off_tail, globals.spawnablePersos.offset);
            }

            if (Settings.s.game == Settings.Game.DD)
            {
                reader.ReadUInt32();
            }
            if (Settings.s.engineVersion > Settings.EngineVersion.Montreal)
            {
                Pointer dword_4A6B1C_always_header = Pointer.Read(reader);
                Pointer dword_4A6B20_always_last   = Pointer.Read(reader);

                Pointer v28 = Pointer.Read(reader);
                Pointer v31 = Pointer.Read(reader);
                Pointer v32 = Pointer.Read(reader);
                Pointer v33 = Pointer.Read(reader);

                // These things aren't parsed, but in raycap they're null. This way we'll notice when they aren't.
                if (v28 != null)
                {
                    print("v28 is not null, it's " + v28);
                }
                if (v31 != null)
                {
                    print("v31 is not null, it's " + v31);
                }
                if (v32 != null)
                {
                    print("v32 is not null, it's " + v32);
                }
                if (v33 != null)
                {
                    print("v33 is not null, it's " + v33);
                }

                // Fill in pointers for the unknown table related to "always".
                FillLinkedListPointers(reader, dword_4A6B20_always_last, dword_4A6B1C_always_header);
            }

            // Fill in pointers for the object type tables and read them
            objectTypes = new ObjectType[3][];
            for (uint i = 0; i < 3; i++)
            {
                Pointer off_names_header = Pointer.Current(reader);
                Pointer off_names_first  = Pointer.Read(reader);
                Pointer off_names_last   = Pointer.Read(reader);
                uint    num_names        = reader.ReadUInt32();

                FillLinkedListPointers(reader, off_names_last, off_names_header);
                ReadObjectNamesTable(reader, off_names_first, num_names, i);
            }

            // Begin of engineStructure
            loadingState = "Loading engine structure";
            await WaitIfNecessary();

            print("Start of EngineStructure: " + Pointer.Current(reader));
            if (Settings.s.engineVersion > Settings.EngineVersion.Montreal)
            {
                reader.ReadByte();
                string mapName = reader.ReadString(0x1E);
                reader.ReadChars(0x1E);
                string mapName2 = reader.ReadString(0x1E);
                reader.ReadByte();
                reader.ReadBytes(0x178); // don't know what this data is
            }
            else
            {
                reader.ReadByte();
                string mapName = reader.ReadString(0x104);
                reader.ReadChars(0x104);
                string mapName2 = reader.ReadString(0x104);
                if (Settings.s.game == Settings.Game.PlaymobilLaura)
                {
                    reader.ReadChars(0x104);
                    reader.ReadChars(0x104);
                }
                string mapName3 = reader.ReadString(0x104);
                if (Settings.s.game == Settings.Game.TT)
                {
                    reader.ReadBytes(0x47F7); // don't know what this data is
                }
                else if (Settings.s.game == Settings.Game.TTSE)
                {
                    reader.ReadBytes(0x240F);
                }
                else if (Settings.s.game == Settings.Game.PlaymobilLaura)
                {
                    reader.ReadBytes(0x240F); // don't know what this data is
                }
                else                          // Hype & Alex
                {
                    reader.ReadBytes(0x2627); // don't know what this data is
                }
            }
            Pointer off_unknown_first = Pointer.Read(reader);
            Pointer off_unknown_last  = Pointer.Read(reader);
            uint    num_unknown       = reader.ReadUInt32();

            families = LinkedList <Family> .ReadHeader(reader, Pointer.Current(reader), type : LinkedList.Type.Double);

            families.FillPointers(reader, families.off_tail, families.off_head);

            if (Settings.s.game == Settings.Game.PlaymobilLaura)
            {
                LinkedList <int> .ReadHeader(reader, Pointer.Current(reader), type : LinkedList.Type.Double);
            }

            LinkedList <SuperObject> alwaysActiveCharacters = LinkedList <SuperObject> .ReadHeader(reader, Pointer.Current(reader), type : LinkedList.Type.Double);

            if (Settings.s.engineVersion > Settings.EngineVersion.Montreal)
            {
                reader.ReadUInt32();
                reader.ReadUInt32();
                reader.ReadUInt32();
                if (Settings.s.game == Settings.Game.RedPlanet || Settings.s.game == Settings.Game.R2Demo)
                {
                    reader.ReadUInt32();
                }
                Pointer off_languages = Pointer.Read(reader);
                reader.ReadUInt32();

                Pointer.DoAt(ref reader, off_languages, () => {
                    ReadLanguages(reader, off_languages, localization.num_languages);
                });

                for (uint i = 0; i < 2; i++)
                {
                    Pointer off_matrix = Pointer.Current(reader);
                    Matrix  mat        = Matrix.Read(reader, off_matrix);
                }

                reader.ReadUInt32();
                reader.ReadUInt16();

                ReadLevelNames(reader, Pointer.Current(reader), 80);
                uint num_mapNames = reader.ReadUInt32();
                Array.Resize(ref levels, (int)num_mapNames);
                reader.ReadUInt16();
                reader.ReadUInt32();
                reader.ReadUInt32();

                if (Settings.s.game == Settings.Game.DD)
                {
                    reader.ReadUInt32();
                }

                // End of engineStructure
                Pointer off_light    = Pointer.Read(reader); // the offset of a light. It's just an ordinary light.
                Pointer off_mainChar = Pointer.Read(reader); // superobject
                Pointer off_characterLaunchingSoundEvents = Pointer.Read(reader);
                if (Settings.s.game == Settings.Game.DD)
                {
                    globals.off_backgroundGameMaterial = Pointer.Read(reader);
                }
                Pointer off_shadowPolygonVisualMaterial   = Pointer.Read(reader);
                Pointer off_shadowPolygonGameMaterialInit = Pointer.Read(reader);
                Pointer off_shadowPolygonGameMaterial     = Pointer.Read(reader);
                Pointer off_textureOfTextureShadow        = Pointer.Read(reader);
                Pointer off_col_taggedFacesTable          = Pointer.Read(reader);

                for (int i = 0; i < 10; i++)
                {
                    Pointer off_elementForShadow      = Pointer.Read(reader);
                    Pointer off_geometricShadowObject = Pointer.Read(reader);
                }
                Pointer.Read(reader); // DemoSOList

                if (Settings.s.game == Settings.Game.R2Demo || Settings.s.game == Settings.Game.RedPlanet || Settings.s.mode == Settings.Mode.DonaldDuckPCDemo)
                {
                    Pointer.Read(reader);
                }

                if (Settings.s.mode == Settings.Mode.DonaldDuckPCDemo)
                {
                    reader.ReadUInt32();
                    reader.ReadUInt32();
                }

                loadingState = "Loading level animation bank";
                //print("Animation bank: " + Pointer.Current(reader));
                await WaitIfNecessary();

                AnimationBank.Read(reader, Pointer.Current(reader), 0, 1, files_array[Mem.LvlKeyFrames], append: true);
                animationBanks[1] = animationBanks[0];
            }
            if (FileSystem.mode != FileSystem.Mode.Web)
            {
                string levelsFolder = gameDataBinFolder + ConvertPath(gameDsb.levelsDataPath) + "/";
                ((SNA)files_array[0]).CreateMemoryDump(levelsFolder + "fix.dmp", true);
                ((SNA)files_array[1]).CreateMemoryDump(levelsFolder + lvlName + "/" + lvlName + ".dmp", true);
            }

            // Read PTX
            loadingState = "Loading level textures";
            await WaitIfNecessary();

            // Can't yield inside a lambda, so we must do it the old fashioned way, with off_current
            if (sna.PTX != null)
            {
                off_current = Pointer.Goto(ref reader, sna.PTX);
                await ReadTexturesLvl(reader, Pointer.Current(reader));

                Pointer.Goto(ref reader, off_current);
            }

            /*Pointer.DoAt(ref reader, sna.PTX, () => {
             * ReadTexturesLvl(reader, Pointer.Current(reader));
             * });*/

            // Read background game material (DD only)
            globals.backgroundGameMaterial = GameMaterial.FromOffsetOrRead(globals.off_backgroundGameMaterial, reader);

            // Parse actual world & always structure
            loadingState = "Loading families";
            await WaitIfNecessary();

            ReadFamilies(reader);

            loadingState = "Creating animation bank";
            await WaitIfNecessary();

            if (Settings.s.engineVersion == Settings.EngineVersion.Montreal)
            {
                animationBanks    = new AnimationBank[2];
                animationBanks[0] = new AnimationBank(null)
                {
                    animations = new Animation.Component.AnimA3DGeneral[0]
                };
                animationBanks[1] = animationBanks[0];
            }
            else if (Settings.s.engineVersion <= Settings.EngineVersion.TT)
            {
                uint maxAnimIndex = 0;
                foreach (State s in states)
                {
                    if (s.anim_ref != null && s.anim_ref.anim_index > maxAnimIndex)
                    {
                        maxAnimIndex = s.anim_ref.anim_index;
                    }
                }
                animationBanks    = new AnimationBank[2];
                animationBanks[0] = new AnimationBank(null)
                {
                    animations = new Animation.Component.AnimA3DGeneral[maxAnimIndex + 1]
                };
                foreach (State s in states)
                {
                    if (s.anim_ref != null)
                    {
                        animationBanks[0].animations[s.anim_ref.anim_index] = s.anim_ref.a3d;
                    }
                }
                animationBanks[1] = animationBanks[0];
            }

            loadingState = "Loading superobject hierarchy";
            await WaitIfNecessary();
            await ReadSuperObjects(reader);

            loadingState = "Loading always structure";
            await WaitIfNecessary();

            ReadAlways(reader);
            loadingState = "Filling in cross-references";
            await WaitIfNecessary();

            ReadCrossReferences(reader);

            // TODO: Make more generic
            if (Settings.s.game == Settings.Game.R2)
            {
                loadingState = "Filling in comport names";
                await WaitIfNecessary();

                string path = gameDataBinFolder + "R2DC_Comports.json";

                if (!FileSystem.FileExists(path))
                {
                    path = "Assets/StreamingAssets/R2DC_Comports.json"; // Offline, the json doesn't exist, so grab it from StreamingAssets
                }

                Stream stream = FileSystem.GetFileReadStream(path);
                if (stream != null)
                {
                    ReadAndFillComportNames(stream);
                }
            }
        }
Exemplo n.º 4
0
        async UniTask LoadFIXSNA()
        {
            loadingState = "Loading fixed memory";
            await WaitIfNecessary();

            files_array[Mem.Fix].GotoHeader();
            Reader reader = files_array[Mem.Fix].reader;

            print("FIX GPT offset: " + Pointer.Current(reader));
            SNA sna = (SNA)files_array[Mem.Fix];

            if (Settings.s.engineVersion <= Settings.EngineVersion.TT)
            {
                // Tonic Trouble
                inputStruct = new InputStructure(null);
                uint stringCount = Settings.s.game == Settings.Game.TTSE ? 351 : (uint)gameDsb.textFiles.Sum(t => t.strings.Count);
                Pointer.Read(reader);
                Pointer.Read(reader);
                Pointer.Read(reader);
                if (Settings.s.game == Settings.Game.TTSE)
                {
                    for (int i = 0; i < 50; i++)
                    {
                        Pointer.Read(reader);
                    }
                }
                else
                {
                    for (int i = 0; i < 100; i++)
                    {
                        Pointer.Read(reader);
                    }
                }
                reader.ReadUInt32(); // 0x35
                if (Settings.s.game != Settings.Game.TTSE)
                {
                    reader.ReadBytes(0x80);                                        // contains strings like MouseXPos, input related. first dword of this is a pointer to inputstructure probably
                }
                reader.ReadBytes(0x90);
                Pointer.Read(reader);
                reader.ReadUInt32(); // 0x28
                reader.ReadUInt32(); // 0x1
                if (Settings.s.game == Settings.Game.TTSE)
                {
                    Pointer.Read(reader);
                }
                for (int i = 0; i < 100; i++)
                {
                    Pointer.Read(reader);
                }
                for (int i = 0; i < 100; i++)
                {
                    Pointer.Read(reader);
                }
                reader.ReadUInt32(); // 0x1
                if (Settings.s.game == Settings.Game.TTSE)
                {
                    reader.ReadBytes(0xB4);
                }
                else
                {
                    if (stringCount != 598)   // English version and probably other versions have 603 strings. It's a hacky way to check which version.
                    {
                        reader.ReadBytes(0x2CC);
                    }
                    else     // French version: 598
                    {
                        reader.ReadBytes(0x2C0);
                    }
                }
                reader.ReadBytes(0x1C);

                // Init strings
                reader.ReadUInt32(); // 0
                reader.ReadUInt32(); // 1
                reader.ReadUInt32(); // ???
                Pointer.Read(reader);
                for (int i = 0; i < stringCount; i++)
                {
                    Pointer.Read(reader);                  // read num_loaded_strings pointers here
                }
                reader.ReadBytes(0xC);                     // dword_51A728. probably a table of some sort: 2 ptrs and a number
                if (Settings.s.game != Settings.Game.TTSE) // There's more but what is even the point in reading all this
                {
                    reader.ReadUInt32();
                    Pointer.Read(reader);
                    reader.ReadBytes(0x14);
                    Pointer.Read(reader);
                    Pointer.Read(reader);
                    Pointer.Read(reader);
                    Pointer.Read(reader);
                    Pointer.Read(reader);
                    Pointer.Read(reader);
                    Pointer.Read(reader);
                    Pointer.Read(reader);
                    reader.ReadUInt32(); // 0, so can be pointer too
                    reader.ReadUInt32(); // 0, so can be pointer too
                    reader.ReadUInt32(); // 0, so can be pointer too
                    reader.ReadUInt32(); // 0, so can be pointer too
                    reader.ReadUInt32(); // 0, so can be pointer too
                    reader.ReadUInt32(); // 0, so can be pointer too
                    reader.ReadUInt32(); // 0, so can be pointer too
                    reader.ReadUInt32(); // 0, so can be pointer too
                    reader.ReadBytes(0x30);
                    reader.ReadBytes(0x960);
                }
            }
            else if (Settings.s.engineVersion == Settings.EngineVersion.Montreal)
            {
                uint num_strings = 0;
                inputStruct = new InputStructure(null);

                // SDA
                Pointer.DoAt(ref reader, sna.SDA, () => {
                    print(Pointer.Current(reader));
                    reader.ReadUInt32();
                    reader.ReadUInt32();                          // same as next
                    num_strings            = reader.ReadUInt32();
                    uint indexOfTextGlobal = reader.ReadUInt32(); // dword_6EEE78
                    uint dword_83EC58      = reader.ReadUInt32();
                    print(num_strings + " - " + Pointer.Current(reader));
                });

                // DLG
                Pointer.DoAt(ref reader, sna.DLG, () => {
                    Pointer off_strings = Pointer.Read(reader);
                    for (int i = 0; i < num_strings; i++)
                    {
                        Pointer.Read(reader);
                    }
                    reader.ReadUInt32();
                });

                // GPT
                sna.GotoHeader();
                Pointer.Read(reader);
                Pointer off_mainLight      = Pointer.Read(reader);
                uint    lpPerformanceCount = reader.ReadUInt32();
                Pointer.Read(reader);
                Pointer off_defaultMaterial  = Pointer.Read(reader);
                Pointer off_geometricObject1 = Pointer.Read(reader);
                Pointer off_geometricObject2 = Pointer.Read(reader);
                Pointer off_geometricObject3 = Pointer.Read(reader);
                reader.ReadBytes(0x90);   // FON_ related
                reader.ReadBytes(0x3D54); // FON_ related
                for (int i = 0; i < 100; i++)
                {
                    Pointer.Read(reader);                 // matrix in stack
                }
                uint matrixInStack = reader.ReadUInt32(); // number of matrix in stack
                reader.ReadBytes(0xC);
                reader.ReadBytes(0x20);
                reader.ReadUInt32();
                reader.ReadUInt32();
                Pointer.Read(reader);
                Pointer.Read(reader);
                for (int i = 0; i < num_strings; i++)
                {
                    Pointer.Read(reader);
                }
                LinkedList <int> fontDefinitions = LinkedList <int> .ReadHeader(reader, Pointer.Current(reader));

                Pointer.Read(reader);
                reader.ReadUInt32();
                reader.ReadUInt32();
                reader.ReadUInt32();
                Pointer off_geometricObject4 = Pointer.Read(reader);
                Pointer off_geometricObject5 = Pointer.Read(reader);
                Pointer off_geometricObject6 = Pointer.Read(reader);
                Pointer off_visualmaterial1  = Pointer.Read(reader);
                Pointer off_visualmaterial2  = Pointer.Read(reader);
                for (int i = 0; i < 10; i++)
                {
                    Pointer off_texture = Pointer.Read(reader);
                }
                Pointer off_visualmaterial3         = Pointer.Read(reader);
                Pointer off_gamematerial            = Pointer.Read(reader);
                uint    geometricElementIndexGlobal = reader.ReadUInt32();
                Pointer off_texture2         = Pointer.Read(reader);
                Pointer off_geometricObject7 = Pointer.Read(reader);
                for (uint i = 0; i < 7; i++)
                {
                    Pointer.Read(reader); // Material for stencils. Order: corner, border, center, side, redarrow, bullet, and another one
                }
                Pointer dword_5DCB9C = Pointer.Read(reader);

                // Now comes INV_fn_vSnaMultilanguageLoading


                print(Pointer.Current(reader));
            }
            else
            {
                Pointer off_identityMatrix = Pointer.Read(reader);
                reader.ReadBytes(50 * 4);
                uint    matrixInStack             = reader.ReadUInt32();
                Pointer off_collisionGeoObj       = Pointer.Read(reader);
                Pointer off_staticCollisionGeoObj = Pointer.Read(reader);
                loadingState = "Loading input structure";
                await WaitIfNecessary();

                for (int i = 0; i < Settings.s.numEntryActions; i++)
                {
                    Pointer.Read(reader); // 3DOS_EntryActions
                }
                Pointer off_IPT_keyAndPadDefine = Pointer.Read(reader);
                ReadKeypadDefine(reader, off_IPT_keyAndPadDefine);

                inputStruct = InputStructure.Read(reader, Pointer.Current(reader));
                foreach (EntryAction ea in inputStruct.entryActions)
                {
                    print(ea.ToString());
                }
                print("Num entractions: " + inputStruct.num_entryActions);
                print("Off entryactions: " + inputStruct.off_entryActions);
                Pointer off_IPT_entryElementList = Pointer.Read(reader);
                print("Off entryelements: " + off_IPT_entryElementList);

                loadingState = "Loading text";
                await WaitIfNecessary();

                localization = FromOffsetOrRead <LocalizationStructure>(reader, Pointer.Current(reader), inline: true); // FON_g_stGeneral

                loadingState = "Loading fixed animation bank";
                await WaitIfNecessary();

                animationBanks    = new AnimationBank[2]; // 1 in fix, 1 in lvl
                animationBanks[0] = AnimationBank.Read(reader, Pointer.Current(reader), 0, 1, files_array[Mem.FixKeyFrames])[0];
                print("Fix animation bank: " + animationBanks[0].off_header);
                Pointer off_fixInfo = Pointer.Read(reader);
            }

            // Read PTX
            loadingState = "Loading fixed textures";
            await WaitIfNecessary();

            // Can't yield inside a lambda, so we must do it the old fashioned way, with off_current
            if (sna.PTX != null)
            {
                Pointer off_current = Pointer.Goto(ref reader, sna.PTX);
                await ReadTexturesFix(reader, Pointer.Current(reader));

                Pointer.Goto(ref reader, off_current);
            }

            /*Pointer.DoAt(ref reader, sna.PTX, () => {
             *  ReadTexturesFix(reader, Pointer.Current(reader));
             * });*/
        }
Exemplo n.º 5
0
        async Task LoadLVL()
        {
            loadingState = "Loading level memory";
            await WaitIfNecessary();

            files_array[Mem.Lvl].GotoHeader();
            Reader reader    = files_array[Mem.Lvl].reader;
            long   totalSize = reader.BaseStream.Length;

            //reader.ReadUInt32();
            if (Settings.s.game == Settings.Game.R3 &&
                (Settings.s.platform == Settings.Platform.PC ||
                 Settings.s.platform == Settings.Platform.Xbox ||
                 Settings.s.platform == Settings.Platform.Xbox360 ||
                 Settings.s.platform == Settings.Platform.PS3))
            {
                reader.ReadUInt32();                 // fix checksum?
            }
            reader.ReadUInt32();
            reader.ReadUInt32();
            reader.ReadUInt32();
            reader.ReadUInt32();
            if (Settings.s.platform == Settings.Platform.PC ||
                Settings.s.platform == Settings.Platform.Xbox ||
                Settings.s.platform == Settings.Platform.Xbox360 ||
                Settings.s.platform == Settings.Platform.PS3)
            {
                if (Settings.s.game == Settings.Game.R3)
                {
                    string timeStamp = reader.ReadString(0x18);
                    reader.ReadUInt32();
                    reader.ReadUInt32();
                    reader.ReadUInt32();
                    reader.ReadUInt32();
                    reader.ReadUInt32();
                    reader.ReadUInt32();
                    reader.ReadUInt32();
                }
                else if (Settings.s.game == Settings.Game.RM ||
                         Settings.s.game == Settings.Game.RA ||
                         Settings.s.game == Settings.Game.Dinosaur)
                {
                    reader.ReadUInt32();
                    reader.ReadUInt32();
                }
            }
            reader.ReadBytes(0x104);             // vignette
            if (Settings.s.game != Settings.Game.Dinosaur)
            {
                reader.ReadUInt32();
            }
            loadingState = "Loading level textures";
            await ReadTexturesLvl(reader, Pointer.Current(reader));

            if ((Settings.s.platform == Settings.Platform.PC ||
                 Settings.s.platform == Settings.Platform.Xbox ||
                 Settings.s.platform == Settings.Platform.Xbox360 ||
                 Settings.s.platform == Settings.Platform.PS3) &&
                !hasTransit && Settings.s.game != Settings.Game.Dinosaur)
            {
                Pointer off_lightMapTexture = Pointer.Read(reader);                 // g_p_stLMTexture
                Pointer.DoAt(ref reader, off_lightMapTexture, () => {
                    lightmapTexture = TextureInfo.Read(reader, off_lightMapTexture);
                });
                if (Settings.s.game == Settings.Game.R3)
                {
                    Pointer off_overlightTexture = Pointer.Read(reader);                     // *(_DWORD *)(GLI_BIG_GLOBALS + 370068)
                    Pointer.DoAt(ref reader, off_overlightTexture, () => {
                        overlightTexture = TextureInfo.Read(reader, off_overlightTexture);
                    });
                }
            }
            Pointer off_animBankLvl = null;

            if (Settings.s.game == Settings.Game.Dinosaur)
            {
                // animation bank is read right here.
                off_animBankLvl = Pointer.Current(reader);                 // Note: only one 0x104 bank in fix.
                print("Lvl animation bank address: " + off_animBankLvl);
                animationBanks = new AnimationBank[5];
                AnimationBank[] banks = AnimationBank.Read(reader, off_animBankLvl, 0, 1, files_array[Mem.LvlKeyFrames]);
                animationBanks[0] = banks[0];
            }
            loadingState = "Loading globals";
            await WaitIfNecessary();

            globals.off_transitDynamicWorld = null;
            globals.off_actualWorld         = Pointer.Read(reader);
            globals.off_dynamicWorld        = Pointer.Read(reader);
            if (Settings.s.game == Settings.Game.R3 &&
                (Settings.s.platform == Settings.Platform.PC ||
                 Settings.s.platform == Settings.Platform.Xbox ||
                 Settings.s.platform == Settings.Platform.Xbox360 ||
                 Settings.s.platform == Settings.Platform.PS3))
            {
                reader.ReadUInt32();                 // ???
            }
            globals.off_inactiveDynamicWorld = Pointer.Read(reader);
            globals.off_fatherSector         = Pointer.Read(reader);     // It is I, Father Sector.
            globals.off_firstSubMapPosition  = Pointer.Read(reader);
            globals.num_always      = reader.ReadUInt32();
            globals.spawnablePersos = LinkedList <Perso> .ReadHeader(reader, Pointer.Current(reader), LinkedList.Type.Double);

            globals.off_always_reusableSO       = Pointer.Read(reader);       // There are (num_always) empty SuperObjects starting with this one.
            globals.off_always_reusableUnknown1 = Pointer.Read(reader);       // (num_always) * 0x2c blocks
            globals.off_always_reusableUnknown2 = Pointer.Read(reader);       // (num_always) * 0x4 blocks

            // Read object types
            objectTypes = new ObjectType[3][];
            for (uint i = 0; i < 3; i++)
            {
                Pointer off_names_header = Pointer.Current(reader);
                Pointer off_names_first  = Pointer.Read(reader);
                Pointer off_names_last   = Pointer.Read(reader);
                uint    num_names        = reader.ReadUInt32();

                ReadObjectNamesTable(reader, off_names_first, num_names, i);
            }

            Pointer off_light = Pointer.Read(reader);             // the offset of a light. It's just an ordinary light.
            Pointer off_characterLaunchingSoundEvents = Pointer.Read(reader);
            Pointer off_collisionGeoObj       = Pointer.Read(reader);
            Pointer off_staticCollisionGeoObj = Pointer.Read(reader);

            if (!hasTransit)
            {
                reader.ReadUInt32();                 // viewport related <--- cameras in here
            }

            Pointer off_unknown_first = Pointer.Read(reader);
            Pointer off_unknown_last  = Pointer.Read(reader);
            uint    num_unknown       = reader.ReadUInt32();

            families = LinkedList <Family> .ReadHeader(reader, Pointer.Current(reader), type : LinkedList.Type.Double);

            Pointer off_alwaysActiveCharacters_first = Pointer.Read(reader);
            Pointer off_alwaysActiveCharacters_last  = Pointer.Read(reader);
            uint    num_alwaysActiveChars            = reader.ReadUInt32();

            if (!hasTransit)
            {
                Pointer off_mainCharacters_first   = Pointer.Read(reader);
                Pointer off_mainCharacters_last    = Pointer.Read(reader);
                uint    num_mainCharacters_entries = reader.ReadUInt32();
            }

            reader.ReadUInt32();             // only used if there was no transit in the previous lvl. Always 00165214 in R3GC?
            reader.ReadUInt32();             // related to "SOL". What is this? Good question.
            reader.ReadUInt32();             // same
            if (Settings.s.game != Settings.Game.Dinosaur)
            {
                reader.ReadUInt32();                 // same
            }
            Pointer off_cineManager  = Pointer.Read(reader);
            byte    unk              = reader.ReadByte();
            byte    IPO_numRLItables = reader.ReadByte();

            reader.ReadUInt16();
            Pointer off_COL_taggedFacesTable = Pointer.Read(reader);
            uint    num_COL_maxTaggedFaces   = reader.ReadUInt32();

            off_collisionGeoObj       = Pointer.Read(reader);
            off_staticCollisionGeoObj = Pointer.Read(reader);

            // The ptrsTable seems to be related to sound events. Perhaps cuuids.
            reader.ReadUInt32();
            if (Settings.s.game == Settings.Game.Dinosaur)
            {
                for (int i = 0; i < 50; i++)
                {
                    reader.ReadUInt32();
                }
                // Actually, the previous uint is an amount for this array of uints, but it's padded to always be 50 long
            }
            uint num_ptrsTable = reader.ReadUInt32();

            if (Settings.s.game == Settings.Game.R3)
            {
                uint bool_ptrsTable = reader.ReadUInt32();
            }
            Pointer off_ptrsTable = Pointer.Read(reader);


            uint num_internalStructure = num_ptrsTable;

            if (Settings.s.mode == Settings.Mode.Rayman3GC)
            {
                reader.ReadUInt32();
            }
            Pointer off_internalStructure_first = Pointer.Read(reader);
            Pointer off_internalStructure_last  = Pointer.Read(reader);

            if (!hasTransit && Settings.s.game == Settings.Game.R3)
            {
                uint    num_geometric              = reader.ReadUInt32();
                Pointer off_array_geometric        = Pointer.Read(reader);
                Pointer off_array_geometric_RLI    = Pointer.Read(reader);
                Pointer off_array_transition_flags = Pointer.Read(reader);
            }
            else if (Settings.s.game == Settings.Game.RA ||
                     Settings.s.game == Settings.Game.RM ||
                     Settings.s.game == Settings.Game.Dinosaur ||
                     Settings.s.game == Settings.Game.DDPK)
            {
                uint    num_unk   = reader.ReadUInt32();
                Pointer unk_first = Pointer.Read(reader);
                if (Settings.s.game != Settings.Game.Dinosaur)
                {
                    Pointer unk_last = Pointer.Read(reader);
                }
            }
            uint    num_visual_materials       = reader.ReadUInt32();
            Pointer off_array_visual_materials = Pointer.Read(reader);

            if (Settings.s.mode != Settings.Mode.RaymanArenaGC &&
                Settings.s.mode != Settings.Mode.RaymanArenaGCDemo &&
                Settings.s.mode != Settings.Mode.DonaldDuckPKGC)
            {
                Pointer off_dynamic_so_list = Pointer.Read(reader);

                // Parse SO list
                Pointer.DoAt(ref reader, off_dynamic_so_list, () => {
                    LinkedList <SuperObject> .ReadHeader(reader, off_dynamic_so_list);

                    /*Pointer off_so_list_first = Pointer.Read(reader);
                     * Pointer off_so_list_last = Pointer.Read(reader);
                     * Pointer off_so_list_current = off_so_list_first;
                     * uint num_so_list = reader.ReadUInt32();*/
                    /*if (experimentalObjectLoading) {
                     * for (uint i = 0; i < num_so_list; i++) {
                     * R3Pointer.Goto(ref reader, off_so_list_current);
                     * R3Pointer off_so_list_next = R3Pointer.Read(reader);
                     * R3Pointer off_so_list_prev = R3Pointer.Read(reader);
                     * R3Pointer off_so_list_start = R3Pointer.Read(reader);
                     * R3Pointer off_so = R3Pointer.Read(reader);
                     * R3Pointer.Goto(ref reader, off_so);
                     * ParseSuperObject(reader, off_so, true, true);
                     * off_so_list_current = off_so_list_next;
                     * }
                     * }*/
                });
            }

            // Parse materials list
            loadingState = "Loading visual materials";
            await WaitIfNecessary();

            Pointer.DoAt(ref reader, off_array_visual_materials, () => {
                for (uint i = 0; i < num_visual_materials; i++)
                {
                    Pointer off_material = Pointer.Read(reader);
                    Pointer.DoAt(ref reader, off_material, () => {
                        //print(Pointer.Current(reader));
                        visualMaterials.Add(VisualMaterial.Read(reader, off_material));
                    });
                }
            });

            if (hasTransit)
            {
                loadingState = "Loading transit memory";
                await WaitIfNecessary();

                Pointer off_transit = new Pointer(16, files_array[Mem.Transit]);                 // It's located at offset 20 in transit
                Pointer.DoAt(ref reader, off_transit, () => {
                    if (Settings.s.platform == Settings.Platform.PC ||
                        Settings.s.platform == Settings.Platform.Xbox ||
                        Settings.s.platform == Settings.Platform.Xbox360 ||
                        Settings.s.platform == Settings.Platform.PS3)
                    {
                        Pointer off_lightMapTexture = Pointer.Read(reader);                         // g_p_stLMTexture
                        Pointer.DoAt(ref reader, off_lightMapTexture, () => {
                            lightmapTexture = TextureInfo.Read(reader, off_lightMapTexture);
                        });
                        if (Settings.s.game == Settings.Game.R3)
                        {
                            Pointer off_overlightTexture = Pointer.Read(reader);                             // *(_DWORD *)(GLI_BIG_GLOBALS + 370068)
                            Pointer.DoAt(ref reader, off_overlightTexture, () => {
                                overlightTexture = TextureInfo.Read(reader, off_overlightTexture);
                            });
                        }
                    }
                    globals.off_transitDynamicWorld  = Pointer.Read(reader);
                    globals.off_actualWorld          = Pointer.Read(reader);
                    globals.off_dynamicWorld         = Pointer.Read(reader);
                    globals.off_inactiveDynamicWorld = Pointer.Read(reader);
                });
            }

            // Parse actual world & always structure
            loadingState = "Loading families";
            await WaitIfNecessary();

            ReadFamilies(reader);
            loadingState = "Loading superobject hierarchy";
            await WaitIfNecessary();

            ReadSuperObjects(reader);
            loadingState = "Loading always structure";
            await WaitIfNecessary();

            ReadAlways(reader);


            Pointer.DoAt(ref reader, off_cineManager, () => {
                cinematicsManager = CinematicsManager.Read(reader, off_cineManager);
            });

            // off_current should be after the dynamic SO list positions.

            // Parse transformation matrices and other settings(state? :o) for fix characters
            loadingState = "Loading settings for persos in fix";
            await WaitIfNecessary();

            uint num_perso_with_settings_in_fix = (uint)persoInFix.Length;

            if (Settings.s.game == Settings.Game.R3)
            {
                num_perso_with_settings_in_fix = reader.ReadUInt32();
            }
            for (int i = 0; i < num_perso_with_settings_in_fix; i++)
            {
                Pointer     off_perso_so_with_settings_in_fix = null, off_matrix = null;
                SuperObject so = null;
                Matrix      mat = null;
                if (Settings.s.game == Settings.Game.R3)
                {
                    off_perso_so_with_settings_in_fix = Pointer.Read(reader);
                    off_matrix = Pointer.Current(reader);
                    mat        = Matrix.Read(reader, off_matrix);
                    reader.ReadUInt32();                     // is one of these the state? doesn't appear to change tho
                    reader.ReadUInt32();
                    so = SuperObject.FromOffset(off_perso_so_with_settings_in_fix);
                }
                else if (Settings.s.game == Settings.Game.RA ||
                         Settings.s.game == Settings.Game.RM ||
                         Settings.s.game == Settings.Game.Dinosaur)
                {
                    off_matrix = Pointer.Current(reader);
                    mat        = Matrix.Read(reader, off_matrix);
                    so         = superObjects.FirstOrDefault(s => s.off_data == persoInFix[i]);
                }
                if (so != null)
                {
                    so.off_matrix = off_matrix;
                    so.matrix     = mat;
                    if (so.Gao != null)
                    {
                        so.Gao.transform.localPosition = mat.GetPosition(convertAxes: true);
                        so.Gao.transform.localRotation = mat.GetRotation(convertAxes: true);
                        so.Gao.transform.localScale    = mat.GetScale(convertAxes: true);
                    }
                }
            }
            if (Settings.s.platform == Settings.Platform.GC)
            {
                reader.ReadBytes(0x800);                 // floats
            }
            loadingState = "Loading animation banks";
            await WaitIfNecessary();

            if (Settings.s.game != Settings.Game.Dinosaur)
            {
                off_animBankLvl = Pointer.Read(reader);                 // Note: 4 0x104 banks in lvl.
                print("Lvl animation bank address: " + off_animBankLvl);
                animationBanks = new AnimationBank[5];
                if (off_animBankFix != off_animBankLvl)
                {
                    Pointer.DoAt(ref reader, off_animBankFix, () => {
                        animationBanks[0] = AnimationBank.Read(reader, off_animBankFix, 0, 1, files_array[Mem.FixKeyFrames])[0];
                    });
                }
                Pointer.DoAt(ref reader, off_animBankLvl, () => {
                    AnimationBank[] banks = AnimationBank.Read(reader, off_animBankLvl, 1, 4, files_array[Mem.LvlKeyFrames]);
                    for (int i = 0; i < 4; i++)
                    {
                        animationBanks[1 + i] = banks[i];
                    }
                });
                if (off_animBankFix == off_animBankLvl)
                {
                    animationBanks[0] = animationBanks[1];
                }
            }
            // Load additional animation banks
            string extraAnimFolder = "Anim/";

            if (Settings.s.mode == Settings.Mode.RaymanArenaGCDemo)
            {
                extraAnimFolder = lvlName + "/";
            }
            for (int i = 0; i < families.Count; i++)
            {
                if (families[i] != null && families[i].animBank > 4 && objectTypes[0][families[i].family_index].id != 0xFF)
                {
                    int animBank = families[i].animBank;
                    loadingState = "Loading additional animation bank " + animBank;
                    await WaitIfNecessary();

                    int animFileID = objectTypes[0][families[i].family_index].id;
                    if (Settings.s.mode == Settings.Mode.RaymanArenaGCDemo)
                    {
                        animFileID = animBank - 5;
                    }
                    string animName = extraAnimFolder + "ani" + animFileID.ToString();
                    string kfName   = extraAnimFolder + "key" + animFileID.ToString() + "kf";

                    //print(animBank + " - " + objectTypes[0][families[i].family_index].id);
                    int fileID   = animBank + 102;
                    int kfFileID = animBank + 2;                     // Anim bank will start at 5, so this will start at 7
                    if (Settings.s.game == Settings.Game.RM)
                    {
                        fileID = animBank;
                    }

                    // Prepare files for WebGL
                    await PrepareFile(gameDataBinFolder + animName + ".lvl");

                    if (FileSystem.FileExists(gameDataBinFolder + animName + ".lvl"))
                    {
                        await PrepareFile(gameDataBinFolder + animName + ".ptr");
                    }
                    await PrepareFile(gameDataBinFolder + kfName + ".lvl");

                    if (FileSystem.FileExists(gameDataBinFolder + kfName + ".lvl"))
                    {
                        await PrepareFile(gameDataBinFolder + kfName + ".ptr");
                    }

                    FileWithPointers animFile = InitExtraLVL(animName, fileID);
                    FileWithPointers kfFile   = InitExtraLVL(kfName, fileID);
                    if (animFile != null)
                    {
                        if (animBank >= animationBanks.Length)
                        {
                            Array.Resize(ref animationBanks, animBank + 1);
                        }
                        Pointer off_animBankExtra = new Pointer(0, animFile);
                        Pointer.DoAt(ref reader, off_animBankExtra, () => {
                            int alignBytes = reader.ReadInt32();
                            if (alignBytes > 0)
                            {
                                reader.Align(4, alignBytes);
                            }
                            off_animBankExtra        = Pointer.Current(reader);
                            animationBanks[animBank] = AnimationBank.Read(reader, off_animBankExtra, (uint)animBank, 1, kfFile)[0];
                        });
                    }
                }
            }

            loadingState = "Filling in cross-references";
            await WaitIfNecessary();

            ReadCrossReferences(reader);
        }
Exemplo n.º 6
0
        static int Main(string[] args)
        {
            if (args.Length < 3)
            {
                return(-1);
            }

            TestBench.StartLogging(ELogType.Warning);

            Level level = TestBench.LoadAndTrackLVL(args[0]);

            if (level == null)
            {
                TestBench.StopLogging();
                return(-1);
            }

            string animSetName   = args[1];
            string animationName = args[2];

            List <uint> boneCRCs = new List <uint>();

            for (int i = 0; i < args.Length - 3; i++)
            {
                boneCRCs.Add(HashUtils.GetCRC(args[3 + i]));
            }


            AnimationBank bank = level.GetAnimationBank(animSetName);

            if (bank == null)
            {
                Console.WriteLine("Animation bank not found!");
                TestBench.StopLogging();
                return(-1);
            }


            uint[] animHashes = bank.GetAnimationCRCs();

            foreach (uint hash in animHashes)
            {
                if (hash == HashUtils.GetCRC(animationName))
                {
                    bank.GetAnimationMetadata(hash, out int numFrames, out int numBones);


                    Console.WriteLine("Printing bone curves for {0}(0x{1:X})", animationName, hash);
                    Console.WriteLine("{0} transforms {1} bones over {2} frames...", animationName, numBones, numFrames);
                    for (int i = 0; i < boneCRCs.Count; i++)
                    {
                        string boneName = args[3 + i];
                        uint   boneHash = boneCRCs[i];

                        Console.WriteLine("\tBone #{0}: {1} (0x{2:X})", i, boneName, boneHash);

                        bool status = bank.GetCurve(hash, boneHash, 0,
                                                    out ushort[] inds, out float[] values);

                        if (!status)
                        {
                            Console.WriteLine("\t\tFailed to fetch curve!");
                            TestBench.StopLogging();
                            return(-1);
                        }

                        Console.WriteLine("\t\tRotation X component: ");

                        for (int j = 0; j < inds.Length && j < 5; j++)
                        {
                            Console.WriteLine("\t\t\t{0}: {1}", inds[j], values[j]);
                        }
                    }

                    TestBench.StopLogging();
                    return(0);
                }
            }

            Console.WriteLine("Animation not found!");
            TestBench.StopLogging();
            return(-1);
        }