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 } } }
/// <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); } }