Esempio n. 1
0
        private static NpkPath GetImgPath(CommandLineArgs cmdLine, NpkReader npk)
        {
            if (cmdLine.ImgPath != null)
            {
                NpkPath imgPath = new NpkPath(cmdLine.ImgPath);
                IList<NpkPath> imgPathComponents = imgPath.GetPathComponents();
                if (imgPathComponents.Count >= 1 && imgPathComponents[0].Path.Equals("sprite", StringComparison.OrdinalIgnoreCase))
                {
                    // strip sprite/ prefix if present
                    imgPath = imgPath.StripPrefix();
                }

                if (!npk.Images.ContainsKey(imgPath))
                {
                    Console.Error.WriteLine("There is no img file with path {0} in NPK file {1}", cmdLine.ImgPath, cmdLine.NpkPath);
                    Environment.Exit(1);
                }

                return imgPath;
            }
            else
            {
                List<NpkPath> matchingPaths = new List<NpkPath>();

                // Only the .img name was given. Look for it.
                foreach (NpkPath path in npk.Images.Keys)
                {
                    if (path.GetFileName().Path.Equals(cmdLine.ImgName, StringComparison.OrdinalIgnoreCase))
                    {
                        matchingPaths.Add(path);
                    }
                }

                if (matchingPaths.Count == 1)
                {
                    return matchingPaths[0];
                }
                else if (matchingPaths.Count == 0)
                {
                    Console.Error.WriteLine("There is no img file called {0} in NPK file {1}", cmdLine.ImgName, cmdLine.NpkPath);
                    Environment.Exit(1);
                    return null; // not reached
                }
                else
                {
                    Console.Error.WriteLine("There are multiple img files matching the name {0} in NPK file {1}: {2}", cmdLine.ImgName, cmdLine.NpkPath, string.Join(", ", matchingPaths));
                    Environment.Exit(1);
                    return null; // not reached
                }
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Helper function that loads the first part of the .npk header. m_imagefileLocations and
        /// m_soundFileLocations are loaded when this function completes. The stream's read pointer will
        /// be right after the file table part of the header after completion. This function is only
        /// intended to be called from LoadNpkHeader().
        /// </summary>
        /// <exception cref="System.IO.EndOfStreamException">Unexpected end of file.</exception>
        /// <exception cref="System.IO.IOException">I/O error.</exception>
        /// <exception cref="DFO.Npk.NpkException">The file is corrupt or the format has changed.</exception>
        private void LoadNpkFileTable()
        {
            // file starts with "NeoplePack_Bill\0" in ASCII
            try
            {
                string dirListingHeader = "NeoplePack_Bill\0";
                byte[] headerBuffer = new byte[dirListingHeader.Length];
                m_npkStream.ReadOrDie(headerBuffer, headerBuffer.Length);
                string headerString = Encoding.ASCII.GetString(headerBuffer);
                if (!string.Equals(dirListingHeader, headerString, StringComparison.Ordinal))
                {
                    throw new NpkException("Did not find expected directory listing header.");
                }

                // Next is a 32-bit unsigned int that is the number of files packed in the .npk
                uint numFiles = GetUnsigned32Le();

                byte[] subNameBuffer = new byte[256];
                // Next is a listing of all the files and their location inside the file.
                for (uint fileIndex = 0; fileIndex < numFiles; fileIndex++)
                {
                    // First is a 32-bit unsigned int that is the byte offset in the .npk of where the file is located.
                    uint absoluteLocation = GetUnsigned32Le();
                    // Followed by the size of the file in bytes
                    uint size = GetUnsigned32Le();
                    // And then the path of the file, including the prefix indicating whether it is an image
                    // (sprite/) or a sound (sounds/)
                    // There are always 256 bytes to be read here.
                    // Each byte read is XOR'ed with the corresponding byte in the key.
                    // Then the bytes can be treated as a null-terminated ASCII string.
                    m_npkStream.ReadOrDie(subNameBuffer, subNameBuffer.Length);

                    for (int keyIndex = 0; keyIndex < subNameBuffer.Length; keyIndex++)
                    {
                        subNameBuffer[keyIndex] ^= s_key[keyIndex];
                    }

                    string subNameString = Encoding.ASCII.GetString(subNameBuffer);
                    subNameString = subNameString.TrimEnd('\0');
                    NpkPath pathWithPrefix = new NpkPath(subNameString);

                    // That gives a path like sprite/character/gunner/effect/aerialdashattack.img
                    // We need to strip off the sprite/ or sound/ prefix.
                    // The following code assumes that a prefix of, say, sprite// or sprite\ is still valid.
                    // If not, the code could be simplified.
                    IList<NpkPath> pathComponents = pathWithPrefix.GetPathComponents();
                    if (pathComponents.Count >= 1)
                    {
                        // Build up the NpkPath that is the same NpkPath but without the first component
                        NpkPath pathWithoutPrefix = pathWithPrefix.StripPrefix();

                        NpkByteRange fileLocation = new NpkByteRange(absoluteLocation, (int)size);
                        if (pathComponents[0].Equals("sprite"))
                        {
                            m_imageFileLocations[pathWithoutPrefix] = fileLocation;
                            m_imagesInFile[pathWithoutPrefix] = true;
                        }
                        else if (pathComponents[0].Equals("sounds"))
                        {
                            m_soundFileLocations[pathWithoutPrefix] = fileLocation;
                        }
                        else
                        {
                            // Not an image or a sound. Ignore it I guess, no sense throwing an exception.
                            // Don't break any programs just because a new file type was added or something.
                            OnErrorDetected("Something other than a sprite or sounds file at packed file index {0}: {1}".F(fileIndex, pathComponents[0]));
                        }
                    }
                    else
                    {
                        // empty path? O_o Ignore it I guess.
                        OnErrorDetected("Empty path at packed file index {0}.".F(fileIndex));
                    }
                }
            }
            catch (EndOfStreamException ex)
            {
                throw new NpkException("Unexpected end of file.", ex);
            }
        }