private void determinePVarControls(RatchetMoby moby)
        {
            mobyPVarGroup.Controls.Clear();
            int yOffset = 15;
            int xOffset = 5;

            if (moby.pVarConfig != null)
            {
                foreach (MobyPVar pVar in moby.pVarConfig)
                {
                    switch (pVar.control)
                    {
                    case "float":
                        FloatControl floatControl = new FloatControl(moby.pVars, pVar);
                        floatControl.Location        = new Point(xOffset, yOffset);
                        floatControl.OnValueChanged += (s, e) => handleChange(pVar, e);
                        mobyPVarGroup.Controls.Add(floatControl);
                        yOffset += floatControl.Height;
                        break;

                    case "number":
                        IntegerControl intControl = new IntegerControl(moby.pVars, pVar);
                        intControl.Location        = new Point(xOffset, yOffset);
                        intControl.OnValueChanged += (s, e) => handleChange(pVar, e);
                        mobyPVarGroup.Controls.Add(intControl);
                        yOffset += intControl.Height;
                        break;
                    }
                }
                ;
            }
        }
        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            selectedMoby           = DataStore.mobs[listBox1.SelectedIndex];
            DataStore.selectedMoby = selectedMoby;
            updateVals();

            missionBox.Text = selectedMoby.missionID.ToString("X8");
            if (mainForm.modelViewer.Visible)
            {
                mainForm.modelViewer.selectedModel = DataStore.spawnableModels.Find(x => x.modelID == selectedMoby.modelID);
                mainForm.modelViewer.inval();
            }
            DataStore.selectedMoby = selectedMoby;
            mainForm.terrainViewer.updateView();
        }
        public static void parseMap(string path, string fileName)
        {
            FileStream fs = File.OpenRead(path + "/" + fileName);

            FileStream vfs = null;

            if (File.Exists(path + "/vram.ps3"))
            {
                vfs = File.OpenRead(path + "/vram.ps3");
            }

            FileStream gpf = null;

            if (File.Exists(path + "/gameplay_ntsc"))
            {
                gpf = File.OpenRead(path + "/gameplay_ntsc");
            }

            uint racNum = 0;

            ushort magic = BAToUInt16(ReadBlock(fs, 0xB0, 2), 0);

            switch (magic)
            {
            case 0x7533:
                racNum = 1;
                break;

            case 0xEA9C:
                racNum = 2;
                break;

            case 0x0000:
            case 0x755D:
                racNum = 3;
                break;
            }
            Console.WriteLine("Game determined to be ratchet" + racNum.ToString());

            List <MobyPropertyVariables> pVarConfigs = new List <MobyPropertyVariables>();
            string jsonString = File.ReadAllText(String.Format("./Config/Rac{0}/MobyPropertyVariables.json", racNum));

            pVarConfigs       = JsonConvert.DeserializeObject <List <MobyPropertyVariables> >(jsonString);
            DataStore.pVarMap = pVarConfigs;

            #region GameplayHeader
            GameplayHeader gameplayHeader = new GameplayHeader(gpf, racNum);

            DataStore.gameplayHeader = gameplayHeader;

            #endregion

            #region pVars
            List <byte[]> pVars;
            uint          numpVars;
            byte[]        pVarHeadBlock;
            uint          pVarSectionLength;
            byte[]        pVarBlock;
            switch (racNum)
            {
            case 1:
            case 2:
            case 3:
                pVars             = new List <byte[]>();
                numpVars          = (gameplayHeader.pVarPointer - gameplayHeader.pVarListPointer) / 8;
                pVarHeadBlock     = ReadBlock(gpf, gameplayHeader.pVarListPointer, numpVars * 8);
                pVarSectionLength = 0;
                for (uint i = 0; i < numpVars; i++)
                {
                    pVarSectionLength += BAToUInt32(pVarHeadBlock, (i * 8) + 0x04);
                }
                pVarBlock = ReadBlock(gpf, gameplayHeader.pVarPointer, pVarSectionLength);
                for (uint i = 0; i < numpVars; i++)
                {
                    uint   mobpVarsStart = BAToUInt32(pVarHeadBlock, (i * 8));
                    uint   mobpVarsCount = BAToUInt32(pVarHeadBlock, (i * 8) + 0x04);
                    byte[] mobpVars      = new byte[mobpVarsCount];
                    mobpVars = getBytes(pVarBlock, (int)mobpVarsStart, (int)mobpVarsCount);
                    pVars.Add(mobpVars);
                }
                DataStore.pVarList = pVars;
                break;
            }
            #endregion pVars

            #region Mobies

            uint   mobyCount = BAToUInt32(ReadBlock(gpf, gameplayHeader.mobyPointer, 4), 0);
            byte[] mobyBlock = ReadBlock(gpf, gameplayHeader.mobyPointer + 0x10, mobyCount * gameplayHeader.mobyElemSize);

            for (uint i = 0; i < mobyCount; i++)
            {
                RatchetMoby mob = new RatchetMoby(racNum, mobyBlock, i);
                DataStore.mobs.Add(mob);
            }
            #endregion

            DataStore.splines = new List <Spline>();

            uint   splineCount       = BAToUInt32(ReadBlock(gpf, gameplayHeader.splinePointer, 4), 0);
            uint   splineOffset      = BAToUInt32(ReadBlock(gpf, gameplayHeader.splinePointer + 4, 4), 0);
            uint   splineSectionSize = BAToUInt32(ReadBlock(gpf, gameplayHeader.splinePointer + 8, 4), 0);
            byte[] splineHeadBlock   = ReadBlock(gpf, gameplayHeader.splinePointer + 0x10, splineCount * 4);
            byte[] splineBlock       = ReadBlock(gpf, gameplayHeader.splinePointer + splineOffset, splineSectionSize);
            for (uint i = 0; i < splineCount; i++)
            {
                uint offset = BAToUInt32(splineHeadBlock, (i * 4));
                DataStore.splines.Add(new Spline(splineBlock, offset));
            }


            gpf.Close();

            EngineHeader engineHeader = new EngineHeader(fs, 1);
            DataStore.engineHeader = engineHeader;

            //Load UYA Spawnable Models
            #region Spawnables
            uint   spawnablesCount = BAToUInt32(ReadBlock(fs, engineHeader.spawnablesPointer, 4), 0);
            byte[] idBlock         = ReadBlock(fs, engineHeader.spawnablesPointer + 4, spawnablesCount * 8);

            for (int x = 0; x < spawnablesCount; x++)
            {
                RatchetModel_General model = new RatchetModel_General();
                model.modelType = ModelType.Spawnable;

                model.modelID = BAToShort(idBlock, (uint)(x * 8) + 2);
                model.offset  = BAToUInt32(idBlock, (uint)(x * 8) + 4);

                if (model.offset != 0)
                {
                    uint modelHeadSize = BAToUInt32(ReadBlock(fs, model.offset, 4), 0);

                    if (modelHeadSize > 0)
                    {
                        byte[] headBlock = ReadBlock(fs, model.offset, modelHeadSize + 0x20); //Head + objectDetails
                        uint   objectPtr = BAToUInt32(headBlock, 0);
                        model.animationsCount = headBlock[0x0C];
                        //(0x04)null
                        //(0x08)[count for 0x14 and 0x18][unknown][unknown][unknown]
                        //(0x0c)[animation count][unknown][unknown][unknown]
                        //(0x10)Pointer to list
                        //(0x14)Pointer to skeleton joints (0x40 structure)
                        //(0x18)Pointer to skeleton somethings (0x16 structure)
                        //(0x1C)Pointer to left arm animations (Ratchet)
                        //(0x20)null
                        model.size = BAToFloat(headBlock, 0x24);
                        uint texCount          = BAToUInt32(headBlock, objectPtr + 0x00);
                        uint otherCount        = BAToUInt32(headBlock, objectPtr + 0x04);
                        uint texBlockPointer   = BAToUInt32(headBlock, objectPtr + 0x08);
                        uint otherBlockPointer = BAToUInt32(headBlock, objectPtr + 0x0C);
                        uint vertPointer       = BAToUInt32(headBlock, objectPtr + 0x10);
                        uint indexPointer      = BAToUInt32(headBlock, objectPtr + 0x14);
                        model.vertexCount = BAToUInt16(headBlock, objectPtr + 0x18);
                        //(0x1A)count
                        //(0x1C)count
                        //(0x1E)null


                        //model.rawData = getModelDataRaw(model.modelType, model.modelID, path + "/" + fileName);

                        model.animPointer = new List <uint>();
                        for (uint i = 0; i < model.animationsCount; i++)
                        {
                            model.animPointer.Add(BAToUInt32(headBlock, (i * sizeof(uint)) + 0x48));
                        }

                        uint   texElemSize = 0x10;
                        byte[] texBlock    = ReadBlock(fs, model.offset + texBlockPointer, texCount * texElemSize);
                        model.textureConfig = new List <RatchetTexture_Model>();
                        model.faceCount     = 0;
                        for (uint t = 0; t < texCount; t++)
                        {
                            RatchetTexture_Model modTex = new RatchetTexture_Model();
                            modTex.ID    = BAToUInt32(texBlock, (t * texElemSize) + 0x0);
                            modTex.start = BAToUInt32(texBlock, (t * texElemSize) + 0x04);
                            modTex.size  = BAToUInt32(texBlock, (t * texElemSize) + 0x08);
                            model.textureConfig.Add(modTex);
                            model.faceCount += modTex.size;
                        }


                        //Flip endianness of vertex array float[vert_x, vert_y, vert_z, norm_x, norm_y, norm_z, uv_u, uv_v, reserved reserved]
                        uint   vertElemSize = 0x28;
                        uint   vertBuffSize = model.vertexCount * vertElemSize;
                        byte[] vertBlock    = ReadBlock(fs, model.offset + vertPointer, vertBuffSize);
                        model.vertBuff = new List <float>();
                        for (uint i = 0; i < model.vertexCount; i++)
                        {
                            model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x00));    //Vertx
                            model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x04));    //Verty
                            model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x08));    //Vertz
                            model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x0C));    //Nomrx
                            model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x10));    //Normy
                            model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x14));    //Normz
                            model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x18));    //UVu
                            model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x1C));    //UVv
                        }

                        //Flip endianness of index array
                        byte[] indiceBuff = ReadBlock(fs, model.offset + indexPointer, model.faceCount * sizeof(ushort));
                        model.indiceBuff = new List <ushort>();
                        for (uint i = 0; i < model.faceCount; i++)
                        {
                            model.indiceBuff.Add(BAToUInt16(indiceBuff, i * sizeof(ushort)));
                        }
                    }
                }
                DataStore.spawnableModels.Add(model);
            }
            #endregion

            //Load UYA Level Models
            #region Level Models
            uint   levelElemSize = 0x40;
            byte[] levelBlock    = ReadBlock(fs, engineHeader.levelModelsPointer, engineHeader.levelModelsCount * levelElemSize);

            for (uint x = 0; x < engineHeader.levelModelsCount; x++)
            {
                RatchetModel_General model = new RatchetModel_General();
                model.modelType = ModelType.Level;
                model.size      = 0.5f;

                uint vertPointer   = BAToUInt32(levelBlock, (x * levelElemSize) + 0x10);
                uint UVPointer     = BAToUInt32(levelBlock, (x * levelElemSize) + 0x14);
                uint indicePointer = BAToUInt32(levelBlock, (x * levelElemSize) + 0x18);
                uint texPointer    = BAToUInt32(levelBlock, (x * levelElemSize) + 0x1C);
                model.vertexCount = (ushort)BAToUInt32(levelBlock, (x * levelElemSize) + 0x24);
                ushort texCount = BAToUInt16(levelBlock, (x * levelElemSize) + 0x28);
                model.modelID = BAToShort(levelBlock, (x * levelElemSize) + 0x30);

                model.offset    = (uint)(x * 0x40) + engineHeader.levelModelsPointer;
                model.modelType = ModelType.Level;

                uint   texElemSize = 0x18;
                byte[] texBlock    = ReadBlock(fs, texPointer, texCount * texElemSize);
                model.textureConfig = new List <RatchetTexture_Model>();
                model.faceCount     = 0;
                for (uint t = 0; t < texCount; t++)
                {
                    RatchetTexture_Model dlt = new RatchetTexture_Model();
                    dlt.ID    = BAToUInt32(texBlock, (t * texElemSize) + 0x00);
                    dlt.start = BAToUInt32(texBlock, (t * texElemSize) + 0x08);
                    dlt.size  = BAToUInt32(texBlock, (t * texElemSize) + 0x0C);
                    model.textureConfig.Add(dlt);
                    model.faceCount += dlt.size;
                }

                //Flip endianness of vertex array float[vert_x, vert_y, vert_z, norm_x, norm_y, norm_z, uv_u, uv_v, reserved reserved]
                uint   vertElemSize = 0x18;
                uint   vertBuffSize = model.vertexCount * vertElemSize;
                byte[] vertBlock    = ReadBlock(fs, vertPointer, vertBuffSize);

                uint   UVElemsize = 0x08;
                uint   UVBuffSize = model.vertexCount * UVElemsize;
                byte[] UVBlock    = ReadBlock(fs, UVPointer, UVBuffSize);


                model.vertBuff = new List <float>();
                for (uint i = 0; i < model.vertexCount; i++)
                {
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x00)); //vertx
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x04)); //verty
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x08)); //vertz
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x0C)); //normx
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x10)); //normy
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x14)); //normz

                    model.vertBuff.Add(BAToFloat(UVBlock, (i * UVElemsize) + 0x00));     //UVu
                    model.vertBuff.Add(BAToFloat(UVBlock, (i * UVElemsize) + 0x04));     //UVv
                }

                //Flip endianness of index array
                byte[] indiceBuff = ReadBlock(fs, indicePointer, model.faceCount * sizeof(ushort));
                model.indiceBuff = new List <ushort>();
                for (uint i = 0; i < model.faceCount; i++)
                {
                    model.indiceBuff.Add(BAToUInt16(indiceBuff, i * sizeof(ushort)));
                }

                DataStore.levelModels.Add(model);
            }
            #endregion

            //Load UYA Scenery Models
            #region Scenery Models
            uint   sceneElemSize = 0x40;
            byte[] sceneBlock    = ReadBlock(fs, engineHeader.sceneryModelsPointer, engineHeader.sceneryModelsCount * sceneElemSize);

            for (uint x = 0; x < engineHeader.sceneryModelsCount; x++)
            {
                RatchetModel_General model = new RatchetModel_General();
                model.modelType = ModelType.Scenery;
                model.size      = 0.5f;

                uint vertPointer   = BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x10);
                uint UVPointer     = BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x14);
                uint indicePointer = BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x18);
                uint texPointer    = BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x1C);
                model.vertexCount = (ushort)BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x24);
                ushort texCount = BAToUInt16(sceneBlock, (x * sceneElemSize) + 0x28);
                model.modelID = BAToShort(sceneBlock, (x * sceneElemSize) + 0x30);

                uint   texElemSize = 0x10;
                byte[] texBlock    = ReadBlock(fs, texPointer, texCount * texElemSize);
                model.textureConfig = new List <RatchetTexture_Model>();
                model.faceCount     = 0;
                for (uint t = 0; t < texCount; t++)
                {
                    RatchetTexture_Model dlt = new RatchetTexture_Model();
                    dlt.ID    = BAToUInt32(texBlock, (t * texElemSize) + 0x00);
                    dlt.start = BAToUInt32(texBlock, (t * texElemSize) + 0x04);
                    dlt.size  = BAToUInt32(texBlock, (t * texElemSize) + 0x08);
                    model.textureConfig.Add(dlt);
                    model.faceCount += dlt.size;
                }

                //Flip endianness of vertex array float[vert_x, vert_y, vert_z, norm_x, norm_y, norm_z, uv_u, uv_v, reserved reserved]
                uint   vertElemSize = 0x18;
                uint   vertBuffSize = model.vertexCount * vertElemSize;
                byte[] vertBlock    = ReadBlock(fs, vertPointer, vertBuffSize);

                uint   UVElemsize = 0x08;
                uint   UVBuffSize = model.vertexCount * UVElemsize;
                byte[] UVBlock    = ReadBlock(fs, UVPointer, UVBuffSize);


                model.vertBuff = new List <float>();
                for (uint i = 0; i < model.vertexCount; i++)
                {
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x00)); //vertx
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x04)); //verty
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x08)); //vertz
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x0C)); //normx
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x10)); //normy
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x14)); //normz

                    model.vertBuff.Add(BAToFloat(UVBlock, (i * UVElemsize) + 0x00));     //UVu
                    model.vertBuff.Add(BAToFloat(UVBlock, (i * UVElemsize) + 0x04));     //UVv
                }

                //Flip endianness of index array
                byte[] indiceBuff = ReadBlock(fs, indicePointer, model.faceCount * sizeof(ushort));
                model.indiceBuff = new List <ushort>();
                for (uint i = 0; i < model.faceCount; i++)
                {
                    model.indiceBuff.Add(BAToUInt16(indiceBuff, i * sizeof(ushort)));
                }

                DataStore.sceneryModels.Add(model);
                //Console.WriteLine("Scenery Model Added: 0x" + model.modelID.ToString("X4"));
            }
            #endregion

            //Load Terrain
            #region Terrain
            {
                uint terrainElemSize = 0x30;
                uint texElemSize     = 0x10;
                uint vertElemSize    = 0x1c;
                uint UVElemSize      = 0x08;
                uint ColorElemSize   = 0x04;

                RatchetModel_Terrain model = new RatchetModel_Terrain();
                model.offset    = engineHeader.terrainPointer;
                model.modelID   = 1111;
                model.modelType = ModelType.Terrain;
                byte[] terrainHeadBlock = ReadBlock(fs, engineHeader.terrainPointer, 0x60);

                uint   headPointer = BAToUInt32(terrainHeadBlock, 0x0);
                ushort headCount   = BAToUInt16(terrainHeadBlock, 0x06);

                byte[] terrainBlock = ReadBlock(fs, headPointer, headCount * terrainElemSize);
                model.textureConfig = new List <RatchetTexture_Model>();
                model.vertBuff      = new List <float>();
                model.indiceBuff    = new List <uint>();
                uint vertCount         = 0;
                uint prevVertCount     = 0;
                uint prevFaceCount     = 0;
                uint prevHeadCount     = 0;
                uint prevPrevFaceCount = 0;

                for (uint i = 0; i < 4; i++)    //I have yet to see any level have more than two of these, but the header theoretically has space for 4
                {
                    uint vertPointer   = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x08);
                    uint colPointer    = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x18);
                    uint UVPointer     = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x28);
                    uint indicePointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x38);

                    prevFaceCount = 0;
                    if (vertPointer != 0 && UVPointer != 0 && indicePointer != 0)    //Check that there's data at the pointers
                    {
                        //Loop throught the heads, and stop when the overflow counter increases
                        for (uint ii = prevHeadCount; ii < headCount && i == BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x22); ii++)
                        {
                            uint   localFaceCount = 0;
                            uint   texPointer     = BAToUInt32(terrainBlock, (ii * terrainElemSize) + 0x10);
                            uint   texCount       = BAToUInt32(terrainBlock, (ii * terrainElemSize) + 0x14);
                            ushort vertStart      = BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x18);
                            ushort headVertCount  = BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x1A);
                            vertCount += headVertCount;

                            byte[] texBlock = ReadBlock(fs, texPointer, texElemSize * texCount);
                            for (uint iii = 0; iii < texCount; iii++)
                            {
                                RatchetTexture_Model tex = new RatchetTexture_Model();
                                tex.ID          = BAToUInt32(texBlock, (iii * texElemSize) + 0x00);
                                tex.start       = BAToUInt32(texBlock, (iii * texElemSize) + 0x04) + prevPrevFaceCount;
                                tex.size        = BAToUInt32(texBlock, (iii * texElemSize) + 0x08) + prevPrevFaceCount;
                                localFaceCount += BAToUInt32(texBlock, (iii * texElemSize) + 0x08);
                                model.textureConfig.Add(tex);
                            }

                            byte[] vertBlock = ReadBlock(fs, vertPointer + vertStart * vertElemSize, headVertCount * vertElemSize);
                            byte[] colBlock  = ReadBlock(fs, colPointer + vertStart * ColorElemSize, headVertCount * ColorElemSize);
                            byte[] UVBlock   = ReadBlock(fs, UVPointer + vertStart * UVElemSize, headVertCount * UVElemSize);

                            for (uint iii = 0; iii < headVertCount; iii++)
                            {
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x00)); //vertx
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x04)); //verty
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x08)); //vertz
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x0C)); //normx
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x10)); //normy
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x14)); //normz

                                model.vertBuff.Add(BAToFloat(UVBlock, (iii * UVElemSize) + 0x00));     //UVu
                                model.vertBuff.Add(BAToFloat(UVBlock, (iii * UVElemSize) + 0x04));     //UVv

                                model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x00] / 255f);     //color r
                                model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x01] / 255f);     //color g
                                model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x02] / 255f);     //color b
                                model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x03] / 255f);     //color a
                            }

                            byte[] indiceBuff = ReadBlock(fs, indicePointer + prevFaceCount * sizeof(ushort), localFaceCount * sizeof(ushort));
                            for (uint iii = 0; iii < localFaceCount; iii++)
                            {
                                model.indiceBuff.Add(BAToUInt16(indiceBuff, iii * sizeof(ushort)) + prevVertCount);
                            }
                            prevFaceCount += localFaceCount;
                            prevHeadCount  = ii + 1;
                        }
                        prevVertCount     = vertCount;
                        prevPrevFaceCount = prevFaceCount;
                    }
                }
                model.vertexCount      = vertCount;
                model.faceCount        = prevFaceCount;
                DataStore.terrainModel = model;
            }
            #endregion

            //Load Level Objects
            #region Level objects
            byte[] levelObjectBlock = ReadBlock(fs, engineHeader.levelObjectPointer, engineHeader.levelObjectCount * 0x70);
            DataStore.levelObjects = new List <LevelObject>();
            for (uint i = 0; i < engineHeader.levelObjectCount; i++)
            {
                LevelObject levObj = new LevelObject(levelObjectBlock, i);
                DataStore.levelObjects.Add(levObj);
            }
            #endregion

            //Load Scenery Objects
            #region Scenery objects
            byte[] sceneryObjectBlock = ReadBlock(fs, engineHeader.sceneryObjectsPointer, engineHeader.sceneryObjectsCount * 0x70);
            DataStore.sceneryObjects = new List <LevelObject>();
            for (uint i = 0; i < engineHeader.sceneryObjectsCount; i++)
            {
                LevelObject levObj = new LevelObject(sceneryObjectBlock, i);
                DataStore.sceneryObjects.Add(levObj);
            }
            #endregion

            //Load Textures
            #region Textures
            RatchetTexture_General texture = new RatchetTexture_General();
            for (int x = 0; x < engineHeader.UYATextureCount; x++)
            {
                texture.texHeader = ReadBlock(fs, engineHeader.texturesPointer + (uint)(0x24 * x), 0x24);
                uint nextTexturePointer    = x < engineHeader.UYATextureCount - 1 ? ReadUInt32(ReadBlock(fs, engineHeader.texturesPointer + (uint)(0x24 * (x + 1)), 0x4), 0) : vfs != null ? (uint)vfs.Length : 0;
                uint currentTexturePointer = ReadUInt32(texture.texHeader, 0);
                //Console.WriteLine("Parsing texture " + x + " " + currentTexturePointer.ToString("X") + " " + nextTexturePointer.ToString("X"));
                texture.ID      = x;
                texture.width   = BAToShort(texture.texHeader, 0x18);
                texture.height  = BAToShort(texture.texHeader, 0x1A);
                texture.texData = vfs != null?ReadBlock(vfs, currentTexturePointer, nextTexturePointer - currentTexturePointer) : null;

                texture.reverseRGB = false;
                DataStore.textures.Add(texture);
                //Console.WriteLine("Texture : " + x + " Width: " + texture.width + " Height: " + texture.height);
            }
            #endregion



            //Terrain Collision
            #region Terrain Collision
            float div = 1024f;

            uint collisionVertCount = 0;

            uint   collisionStart  = engineHeader.collisionPointer + BAToUInt32(ReadBlock(fs, engineHeader.collisionPointer + 0x00, 4), 0);
            uint   collisionLength = engineHeader.collisionPointer + collisionStart + BAToUInt32(ReadBlock(fs, engineHeader.collisionPointer + 0x04, 4), 0);
            byte[] collision       = ReadBlock(fs, collisionStart, collisionLength);

            List <float> collisionVertexBuff = new List <float>();
            List <uint>  collisionIndiceBuff = new List <uint>();

            ushort zShift = BAToUInt16(collision, 0);
            ushort zCount = BAToUInt16(collision, 2);

            for (uint z = 0; z < zCount; z++)
            {
                uint yOffset = BAToUInt32(collision, (z * 4) + 0x04);
                if (yOffset != 0)
                {
                    ushort yShift = BAToUInt16(collision, yOffset + 0);
                    ushort yCount = BAToUInt16(collision, yOffset + 2);
                    for (uint y = 0; y < yCount; y++)
                    {
                        uint xOffset = BAToUInt32(collision, yOffset + (y * 4) + 0x04);
                        if (xOffset != 0)
                        {
                            ushort xShift = BAToUInt16(collision, xOffset + 0);
                            ushort xCount = BAToUInt16(collision, xOffset + 2);
                            for (uint x = 0; x < xCount; x++)
                            {
                                uint   vOffset     = BAToUInt32(collision, xOffset + (x * 4) + 4);
                                ushort faceCount   = BAToUInt16(collision, vOffset);
                                byte   vertexCount = collision[vOffset + 2];
                                byte   rCount      = collision[vOffset + 3];

                                if (vOffset != 0)
                                {
                                    byte[] collisionType = new byte[vertexCount];
                                    //Console.WriteLine("Facecount: " + faceCount.ToString("X2") + "VertCount: " + vertexCount.ToString("X2"));
                                    for (uint f = 0; f < faceCount; f++)
                                    {
                                        uint   fOffset = vOffset + ((uint)12 * vertexCount) + 4 + (f * 4);
                                        byte[] fArray  = new byte[4];
                                        Array.Copy(collision, fOffset, fArray, 0, 4);

                                        collisionType[fArray[0]] = fArray[3];
                                        collisionType[fArray[1]] = fArray[3];
                                        collisionType[fArray[2]] = fArray[3];

                                        uint f1 = collisionVertCount + fArray[0];
                                        uint f2 = collisionVertCount + fArray[1];
                                        uint f3 = collisionVertCount + fArray[2];
                                        collisionIndiceBuff.Add(f1);
                                        collisionIndiceBuff.Add(f2);
                                        collisionIndiceBuff.Add(f3);
                                        if (f < rCount)
                                        {
                                            uint rOffset = vOffset + 4 + (uint)(12 * vertexCount) + (uint)(4 * faceCount) + f;
                                            uint f4      = collisionVertCount + collision[rOffset];
                                            collisionIndiceBuff.Add(f1);
                                            collisionIndiceBuff.Add(f3);
                                            collisionIndiceBuff.Add(f4);
                                            collisionType[collision[rOffset]] = fArray[3];
                                        }
                                    }

                                    for (uint v = 0; v < vertexCount; v++)
                                    {
                                        uint  pOffset = vOffset + (12 * v) + 4;
                                        float pX      = BAToFloat(collision, pOffset + 0) / div + 4 * (xShift + x + 0.5f);
                                        float pY      = BAToFloat(collision, pOffset + 4) / div + 4 * (yShift + y + 0.5f);
                                        float pZ      = BAToFloat(collision, pOffset + 8) / div + 4 * (zShift + z + 0.5f);
                                        collisionVertexBuff.Add(pX);
                                        collisionVertexBuff.Add(pY);
                                        collisionVertexBuff.Add(pZ);
                                        switch (collisionType[v])
                                        {
                                        case 0x1F:
                                            collisionVertexBuff.Add(0.0f);
                                            collisionVertexBuff.Add(0.0f);
                                            collisionVertexBuff.Add(0.0f);
                                            break;

                                        case 0x08:
                                            collisionVertexBuff.Add(1.0f);
                                            collisionVertexBuff.Add(0.0f);
                                            collisionVertexBuff.Add(0.0f);
                                            break;

                                        case 0x0C:
                                            collisionVertexBuff.Add(0.0f);
                                            collisionVertexBuff.Add(1.0f);
                                            collisionVertexBuff.Add(0.0f);
                                            break;

                                        case 0x01:
                                            //This
                                            collisionVertexBuff.Add(0.0f);
                                            collisionVertexBuff.Add(0.0f);
                                            collisionVertexBuff.Add(0.0f);
                                            break;

                                        case 0x3F:
                                            collisionVertexBuff.Add(0.5f);
                                            collisionVertexBuff.Add(0.0f);
                                            collisionVertexBuff.Add(0.0f);
                                            break;

                                        case 0x0B:
                                            collisionVertexBuff.Add(0.0f);
                                            collisionVertexBuff.Add(0.5f);
                                            collisionVertexBuff.Add(0.0f);
                                            break;

                                        case 0x0A:
                                            collisionVertexBuff.Add(0.0f);
                                            collisionVertexBuff.Add(0.0f);
                                            collisionVertexBuff.Add(0.5f);
                                            break;

                                        case 0x28:
                                            collisionVertexBuff.Add(0.25f);
                                            collisionVertexBuff.Add(0.0f);
                                            collisionVertexBuff.Add(0.0f);
                                            break;

                                        case 0x5F:
                                            collisionVertexBuff.Add(0.0f);
                                            collisionVertexBuff.Add(0.25f);
                                            collisionVertexBuff.Add(0.0f);
                                            break;

                                        case 0x09:
                                            collisionVertexBuff.Add(0.0f);
                                            collisionVertexBuff.Add(0.0f);
                                            collisionVertexBuff.Add(0.25f);
                                            break;

                                        case 0x00:
                                            collisionVertexBuff.Add(0.0f);
                                            collisionVertexBuff.Add(0.0f);
                                            collisionVertexBuff.Add(1.0f);
                                            break;

                                        case 0x6C:
                                            collisionVertexBuff.Add(0.5f);
                                            collisionVertexBuff.Add(0.5f);
                                            collisionVertexBuff.Add(0.5f);
                                            break;

                                        default:
                                            collisionVertexBuff.Add(1.0f);
                                            collisionVertexBuff.Add(1.0f);
                                            collisionVertexBuff.Add(1.0f);
                                            break;
                                        }
                                        collisionVertCount++;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            DataStore.collVertBuff = collisionVertexBuff;
            DataStore.collIndBuff  = collisionIndiceBuff;
            #endregion

            #region Chunks
            List <int> chunkIds = new List <int>();
            for (int chunkIndex = 0; chunkIndex < 5; chunkIndex++)
            {
                if (File.Exists(path + "/chunk" + chunkIndex + ".ps3"))
                {
                    chunkIds.Add(chunkIndex);
                }
            }

            foreach (int chunkId in chunkIds)
            {
                FileStream cfs = File.OpenRead(path + "/chunk" + chunkId + ".ps3");
                Console.WriteLine("Loading chunk " + chunkId);
                uint terrainElemSize = 0x30;
                uint texElemSize     = 0x10;
                uint vertElemSize    = 0x1c;
                uint UVElemSize      = 0x08;
                uint ColorElemSize   = 0x04;

                RatchetModel_Terrain model = new RatchetModel_Terrain();
                model.offset    = 0x10;
                model.modelID   = 1111;
                model.modelType = ModelType.Terrain;
                byte[] terrainHeadBlock = ReadBlock(cfs, 0x10, 0x60);

                uint   headPointer = BAToUInt32(terrainHeadBlock, 0x0);
                ushort headCount   = BAToUInt16(terrainHeadBlock, 0x06);

                byte[] terrainBlock = ReadBlock(cfs, headPointer, headCount * terrainElemSize);

                model.textureConfig = new List <RatchetTexture_Model>();
                model.vertBuff      = new List <float>();
                model.indiceBuff    = new List <uint>();
                uint vertCount         = 0;
                uint prevVertCount     = 0;
                uint prevFaceCount     = 0;
                uint prevHeadCount     = 0;
                uint prevPrevFaceCount = 0;

                for (uint i = 0; i < 4; i++)   //I have yet to see any level have more than two of these, but the header theoretically has space for 4
                {
                    uint vertPointer   = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x08);
                    uint colPointer    = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x18);
                    uint UVPointer     = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x28);
                    uint indicePointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x38);

                    prevFaceCount = 0;
                    if (vertPointer != 0 && UVPointer != 0 && indicePointer != 0)    //Check that there's data at the pointers
                    {
                        //Loop throught the heads, and stop when the overflow counter increases
                        for (uint ii = prevHeadCount; ii < headCount && i == BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x22); ii++)
                        {
                            uint   localFaceCount = 0;
                            uint   texPointer     = BAToUInt32(terrainBlock, (ii * terrainElemSize) + 0x10);
                            uint   texCount       = BAToUInt32(terrainBlock, (ii * terrainElemSize) + 0x14);
                            ushort vertStart      = BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x18);
                            ushort headVertCount  = BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x1A);
                            vertCount += headVertCount;

                            byte[] texBlock = ReadBlock(cfs, texPointer, texElemSize * texCount);
                            for (uint iii = 0; iii < texCount; iii++)
                            {
                                RatchetTexture_Model tex = new RatchetTexture_Model();
                                tex.ID    = BAToUInt32(texBlock, (iii * texElemSize) + 0x00);
                                tex.start = BAToUInt32(texBlock, (iii * texElemSize) + 0x04) + prevPrevFaceCount;
                                tex.size  = BAToUInt32(texBlock, (iii * texElemSize) + 0x08) + prevPrevFaceCount;

                                localFaceCount += BAToUInt32(texBlock, (iii * texElemSize) + 0x08);

                                model.textureConfig.Add(tex);
                            }


                            byte[] vertBlock = ReadBlock(cfs, vertPointer + vertStart * vertElemSize, headVertCount * vertElemSize);
                            byte[] colBlock  = ReadBlock(cfs, colPointer + vertStart * ColorElemSize, headVertCount * ColorElemSize);
                            byte[] UVBlock   = ReadBlock(cfs, UVPointer + vertStart * UVElemSize, headVertCount * UVElemSize);

                            for (uint iii = 0; iii < headVertCount; iii++)
                            {
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x00)); //vertx
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x04)); //verty
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x08)); //vertz
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x0C)); //normx
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x10)); //normy
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x14)); //normz

                                model.vertBuff.Add(BAToFloat(UVBlock, (iii * UVElemSize) + 0x00));     //UVu
                                model.vertBuff.Add(BAToFloat(UVBlock, (iii * UVElemSize) + 0x04));     //UVv


                                model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x00] / 255f);    //color r
                                model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x01] / 255f);    //color g
                                model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x02] / 255f);    //color b
                                model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x03] / 255f);    //color a
                            }



                            byte[] indiceBuff = ReadBlock(cfs, indicePointer + prevFaceCount * sizeof(ushort), localFaceCount * sizeof(ushort));
                            //Console.WriteLine(localFaceCount.ToString("X8"));
                            for (uint iii = 0; iii < localFaceCount; iii++)
                            {
                                model.indiceBuff.Add(BAToUInt16(indiceBuff, iii * sizeof(ushort)) + prevVertCount);
                            }

                            prevFaceCount += localFaceCount;
                            prevHeadCount  = ii + 1;
                        }
                        prevVertCount     = vertCount;
                        prevPrevFaceCount = prevFaceCount;
                    }
                }
                model.vertexCount = vertCount;
                model.faceCount   = prevFaceCount;
                DataStore.chunks.Add(model);
            }
            #endregion

            //TODO: textureConfig - Menus

            //TODO: textureConfig - 2D GFX

            //TODO: Sprites


            //Load the remaining unknown or unhandled data
            #region Remaining Data

            /*
             * DataStore.mapRenderDefintions = getSection(fs, 0x04);
             * DataStore.Ptr_08 = getSection(fs, 0x08);
             * DataStore.Ptr_0C = getSection(fs, 0x0C);
             * DataStore.skyBox = getSection(fs, 0x10);
             * DataStore.collisionMap = getSection(fs, 0x14);
             * DataStore.campaignPlayerAnimations = getSection(fs, 0x18);
             * DataStore.Ptr_40 = getSection(fs, 0x40);
             * DataStore.Ptr_44 = getSection(fs, 0x44);
             * DataStore.soundsConfig = getSection(fs, 0x48);
             * DataStore.Ptr_4C = getSection(fs, 0x4C);
             * DataStore.Ptr_50 = getSection(fs, 0x50);
             * DataStore.lighting = getSection(fs, 0x5C);
             * DataStore.lightingConfig = getSection(fs, 0x64);
             * DataStore.textureConfigMenu = getSection(fs, 0x68);
             * DataStore.textureConfig2DGFX = getSection(fs, 0x70);
             * DataStore.spriteDef = getSection(fs, 0x74);
             */
            #endregion

            #region raw Data //need to properly handle these eventually
            //DataStore.terrainModel.rawData = getSection(fs, 0x3C);
            //rawLevelModelBlock = getSection(fs, 0x1C);
            //rawSceneryModelBlock = getSection(fs, 0x2C);
            #endregion

            fs.Close();

            Console.WriteLine("Engine data loaded with new engine parser for UYA.");
        }
        private void button1_Click(object sender, EventArgs e)
        {
            int mobElemSize = (int)DataStore.gameplayHeader.mobyElemSize;
            int mobCount    = DataStore.mobs.Count();

            byte[] test = new byte[mobCount * mobElemSize];

            switch (DataStore.gameplayHeader.gameNum)
            {
            case 1:
                for (int i = 0; i < mobCount; i++)
                {
                    RatchetMoby mob = DataStore.mobs[i];
                    WriteUint32(ref test, (i * mobElemSize) + 0x00, mob.length);
                    WriteUint32(ref test, (i * mobElemSize) + 0x04, mob.missionID);
                    WriteUint32(ref test, (i * mobElemSize) + 0x08, mob.unk1);
                    WriteUint32(ref test, (i * mobElemSize) + 0x0C, mob.dataval);

                    WriteUint32(ref test, (i * mobElemSize) + 0x10, mob.dropamnt);
                    WriteUint32(ref test, (i * mobElemSize) + 0x14, mob.unk2);
                    WriteUint32(ref test, (i * mobElemSize) + 0x18, mob.modelID);
                    WriteFloat(ref test, (i * mobElemSize) + 0x1C, mob.size);

                    WriteUint32(ref test, (i * mobElemSize) + 0x20, mob.rend1);
                    WriteUint32(ref test, (i * mobElemSize) + 0x24, mob.rend2);
                    WriteUint32(ref test, (i * mobElemSize) + 0x28, mob.unk3);
                    WriteUint32(ref test, (i * mobElemSize) + 0x2C, mob.unk4);

                    WriteFloat(ref test, (i * mobElemSize) + 0x30, mob.x);
                    WriteFloat(ref test, (i * mobElemSize) + 0x34, mob.y);
                    WriteFloat(ref test, (i * mobElemSize) + 0x38, mob.z);
                    WriteFloat(ref test, (i * mobElemSize) + 0x3C, mob.rot1);

                    WriteFloat(ref test, (i * mobElemSize) + 0x40, mob.rot2);
                    WriteFloat(ref test, (i * mobElemSize) + 0x44, mob.rot3);
                    WriteUint32(ref test, (i * mobElemSize) + 0x48, mob.unk5);
                    WriteInt32(ref test, (i * mobElemSize) + 0x4C, mob.test1);

                    WriteFloat(ref test, (i * mobElemSize) + 0x50, mob.z2);
                    WriteUint32(ref test, (i * mobElemSize) + 0x54, mob.unk8);
                    WriteUint32(ref test, (i * mobElemSize) + 0x58, mob.propIndex);
                    WriteUint32(ref test, (i * mobElemSize) + 0x5C, mob.unk9);

                    WriteUint32(ref test, (i * mobElemSize) + 0x60, mob.unk10);
                    WriteUint32(ref test, (i * mobElemSize) + 0x64, mob.r);
                    WriteUint32(ref test, (i * mobElemSize) + 0x68, mob.g);
                    WriteUint32(ref test, (i * mobElemSize) + 0x6C, mob.b);

                    WriteUint32(ref test, (i * mobElemSize) + 0x70, mob.light);
                    WriteInt32(ref test, (i * mobElemSize) + 0x74, mob.cutScene);
                }
                break;

            case 2:
            case 3:
                for (int i = 0; i < mobCount; i++)
                {
                    RatchetMoby mob = DataStore.mobs[i];
                    WriteUint32(ref test, (i * mobElemSize) + 0x00, mob.length);
                    WriteUint32(ref test, (i * mobElemSize) + 0x04, mob.missionID);
                    WriteUint32(ref test, (i * mobElemSize) + 0x08, mob.unk1);
                    WriteUint32(ref test, (i * mobElemSize) + 0x0C, mob.dataval);

                    WriteUint32(ref test, (i * mobElemSize) + 0x10, mob.unk2);
                    WriteUint32(ref test, (i * mobElemSize) + 0x14, mob.dropamnt);
                    WriteUint32(ref test, (i * mobElemSize) + 0x18, mob.unk3);
                    WriteUint32(ref test, (i * mobElemSize) + 0x1C, mob.unk4);

                    WriteUint32(ref test, (i * mobElemSize) + 0x20, mob.unk5);
                    WriteUint32(ref test, (i * mobElemSize) + 0x24, mob.unk6);
                    WriteUint32(ref test, (i * mobElemSize) + 0x28, mob.modelID);
                    WriteFloat(ref test, (i * mobElemSize) + 0x2C, mob.size);

                    WriteUint32(ref test, (i * mobElemSize) + 0x30, mob.rend1);
                    WriteUint32(ref test, (i * mobElemSize) + 0x34, mob.rend2);
                    WriteUint32(ref test, (i * mobElemSize) + 0x38, mob.unk7);
                    WriteUint32(ref test, (i * mobElemSize) + 0x3C, mob.unk8);

                    WriteFloat(ref test, (i * mobElemSize) + 0x40, mob.x);
                    WriteFloat(ref test, (i * mobElemSize) + 0x44, mob.y);
                    WriteFloat(ref test, (i * mobElemSize) + 0x48, mob.z);
                    WriteFloat(ref test, (i * mobElemSize) + 0x4C, mob.rot1);

                    WriteFloat(ref test, (i * mobElemSize) + 0x50, mob.rot2);
                    WriteFloat(ref test, (i * mobElemSize) + 0x54, mob.rot3);
                    WriteUint32(ref test, (i * mobElemSize) + 0x58, mob.unk9);
                    WriteUint32(ref test, (i * mobElemSize) + 0x5C, mob.unk10);

                    WriteUint32(ref test, (i * mobElemSize) + 0x60, mob.unk11);
                    WriteUint32(ref test, (i * mobElemSize) + 0x64, mob.unk12);
                    WriteUint32(ref test, (i * mobElemSize) + 0x68, mob.propIndex);
                    WriteUint32(ref test, (i * mobElemSize) + 0x6C, mob.unk14);

                    WriteUint32(ref test, (i * mobElemSize) + 0x70, mob.unk15);
                    WriteUint32(ref test, (i * mobElemSize) + 0x74, mob.r);
                    WriteUint32(ref test, (i * mobElemSize) + 0x78, mob.g);
                    WriteUint32(ref test, (i * mobElemSize) + 0x7C, mob.b);

                    WriteUint32(ref test, (i * mobElemSize) + 0x80, mob.light);
                    WriteUint32(ref test, (i * mobElemSize) + 0x84, mob.unk16);
                }
                break;

            case 4:
                for (int i = 0; i < mobCount; i++)
                {
                    RatchetMoby mob = DataStore.mobs[i];
                    WriteUint32(ref test, (i * mobElemSize) + 0x00, mob.length);
                    WriteUint32(ref test, (i * mobElemSize) + 0x04, mob.missionID);
                    WriteUint32(ref test, (i * mobElemSize) + 0x08, mob.dataval);
                    WriteUint32(ref test, (i * mobElemSize) + 0x0C, mob.unk1);

                    WriteUint32(ref test, (i * mobElemSize) + 0x10, mob.modelID);
                    WriteFloat(ref test, (i * mobElemSize) + 0x14, mob.size);
                    WriteUint32(ref test, (i * mobElemSize) + 0x18, mob.rend1);
                    WriteUint32(ref test, (i * mobElemSize) + 0x1C, mob.rend2);

                    WriteUint32(ref test, (i * mobElemSize) + 0x20, mob.unk2);
                    WriteUint32(ref test, (i * mobElemSize) + 0x24, mob.unk3);
                    WriteFloat(ref test, (i * mobElemSize) + 0x28, mob.x);
                    WriteFloat(ref test, (i * mobElemSize) + 0x2C, mob.y);

                    WriteFloat(ref test, (i * mobElemSize) + 0x30, mob.z);
                    WriteFloat(ref test, (i * mobElemSize) + 0x34, mob.rot1);
                    WriteFloat(ref test, (i * mobElemSize) + 0x38, mob.rot2);
                    WriteFloat(ref test, (i * mobElemSize) + 0x3C, mob.rot3);

                    WriteUint32(ref test, (i * mobElemSize) + 0x40, mob.unk4);
                    WriteUint32(ref test, (i * mobElemSize) + 0x44, mob.unk5);
                    WriteUint32(ref test, (i * mobElemSize) + 0x48, mob.unk6);
                    WriteUint32(ref test, (i * mobElemSize) + 0x4C, mob.unk7);

                    WriteUint32(ref test, (i * mobElemSize) + 0x50, mob.propIndex);
                    WriteUint32(ref test, (i * mobElemSize) + 0x54, mob.unk8);
                    WriteUint32(ref test, (i * mobElemSize) + 0x58, mob.unk9);
                    WriteUint32(ref test, (i * mobElemSize) + 0x5C, mob.r);

                    WriteUint32(ref test, (i * mobElemSize) + 0x60, mob.g);
                    WriteUint32(ref test, (i * mobElemSize) + 0x64, mob.b);
                    WriteUint32(ref test, (i * mobElemSize) + 0x68, mob.light);
                    WriteUint32(ref test, (i * mobElemSize) + 0x6C, mob.unk14);
                }
                break;
            }


            FileStream gameplayFile = null;

            gameplayFile = File.OpenWrite(DataStore.workingDirectory + "/gameplay_ntsc");
            Console.WriteLine((DataStore.gameplayHeader.mobyPointer + 0x10).ToString("X8"));
            gameplayFile.Seek(DataStore.gameplayHeader.mobyPointer + 0x10, SeekOrigin.Begin);
            gameplayFile.Write(test, 0, mobCount * mobElemSize);
            gameplayFile.Close();
            Console.WriteLine("File written successfully, enjoy :)");
        }
Beispiel #5
0
        public static void parseMap(string path, string fileName)
        {
            FileStream fs = File.OpenRead(path + "/" + fileName);

            FileStream vfs = null;

            if (File.Exists(path + "/vram.ps3"))
            {
                vfs = File.OpenRead(path + "/vram.ps3");
            }

            FileStream gpf = null;

            if (File.Exists(path + "/gameplay_ntsc"))
            {
                gpf = File.OpenRead(path + "/gameplay_ntsc");
            }

            loadMobyPvarMap();


            uint racNum = 4;

            #region GameplayHeader
            GameplayHeader gameplayHeader = new GameplayHeader(gpf, racNum);
            DataStore.gameplayHeader = gameplayHeader;

            #endregion

            #region pVars
            List <byte[]> pVars;
            uint          numpVars;
            byte[]        pVarHeadBlock;
            uint          pVarSectionLength;
            byte[]        pVarBlock;
            switch (racNum)
            {
            case 4:
                pVars             = new List <byte[]>();
                numpVars          = (gameplayHeader.pVarPointer - gameplayHeader.pVarListPointer) / 8;
                pVarHeadBlock     = ReadBlock(gpf, gameplayHeader.pVarListPointer, numpVars * 8);
                pVarSectionLength = 0;
                for (uint i = 0; i < numpVars; i++)
                {
                    pVarSectionLength += BAToUInt32(pVarHeadBlock, (i * 8) + 0x04);
                }
                pVarBlock = ReadBlock(gpf, gameplayHeader.pVarPointer, pVarSectionLength);
                for (uint i = 0; i < numpVars; i++)
                {
                    uint   mobpVarsStart = BAToUInt32(pVarHeadBlock, (i * 8));
                    uint   mobpVarsCount = BAToUInt32(pVarHeadBlock, (i * 8) + 0x04);
                    byte[] mobpVars      = new byte[mobpVarsCount];
                    mobpVars = getBytes(pVarBlock, (int)mobpVarsStart, (int)mobpVarsCount);
                    pVars.Add(mobpVars);
                }
                DataStore.pVarList = pVars;
                break;
            }
            #endregion pVars

            #region Mobies

            uint   mobyCount = BAToUInt32(ReadBlock(gpf, gameplayHeader.mobyPointer, 4), 0);
            byte[] mobyBlock = ReadBlock(gpf, gameplayHeader.mobyPointer + 0x10, mobyCount * gameplayHeader.mobyElemSize);

            for (uint i = 0; i < mobyCount; i++)
            {
                RatchetMoby mob = new RatchetMoby(racNum, mobyBlock, i);
                DataStore.mobs.Add(mob);
            }
            #endregion

            DataStore.splines = new List <Spline>();

            uint   splineCount       = BAToUInt32(ReadBlock(gpf, gameplayHeader.splinePointer, 4), 0);
            uint   splineOffset      = BAToUInt32(ReadBlock(gpf, gameplayHeader.splinePointer + 4, 4), 0);
            uint   splineSectionSize = BAToUInt32(ReadBlock(gpf, gameplayHeader.splinePointer + 8, 4), 0);
            byte[] splineHeadBlock   = ReadBlock(gpf, gameplayHeader.splinePointer + 0x10, splineCount * 4);
            byte[] splineBlock       = ReadBlock(gpf, gameplayHeader.splinePointer + splineOffset, splineSectionSize);
            for (uint i = 0; i < splineCount; i++)
            {
                uint offset = BAToUInt32(splineHeadBlock, (i * 4));
                DataStore.splines.Add(new Spline(splineBlock, offset));
            }


            #region EngineHeader
            byte[] engineHeader = ReadBlock(fs, 0, 0x90);

            //Data from header
            uint spawnablesPointer = BAToUInt32(engineHeader, 0x00);
            //(0x04)Map render definitions
            //(0x08)null
            //(0x0C)null
            //(0x14)Skybox
            //(0x18)Collisionmap
            uint levelModelsPointer            = BAToUInt32(engineHeader, 0x20);
            uint levelModelsCount              = BAToUInt32(engineHeader, 0x24);
            uint levelModelsPlacementPointer   = BAToUInt32(engineHeader, 0x28);
            uint levelObjectsCount             = BAToUInt32(engineHeader, 0x2C);
            uint sceneryModelsPointer          = BAToUInt32(engineHeader, 0x34);
            uint sceneryModelsCount            = BAToUInt32(engineHeader, 0x38);
            uint sceneryModelsPlacementPointer = BAToUInt32(engineHeader, 0x3C);
            uint sceneryObjectsCount           = BAToUInt32(engineHeader, 0x40);
            uint terrainPointer = BAToUInt32(engineHeader, 0x48);
            //(0x44) ??
            //(0x54)Sound config (Menus + terrain)
            uint texturesPointer = BAToUInt32(engineHeader, 0x60);
            uint textureCount    = BAToUInt32(engineHeader, 0x64);
            //(0x68)Lighting pointer
            uint lightingLevel          = BAToUInt32(engineHeader, 0x6C);
            uint textureConfigMenuCount = BAToUInt32(engineHeader, 0x78);
            //(0x7C)textureConfig2DGFX
            //(0x80)Sprite def
            //(0x88) sound config (spawnables + everything else)

            EngineHeader engHead = new EngineHeader(fs, 4);
            DataStore.engineHeader = engHead;
            #endregion

            //Load DL Spawnable Models
            #region Spawnables
            uint   spawnablesCount = BAToUInt32(ReadBlock(fs, spawnablesPointer, 4), 0);
            byte[] idBlock         = ReadBlock(fs, spawnablesPointer + 4, spawnablesCount * 8);

            for (int x = 0; x < spawnablesCount; x++)
            {
                RatchetModel_General model = new RatchetModel_General();
                model.modelType = ModelType.Spawnable;

                model.modelID = BAToShort(idBlock, (uint)(x * 8) + 2);
                model.offset  = BAToUInt32(idBlock, (uint)(x * 8) + 4);

                if (model.offset != 0)
                {
                    uint modelHeadSize = BAToUInt32(ReadBlock(fs, model.offset, 4), 0);

                    if (modelHeadSize > 0)
                    {
                        byte[] headBlock = ReadBlock(fs, model.offset, modelHeadSize + 0x20); //Head + objectDetails
                        uint   objectPtr = BAToUInt32(headBlock, 0);
                        model.animationsCount = headBlock[0x0C];
                        //(0x04)null
                        //(0x08)[count for 0x14 and 0x18][unknown][unknown][unknown]
                        //(0x0c)[animation count][unknown][unknown][unknown]
                        //(0x10)Pointer to list
                        //(0x14)Pointer to skeleton joints (0x40 structure)
                        //(0x18)Pointer to skeleton somethings (0x16 structure)
                        //(0x1C)Pointer to left arm animations (Ratchet)
                        //(0x20)null
                        model.size = BAToFloat(headBlock, 0x24);
                        uint texCount          = BAToUInt32(headBlock, objectPtr + 0x00);
                        uint otherCount        = BAToUInt32(headBlock, objectPtr + 0x04);
                        uint texBlockPointer   = BAToUInt32(headBlock, objectPtr + 0x08);
                        uint otherBlockPointer = BAToUInt32(headBlock, objectPtr + 0x0C);
                        uint vertPointer       = BAToUInt32(headBlock, objectPtr + 0x10);
                        uint indexPointer      = BAToUInt32(headBlock, objectPtr + 0x14);
                        model.vertexCount = BAToUInt16(headBlock, objectPtr + 0x18);
                        //(0x1A)count
                        //(0x1C)count
                        //(0x1E)null


                        //model.rawData = getModelDataRaw(model.modelType, model.modelID, path + "/" + fileName);

                        model.animPointer = new List <uint>();
                        for (uint i = 0; i < model.animationsCount; i++)
                        {
                            model.animPointer.Add(BAToUInt32(headBlock, (i * sizeof(uint)) + 0x48));
                        }

                        uint   texElemSize = 0x10;
                        byte[] texBlock    = ReadBlock(fs, model.offset + texBlockPointer, texCount * texElemSize);
                        model.textureConfig = new List <RatchetTexture_Model>();
                        model.faceCount     = 0;
                        for (uint t = 0; t < texCount; t++)
                        {
                            RatchetTexture_Model modTex = new RatchetTexture_Model();
                            modTex.ID    = BAToUInt32(texBlock, (t * texElemSize) + 0x0);
                            modTex.start = BAToUInt32(texBlock, (t * texElemSize) + 0x04);
                            modTex.size  = BAToUInt32(texBlock, (t * texElemSize) + 0x08);
                            model.textureConfig.Add(modTex);
                            model.faceCount += modTex.size;
                        }


                        //Flip endianness of vertex array float[vert_x, vert_y, vert_z, norm_x, norm_y, norm_z, uv_u, uv_v, reserved reserved]
                        uint   vertElemSize = 0x28;
                        uint   vertBuffSize = model.vertexCount * vertElemSize;
                        byte[] vertBlock    = ReadBlock(fs, model.offset + vertPointer, vertBuffSize);
                        model.vertBuff = new List <float>();
                        for (uint i = 0; i < model.vertexCount; i++)
                        {
                            model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x00));    //Vertx
                            model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x04));    //Verty
                            model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x08));    //Vertz
                            model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x0C));    //Nomrx
                            model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x10));    //Normy
                            model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x14));    //Normz
                            model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x18));    //UVu
                            model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x1C));    //UVv
                        }

                        //Flip endianness of index array
                        byte[] indiceBuff = ReadBlock(fs, model.offset + indexPointer, model.faceCount * sizeof(ushort));
                        model.indiceBuff = new List <ushort>();
                        for (uint i = 0; i < model.faceCount; i++)
                        {
                            model.indiceBuff.Add(BAToUInt16(indiceBuff, i * sizeof(ushort)));
                        }
                    }
                }
                DataStore.spawnableModels.Add(model);
            }
            #endregion

            //Load DL Level Models
            #region Level Models
            uint   levelElemSize = 0x40;
            byte[] levelBlock    = ReadBlock(fs, levelModelsPointer, levelModelsCount * levelElemSize);

            for (uint x = 0; x < levelModelsCount; x++)
            {
                RatchetModel_General model = new RatchetModel_General();
                model.modelType = ModelType.Level;
                model.size      = 0.5f;

                uint vertPointer   = BAToUInt32(levelBlock, (x * levelElemSize) + 0x10);
                uint UVPointer     = BAToUInt32(levelBlock, (x * levelElemSize) + 0x14);
                uint indicePointer = BAToUInt32(levelBlock, (x * levelElemSize) + 0x18);
                uint texPointer    = BAToUInt32(levelBlock, (x * levelElemSize) + 0x1C);
                model.vertexCount = (ushort)BAToUInt32(levelBlock, (x * levelElemSize) + 0x24);
                ushort texCount = BAToUInt16(levelBlock, (x * levelElemSize) + 0x28);
                model.modelID = BAToShort(levelBlock, (x * levelElemSize) + 0x30);

                model.offset    = (uint)(x * 0x40) + levelModelsPointer;
                model.modelType = ModelType.Level;

                uint   texElemSize = 0x18;
                byte[] texBlock    = ReadBlock(fs, texPointer, texCount * texElemSize);
                model.textureConfig = new List <RatchetTexture_Model>();
                model.faceCount     = 0;
                for (uint t = 0; t < texCount; t++)
                {
                    RatchetTexture_Model dlt = new RatchetTexture_Model();
                    dlt.ID    = BAToUInt32(texBlock, (t * texElemSize) + 0x00);
                    dlt.start = BAToUInt32(texBlock, (t * texElemSize) + 0x08);
                    dlt.size  = BAToUInt32(texBlock, (t * texElemSize) + 0x0C);
                    model.textureConfig.Add(dlt);
                    model.faceCount += dlt.size;
                }

                //Flip endianness of vertex array float[vert_x, vert_y, vert_z, norm_x, norm_y, norm_z, uv_u, uv_v, reserved reserved]
                uint   vertElemSize = 0x18;
                uint   vertBuffSize = model.vertexCount * vertElemSize;
                byte[] vertBlock    = ReadBlock(fs, vertPointer, vertBuffSize);

                uint   UVElemsize = 0x08;
                uint   UVBuffSize = model.vertexCount * UVElemsize;
                byte[] UVBlock    = ReadBlock(fs, UVPointer, UVBuffSize);


                model.vertBuff = new List <float>();
                for (uint i = 0; i < model.vertexCount; i++)
                {
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x00)); //vertx
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x04)); //verty
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x08)); //vertz
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x0C)); //normx
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x10)); //normy
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x14)); //normz

                    model.vertBuff.Add(BAToFloat(UVBlock, (i * UVElemsize) + 0x00));     //UVu
                    model.vertBuff.Add(BAToFloat(UVBlock, (i * UVElemsize) + 0x04));     //UVv
                }

                //Flip endianness of index array
                byte[] indiceBuff = ReadBlock(fs, indicePointer, model.faceCount * sizeof(ushort));
                model.indiceBuff = new List <ushort>();
                for (uint i = 0; i < model.faceCount; i++)
                {
                    model.indiceBuff.Add(BAToUInt16(indiceBuff, i * sizeof(ushort)));
                }

                DataStore.levelModels.Add(model);
            }
            #endregion

            //Load DL Scenery Models
            #region Scenery Models
            uint   sceneElemSize = 0x40;
            byte[] sceneBlock    = ReadBlock(fs, sceneryModelsPointer, sceneryModelsCount * sceneElemSize);

            for (uint x = 0; x < sceneryModelsCount; x++)
            {
                RatchetModel_General model = new RatchetModel_General();
                model.modelType = ModelType.Scenery;
                model.size      = 0.5f;

                uint vertPointer   = BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x10);
                uint UVPointer     = BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x14);
                uint indicePointer = BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x18);
                uint texPointer    = BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x1C);
                model.vertexCount = (ushort)BAToUInt32(sceneBlock, (x * sceneElemSize) + 0x24);
                ushort texCount = BAToUInt16(sceneBlock, (x * sceneElemSize) + 0x28);
                model.modelID = BAToShort(sceneBlock, (x * sceneElemSize) + 0x30);

                uint   texElemSize = 0x10;
                byte[] texBlock    = ReadBlock(fs, texPointer, texCount * texElemSize);
                model.textureConfig = new List <RatchetTexture_Model>();
                model.faceCount     = 0;
                for (uint t = 0; t < texCount; t++)
                {
                    RatchetTexture_Model dlt = new RatchetTexture_Model();
                    dlt.ID    = BAToUInt32(texBlock, (t * texElemSize) + 0x00);
                    dlt.start = BAToUInt32(texBlock, (t * texElemSize) + 0x04);
                    dlt.size  = BAToUInt32(texBlock, (t * texElemSize) + 0x08);
                    model.textureConfig.Add(dlt);
                    model.faceCount += dlt.size;
                }

                //Flip endianness of vertex array float[vert_x, vert_y, vert_z, norm_x, norm_y, norm_z, uv_u, uv_v, reserved reserved]
                uint   vertElemSize = 0x18;
                uint   vertBuffSize = model.vertexCount * vertElemSize;
                byte[] vertBlock    = ReadBlock(fs, vertPointer, vertBuffSize);

                uint   UVElemsize = 0x08;
                uint   UVBuffSize = model.vertexCount * UVElemsize;
                byte[] UVBlock    = ReadBlock(fs, UVPointer, UVBuffSize);


                model.vertBuff = new List <float>();
                for (uint i = 0; i < model.vertexCount; i++)
                {
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x00)); //vertx
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x04)); //verty
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x08)); //vertz
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x0C)); //normx
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x10)); //normy
                    model.vertBuff.Add(BAToFloat(vertBlock, (i * vertElemSize) + 0x14)); //normz

                    model.vertBuff.Add(BAToFloat(UVBlock, (i * UVElemsize) + 0x00));     //UVu
                    model.vertBuff.Add(BAToFloat(UVBlock, (i * UVElemsize) + 0x04));     //UVv
                }

                //Flip endianness of index array
                byte[] indiceBuff = ReadBlock(fs, indicePointer, model.faceCount * sizeof(ushort));
                model.indiceBuff = new List <ushort>();
                for (uint i = 0; i < model.faceCount; i++)
                {
                    model.indiceBuff.Add(BAToUInt16(indiceBuff, i * sizeof(ushort)));
                }

                DataStore.sceneryModels.Add(model);
                //Console.WriteLine("Scenery Model Added: 0x" + model.modelID.ToString("X4"));
            }
            #endregion

            //Load Terrain
            #region Terrain
            {
                uint terrainElemSize = 0x30;
                uint texElemSize     = 0x10;
                uint vertElemSize    = 0x1c;
                uint UVElemSize      = 0x08;
                uint ColorElemSize   = 0x04;

                RatchetModel_Terrain model = new RatchetModel_Terrain();
                model.offset    = terrainPointer;
                model.modelID   = 1111;
                model.modelType = ModelType.Terrain;
                byte[] terrainHeadBlock = ReadBlock(fs, terrainPointer, 0x60);

                uint   headPointer = BAToUInt32(terrainHeadBlock, 0x0);
                ushort headCount   = BAToUInt16(terrainHeadBlock, 0x06);

                byte[] terrainBlock = ReadBlock(fs, headPointer, headCount * terrainElemSize);
                model.textureConfig = new List <RatchetTexture_Model>();
                model.vertBuff      = new List <float>();
                model.indiceBuff    = new List <uint>();
                uint vertCount         = 0;
                uint prevVertCount     = 0;
                uint prevFaceCount     = 0;
                uint prevHeadCount     = 0;
                uint prevPrevFaceCount = 0;

                for (uint i = 0; i < 4; i++)    //I have yet to see any level have more than two of these, but the header theoretically has space for 4
                {
                    uint vertPointer   = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x08);
                    uint colPointer    = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x18);
                    uint UVPointer     = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x28);
                    uint indicePointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x38);

                    prevFaceCount = 0;
                    if (vertPointer != 0 && UVPointer != 0 && indicePointer != 0)    //Check that there's data at the pointers
                    {
                        //Loop throught the heads, and stop when the overflow counter increases
                        for (uint ii = prevHeadCount; ii < headCount && i == BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x22); ii++)
                        {
                            uint   localFaceCount = 0;
                            uint   texPointer     = BAToUInt32(terrainBlock, (ii * terrainElemSize) + 0x10);
                            uint   texCount       = BAToUInt32(terrainBlock, (ii * terrainElemSize) + 0x14);
                            ushort vertStart      = BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x18);
                            ushort headVertCount  = BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x1A);
                            vertCount += headVertCount;

                            byte[] texBlock = ReadBlock(fs, texPointer, texElemSize * texCount);
                            for (uint iii = 0; iii < texCount; iii++)
                            {
                                RatchetTexture_Model tex = new RatchetTexture_Model();
                                tex.ID          = BAToUInt32(texBlock, (iii * texElemSize) + 0x00);
                                tex.start       = BAToUInt32(texBlock, (iii * texElemSize) + 0x04) + prevPrevFaceCount;
                                tex.size        = BAToUInt32(texBlock, (iii * texElemSize) + 0x08) + prevPrevFaceCount;
                                localFaceCount += BAToUInt32(texBlock, (iii * texElemSize) + 0x08);
                                model.textureConfig.Add(tex);
                            }


                            byte[] vertBlock = ReadBlock(fs, vertPointer + vertStart * vertElemSize, headVertCount * vertElemSize);
                            byte[] colBlock  = ReadBlock(fs, colPointer + vertStart * ColorElemSize, headVertCount * ColorElemSize);
                            byte[] UVBlock   = ReadBlock(fs, UVPointer + vertStart * UVElemSize, headVertCount * UVElemSize);

                            for (uint iii = 0; iii < headVertCount; iii++)
                            {
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x00)); //vertx
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x04)); //verty
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x08)); //vertz
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x0C)); //normx
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x10)); //normy
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x14)); //normz

                                model.vertBuff.Add(BAToFloat(UVBlock, (iii * UVElemSize) + 0x00));     //UVu
                                model.vertBuff.Add(BAToFloat(UVBlock, (iii * UVElemSize) + 0x04));     //UVv


                                model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x00] / 255f);    //color r
                                model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x01] / 255f);    //color g
                                model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x02] / 255f);    //color b
                                model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x03] / 255f);    //color a
                            }

                            byte[] indiceBuff = ReadBlock(fs, indicePointer + prevFaceCount * sizeof(ushort), localFaceCount * sizeof(ushort));
                            for (uint iii = 0; iii < localFaceCount; iii++)
                            {
                                model.indiceBuff.Add(BAToUInt16(indiceBuff, iii * sizeof(ushort)) + prevVertCount);
                            }
                            prevFaceCount += localFaceCount;
                            prevHeadCount  = ii + 1;
                        }
                        prevVertCount     = vertCount;
                        prevPrevFaceCount = prevFaceCount;
                    }
                }
                model.vertexCount      = vertCount;
                model.faceCount        = prevFaceCount;
                DataStore.terrainModel = model;
            }
            #endregion

            #region Chunks
            List <int> chunkIds = new List <int>();
            for (int chunkIndex = 0; chunkIndex < 5; chunkIndex++)
            {
                if (File.Exists(path + "/chunk" + chunkIndex + ".ps3"))
                {
                    chunkIds.Add(chunkIndex);
                }
            }

            foreach (int chunkId in chunkIds)
            {
                FileStream cfs = File.OpenRead(path + "/chunk" + chunkId + ".ps3");
                Console.WriteLine("Loading chunk " + chunkId);
                uint terrainElemSize = 0x30;
                uint texElemSize     = 0x10;
                uint vertElemSize    = 0x1c;
                uint UVElemSize      = 0x08;
                uint ColorElemSize   = 0x04;

                RatchetModel_Terrain model = new RatchetModel_Terrain();
                model.offset    = 0x10;
                model.modelID   = 1111;
                model.modelType = ModelType.Terrain;
                byte[] terrainHeadBlock = ReadBlock(cfs, 0x10, 0x60);

                uint   headPointer = BAToUInt32(terrainHeadBlock, 0x0);
                ushort headCount   = BAToUInt16(terrainHeadBlock, 0x06);

                byte[] terrainBlock = ReadBlock(cfs, headPointer, headCount * terrainElemSize);

                model.textureConfig = new List <RatchetTexture_Model>();
                model.vertBuff      = new List <float>();
                model.indiceBuff    = new List <uint>();
                uint vertCount         = 0;
                uint prevVertCount     = 0;
                uint prevFaceCount     = 0;
                uint prevHeadCount     = 0;
                uint prevPrevFaceCount = 0;

                for (uint i = 0; i < 4; i++)   //I have yet to see any level have more than two of these, but the header theoretically has space for 4
                {
                    uint vertPointer   = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x08);
                    uint colPointer    = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x18);
                    uint UVPointer     = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x28);
                    uint indicePointer = BAToUInt32(terrainHeadBlock, (i * sizeof(uint)) + 0x38);

                    prevFaceCount = 0;
                    if (vertPointer != 0 && UVPointer != 0 && indicePointer != 0)    //Check that there's data at the pointers
                    {
                        //Loop throught the heads, and stop when the overflow counter increases
                        for (uint ii = prevHeadCount; ii < headCount && i == BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x22); ii++)
                        {
                            uint   localFaceCount = 0;
                            uint   texPointer     = BAToUInt32(terrainBlock, (ii * terrainElemSize) + 0x10);
                            uint   texCount       = BAToUInt32(terrainBlock, (ii * terrainElemSize) + 0x14);
                            ushort vertStart      = BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x18);
                            ushort headVertCount  = BAToUInt16(terrainBlock, (ii * terrainElemSize) + 0x1A);
                            vertCount += headVertCount;

                            byte[] texBlock = ReadBlock(cfs, texPointer, texElemSize * texCount);
                            for (uint iii = 0; iii < texCount; iii++)
                            {
                                RatchetTexture_Model tex = new RatchetTexture_Model();
                                tex.ID    = BAToUInt32(texBlock, (iii * texElemSize) + 0x00);
                                tex.start = BAToUInt32(texBlock, (iii * texElemSize) + 0x04) + prevPrevFaceCount;
                                tex.size  = BAToUInt32(texBlock, (iii * texElemSize) + 0x08) + prevPrevFaceCount;

                                localFaceCount += BAToUInt32(texBlock, (iii * texElemSize) + 0x08);

                                model.textureConfig.Add(tex);
                            }


                            byte[] vertBlock = ReadBlock(cfs, vertPointer + vertStart * vertElemSize, headVertCount * vertElemSize);
                            byte[] colBlock  = ReadBlock(cfs, colPointer + vertStart * ColorElemSize, headVertCount * ColorElemSize);
                            byte[] UVBlock   = ReadBlock(cfs, UVPointer + vertStart * UVElemSize, headVertCount * UVElemSize);

                            for (uint iii = 0; iii < headVertCount; iii++)
                            {
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x00)); //vertx
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x04)); //verty
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x08)); //vertz
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x0C)); //normx
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x10)); //normy
                                model.vertBuff.Add(BAToFloat(vertBlock, (iii * vertElemSize) + 0x14)); //normz

                                model.vertBuff.Add(BAToFloat(UVBlock, (iii * UVElemSize) + 0x00));     //UVu
                                model.vertBuff.Add(BAToFloat(UVBlock, (iii * UVElemSize) + 0x04));     //UVv


                                model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x00] / 255f);    //color r
                                model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x01] / 255f);    //color g
                                model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x02] / 255f);    //color b
                                model.vertBuff.Add(colBlock[(iii * ColorElemSize) + 0x03] / 255f);    //color a
                            }



                            byte[] indiceBuff = ReadBlock(cfs, indicePointer + prevFaceCount * sizeof(ushort), localFaceCount * sizeof(ushort));
                            //Console.WriteLine(localFaceCount.ToString("X8"));
                            for (uint iii = 0; iii < localFaceCount; iii++)
                            {
                                model.indiceBuff.Add(BAToUInt16(indiceBuff, iii * sizeof(ushort)) + prevVertCount);
                            }

                            prevFaceCount += localFaceCount;
                            prevHeadCount  = ii + 1;
                        }
                        prevVertCount     = vertCount;
                        prevPrevFaceCount = prevFaceCount;
                    }
                }
                model.vertexCount = vertCount;
                model.faceCount   = prevFaceCount;
                DataStore.chunks.Add(model);
            }
            #endregion


            //Load Level Model Placement
            byte[] levelObjectBlock = ReadBlock(fs, levelModelsPlacementPointer, levelObjectsCount * 0x70);
            DataStore.levelObjects = new List <LevelObject>();
            for (uint i = 0; i < levelObjectsCount; i++)
            {
                LevelObject levObj = new LevelObject(levelObjectBlock, i);
                DataStore.levelObjects.Add(levObj);
            }

            //Load Scenery Model Placement
            byte[] sceneryObjectBlock = ReadBlock(fs, sceneryModelsPlacementPointer, sceneryObjectsCount * 0x70);
            DataStore.sceneryObjects = new List <LevelObject>();
            for (uint i = 0; i < sceneryObjectsCount; i++)
            {
                LevelObject levObj = new LevelObject(sceneryObjectBlock, i);
                DataStore.sceneryObjects.Add(levObj);
            }

            /*
             * //Load Level Model Placement
             #region Level Model Placement
             * for (int x = 0; x < UYALevelObjectsCount; x++)
             * {
             *  UYALevelObjectConfig levelObject = new UYALevelObjectConfig();
             *  byte[] objectBlock = ReadBlock(fs, levelModelsPlacementPointer + (uint)(0x70 * x), 0x70);
             *
             *  levelObject.v1 = BAToQuaternion(objectBlock, 0x00);
             *  levelObject.v2 = BAToQuaternion(objectBlock, 0x10);
             *  levelObject.v3 = BAToQuaternion(objectBlock, 0x20);
             *  levelObject.off = BAToQuaternion(objectBlock, 0x30);
             *  levelObject.size = BAToFloat(objectBlock, 0x3C);
             *  levelObject.off_40 = BAToUInt32(objectBlock, 0x40);
             *  levelObject.off_44 = BAToUInt32(objectBlock, 0x44);
             *  levelObject.off_48 = BAToUInt32(objectBlock, 0x48);
             *  levelObject.off_4C = BAToUInt32(objectBlock, 0x4C);
             *  levelObject.ID = (ushort)BAToShort(objectBlock, 0x52);
             *  levelObject.off_54 = BAToUInt32(objectBlock, 0x54);
             *  levelObject.off_58 = BAToUInt32(objectBlock, 0x58);
             *  levelObject.off_5C = BAToUInt32(objectBlock, 0x5C);
             *  levelObject.ptr_60 = BAToUInt32(objectBlock, 0x60);
             *  levelObject.off_64 = BAToUInt32(objectBlock, 0x64);
             *  levelObject.off_68 = BAToUInt32(objectBlock, 0x68);
             *  levelObject.off_6C = BAToUInt32(objectBlock, 0x6C);
             *  if (x + 1 < UYALevelObjectsCount)
             *      levelObject.unknown_data_block = ReadBlock(fs, levelObject.ptr_60, (BAToUInt32(ReadBlock(fs, levelModelsPlacementPointer + (uint)(0x70 * (x + 1)) + 0x60, 4), 0x00) - levelObject.ptr_60));
             *  else
             *      levelObject.unknown_data_block = ReadBlock(fs, levelObject.ptr_60, FindNextLargest(engineHeader, 0x24) - levelObject.ptr_60);
             *  UYALevelObjects.Add(levelObject);
             * }
             #endregion
             *
             * //Load Scenery Models Placement
             #region Scenery Model Placement
             * for (int x = 0; x < UYASceneryObjectsCount; x++)
             * {
             *  UYASceneryObjectConfig sceneryObject = new UYASceneryObjectConfig();
             *  byte[] objectBlock = ReadBlock(fs, sceneryModelsPlacementPointer + (uint)(0x70 * x), 0x70);
             *
             *  sceneryObject.v1 = BAToQuaternion(objectBlock, 0x00);
             *  sceneryObject.v2 = BAToQuaternion(objectBlock, 0x10);
             *  sceneryObject.v3 = BAToQuaternion(objectBlock, 0x20);
             *  sceneryObject.off = BAToQuaternion(objectBlock, 0x30);
             *  sceneryObject.size = BAToFloat(objectBlock, 0x3C);
             *  sceneryObject.off_40 = BAToUInt32(objectBlock, 0x40);
             *  sceneryObject.off_44 = BAToUInt32(objectBlock, 0x44);
             *  sceneryObject.off_48 = BAToUInt32(objectBlock, 0x48);
             *  sceneryObject.off_4C = BAToUInt32(objectBlock, 0x4C);
             *  sceneryObject.ID = (ushort)BAToShort(objectBlock, 0x52);
             *  sceneryObject.off_54 = BAToUInt32(objectBlock, 0x54);
             *  sceneryObject.off_54 = BAToUInt32(objectBlock, 0x58);
             *  sceneryObject.off_54 = BAToUInt32(objectBlock, 0x5C);
             *  sceneryObject.off_60 = BAToUInt32(objectBlock, 0x60);
             *  sceneryObject.off_64 = BAToUInt32(objectBlock, 0x64);
             *  sceneryObject.off_64 = BAToUInt32(objectBlock, 0x68);
             *  sceneryObject.off_64 = BAToUInt32(objectBlock, 0x6C);
             *
             *  UYASceneryObjects.Add(sceneryObject);
             * }
             #endregion
             */
            //Load Textures
            #region Textures
            RatchetTexture_General texture = new RatchetTexture_General();
            for (int x = 0; x < textureCount; x++)
            {
                texture.texHeader = ReadBlock(fs, texturesPointer + (uint)(0x24 * x), 0x24);
                uint nextTexturePointer    = x < textureCount - 1 ? ReadUInt32(ReadBlock(fs, texturesPointer + (uint)(0x24 * (x + 1)), 0x4), 0) : vfs != null ? (uint)vfs.Length : 0;
                uint currentTexturePointer = ReadUInt32(texture.texHeader, 0);
                //Console.WriteLine("Parsing texture " + x + " " + currentTexturePointer.ToString("X") + " " + nextTexturePointer.ToString("X"));
                texture.ID      = x;
                texture.width   = BAToShort(texture.texHeader, 0x18);
                texture.height  = BAToShort(texture.texHeader, 0x1A);
                texture.texData = vfs != null?ReadBlock(vfs, currentTexturePointer, nextTexturePointer - currentTexturePointer) : null;

                texture.reverseRGB = false;
                DataStore.textures.Add(texture);
                //Console.WriteLine("Texture : " + x + " Width: " + texture.width + " Height: " + texture.height);
            }
            #endregion

            //TODO: textureConfig - Menus

            //TODO: textureConfig - 2D GFX

            //TODO: Sprites


            //Load the remaining unknown or unhandled data
            #region Remaining Data

            DataStore.mapRenderDefintions = getSection(fs, 0x04);
            DataStore.Ptr_08             = getSection(fs, 0x08);
            DataStore.Ptr_0C             = getSection(fs, 0x0C);
            DataStore.skyBox             = getSection(fs, 0x14);
            DataStore.collisionMap       = getSection(fs, 0x18);
            DataStore.Ptr_44             = getSection(fs, 0x44);
            DataStore.soundsConfig       = getSection(fs, 0x54);
            DataStore.Ptr_4C             = getSection(fs, 0x4C);
            DataStore.Ptr_50             = getSection(fs, 0x50);
            DataStore.lighting           = getSection(fs, 0x68);
            DataStore.lightingConfig     = getSection(fs, 0x6C);
            DataStore.textureConfigMenu  = getSection(fs, 0x74);
            DataStore.textureConfig2DGFX = getSection(fs, 0x7C);
            DataStore.spriteDef          = getSection(fs, 0x80);

            #endregion

            #region raw Data //need to properly handle these eventually
            DataStore.terrainModel.rawData = getSection(fs, 0x48);
            //rawLevelModelBlock = getSection(fs, 0x1C);
            //rawSceneryModelBlock = getSection(fs, 0x2C);
            #endregion

            #region Missions
            MissionParser.parseMissions(path);
            #endregion

            fs.Close();
            gpf.Close();


            Console.WriteLine("Engine data loaded with new engine parser for DL.");
        }