Пример #1
0
        private void editFilesizeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            int n = listBox1.SelectedIndex;

            if (n == -1)
            {
                return;
            }
            string    newsize = Microsoft.VisualBasic.Interaction.InputBox("Enter new size in bytes", "ME3 Explorer", content[n].size.ToString());
            Inventory temp    = content[n];

            try
            {
                temp.size = Convert.ToUInt32(newsize);
            }
            catch (FormatException)
            {
                //exit this method
                return;
            }
            content[n] = temp;
            listBox1.Items.Clear();
            uint pos = temp.offset;

            byte[] buff = BitConverter.GetBytes(temp.size);
            for (int i = 0; i < 4; i++)
            {
                memory[pos + i] = buff[i];
            }
            for (int i = 0; i < content.Count(); i++)
            {
                listBox1.Items.Add(content[i].offset.ToString("X") + " : " + content[i].name + " (bytes)" + content[i].size.ToString());
            }
            listBox1.SelectedIndex = n;
        }
Пример #2
0
        /// <summary>
        /// Starts reading 'Bits' array at position 'bitOffset'. Read data is
        /// used on a Huffman Tree to decode read bits into real strings.
        /// 'bitOffset' variable is updated with last read bit PLUS ONE (first unread bit).
        /// </summary>
        /// <param name="bitOffset"></param>
        /// <returns>
        /// decoded string or null if there's an error (last string's bit code is incomplete)
        /// </returns>
        /// <remarks>
        /// Global variables used:
        /// List(of HuffmanNodes) CharacterTree
        /// BitArray Bits
        /// </remarks>
        private string GetString(ref int bitOffset)
        {
            HuffmanNode root    = CharacterTree[0];
            HuffmanNode curNode = root;

            string curString = "";
            int    i;

            for (i = bitOffset; i < Bits.Length; i++)
            {
                /* reading bits' sequence and decoding it to Strings while traversing Huffman Tree */
                int nextNodeID;
                if (Bits[i])
                {
                    nextNodeID = curNode.RightNodeID;
                }
                else
                {
                    nextNodeID = curNode.LeftNodeID;
                }

                /* it's an internal node - keep looking for a leaf */
                if (nextNodeID >= 0)
                {
                    curNode = CharacterTree[nextNodeID];
                }
                else
                /* it's a leaf! */
                {
                    char c = BitConverter.ToChar(BitConverter.GetBytes(0xffff - nextNodeID), 0);
                    if (c != '\0')
                    {
                        /* it's not NULL */
                        curString += c;
                        curNode    = root;
                    }
                    else
                    {
                        /* it's a NULL terminating processed string, we're done */
                        bitOffset = i + 1;
                        return(curString);
                    }
                }
            }
            bitOffset = i + 1;
            return(null);
        }
Пример #3
0
        public bool UpdateFile(string name, uint size, string path)
        {
            loadTOCfile(path);
            int n = -1;

            for (int i = 0; i < content.Count(); i++)
            {
                if (content[i].name.EndsWith(name))
                {
                    n = i;
                }
            }
            if (n == -1)
            {
                return(false);
            }
            //edit entry
            Inventory temp = content[n];

            temp.size  = size;
            content[n] = temp;
            uint pos = temp.offset;

            BitConverter.IsLittleEndian = true;
            byte[] buff = BitConverter.GetBytes(size);
            for (int i = 0; i < 4; i++)
            {
                memory[pos + i] = buff[i];
            }
            //write file
            FileStream fileStream = new FileStream(path, FileMode.Create, FileAccess.Write);

            for (int i = 0; i < memsize; i++)
            {
                fileStream.WriteByte(memory[i]);
            }
            fileStream.Close();
            return(true);
        }
Пример #4
0
        public void ME3PCCObjectHelper(MemoryStream tempStream, string filePath, bool TablesOnly)
        {
            tempStream.Seek(0, SeekOrigin.Begin);
            DataStream = new MemoryStream();
            tempStream.WriteTo(DataStream);
            Names   = new List <string>();
            Imports = new List <ME3ImportEntry>();
            Exports = new List <ME3ExportEntry>();

            header = tempStream.ReadBytes(headerSize);
            if (magic != ZBlock.magic &&
                magic.Swap() != ZBlock.magic)
            {
                throw new FormatException(filePath + " is not a pcc file");
            }

            if (lowVers != 684 && highVers != 194)
            {
                throw new FormatException("unsupported version");
            }

            if (bCompressed)
            {
                // seeks the blocks info position
                tempStream.Seek(idxOffsets + 60, SeekOrigin.Begin);
                int generator = tempStream.ReadValueS32();
                tempStream.Seek((generator * 12) + 20, SeekOrigin.Current);

                int blockCount = tempStream.ReadValueS32();
                blockList = new List <Block>();

                // creating the Block list
                for (int i = 0; i < blockCount; i++)
                {
                    Block temp = new Block();
                    temp.uncOffset = tempStream.ReadValueS32();
                    temp.uncSize   = tempStream.ReadValueS32();
                    temp.cprOffset = tempStream.ReadValueS32();
                    temp.cprSize   = tempStream.ReadValueS32();
                    blockList.Add(temp);
                }

                // correcting the header, in case there's need to be saved
                Buffer.BlockCopy(BitConverter.GetBytes(0), 0, header, header.Length - 12, sizeof(int));
                tempStream.Read(header, header.Length - 8, 8);
                headerEnd = (int)tempStream.Position;

                // copying the extraNamesList
                int extraNamesLenght = blockList[0].cprOffset - headerEnd;
                if (extraNamesLenght > 0)
                {
                    extraNamesList = new byte[extraNamesLenght];
                    tempStream.Read(extraNamesList, 0, extraNamesLenght);
                    //FileStream fileStream = File.Create(Path.GetDirectoryName(pccFileName) + "\\temp.bin");
                    //fileStream.Write(extraNamesList, 0, extraNamesLenght);
                    //MessageBox.Show("posizione: " + pccStream.Position.ToString("X8"));
                }

                int dataStart = 0;
                using (MemoryStream he = new MemoryStream(header))
                {
                    he.Seek(0, SeekOrigin.Begin);
                    he.ReadValueS32();
                    he.ReadValueS32();
                    dataStart = he.ReadValueS32();
                }

                if (TablesOnly)
                {
                    int TableStart = 0;
                    for (int m = 0; m < blockList.Count; m++)
                    {
                        if (blockList[m].uncOffset + blockList[m].uncSize > dataStart)
                        {
                            TableStart = m;
                            break;
                        }
                    }

                    listsStream = new MemoryStream();
                    tempStream.Seek(blockList[TableStart].cprOffset, SeekOrigin.Begin);
                    listsStream.Seek(blockList[TableStart].uncOffset, SeekOrigin.Begin);
                    listsStream.WriteBytes(ZBlock.Decompress(tempStream, blockList[TableStart].cprSize));
                    DataStream = new MemoryStream();
                    tempStream.WriteTo(DataStream);
                    bCompressed = true;
                }
                else
                {
                    //Decompress ALL blocks
                    listsStream = new MemoryStream();
                    for (int i = 0; i < blockCount; i++)
                    {
                        tempStream.Seek(blockList[i].cprOffset, SeekOrigin.Begin);
                        listsStream.Seek(blockList[i].uncOffset, SeekOrigin.Begin);
                        listsStream.WriteBytes(ZBlock.Decompress(tempStream, blockList[i].cprSize));
                    }
                }
                bCompressed = false;
            }
            else
            {
                listsStream = new MemoryStream();
                listsStream.WriteBytes(tempStream.ToArray());
            }
            tempStream.Dispose();

            //Fill name list
            listsStream.Seek(NameOffset, SeekOrigin.Begin);
            for (int i = 0; i < NameCount; i++)
            {
                int strLength = listsStream.ReadValueS32();
                Names.Add(listsStream.ReadString(strLength * -2, true, Encoding.Unicode));
            }

            // fill import list
            listsStream.Seek(ImportOffset, SeekOrigin.Begin);
            byte[] buffer = new byte[ME3ImportEntry.byteSize];
            for (int i = 0; i < ImportCount; i++)
            {
                Imports.Add(new ME3ImportEntry(this, listsStream));
            }

            //fill export list
            listsStream.Seek(ExportOffset, SeekOrigin.Begin);
            for (int i = 0; i < ExportCount; i++)
            {
                uint expInfoOffset = (uint)listsStream.Position;

                listsStream.Seek(44, SeekOrigin.Current);
                int count = listsStream.ReadValueS32();
                listsStream.Seek(-48, SeekOrigin.Current);

                int expInfoSize = 68 + (count * 4);
                buffer = new byte[expInfoSize];

                listsStream.Read(buffer, 0, buffer.Length);
                Exports.Add(new ME3ExportEntry(this, buffer, expInfoOffset));
            }
        }
Пример #5
0
        /// <summary>
        /// This method is an alternate way of saving PCCs
        /// Instead of reconstructing the PCC from the data taken, it instead copies across the existing
        /// data, appends new exports, updates the export list, changes the namelist location and updates the
        /// value in the header
        /// </summary>
        /// <param name="newFileName">The filename to write to</param>
        /// <param name="attemptOverwrite">Do you wish to attempt to overwrite the existing export</param>
        public string altSaveToFile(string newFileName, bool attemptOverwrite, int HeadeNameOffset = 34)
        {
            DebugOutput.PrintLn("Saving pcc with alternate method.");
            string rtValues = "";
            string loc      = KFreonLib.Misc.Methods.GetExecutingLoc();

            //Check whether compressed
            if (this.bCompressed)
            {
                KFreonLib.PCCObjects.Misc.PCCDecompress(this.pccFileName);
            }

            //Get info
            expInfoEndOffset = ExportOffset + Exports.Sum(export => export.info.Length);
            if (expDataBegOffset < expInfoEndOffset)
            {
                expDataBegOffset = expInfoEndOffset;
            }
            //List<ExportEntry> unchangedExports = Exports.Where(export => !export.hasChanged || (export.hasChanged && export.Data.Length <= export.DataSize)).ToList();
            List <ME3ExportEntry> unchangedExports = Exports.Where(export => !export.hasChanged).ToList();
            List <ME3ExportEntry> changedExports;
            List <ME3ExportEntry> replaceExports = null;

            if (!attemptOverwrite)
            {
                //If not trying to overwrite, then select all exports that have been changed
                changedExports = Exports.Where(export => export.hasChanged).ToList();
                //MessageBox.Show("No changed exports = " + changedExports.Count);
                //throw new NullReferenceException();
            }
            else
            {
                //If we are trying to overwrite, then split up the exports that have been changed that can and can't overwrite the originals
                changedExports = Exports.Where(export => export.hasChanged && export.Data.Length > export.DataSize).ToList();
                replaceExports = Exports.Where(export => export.hasChanged && export.Data.Length <= export.DataSize).ToList();
            }
            //ExportEntry lastExport = unchangedExports.Find(export => export.DataOffset == unchangedExports.Max(maxExport => maxExport.DataOffset));


            uint           max        = Exports.Max(maxExport => maxExport.DataOffset);
            ME3ExportEntry lastExport = Exports.Find(export => export.DataOffset == max);

            int lastDataOffset = (int)(lastExport.DataOffset + lastExport.DataSize);

            byte[] oldPCC = new byte[lastDataOffset];
            //byte[] oldName;

            if (!attemptOverwrite)
            {
                int offset = ExportOffset;
                foreach (ME3ExportEntry export in Exports)
                {
                    if (!export.hasChanged)
                    {
                        offset += export.info.Length;
                    }
                    else
                    {
                        break;
                    }
                }
                rtValues += offset.ToString() + " ";
                using (FileStream stream = new FileStream(loc + "\\exec\\infoCache.bin", FileMode.Append))
                {
                    stream.Seek(0, SeekOrigin.End);
                    rtValues += stream.Position + " ";
                    //throw new FileNotFoundException();
                    stream.Write(changedExports[0].info, 32, 8);
                }
            }


            using (FileStream oldPccStream = new FileStream(this.pccFileName, FileMode.Open))
            {
                //Read the original data up to the last export
                oldPccStream.Read(oldPCC, 0, lastDataOffset);
                #region Unused code

                /* Maybe implement this if I want to directly copy the names across.
                 * Not useful at this time
                 * if (NameOffset == 0x8E)
                 * {
                 *  oldName = new byte[ImportOffset - 0x8E];
                 *  oldPccStream.Seek(0x8E, SeekOrigin.Begin);
                 *  oldPccStream.Read(oldName, 0, (int)oldPccStream.Length - lastDataOffset);
                 * }
                 * else
                 * {
                 *  oldName = new byte[oldPccStream.Length - lastDataOffset];
                 *  oldPccStream.Seek(lastDataOffset, SeekOrigin.Begin);
                 *  oldPccStream.Read(oldName, 0, (int)oldPccStream.Length - lastDataOffset);
                 * }
                 * */
                #endregion
            }
            //Start writing the new file
            using (FileStream newPCCStream = new FileStream(newFileName, FileMode.Create))
            {
                Console.WriteLine();
                Console.WriteLine("Starting Save");
                newPCCStream.Seek(0, SeekOrigin.Begin);
                Console.WriteLine("newPCCStream length: " + newPCCStream.Length);
                //Write the original file up til the last original export (note that this leaves in all the original exports)
                newPCCStream.Write(oldPCC, 0, lastDataOffset);
                Console.WriteLine("OldPCC length: " + oldPCC.Length);
                Console.WriteLine("lastDataOFfset: " + lastDataOffset);
                Console.WriteLine("overwriting?: " + attemptOverwrite);
                if (!attemptOverwrite)
                {
                    //If we're not trying to overwrite then just append all the changed exports
                    foreach (ME3ExportEntry export in changedExports)
                    {
                        export.DataOffset = (uint)newPCCStream.Position;
                        export.DataSize   = export.Data.Length;
                        newPCCStream.Write(export.Data, 0, export.Data.Length);
                    }
                }
                else
                {
                    Console.WriteLine("replaceExports count: " + replaceExports.Count);
                    //If we are then move to each offset and overwrite the data with the new exports
                    foreach (ME3ExportEntry export in replaceExports)
                    {
                        //newPCCStream.Position = export.DataOffset;
                        newPCCStream.Seek(export.DataOffset, SeekOrigin.Begin);
                        export.DataSize = export.Data.Length;
                        newPCCStream.Write(export.Data, 0, export.Data.Length);
                        //Console.WriteLine("exports.DataOffset: " + export.DataOffset);
                        //Console.WriteLine("export datalength: " + export.Data.Length);
                    }
                    //Then move to the end and append the new data
                    //newPCCStream.Position = lastDataOffset;
                    newPCCStream.Seek(lastDataOffset, SeekOrigin.Begin);

                    Console.WriteLine("changedExports count: " + changedExports.Count);
                    foreach (ME3ExportEntry export in changedExports)
                    {
                        export.DataOffset = (uint)newPCCStream.Position;
                        //Console.WriteLine("newstream position: " + newPCCStream.Position);
                        export.DataSize = export.Data.Length;
                        //Console.WriteLine("export size: " + export.DataSize);
                        newPCCStream.Write(export.Data, 0, export.Data.Length);
                        //Console.WriteLine("datalength: " + export.Data.Length);
                    }
                }
                //Set the new nameoffset and namecounts
                NameOffset = (int)newPCCStream.Position;
                Console.WriteLine("nameoffset: " + NameOffset);
                NameCount = Names.Count;
                Console.WriteLine("namecount: " + Names.Count);
                //Then write out the namelist
                foreach (string name in Names)
                {
                    //Console.WriteLine("name: " + name);
                    newPCCStream.WriteValueS32(-(name.Length + 1));
                    newPCCStream.WriteString(name + "\0", (uint)(name.Length + 1) * 2, Encoding.Unicode);
                }
                Console.WriteLine("newPCCStream.length: " + newPCCStream.Length);
                //Move to the name info position in the header - not a strong piece of code, but it's working so far
                //newPCCStream.Position = 34;
                newPCCStream.Seek(HeadeNameOffset, SeekOrigin.Begin);
                Console.WriteLine("headernameoffset: " + HeadeNameOffset);
                //And write the new info
                byte[] nameHeader = new byte[8];
                byte[] nameCount  = BitConverter.GetBytes(NameCount);
                byte[] nameOff    = BitConverter.GetBytes(NameOffset);
                for (int i = 0; i < 4; i++)
                {
                    nameHeader[i] = nameCount[i];
                }
                for (int i = 0; i < 4; i++)
                {
                    nameHeader[i + 4] = nameOff[i];
                }
                newPCCStream.Write(nameHeader, 0, 8);

                //Finally, update the export list
                newPCCStream.Seek(ExportOffset, SeekOrigin.Begin);
                foreach (ME3ExportEntry export in Exports)
                {
                    newPCCStream.Write(export.info, 0, export.info.Length);
                }

                if (!attemptOverwrite)
                {
                    using (FileStream stream = new FileStream(loc + "\\exec\\infoCache.bin", FileMode.Append))
                    {
                        stream.Seek(0, SeekOrigin.End);
                        rtValues += stream.Position + " ";
                        stream.Write(changedExports[0].info, 32, 8);
                    }
                }
            }
            return(rtValues);
        }