public int MarioFunction(SuperObject *spo, int *nodeInterp)
        {
            RaymanState state          = RaymanState.Inactive;
            byte        dsgVar16_value = 0;
            int *       idleTimer      = null;

            if (spo->PersoData->GetModelName(w) == "YLT_RaymanModel")
            {
                var dsgVars = spo->PersoData->GetDsgVarList();
                dsgVar16_value = *(byte *)dsgVars[16].valuePtrCurrent.ToPointer();
                byte dsgVar9_value = *(byte *)dsgVars[9].valuePtrCurrent.ToPointer();
                state     = (RaymanState)dsgVar9_value;
                idleTimer = (int *)dsgVars[24].valuePtrCurrent;
            }

            bool strafing = InputStructure.GetInputStructure()->GetEntryAction(EntryActionNames.Action_Strafe)->IsValidated();

            if (spo->PersoData->GetInstanceName(w) != "Rayman" || dsgVar16_value != 1 || !AllowTankControlState(state))
            {
                currentSpeed = 0;

                return(EngineFunctions.fn_p_stReadAnalogJoystickMario.Call(spo, nodeInterp));
            }

            int result = OriginalScript(spo, nodeInterp);

            DoTankControls(spo, state, strafing, idleTimer);

            return(result);
        }
Example #2
0
        static InputStructure Parse(string fileName)
        {
            Console.WriteLine($"parsing file started: {fileName}");

            var inputStructure = new InputStructure();

            using (var sr = new StreamReader(fileName))
            {
                var firstLine = sr.ReadLine().Split(' ');
                inputStructure.rows          = Int32.Parse(firstLine[0]);
                inputStructure.columns       = Int32.Parse(firstLine[1]);
                inputStructure.vehiclesNo    = Int32.Parse(firstLine[2]);
                inputStructure.numberOfRides = Int32.Parse(firstLine[3]);
                inputStructure.perRideBonus  = Int32.Parse(firstLine[4]);
                inputStructure.numberOfSteps = Int32.Parse(firstLine[5]);
                inputStructure.rides         = new List <Ride>();

                string line;
                int    rideNo = 0;
                while ((line = sr.ReadLine()) != null)
                {
                    var splitted = line.Split(' ');
                    var ride     = new Ride();
                    ride.rideNo        = rideNo++;
                    ride.rowStart      = Int32.Parse(splitted[0]);
                    ride.colStart      = Int32.Parse(splitted[1]);
                    ride.rowEnd        = Int32.Parse(splitted[2]);
                    ride.colEnd        = Int32.Parse(splitted[3]);
                    ride.earliestStart = Int32.Parse(splitted[4]);
                    ride.latestEnd     = Int32.Parse(splitted[5]);
                    inputStructure.rides.Add(ride);
                }
            }

            Console.WriteLine($"parsing file finished: {fileName}");
            return(inputStructure);
        }
Example #3
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);
             * }
             * }
             * });
             * }*/
        }
Example #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));
             * });*/
        }
Example #5
0
        async Task LoadFIX()
        {
            loadingState = "Loading fixed memory";
            await WaitIfNecessary();

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

            // Read fix header
            //reader.ReadUInt32();
            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();
                }
            }
            Pointer off_identityMatrix = Pointer.Read(reader);

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

            localization = FromOffsetOrRead <LocalizationStructure>(reader, Pointer.Current(reader), inline: true);
            uint num_lvlNames    = reader.ReadUInt32();
            uint num_fixEntries1 = reader.ReadUInt32();

            // Read tables under header
            for (uint i = 0; i < num_fixEntries1; i++)
            {
                string savName = new string(reader.ReadChars(0xC));
            }
            for (uint i = 0; i < num_fixEntries1; i++)
            {
                string savMapName = new string(reader.ReadChars(0xC));
            }
            ReadLevelNames(reader, Pointer.Current(reader), num_lvlNames);
            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)
            {
                reader.ReadChars(0x1E);
                reader.ReadChars(0x1E);                 // two zero entries
            }
            string firstMapName = new string(reader.ReadChars(0x1E));

            //print(firstMapName);
            if (reader.BaseStream.Position % 4 == 0)
            {
                reader.ReadUInt32();
            }
            else
            {
                reader.ReadUInt16();
            }
            uint    num_languages = reader.ReadUInt32();
            Pointer off_languages = Pointer.Read(reader);

            Pointer.DoAt(ref reader, off_languages, () => {
                ReadLanguages(reader, off_languages, num_languages);
            });
            loadingState = "Loading fixed textures";
            print("Fix textures address: " + Pointer.Current(reader));
            await ReadTexturesFix(reader, Pointer.Current(reader));

            // Defaults for Rayman 3 PC. Sizes are hardcoded in the exes and might differ for versions too :/
            int sz_entryActions    = 0x100;
            int sz_randomStructure = 0xDC;
            int sz_videoStructure  = 0x18;
            int sz_musicMarkerSlot = 0x28;
            int sz_binDataForMenu  = 0x020C;
            int num_menuPages      = 35;

            if (Settings.s.mode == Settings.Mode.Rayman3GC)
            {
                sz_entryActions   = 0xE8;
                sz_binDataForMenu = 0x01F0;
            }
            else if (Settings.s.mode == Settings.Mode.RaymanArenaGC ||
                     Settings.s.mode == Settings.Mode.RaymanArenaGCDemo)
            {
                sz_entryActions = 0xC4;
            }
            else if (Settings.s.mode == Settings.Mode.RaymanArenaPC ||
                     Settings.s.mode == Settings.Mode.RaymanMPC)
            {
                sz_entryActions = 0xDC;
            }
            else if (Settings.s.mode == Settings.Mode.DinosaurPC)
            {
                sz_entryActions    = 0xD8;
                sz_randomStructure = 0xE0;
            }
            else if (Settings.s.mode == Settings.Mode.DonaldDuckPKGC)
            {
                sz_entryActions = 0xC0;
            }
            else if (Settings.s.mode == Settings.Mode.RaymanArenaXbox)
            {
                sz_entryActions = 0xF0;
            }
            if (Settings.s.platform == Settings.Platform.Xbox)
            {
                sz_videoStructure = 0x108;
                sz_binDataForMenu = 0x1AC;
            }
            else if (Settings.s.platform == Settings.Platform.Xbox360)
            {
                sz_videoStructure = 0x108;
                sz_entryActions   = 0x108;
                sz_binDataForMenu = 0x33C;
                num_menuPages     = 96;
            }
            else if (Settings.s.platform == Settings.Platform.PS3)
            {
                sz_videoStructure = 0x108;
                sz_entryActions   = 0x108;
                sz_binDataForMenu = 0x348;
                num_menuPages     = 96;
            }
            loadingState = "Loading input structure";
            await WaitIfNecessary();

            inputStruct = InputStructure.Read(reader, Pointer.Current(reader));
            foreach (EntryAction ea in inputStruct.entryActions)
            {
                print(ea.ToString());
            }
            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_IPT_keyAndPadDefine = Pointer.Read(reader);
                ReadKeypadDefine(reader, off_IPT_keyAndPadDefine);
            }
            reader.ReadBytes(sz_entryActions);             // 3DOS_EntryActions
            uint num_persoInFix = reader.ReadUInt32();

            persoInFix = new Pointer[num_persoInFix];
            for (int i = 0; i < num_persoInFix; i++)
            {
                persoInFix[i] = Pointer.Read(reader);
            }
            reader.ReadBytes(sz_randomStructure);
            uint    soundEventTableIndexInFix = reader.ReadUInt32();
            Pointer off_soundEventTable       = Pointer.Read(reader);

            fonts = FromOffsetOrRead <FontStructure>(reader, Pointer.Current(reader), inline: true);
            reader.ReadBytes(sz_videoStructure);             // Contains amount of videos and pointer to video filename table
            print(Pointer.Current(reader));
            if (Settings.s.game == Settings.Game.R3)
            {
                uint num_musicMarkerSlots = reader.ReadUInt32();
                for (int i = 0; i < num_musicMarkerSlots; i++)
                {
                    reader.ReadBytes(sz_musicMarkerSlot);
                }
                reader.ReadBytes(sz_binDataForMenu);
                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_bgMaterialForMenu2D          = Pointer.Read(reader);
                    Pointer off_fixMaterialForMenu2D         = Pointer.Read(reader);
                    Pointer off_fixMaterialForSelectedFilms  = Pointer.Read(reader);
                    Pointer off_fixMaterialForArcadeAndFilms = Pointer.Read(reader);
                    for (int i = 0; i < num_menuPages; i++)
                    {
                        Pointer off_menuPage = Pointer.Read(reader);
                    }
                }
            }

            /*loadingState = "Loading fixed animation bank";
             * await WaitIfNecessary();*/
            if (Settings.s.game != Settings.Game.Dinosaur)
            {
                off_animBankFix = Pointer.Read(reader);                 // Note: only one 0x104 bank in fix.
                //print(Pointer.Current(reader));
                print("Fix animation bank address: " + off_animBankFix);
            }

            /*if (off_animBankFix.file == files_array[Mem.Lvl]) {
             *      animationBanks = new AnimationBank[4]; // 1 in fix, 4 in lvl
             *      Pointer.DoAt(ref reader, off_animBankFix, () => {
             *              animationBanks[0] = AnimationBank.Read(reader, off_animBankFix, 0, 1, files_array[Mem.FixKeyFrames])[0];
             *      });
             * } else {
             *      animationBanks = new AnimationBank[5]; // 1 in fix, 4 in lvl
             *      Pointer.DoAt(ref reader, off_animBankFix, () => {
             *              animationBanks[0] = AnimationBank.Read(reader, off_animBankFix, 0, 1, files_array[Mem.FixKeyFrames])[0];
             *      });
             * }*/
        }
        private void DoTankControls(SuperObject *spo, RaymanState state, bool strafing, int *idleTimer)
        {
            EntryAction *leftAction    = *(EntryAction **)0x4B9B90;
            EntryAction *rightAction   = *(EntryAction **)0x4B9B94;
            EntryAction *forwardAction = *(EntryAction **)0x4B9B88;
            EntryAction *backAction    = *(EntryAction **)0x4B9B8C;
            EntryAction *shiftAction   = *(EntryAction **)0x4B9B98;

            rayman = spo;
            var transformationMatrix = rayman->PersoData->dynam->DynamicsAsBigDynamics->matrixA.TransformationMatrix;
            var rotation             = Quaternion.CreateFromRotationMatrix(transformationMatrix);

            float rotationSpeedTarget = ((leftAction->IsValidated() ? 1f : 0) + (rightAction->IsValidated() ? -1f : 0)) * maxRotationSpeed * (shiftAction->IsValidated()?0.75f:1f);

            if (state == RaymanState.Swimming || state == RaymanState.Sliding)
            {
                rotationSpeedTarget *= 8.0f;
            }

            // Interpolate to target speed
            rotationSpeed += (rotationSpeedTarget - rotationSpeed) * rotationSpeedLerp;

            if (state == RaymanState.LedgeGrab)
            {
                if (forwardAction->IsValidated())
                {
                    currentSpeed = 10;
                }
                else if (backAction->IsValidated())
                {
                    currentSpeed = -10;
                }
                else
                {
                    currentSpeed = 0;
                }
            }
            else if (strafing && state != RaymanState.Swimming && state != RaymanState.Sliding)
            {
                float strafeX = ((leftAction->IsValidated() ? 1f : 0) + (rightAction->IsValidated() ? -1f : 0));
                float strafeY = ((forwardAction->IsValidated() ? 1f : 0) + (backAction->IsValidated() ? -1f : 0));

                float strafeMagnitude = (float)Math.Sqrt(strafeX * strafeX + strafeY * strafeY);

                if (strafeMagnitude == 0 || float.IsNaN(strafeMagnitude) || float.IsInfinity(strafeMagnitude))
                {
                    strafeMagnitude = 1.0f;
                }

                // Normalize and set length to 100
                strafeX *= 100.0f / strafeMagnitude;
                strafeY *= 100.0f / strafeMagnitude;

                HandleStrafing(rotation, rayman, strafeX, strafeY);

                return;
            }
            else
            {
                // Can be turning?
                if (state == RaymanState.Idle)
                {
                    var entryActions = InputStructure.GetInputStructure()->EntryActions;

                    int[] bannedActions = new int[] { (int)EntryActionNames.Action_Tirer, (int)EntryActionNames.Action_Sauter };

                    bool usingBannedAction = bannedActions.Where(a => entryActions[a]->IsValidated()).Count() > 0;

                    if (!usingBannedAction)
                    {
                        if (rightAction->IsValidated() && !leftAction->IsValidated())
                        {
                            if (rayman->PersoData->GetStateIndex() != 70)
                            {
                                rayman->PersoData->SetState(70);
                            }
                            playTurnAnimation = true;
                        }
                        else if (leftAction->IsValidated() && !rightAction->IsValidated())
                        {
                            if (rayman->PersoData->GetStateIndex() != 71)
                            {
                                rayman->PersoData->SetState(71);
                            }
                            playTurnAnimation = true;
                        }
                        else
                        {
                            playTurnAnimation = false;
                        }
                    }
                }

                rotation *= Quaternion.CreateFromYawPitchRoll(0, 0, rotationSpeed); // Add rotation

                float targetSpeed = (forwardAction->IsValidated() ? 100f : 0f) * (shiftAction->IsValidated() ? 0.5f : 1f);
                currentSpeed += (targetSpeed - currentSpeed) * 0.1f;
            }

            if (currentSpeed > 0 && currentSpeed < 0.5f)
            {
                currentSpeed = 0;
            }

            if (currentSpeed < 70 && Math.Abs(rotationSpeed) > 0.01f && state == RaymanState.Sliding)
            {
                currentSpeed = 70;
            }

            WriteVariables(rotation, rotationSpeed, transformationMatrix, rayman);
        }
Example #7
0
        // 16 - 11237747
        // 32 - 11428838
        // 48 - 11560597
        // 64 - 11629076
        // 96 - 11639283
        // 100 - 11652814
        // 128 - 11563526
        // 158 - 11367549
        static OutputStructure Solve(InputStructure inputStructure, bool metropolisHax = false)
        {
            var os = new OutputStructure();

            var vehicles = new List <Vehicle>();

            for (int i = 0; i < inputStructure.vehiclesNo; i++)
            {
                vehicles.Add(new Vehicle()
                {
                    bonusPointsIfOnTime = inputStructure.perRideBonus, vehicleNo = i
                });
            }

            var allVehiclesAtAll = vehicles.ToList();

            var ridesLeft = inputStructure.rides.ToList();

            List <Ride> ridesForTheEnd = null;

            if (metropolisHax)
            {
                ridesLeft = ridesLeft
                            .Where(x => x.rowStart > 1600)
                            .Where(x => x.rowEnd < 4000)
                            .Where(x => x.colStart > 0)
                            .Where(x => x.colEnd < 2500)
                            .ToList();

                ridesForTheEnd = inputStructure.rides.ToList();
                ridesForTheEnd.RemoveAll(x => ridesLeft.Any(y => x.rideNo == y.rideNo));
            }

            while (ridesLeft.Count > 0 && vehicles.Count > 0)
            {
                var currVehicle    = vehicles.MinElement(x => x.availableAtTime);
                var availableRides = ridesLeft.Where(ride => currVehicle.canFulfill(ride)).ToList();

                if (availableRides.Count == 0 && ridesForTheEnd != null)
                {
                    ridesLeft.AddRange(ridesForTheEnd);
                    availableRides = ridesLeft.Where(ride => currVehicle.canFulfill(ride)).ToList();  // HAX
                    ridesForTheEnd = null;
                }

                if (currVehicle.vehicleNo < 100 && metropolisHax && ridesForTheEnd != null)
                {
                    availableRides = ridesForTheEnd.Where(ride => currVehicle.canFulfill(ride)).ToList();
                }

                if (availableRides.Count == 0)
                {
                    vehicles.Remove(currVehicle);
                    continue;
                }

                var bestRide      = availableRides.MaxElement(ride => ((double)currVehicle.pointsFor(ride)) / currVehicle.timeSpent(ride));
                var pointsForRide = currVehicle.pointsFor(bestRide);
                var timeSpent     = currVehicle.timeSpent(bestRide);

                ridesLeft.Remove(bestRide);
                if (ridesForTheEnd != null)
                {
                    ridesForTheEnd.RemoveAll(x => x.rideNo == bestRide.rideNo);
                }

                if (currVehicle.pointsFor(bestRide) == 0)
                {
                    throw new ApplicationException();
                }

                currVehicle.executeRide(bestRide);
                if (!os.ridesPerVehicle.ContainsKey(currVehicle))
                {
                    os.ridesPerVehicle.Add(currVehicle, new RidesPerVehicle()
                    {
                        vehicle = currVehicle, rides = new List <Ride>()
                    });
                }
                os.ridesPerVehicle[currVehicle].rides.Add(bestRide);
            }

            return(os);
        }
Example #8
0
        async Task LoadFIX()
        {
            textures     = new TextureInfo[0];
            loadingState = "Loading fixed memory";
            await WaitIfNecessary();

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

            reader.ReadUInt32();             // Offset of languages
            byte num_lvlNames = reader.ReadByte();

            reader.ReadByte();
            reader.ReadByte();
            reader.ReadByte();
            ReadLevelNames(reader, Pointer.Current(reader), num_lvlNames);
            if (Settings.s.platform == Settings.Platform.PC)
            {
                reader.ReadChars(0x1E);
                reader.ReadChars(0x1E);                 // two zero entries
            }
            string firstMapName            = new string(reader.ReadChars(0x1E));
            byte   num_languages_subtitles = reader.ReadByte();
            byte   num_languages_voice     = reader.ReadByte();

            reader.ReadByte();
            reader.ReadByte();
            print(Pointer.Current(reader));
            Pointer off_languages_subtitles = Pointer.Read(reader);
            Pointer off_languages_voice     = Pointer.Read(reader);

            Pointer.DoAt(ref reader, off_languages_subtitles, () => {
                ReadLanguages(reader, off_languages_subtitles, num_languages_subtitles);
            });
            Pointer.DoAt(ref reader, off_languages_voice, () => {
                ReadLanguages(reader, off_languages_voice, num_languages_voice);
            });

            int sz_entryActions = 0xC0;

            reader.ReadBytes(sz_entryActions);             // 3DOS_EntryActions
            reader.ReadUInt16();
            ushort num_matrices = reader.ReadUInt16();

            for (int i = 0; i < 4; i++)
            {
                reader.ReadBytes(0x101);
            }
            loadingState = "Loading input structure";
            await WaitIfNecessary();

            inputStruct = InputStructure.Read(reader, Pointer.Current(reader));
            foreach (EntryAction ea in inputStruct.entryActions)
            {
                print(ea.ToString());
            }
            reader.ReadUInt32();
            reader.ReadUInt32();
            reader.ReadUInt32();
            ushort num_unk2 = reader.ReadUInt16();

            reader.ReadUInt16();
            Pointer off_unk2         = Pointer.Read(reader);
            Pointer off_entryActions = Pointer.Read(reader);

            Pointer[] unkMatrices = new Pointer[2];
            for (int i = 0; i < 2; i++)
            {
                unkMatrices[i] = Pointer.Read(reader);
            }
            fonts = FromOffsetOrRead <FontStructure>(reader, Pointer.Current(reader), inline: true);

            Pointer off_matrices           = Pointer.Read(reader);
            Pointer off_specialEntryAction = Pointer.Read(reader);
            Pointer off_identityMatrix     = Pointer.Read(reader);
            Pointer off_unk = Pointer.Read(reader);

            reader.ReadUInt32();
            reader.ReadUInt32();
            reader.ReadBytes(0xc8);
            reader.ReadUInt16();
            reader.ReadUInt16();
            reader.ReadByte();
            reader.ReadByte();
            reader.ReadByte();
            reader.ReadByte();
            Pointer.Read(reader);
            Pointer off_haloTexture = Pointer.Read(reader);
            Pointer off_material1   = Pointer.Read(reader);
            Pointer off_material2   = Pointer.Read(reader);

            for (int i = 0; i < 10; i++)
            {
                reader.ReadBytes(0xcc);
            }
        }
Example #9
0
        async Task LoadPS2()
        {
            await WaitIfNecessary();

            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);

            loadingState = "Loading input struct";
            await WaitIfNecessary();

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

            inputStruct = InputStructure.Read(reader, Pointer.Current(reader));
            foreach (EntryAction ea in inputStruct.entryActions)
            {
                print(ea.ToString());
            }
            localization = FromOffsetOrRead <LocalizationStructure>(reader, Pointer.Current(reader), inline: true);

            /*
             * 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());
             *      }
             * });*/


            /*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);
             * Pointer.DoAt(ref reader, off_text_general, () => {
             * fontStruct = FontStructure.Read(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 && fontStruct != 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();
             * fontStruct.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(tplPaths[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;
            string build = reader.ReadString(0x20);

            reader.ReadUInt32();
            reader.ReadUInt32();             // 0xc
            reader.ReadUInt32();             // 0
            Pointer.Read(reader);
            Pointer.Read(reader);

            // Globals
            globals.off_actualWorld  = Pointer.Read(reader);
            globals.off_dynamicWorld = Pointer.Read(reader);
            globals.off_fatherSector = Pointer.Read(reader);
            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);
            Pointer.Read(reader);                                 // format: (0x4 number, number * 0x4: null)
            globals.off_always_reusableSO = Pointer.Read(reader); // There are (num_always) empty SuperObjects starting with this one.
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);

            LinkedList <Perso> cameras = LinkedList <Perso> .ReadHeader(reader, Pointer.Current(reader), LinkedList.Type.Double);

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

            LinkedList <Perso> mainChars = LinkedList <Perso> .ReadHeader(reader, Pointer.Current(reader), LinkedList.Type.Double);

            Pointer.Read(reader);                      // Rayman
            reader.ReadUInt32();
            globals.off_camera = Pointer.Read(reader); // Camera
            Pointer.Read(reader);
            Pointer.Read(reader);
            Pointer.Read(reader);

            uint numMeshes             = (uint)files_array[Mem.Lvl].extraData["numMeshes"];
            uint numMaterials          = (uint)files_array[Mem.Lvl].extraData["numMaterials"];
            uint numTextures           = (uint)files_array[Mem.Lvl].extraData["numTextures"];
            uint numLightmappedObjects = (uint)files_array[Mem.Lvl].extraData["numLightmappedObjects"];

            //print("numTextures " + numTextures + " - " + txds[0].Count + " - " + numMeshes + " - " + ato.numAtomics + " - " + numLightmappedObjects);


            textures = new TextureInfo[numTextures];
            Pointer[] off_meshes = new Pointer[numMeshes];
            off_materials = new Pointer[numMaterials];
            for (int i = 0; i < numMeshes; i++)
            {
                off_meshes[i] = Pointer.Read(reader);
            }
            for (int i = 0; i < numMaterials; i++)
            {
                off_materials[i] = Pointer.Read(reader);
            }
            for (int i = 0; i < numTextures; i++)
            {
                Pointer off_textureInfo = Pointer.Read(reader);
                int     texture_index   = reader.ReadInt32();
                Pointer.DoAt(ref reader, off_textureInfo, () => {
                    textures[i]         = TextureInfo.Read(reader, off_textureInfo);
                    textures[i].Texture = txds[0].Lookup(texture_index.ToString("D3"));
                    //textures[i].Texture = txds[0].textures[txds[0].Count - 1 - texture_index];
                });
            }
            Pointer.Read(reader);
            reader.ReadUInt32();
            reader.ReadUInt32();
            Pointer.Read(reader);
            uint num_unk = reader.ReadUInt32();

            for (int i = 0; i < num_unk; i++)
            {
                Pointer.Read(reader);
            }
            uint num_unk2 = reader.ReadUInt32();

            for (int i = 0; i < num_unk2; i++)
            {
                Pointer.Read(reader);
            }
            Pointer.Read(reader);
            reader.ReadSingle();             // a bounding volume most likely
            reader.ReadSingle();
            reader.ReadSingle();
            reader.ReadSingle();
            reader.ReadSingle();
            reader.ReadSingle();
            Pointer.Read(reader);
            reader.ReadUInt32();             // 2?
            uint    num_poTable = reader.ReadUInt32();
            Pointer off_poTable = Pointer.Read(reader);

            reader.ReadUInt32();             // 1. 10x 0
            reader.ReadUInt32();             // 2
            reader.ReadUInt32();             // 3
            reader.ReadUInt32();             // 4
            reader.ReadUInt32();             // 5
            reader.ReadUInt32();             // 6
            reader.ReadUInt32();             // 7
            reader.ReadUInt32();             // 8
            reader.ReadUInt32();             // 9
            reader.ReadUInt32();             // 10
            uint num_lightCookies = reader.ReadUInt32();

            lightCookieColors = new Color[num_lightCookies];
            for (int i = 0; i < num_lightCookies; i++)
            {
                reader.ReadUInt32();
                reader.ReadUInt32();
                reader.ReadUInt32();
                reader.ReadUInt32();
                byte b = reader.ReadByte();
                byte g = reader.ReadByte();
                byte r = reader.ReadByte();
                reader.ReadByte();
                lightCookieColors[i] = new Color(r / 255f, g / 255f, b / 255f, 1f);
                reader.ReadUInt32();
                reader.ReadInt32();
                reader.ReadUInt32();
            }
            for (int i = 0; i < num_lightCookies; i++)
            {
                reader.ReadByte();
            }
            reader.Align(0x4);
            Pointer off_lightCookieMaterial = Pointer.Read(reader);

            lightCookieMaterial = VisualMaterial.FromOffsetOrRead(off_lightCookieMaterial, reader);
            off_lightmapUV      = new Pointer[numLightmappedObjects];
            for (int i = 0; i < numLightmappedObjects; i++)
            {
                reader.ReadUInt32();
                reader.ReadUInt32();
                reader.ReadUInt32();
                off_lightmapUV[i] = Pointer.Read(reader);
            }



            for (int i = 0; i < numMaterials; i++)
            {
                VisualMaterial.FromOffsetOrRead(off_materials[i], reader);
            }
            for (int i = 0; i < numMeshes; i++)
            {
                Pointer.DoAt(ref reader, off_meshes[i], () => {
                    GeometricObject mesh = GeometricObject.Read(reader, off_meshes[i]);
                    meshObjects.Add(mesh);
                    //print("Mesh " + i + ": " + mesh.num_vertices + " - " + mesh.subblock_types[0] + " - " + mesh.num_subblocks);
                });
            }

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

            ReadFamilies(reader);
            //print("Families: " + families.Count);
            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);
            await WaitIfNecessary();
        }