Example #1
0
        /// <summary>
        /// Gets spoilers from slottype block and sets to cartypeinfo.
        /// </summary>
        /// <param name="db">Database of classes.</param>
        private static void E_Spoilers(Database.MostWanted db)
        {
            if (db.SlotTypes.Spoilers == null)
            {
                return;
            }
            var CNameList = new List <string>();

            foreach (var car in db.CarTypeInfos.Collections)
            {
                CNameList.Add(car.CollectionName);
            }
            var AllSlots = db.SlotTypes.Spoilers.GetSpoilers(CNameList);

            if (AllSlots == null || AllSlots.Count == 0)
            {
                return;
            }
            foreach (var Slot in AllSlots)
            {
                var car = db.CarTypeInfos.FindCollection(Slot.CarTypeInfo);
                if (car == null)
                {
                    continue;
                }
                car.Spoiler = Slot.Spoiler;
            }
        }
Example #2
0
 /// <summary>
 /// Writes all materials into the Global data.
 /// </summary>
 /// <param name="db">Database with classes.</param>
 /// <param name="bw">BinaryWriter for writing data.</param>
 private static void I_Materials(Database.MostWanted db, BinaryWriter bw)
 {
     foreach (var material in db.Materials.Collections)
     {
         bw.Write(material.Assemble());
     }
 }
Example #3
0
        /// <summary>
        /// Gets the frontend group, decompresses it if needed, and plugs into Vector.
        /// </summary>
        /// <param name="byteptr_t">Pointer to the beginning of frontend group in Global data.</param>
        /// <param name="length">Length of the block to be read.</param>
        /// <param name="db">Database to which add classes.</param>
        private static unsafe void E_FNGroup(byte *byteptr_t, uint length, Database.MostWanted db)
        {
            // Copy data and decompress
            var data = new byte[length];

            fixed(byte *dataptr_t = &data[0])
            {
                for (int a1 = 0; a1 < data.Length; ++a1)
                {
                    *(dataptr_t + a1) = *(byteptr_t + a1);
                }
            }

            data = Utils.EA.SAT.Decompress(data);
            var Class = new FNGroup(data, db);

            // Check whether this FEng class already exists in the database
            if (Class.Destroy)
            {
                return;
            }
            if (db.FNGroups.FindCollection(Class.CollectionName) != null)
            {
                return;
            }
            db.FNGroups.Collections.Add(Class);
            Bin.Hash(Class.CollectionName);
        }
Example #4
0
        /// <summary>
        /// Writes all collisions into the Global data.
        /// </summary>
        /// <param name="db">Database with classes.</param>
        /// <param name="bw">BinaryWriter for writing data.</param>
        private static unsafe void I_Collisions(Database.MostWanted db, BinaryWriter bw)
        {
            bw.Write(Global.Collisions);
            bw.Write(0xFFFFFFFF); // write temp size
            int initial_size = (int)bw.BaseStream.Position;

            // Copy all collisions by the internal names
            foreach (var info in db.CarTypeInfos.Collections)
            {
                if (info.CollisionExternalName == BaseArguments.NULL)
                {
                    continue;
                }
                uint extkey = Vlt.Hash(info.CollisionExternalName);
                uint intkey = Vlt.Hash(info.CollisionInternalName);
                if (db.SlotTypes.Collisions.TryGetValue(intkey, out var collision))
                {
                    bw.Write(collision.GetData(extkey));
                }
            }

            // Copy all unknown collisions
            foreach (var collision in db.SlotTypes.Collisions)
            {
                if (collision.Value.Unknown)
                {
                    bw.Write(collision.Value.GetData(0));
                }
            }

            // Fix size
            bw.BaseStream.Position = initial_size - 4;
            bw.Write((int)bw.BaseStream.Length - initial_size);
            bw.BaseStream.Position = bw.BaseStream.Length;
        }
Example #5
0
        /// <summary>
        /// Saves database data into GlobalA file.
        /// </summary>
        /// <param name="GlobalA_dir">Game directory.</param>
        /// <param name="db">Database of classes.</param>
        /// <returns>True if success.</returns>
        public static bool SaveGlobalA(string GlobalA_dir, Database.MostWanted db)
        {
            GlobalA_dir += @"\GLOBAL\GlobalA.bun";

            using (var br = new BinaryReader(new MemoryStream(db._GlobalABUN)))
                using (var bw = new BinaryWriter(File.Open(GlobalA_dir, FileMode.Create)))
                {
                    int tpkindex = 0;

                    while (br.BaseStream.Position < br.BaseStream.Length)
                    {
                        // Set Offset, ID and Size values, read starting in the beginning of the file
                        uint WriterSlotOffset = (uint)br.BaseStream.Position;
                        uint WriterSlotID     = br.ReadUInt32();
                        int  WriterSlotSize   = br.ReadInt32();

                        // If one of the necessary slots is reached, replace it
                        switch (WriterSlotID)
                        {
                        case 0:
                            uint key = br.ReadUInt32();
                            br.BaseStream.Position -= 4;
                            if (key == Global.GlobalLib)
                            {
                                br.BaseStream.Position += WriterSlotSize;
                                break;
                            }
                            else
                            {
                                goto default;
                            }

                        case Global.TPKBlocks:
                            while (!db.TPKBlocks[tpkindex].InGlobalA)
                            {
                                ++tpkindex;
                            }
                            I_TPKBlock(db, bw, ref tpkindex);
                            br.BaseStream.Position += WriterSlotSize;
                            break;

                        case Global.FEngFiles:
                        case Global.FNGCompress:
                            br.BaseStream.Position += WriterSlotSize;
                            break;

                        default:
                            bw.Write(WriterSlotID);
                            bw.Write(WriterSlotSize);
                            bw.Write(br.ReadBytes(WriterSlotSize));
                            break;
                        }
                    }

                    // Write all FEng files
                    I_FNGroup(db, bw);
                }
            return(true);
        }
Example #6
0
 /// <summary>
 /// Writes all frontend groups into the Global data.
 /// </summary>
 /// <param name="db">Database with classes.</param>
 /// <param name="bw">BinaryWriter for writing data.</param>
 private static void I_FNGroup(Database.MostWanted db, BinaryWriter bw)
 {
     for (int a1 = 0; a1 < db.FNGroups.Length; ++a1)
     {
         I_GlobalLibBlock(bw);
         bw.Write(db.FNGroups[a1].Assemble());
     }
 }
Example #7
0
 /// <summary>
 /// Writes all preset rides into the Global data.
 /// </summary>
 /// <param name="db">Database with classes.</param>
 /// <param name="bw">BinaryWriter for writing data.</param>
 private static void I_PresetRides(Database.MostWanted db, BinaryWriter bw)
 {
     bw.Write(Global.PresetRides);
     bw.Write(db.PresetRides.Length * 0x290);
     foreach (var ride in db.PresetRides.Collections)
     {
         bw.Write(ride.Assemble());
     }
 }
Example #8
0
 // Default constructor: create new texture for memory cast
 public Texture(string CName, string _TPK, Database.MostWanted db)
 {
     this.Database         = db;
     this._collection_name = CName;
     this._parent_TPK      = _TPK;
     this.BinKey           = Bin.Hash(CName);
     this.PaletteOffset    = 0;
     this._padding         = 1;
 }
Example #9
0
 public unsafe TPKBlock(byte *byteptr_t, int index, Database.MostWanted db)
 {
     if (index < 0)
     {
         this._use_current_cname = true;
     }
     this.Database = db;
     this.Index    = index;
     this.Disassemble(byteptr_t);
 }
Example #10
0
 // Default constructor: disassemble texture
 public unsafe Texture(byte *byteptr_t, uint offset, uint size, string _TPK, Database.MostWanted db)
 {
     this.Database       = db;
     this._located_at    = (int)offset;
     this._size_of_block = (int)size;
     this._parent_TPK    = _TPK;
     this.PaletteOffset  = 0;
     this._padding       = 1;
     this.Disassemble(byteptr_t + this._located_at);
 }
Example #11
0
        /// <summary>
        /// Decompile entire carparts block into separate elements.
        /// </summary>
        /// <param name="byteptr_t">Pointer to the beginning of carparts block in Global data.</param>
        /// <param name="length">Length of the block to be read.</param>
        /// <param name="db">Database to which add classes.</param>
        private static unsafe void E_CarParts(byte *byteptr_t, uint length, Database.MostWanted db)
        {
            uint  offset     = 0;
            uint  ID         = 0;
            uint  size       = 0;
            byte *part5ptr_t = byteptr_t; // pointer to the part5 of the block
            byte *part6ptr_t = byteptr_t; // pointer to the part6 of the block

            while (offset < length)
            {
                ID   = *(uint *)(byteptr_t + offset);
                size = *(uint *)(byteptr_t + offset + 4);
                if (offset + size > length)
                {
                    return;                         // in case of reading beyong the stream
                }
                switch (ID)
                {
                case CarParts.Part0:
                    db.SlotTypes.Part0.Data = CPE_Part0(byteptr_t + offset, size + 8);
                    goto default;

                case CarParts.Part1:
                    db.SlotTypes.Part1.Data = CPE_Part1(byteptr_t + offset, size + 8);
                    goto default;

                case CarParts.Part2:
                    db.SlotTypes.Part2.Data = CPE_Part2(byteptr_t + offset, size + 8);
                    goto default;

                case CarParts.Part3:
                    db.SlotTypes.Part3.Data = CPE_Part3(byteptr_t + offset, size + 8);
                    goto default;

                case CarParts.Part4:
                    db.SlotTypes.Part4.Data = CPE_Part4(byteptr_t + offset, size + 8);
                    goto default;

                case CarParts.Part5:
                    part5ptr_t = byteptr_t + offset;
                    goto default;

                case CarParts.Part6:
                    part6ptr_t = byteptr_t + offset;
                    goto default;

                default:
                    offset += 8 + size;
                    break;
                }
            }
            // Disassemble part5 and part6
            CPE_Part56(part5ptr_t, part6ptr_t, db);
        }
Example #12
0
 // Default constructor: disassemble cartypeinfo
 public unsafe CarTypeInfo(IntPtr byteptr_t, string CName, Database.MostWanted db)
 {
     this.Database         = db;
     this._collection_name = CName;
     this.OriginalName     = CName;
     this.Disassemble((byte *)byteptr_t);
     if (this.Index <= (int)eBoundValues.MIN_INFO_MOSTWANTED)
     {
         this.Deletable = false;
     }
     this.Modified = false;
 }
Example #13
0
        /// <summary>
        /// Get the material name, initialize its class and inject into Vector.
        /// </summary>
        /// <param name="byteptr_t">Pointer to the beginning of material block in Global data.</param>
        /// <param name="db">Database to which add classes.</param>
        private static unsafe void E_Material(byte *byteptr_t, Database.MostWanted db)
        {
            // Get collection name of the material, starts at 0x14
            string CName = ScriptX.NullTerminatedString(byteptr_t + 0x1C, 0x1C);

            CName = Resolve.GetPathFromCollection(CName);
            Resolve.GetWindowTintString(CName);
            Map.BinKeys[Bin.Hash(CName)] = CName;

            var Class = new Material((IntPtr)byteptr_t, CName, db);

            db.Materials.Collections.Add(Class);
        }
Example #14
0
        /// <summary>
        /// Writes all cartypeinfo into the Global data.
        /// </summary>
        /// <param name="db">Database with classes.</param>
        /// <param name="bw">BinaryWriter for writing data.</param>
        private static void I_CarTypeInfo(Database.MostWanted db, BinaryWriter bw)
        {
            int index = 0;

            bw.Write(Global.CarTypeInfo);
            bw.Write(db.CarTypeInfos.Length * 0xD0 + 8);
            bw.Write(0x1111111111111111);
            foreach (var car in db.CarTypeInfos.Collections)
            {
                car.Index = index++;
                bw.Write(car.Assemble());
            }
        }
Example #15
0
        /// <summary>
        /// Extracts slottype block into memory.
        /// </summary>
        /// <param name="byteptr_t">Pointer to the ID of spoilerss block in Global data.</param>
        /// <param name="length">Length of the block to be read (including ID and size).</param>
        /// <param name="db">Database to which add classes.</param>
        private static unsafe void E_SlotType(byte *byteptr_t, uint length, Database.MostWanted db)
        {
            var Data = new byte[length];

            fixed(byte *dataptr_t = &Data[0])
            {
                for (int a1 = 0; a1 < length; ++a1)
                {
                    *(dataptr_t + a1) = *(byteptr_t + a1);
                }
            }

            db.SlotTypes.Spoilers = new Spoilers(Data);
        }
Example #16
0
 // Default constructor: disassemble preset
 public unsafe PresetRide(IntPtr byteptr_t, string CName, Database.MostWanted db)
 {
     this.Database             = db;
     this.data                 = new byte[0x290];
     this._collection_name     = CName;
     this.Exists               = true;
     this.DECALS_FRONT_WINDOW  = new DecalArray();
     this.DECALS_REAR_WINDOW   = new DecalArray();
     this.DECALS_LEFT_DOOR     = new DecalArray();
     this.DECALS_RIGHT_DOOR    = new DecalArray();
     this.DECALS_LEFT_QUARTER  = new DecalArray();
     this.DECALS_RIGHT_QUARTER = new DecalArray();
     this.Disassemble((byte *)byteptr_t);
     this.Modified = false;
 }
Example #17
0
 // Default constructor: create new cartypeinfo
 public CarTypeInfo(string CName, Database.MostWanted db)
 {
     this.Database                = db;
     this.CollectionName          = CName;
     this.ManufacturerName        = "GENERIC";
     this.Deletable               = true;
     this.Modified                = true;
     this.WhatGame                = 1;
     this.WheelOuterRadius        = 26;
     this.WheelInnerRadiusMin     = 17;
     this.WheelInnerRadiusMax     = 20;
     this.DefaultSkinNumber       = 1;
     this.CollisionExternalName   = CollectionName;
     this.CollisionInternalName   = "CARRERAGT";
     Map.BinKeys[Bin.Hash(CName)] = CName;
 }
Example #18
0
 // Default constructor: create new preset
 public PresetRide(string CName, Database.MostWanted db)
 {
     this.Database                = db;
     this.CollectionName          = CName;
     this.data                    = new byte[0x290];
     this.MODEL                   = "SUPRA";
     this.Frontend                = "supra";
     this.Pvehicle                = "supra";
     this.DECALS_FRONT_WINDOW     = new DecalArray();
     this.DECALS_REAR_WINDOW      = new DecalArray();
     this.DECALS_LEFT_DOOR        = new DecalArray();
     this.DECALS_RIGHT_DOOR       = new DecalArray();
     this.DECALS_LEFT_QUARTER     = new DecalArray();
     this.DECALS_RIGHT_QUARTER    = new DecalArray();
     Map.BinKeys[Bin.Hash(CName)] = CName;
     this.Modified                = true;
 }
Example #19
0
        /// <summary>
        /// Writes all slottype into the Global data.
        /// </summary>
        /// <param name="db">Database with classes.</param>
        /// <param name="bw">BinaryWriter for writing data.</param>
        private static void I_SlotType(Database.MostWanted db, BinaryWriter bw)
        {
            var SetList = new List <CarSpoilerType>();

            // Get all cartypeinfos with non-base spoilers
            foreach (var info in db.CarTypeInfos.Collections)
            {
                if (info.Spoiler != eSpoiler.SPOILER)
                {
                    var Class = new CarSpoilerType();
                    Class.CarTypeInfo = info.CollectionName;
                    Class.Spoiler     = info.Spoiler;
                    SetList.Add(Class);
                }
            }

            bw.Write(db.SlotTypes.Spoilers.SetSpoilers(SetList));
        }
Example #20
0
        /// <summary>
        /// Decompile entire preset rides block into Vector of separate elements.
        /// </summary>
        /// <param name="byteptr_t">Pointer to the beginning of preset rides block in Global data.</param>
        /// <param name="length">Length of the block to be read.</param>
        /// <param name="db">Database to which add classes.</param>
        private static unsafe void E_PresetRides(byte *byteptr_t, uint length, Database.MostWanted db)
        {
            uint size = 0x290;

            for (uint loop = 0; loop < length / size; ++loop)
            {
                uint offset = loop * size; // current offset of the preset ride

                // Get CollectionName
                string CName = ScriptX.NullTerminatedString(byteptr_t + offset + 0x28, 0x20);

                CName = Resolve.GetPathFromCollection(CName);
                Map.BinKeys[Bin.Hash(CName)] = CName;

                var Class = new PresetRide((IntPtr)(byteptr_t + offset), CName, db);
                db.PresetRides.Collections.Add(Class);
            }
        }
Example #21
0
        /// <summary>
        /// Loads English file and disassembles its blocks
        /// </summary>
        /// <param name="Language_dir">Directory of the game.</param>
        /// <param name="db">Database of classes.</param>
        /// <returns>True if success.</returns>
        public static unsafe bool LoadLanguage(string Language_dir, Database.MostWanted db)
        {
            Language_dir += @"\LANGUAGES\";

            // Get everything from language files
            try
            {
                db._LngGlobal = File.ReadAllBytes(Language_dir + "English.bin");
                db._LngLabels = File.ReadAllBytes(Language_dir + "Labels.bin");
                Log.Write("Reading data from English.bin...");
                Log.Write("Reading data from Labels.bin...");
            }
            catch (Exception e)
            {
                while (e.InnerException != null)
                {
                    e = e.InnerException;
                }
                if (Process.MessageShow)
                {
                    MessageBox.Show($"Error occured: {e.Message}", "Failure", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    Console.WriteLine(e.Message);
                }
                return(false);
            }

            // Decompress if compressed
            db._LngGlobal = JDLZ.Decompress(db._LngGlobal);
            db._LngLabels = JDLZ.Decompress(db._LngLabels);

            // Use pointers to speed up process
            fixed(byte *strptr = &db._LngGlobal[0], labptr = &db._LngLabels[0])
            {
                db.STRBlocks.Collections.Add(new STRBlock(strptr, labptr, db._LngGlobal.Length, db._LngLabels.Length, db));
            }

            return(true);
        }
Example #22
0
        /// <summary>
        /// Decompile entire cartypeinfo block into Vector of separate elements.
        /// </summary>
        /// <param name="byteptr_t">Pointer to the beginning of cartypeinfo block in Global data.</param>
        /// <param name="length">Length of the block to be read.</param>
        /// <param name="db">Database to which add classes.</param>
        private static unsafe void E_CarTypeInfo(byte *byteptr_t, uint length, Database.MostWanted db)
        {
            uint size = 0xD0;

            for (uint loop = 0; loop < length / size; ++loop)
            {
                uint offset = 8 + loop * size; // current offset of the cartypeinfo (padding included)

                // Get CollectionName
                string CName = ScriptX.NullTerminatedString(byteptr_t + offset, 0x10);

                CName = Resolve.GetPathFromCollection(CName);
                Map.BinKeys[Bin.Hash(CName)] = CName;
                if (!LibColBlockExists)
                {
                    Map.CollisionMap[Vlt.Hash(CName)] = CName;
                }

                var Class = new CarTypeInfo((IntPtr)(byteptr_t + offset), CName, db);
                db.CarTypeInfos.Collections.Add(Class);
            }
        }
Example #23
0
        /// <summary>
        /// Saves database data into GlobalB file.
        /// </summary>
        /// <param name="GlobalB_dir">Game directory.</param>
        /// <param name="db">Database of classes.</param>
        /// <returns>True if success.</returns>
        public static bool SaveGlobalB(string GlobalB_dir, Database.MostWanted db)
        {
            GlobalB_dir += @"\GLOBAL\GlobalB.lzc";

            using (var br = new BinaryReader(new MemoryStream(db._GlobalBLZC)))
                using (var bw = new BinaryWriter(File.Open(GlobalB_dir, FileMode.Create)))
                {
                    int tpkindex = 0;
                    I_Materials(db, bw);
                    I_CollisionLibBlock(db, bw);

                    while (br.BaseStream.Position < br.BaseStream.Length)
                    {
                        // Set Offset, ID and Size values, read starting in the beginning of the file
                        uint WriterSlotOffset = (uint)br.BaseStream.Position;
                        uint WriterSlotID     = br.ReadUInt32();
                        int  WriterSlotSize   = br.ReadInt32();

                        // If one of the necessary slots is reached, replace it
                        switch (WriterSlotID)
                        {
                        case 0:
                            uint key = br.ReadUInt32();
                            br.BaseStream.Position -= 4;
                            if (key == Global.GlobalLib)
                            {
                                br.BaseStream.Position += WriterSlotSize;
                                break;
                            }
                            else
                            {
                                goto default;
                            }

                        case Global.Materials:
                            br.BaseStream.Position += WriterSlotSize;
                            break;

                        case Global.TPKBlocks:
                            while (db.TPKBlocks[tpkindex].InGlobalA)
                            {
                                ++tpkindex;
                            }
                            I_TPKBlock(db, bw, ref tpkindex);
                            br.BaseStream.Position += WriterSlotSize;
                            break;

                        case Global.CarTypeInfo:
                            I_CarTypeInfo(db, bw);
                            br.BaseStream.Position += WriterSlotSize;
                            break;

                        case Global.PresetRides:
                            I_PresetRides(db, bw);
                            br.BaseStream.Position += WriterSlotSize;
                            break;

                        case Global.CarParts:
                            I_CarParts(db, bw);
                            br.BaseStream.Position += WriterSlotSize;
                            break;

                        case Global.Collisions:
                            I_Collisions(db, bw);
                            br.BaseStream.Position += WriterSlotSize;
                            break;

                        case Global.SlotTypes:
                            I_SlotType(db, bw);
                            br.BaseStream.Position += WriterSlotSize;
                            break;

                        default:
                            bw.Write(WriterSlotID);
                            bw.Write(WriterSlotSize);
                            bw.Write(br.ReadBytes(WriterSlotSize));
                            break;
                        }
                    }
                }
            return(true);
        }
Example #24
0
        private static unsafe void E_Collisions(byte *byteptr_t, uint length, Database.MostWanted db)
        {
            db.SlotTypes.Collisions = new Dictionary <uint, Collision>();

            // Make a map of vlt hash cartypeinfo and indexes
            var CNameToIndex = new Dictionary <uint, string>();

            foreach (var car in db.CarTypeInfos.Collections)
            {
                CNameToIndex[car.VltKey] = car.CollectionName;
            }

            uint offset = 0;

            while (offset < length)
            {
                uint ID   = *(uint *)(byteptr_t + offset);
                int  size = *(int *)(byteptr_t + offset + 4);
                if (ID == CarParts.Collision)
                {
                    uint intkey = *(uint *)(byteptr_t + offset + 8);
                    uint extkey = *(uint *)(byteptr_t + offset + 16);

                    // If internal key exists and map shows a string for it
                    if (intkey != 0x11111111 && intkey != 0 && Map.CollisionMap.TryGetValue(intkey, out string CName))
                    {
                        // If collision is not in the map, plug it in
                        if (!db.SlotTypes.Collisions.ContainsKey(intkey))
                        {
                            // Copy whole data, get it into collision map
                            var data = new byte[size + 8];
                            fixed(byte *dataptr_t = &data[0])
                            {
                                for (int a1 = 0; a1 < size + 8; ++a1)
                                {
                                    *(dataptr_t + a1) = *(byteptr_t + offset + a1);
                                }
                                *(uint *)(dataptr_t + 16) = 0xFFFFFFFF;
                            }

                            var Class = new Collision(data, CName);
                            db.SlotTypes.Collisions[intkey] = Class;
                        }

                        // Check if cartypeinfo with a set external key exists
                        if (CNameToIndex.TryGetValue(extkey, out var name))
                        {
                            var car = db.CarTypeInfos.FindCollection(name);
                            car.CollisionExternalName = car.CollectionName;
                            car.CollisionInternalName = CName;
                        }
                    }
                    else
                    {
                        // Copy entire collision block
                        var data = new byte[size + 8];
                        fixed(byte *dataptr_t = &data[0])
                        {
                            for (int a1 = 0; a1 < size + 8; ++a1)
                            {
                                *(dataptr_t + a1) = *(byteptr_t + offset + a1);
                            }
                            *(uint *)(dataptr_t + 8)  = extkey;
                            *(uint *)(dataptr_t + 16) = 0xFFFFFFFF;
                        }

                        // If collision map has value for external key
                        if (Map.CollisionMap.TryGetValue(extkey, out string ExName))
                        {
                            var Class = new Collision(data, ExName);
                            db.SlotTypes.Collisions[extkey] = Class;

                            // Check if cartypeinfo with a set external key exists
                            if (CNameToIndex.TryGetValue(extkey, out var name))
                            {
                                var car = db.CarTypeInfos.FindCollection(name);
                                car.CollisionExternalName = car.CollectionName;
                                car.CollisionInternalName = car.CollectionName;
                            }
                        }
                        else
                        {
                            var Class = new Collision(data, null);
                            db.SlotTypes.Collisions[extkey] = Class;
                        }
                    }
                }
                offset += (uint)size + 8;
            }

            // New collision map based on real collisions
            Map.CollisionMap.Clear();
            foreach (var collision in db.SlotTypes.Collisions)
            {
                if (!collision.Value.Unknown)
                {
                    Map.CollisionMap[collision.Key] = collision.Value.BelongsTo;
                }
            }
        }
Example #25
0
        /// <summary>
        /// Loads GlobalB file and disassembles its blocks
        /// </summary>
        /// <param name="GlobalB_dir">Directory of the game.</param>
        /// <param name="db">Database of classes.</param>
        /// <returns>True if success.</returns>
        public static unsafe bool LoadGlobalB(string GlobalB_dir, Database.MostWanted db)
        {
            LibColBlockExists = false;
            GlobalB_dir      += @"\GLOBAL\GlobalB.lzc";

            // Get everything from GlobalB.lzc
            try
            {
                db._GlobalBLZC = File.ReadAllBytes(GlobalB_dir);
                Log.Write("Reading data from GlobalB.lzc...");
            }
            catch (Exception e)
            {
                while (e.InnerException != null)
                {
                    e = e.InnerException;
                }
                if (Process.MessageShow)
                {
                    MessageBox.Show($"Error occured: {e.Message}", "Failure", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    Console.WriteLine(e.Message);
                }
                return(false);
            }

            // Decompress if compressed
            db._GlobalBLZC = JDLZ.Decompress(db._GlobalBLZC);

            // Use pointers to speed up process
            fixed(byte *byteptr_t = &db._GlobalBLZC[0])
            {
                uint offset = 0; // to calculate current offset
                uint ID     = 0; // to get the ID of the block being read
                uint size   = 0; // to get the size of the block being read

                uint proff  = 0; // offset of the preset rides block
                uint prsize = 0; // size of the preset rides block

                uint cpoff  = 0; // offset of the carparts block
                uint cpsize = 0; // size of the carparts block

                uint cooff  = 0; // offset of the collision block
                uint cosize = 0; // size of the collision block

                while (offset < db._GlobalBLZC.Length)
                {
                    ID   = *(uint *)(byteptr_t + offset);     // read ID
                    size = *(uint *)(byteptr_t + offset + 4); // read size
                    if (offset + size > db._GlobalBLZC.Length)
                    {
                        if (Process.MessageShow)
                        {
                            MessageBox.Show("GlobalB: unable to read beyond the stream.", "Failure");
                        }
                        else
                        {
                            Console.WriteLine("GlobalB: unable to read beyond the stream.");
                        }
                        return(false);
                    }

                    switch (ID)
                    {
                    case 0:
                        if (*(uint *)(byteptr_t + offset + 8) == Global.GlobalLib)
                        {
                            E_GlobalLibBlock(byteptr_t + offset, size + 8);
                        }
                        break;

                    case Global.Materials:
                        E_Material(byteptr_t + offset, db);
                        break;

                    case Global.TPKBlocks:
                        int count = db.TPKBlocks.Length;
                        db.TPKBlocks.Collections.Add(new TPKBlock(byteptr_t + offset, count, db));
                        break;

                    case Global.CarTypeInfo:
                        E_CarTypeInfo(byteptr_t + offset + 8, size, db);
                        break;

                    case Global.PresetRides:
                        proff  = offset + 8;
                        prsize = size;
                        break;

                    case Global.CarParts:
                        cpoff  = offset + 8;
                        cpsize = size;
                        break;

                    case Global.SlotTypes:
                        E_SlotType(byteptr_t + offset, size + 8, db);
                        break;

                    case Global.Collisions:
                        cooff  = offset + 8;
                        cosize = size;
                        break;

                    case Global.FEngFiles:
                    case Global.FNGCompress:
                        E_FNGroup(byteptr_t + offset, size + 8, db);
                        break;

                    default:
                        break;
                    }
                    offset += 8 + size; // advance in offset
                }

                // CarParts and Collisions blocks are the last ones to disassemble
                E_CarParts(byteptr_t + cpoff, cpsize, db);
                E_Collisions(byteptr_t + cooff, cosize, db);
                E_PresetRides(byteptr_t + proff, prsize, db);
            }

            // Disperse spoilers across cartypeinfo
            E_Spoilers(db);
            return(true);
        }
Example #26
0
 // Default constructor: disassemble string block
 public unsafe STRBlock(byte *strptr, byte *labptr, int strlen, int lablen, Database.MostWanted db)
 {
     this.Database = db;
     this.Disassemble(strptr, strlen);
     this.DisperseLabels(labptr, lablen);
 }
Example #27
0
        private static unsafe void CPE_Part56(byte *part5ptr_t, byte *part6ptr_t, Database.MostWanted db)
        {
            int len5 = *(int *)(part5ptr_t + 4) + 8; // size of part5
            int len6 = *(int *)(part6ptr_t + 4);     // size of part6

            // Exclude padding
            while (*(int *)(part5ptr_t + len5 - 4) == 0)
            {
                len5 -= 4;
            }
            while (*(int *)(part6ptr_t + len6 + 4) == 0)
            {
                len6 -= 4;
            }
            len6 = len6 / 0xE * 0xE + 8;

            int off5 = 8; // offset in part5
            int off6 = 8; // offset in part6
            int size = 0; // size of one part in part6

            // Validation check
            int check = *(part6ptr_t + len6 - 7) + 1;
            int total = (len5 - 8) / 4;

            if (check < total)
            {
                len5 = check * 4 + 8;
            }

            db.SlotTypes.Part56 = new List <Part56>();
            var CarCNames = new List <uint>();

            foreach (var car in db.CarTypeInfos.Collections)
            {
                CarCNames.Add(car.BinKey);
            }

            while (off5 < len5)
            {
                uint ckey = *(uint *)(part5ptr_t + off5);
                if (ckey == 0)
                {
                    break;            // padding means end
                }
                bool IsCar   = false;
                byte current = 0;
                byte index   = *(part6ptr_t + off6 + 7);
                while (true)
                {
                    if (off6 + size + 7 >= len6)
                    {
                        break;
                    }
                    current = *(part6ptr_t + off6 + size + 7);
                    if (current != index)
                    {
                        break;
                    }
                    else
                    {
                        size += 0xE;
                    }
                }
                if (CarCNames.Contains(ckey))
                {
                    IsCar = true;
                }
                var Part = new Part56(ckey, part6ptr_t + off6, size, IsCar);
                db.SlotTypes.Part56.Add(Part);
                off5 += 4;
                off6 += size;
                size  = 0;
            }
        }
Example #28
0
        /// <summary>
        /// Saves database data into English file.
        /// </summary>
        /// <param name="Language_dir">Game directory.</param>
        /// <param name="db">Database of classes.</param>
        /// <returns>True if success.</returns>
        public static bool SaveLanguage(string Language_dir, Database.MostWanted db)
        {
            Language_dir += @"\LANGUAGES\";

            using (var br = new BinaryReader(new MemoryStream(db._LngGlobal)))
                using (var bw = new BinaryWriter(File.Open(Language_dir + "English.bin", FileMode.Create)))
                {
                    bool finished = false;
                    while (br.BaseStream.Position < br.BaseStream.Length)
                    {
                        // Set Offset, ID and Size values, read starting in the beginning of the file
                        uint WriterSlotOffset = (uint)br.BaseStream.Position;
                        uint WriterSlotID     = br.ReadUInt32();
                        int  WriterSlotSize   = br.ReadInt32();

                        // If one of the necessary slots is reached, replace it
                        switch (WriterSlotID)
                        {
                        case Global.STRBlocks:
                            if (!finished)
                            {
                                bw.Write(db.STRBlocks[0].Assemble());
                                br.BaseStream.Position += WriterSlotSize;
                                finished = true;
                                break;
                            }
                            else
                            {
                                goto default;
                            }

                        default:
                            bw.Write(WriterSlotID);
                            bw.Write(WriterSlotSize);
                            bw.Write(br.ReadBytes(WriterSlotSize));
                            break;
                        }
                    }
                }

            using (var br = new BinaryReader(new MemoryStream(db._LngLabels)))
                using (var bw = new BinaryWriter(File.Open(Language_dir + "Labels.bin", FileMode.Create)))
                {
                    bool finished = false;
                    while (br.BaseStream.Position < br.BaseStream.Length)
                    {
                        // Set Offset, ID and Size values, read starting in the beginning of the file
                        uint WriterSlotOffset = (uint)br.BaseStream.Position;
                        uint WriterSlotID     = br.ReadUInt32();
                        int  WriterSlotSize   = br.ReadInt32();

                        // If one of the necessary slots is reached, replace it
                        switch (WriterSlotID)
                        {
                        case Global.STRBlocks:
                            if (!finished)
                            {
                                bw.Write(db.STRBlocks[0].ParseLabels());
                                br.BaseStream.Position += WriterSlotSize;
                                finished = true;
                                break;
                            }
                            else
                            {
                                goto default;
                            }

                        default:
                            bw.Write(WriterSlotID);
                            bw.Write(WriterSlotSize);
                            bw.Write(br.ReadBytes(WriterSlotSize));
                            break;
                        }
                    }
                }

            return(true);
        }
Example #29
0
        /// <summary>
        /// Writes all car parts into the Global data.
        /// </summary>
        /// <param name="db">Database with classes.</param>
        /// <param name="bw">BinaryWriter for writing data.</param>
        private static void I_CarParts(Database.MostWanted db, BinaryWriter bw)
        {
            bw.Write(Global.CarParts);
            bw.Write(0xFFFFFFFF); // temp size

            int initial_size  = (int)bw.BaseStream.Position;
            int CarIDOffset   = initial_size + 0x30;
            int PartNumOffset = initial_size + 0x40;
            int padding       = 0;

            var keylists   = new List <uint>();
            var Intermid56 = new List <Part56>();
            var UsedPart56 = new List <Part56>();

            // Copy for processing
            for (int a1 = 0; a1 < db.SlotTypes.Part56.Count; ++a1)
            {
                Intermid56.Add(db.SlotTypes.Part56[a1].MemoryCast());
            }

            // Go through all cartypeinfo, set correct usagetype and keys
            foreach (var car in db.CarTypeInfos.Collections)
            {
                bool   CarDoesExist = false;
                int    index        = 0;
                string CName        = car.CollectionName;
                uint   ckey         = car.BinKey;
                uint   okey         = Bin.Hash(car.OriginalName);
                keylists.Add(ckey);
                for (index = 0; index < Intermid56.Count; ++index)
                {
                    if (okey == Intermid56[index].Key)
                    {
                        CarDoesExist = true;
                        break;
                    }
                }
                if (CarDoesExist)
                {
                    if (ckey != okey || car.Modified)
                    {
                        Intermid56[index] = new Part56(CName, (byte)index);
                    }
                }
                else
                {
                    var Class = new Part56(CName, (byte)index);
                    Intermid56.Add(Class);
                }
            }

            // Make new list of only used Part56 to write
            byte curlength = 0;

            for (int a1 = 0; a1 < Intermid56.Count; ++a1)
            {
                if (Intermid56[a1].IsCar && !keylists.Contains(Intermid56[a1].Key))
                {
                    continue;
                }
                Intermid56[a1].SetIndex(curlength++);
                UsedPart56.Add(Intermid56[a1]);
            }

            // Write parts 1-4
            bw.Write(db.SlotTypes.Part0.Data);
            bw.Write(db.SlotTypes.Part1.Data);
            bw.Write(db.SlotTypes.Part2.Data);
            bw.Write(db.SlotTypes.Part3.Data);
            bw.Write(db.SlotTypes.Part4.Data);

            // Write part 5
            int part5size = UsedPart56.Count * 4;

            padding = 3 - UsedPart56.Count % 4;
            if (padding != 0)
            {
                part5size += padding * 4;
            }
            bw.Write(CarParts.Part5);
            bw.Write(part5size);
            for (int a1 = 0; a1 < UsedPart56.Count; ++a1)
            {
                bw.Write(UsedPart56[a1].Key);
            }
            for (int a1 = 0; a1 < padding * 4; ++a1)
            {
                bw.Write((byte)0);
            }

            // Write part 6
            int part6size = 0;

            bw.Write(CarParts.Part6);
            int size6off = (int)bw.BaseStream.Position;

            bw.Write(0xFFFFFFFF); // temp size
            for (int a1 = 0; a1 < UsedPart56.Count; ++a1)
            {
                bw.Write(UsedPart56[a1].Data);
                part6size += UsedPart56[a1].Data.Length;
            }
            padding = 0x10 - ((part6size + 8) % 0x10);
            if (padding == 0x10)
            {
                padding = 0;
            }
            for (int a1 = 0; a1 < padding; ++a1)
            {
                bw.Write((byte)0);
            }
            part6size += padding;
            bw.BaseStream.Position = size6off;
            bw.Write(part6size);

            // Quick editing
            bw.BaseStream.Position = CarIDOffset;
            bw.Write(UsedPart56.Count);
            bw.BaseStream.Position = PartNumOffset;
            bw.Write(part6size / 0xE);
            bw.BaseStream.Position = initial_size - 4;
            bw.Write((int)bw.BaseStream.Length - initial_size);
            bw.BaseStream.Position = bw.BaseStream.Length;
        }
Example #30
0
 // Default constructor: disassemble frontend group
 public FNGroup(byte[] data, Database.MostWanted db)
 {
     this.Database = db;
     this.Disassemble(data);
 }