Example #1
0
        /// <summary>
        /// Checks whether the buffer size for a file about to be loaded is sufficient and
        /// conditonally returns an address to a new buffer with adequate size.
        /// </summary>
        /// <returns>The address of a new buffer for the game to decompress a file to</returns>
        private static void *CheckBufferSize(int fileIndex, void *addressToDecompressTo, ONEFILE *thisPointer)
        {
            if (fileIndex >= 2)
            {
                // Get pointer and length.
                IntPtr onePointer = (IntPtr)thisPointer[0].InternalDataPointer - 0xC; // The start of file pointer is sometimes unused, so we use the InternalDataPointer instead and offset.
                int    fileLength = thisPointer[0].FileLength;

                // Now the ONE File
                MemoryONEArchive memoryOneFile = MemoryONEArchive.ParseONEFromMemory(onePointer, fileLength);

                // Now we estimate the size of it.
                int           actualFileIndex = fileIndex - 2;
                MemoryONEFile oneFile         = memoryOneFile.Files[actualFileIndex];
                byte[]        oneFileCopy     = GameProcess.ReadMemory((IntPtr)oneFile.CompressedDataPointer, oneFile.DataLength);
                int           oneFileLength   = Prs.Estimate(ref oneFileCopy);

                // Check if the size of allocation is sufficient.
                MemoryAddressDetails addressDetails = Allocator.GetAddressDetails((int)addressToDecompressTo);

                if (addressDetails.MemorySize < oneFileLength)
                {
                    // Allocate some new data for me please
                    addressToDecompressTo = (void *)Allocator.Allocate((int)addressToDecompressTo, oneFileLength);
                }
            }

            return(addressToDecompressTo);
        }
Example #2
0
        /// <summary>
        /// Parses the details of a minimal Heroes .ONE file from a supplied memory
        /// address and length. This is simply a modified version of HeroesONE-R's version.
        /// </summary>
        /// <returns>The structure of a ONE Archive.</returns>
        public static MemoryONEArchive ParseONEFromMemory(IntPtr filePointer, int fileLength)
        {
            // Creates a .ONE Archive instance ready to feed.
            MemoryONEArchive oneArchive = new MemoryONEArchive();

            // Stores a pointer, increasing as we read the individual file structures.
            int pointer = 0;

            // Get the header and individual sections.
            oneArchive.FileHeader            = (ONEHeader *)StructUtilities.MemoryOffsetToPointer <ONEHeader>(filePointer, pointer, ref pointer);
            oneArchive.FileNameSectionHeader = (ONEFileNameSectionHeader *)StructUtilities.MemoryOffsetToPointer <ONEFileNameSectionHeader>(filePointer, pointer, ref pointer);

            // Get the filenames.
            oneArchive.FileNameCount = (*oneArchive.FileNameSectionHeader).GetNameCount();
            oneArchive.FileNames     = (ONEFileName *)StructUtilities.MemoryOffsetToPointer <ONEFileName>(filePointer, pointer);
            pointer += (*oneArchive.FileNameSectionHeader).FileNameSectionLength;

            // Parse all of the files.
            oneArchive.Files = new List <MemoryONEFile>(oneArchive.FileNameCount);
            int fileCount = 0;

            for (int x = 0; x < oneArchive.FileNameCount; x++)
            {
                if (oneArchive.FileNames[x].ToString() != "")
                {
                    fileCount += 1;
                }
            }

            // Some ONE files have been padded at the end of file, thus reading until the end of file may fail - only take as many files as we have filenames.
            while ((pointer < fileLength) && (oneArchive.Files.Count < fileCount))
            {
                // Create ONE ArchiveFile
                MemoryONEFile oneFile = new MemoryONEFile();

                // Parse the contents.
                oneFile.ONEFileHeader         = (ONEFileHeader *)StructUtilities.MemoryOffsetToPointer <ONEFileHeader>(filePointer, pointer, ref pointer);
                oneFile.CompressedDataPointer = (byte *)StructUtilities.MemoryOffsetToPointer <ONEFileHeader>(filePointer, pointer);
                oneFile.DataLength            = oneFile.ONEFileHeader[0].FileSize;
                pointer += oneFile.DataLength;

                // We're done here :3
                oneArchive.Files.Add(oneFile);
            }

            return(oneArchive);
        }