示例#1
0
 /// <summary>
 /// Create IMG archive from directory
 /// </summary>
 /// <param name="sourceDirectoryPath">Source directory path</param>
 /// <param name="destinationIMGArchiveFilePath">Destination IMG archive file path</param>
 /// <param name="includeBaseDirectory">Include base directory in IMG archive</param>
 /// <param name="entryNameEncoding">Entry name encoding</param>
 public static void CreateFromDirectory(string sourceDirectoryPath, string destinationIMGArchiveFilePath, bool includeBaseDirectory, Encoding entryNameEncoding)
 {
     if (sourceDirectoryPath == null)
     {
         throw new ArgumentNullException(nameof(sourceDirectoryPath));
     }
     if (destinationIMGArchiveFilePath == null)
     {
         throw new ArgumentNullException(nameof(destinationIMGArchiveFilePath));
     }
     if (entryNameEncoding == null)
     {
         throw new ArgumentNullException(nameof(entryNameEncoding));
     }
     try
     {
         string source_directory_name         = Path.GetFullPath(sourceDirectoryPath.TrimEnd('\\', '/'));
         string destination_archive_file_name = Path.GetFullPath(destinationIMGArchiveFilePath);
         if (Directory.Exists(source_directory_name))
         {
             string[] files                = Directory.GetFiles(source_directory_name, "*", SearchOption.AllDirectories);
             string[] relative_files       = new string[files.Length];
             bool     file_name_lenghts_ok = true;
             for (int i = 0; i < files.Length; i++)
             {
                 relative_files[i] = IMGUtilities.GetRelativePath(files[i], includeBaseDirectory ? Directory.GetParent(source_directory_name).FullName : source_directory_name).Replace('\\', '/');
                 if (relative_files[i].Length > 24)
                 {
                     file_name_lenghts_ok = false;
                     break;
                 }
             }
             if (file_name_lenghts_ok)
             {
                 using (FileStream img_archive_file_stream = File.Open(destination_archive_file_name, FileMode.Create))
                 {
                     using (BinaryWriter img_archive_file_stream_binary_writer = new BinaryWriter(img_archive_file_stream, entryNameEncoding, true))
                     {
                         int first_entry_offset   = ((((files.Length * 32) % 2048) == 0) ? ((files.Length * 32) / 2048) : (((files.Length * 32) / 2048) + 1));
                         int current_entry_offset = first_entry_offset;
                         List <KeyValuePair <string, int> > entries = new List <KeyValuePair <string, int> >();
                         img_archive_file_stream_binary_writer.Write(new byte[] { 0x56, 0x45, 0x52, 0x32, (byte)(files.Length & 0xFF), (byte)((files.Length >> 8) & 0xFF), 0x0, 0x0 });
                         for (int i = 0; i < files.Length; i++)
                         {
                             long   file_length    = (new FileInfo(files[i])).Length;
                             int    entry_length   = (int)(((file_length % 2048L) == 0L) ? (file_length / 2048L) : ((file_length / 2048L) + 1L));
                             byte[] name_bytes_raw = entryNameEncoding.GetBytes(relative_files[i]);
                             byte[] name_bytes     = new byte[24];
                             Array.Copy(name_bytes_raw, name_bytes, Math.Min(name_bytes_raw.Length, name_bytes.Length));
                             img_archive_file_stream_binary_writer.Write(current_entry_offset);
                             img_archive_file_stream_binary_writer.Write(new byte[] { (byte)(entry_length & 0xFF), (byte)((entry_length >> 8) & 0xFF), 0x0, 0x0 });
                             img_archive_file_stream_binary_writer.Write(name_bytes);
                             entries.Add(new KeyValuePair <string, int>(files[i], current_entry_offset));
                             current_entry_offset += entry_length;
                         }
                         foreach (KeyValuePair <string, int> entry in entries)
                         {
                             using (FileStream stream = File.Open(entry.Key, FileMode.Open, FileAccess.Read))
                             {
                                 while ((img_archive_file_stream.Length / 2048) < entry.Value)
                                 {
                                     img_archive_file_stream.WriteByte(0);
                                 }
                                 byte[] data = new byte[stream.Length];
                                 stream.Read(data, 0, (int)(stream.Length));
                                 img_archive_file_stream_binary_writer.Write(data);
                             }
                         }
                         while ((img_archive_file_stream.Length / 2048) < current_entry_offset)
                         {
                             img_archive_file_stream.WriteByte(0);
                         }
                     }
                 }
             }
         }
     }
     catch (Exception e)
     {
         Console.Error.WriteLine(e);
     }
 }
示例#2
0
        /// <summary>
        /// Open IMG archive
        /// </summary>
        /// <param name="imgArchiveFilePath">IMG archive file path</param>
        /// <param name="accessMode">IMG archive access mode</param>
        /// <param name="entryNameEncoding">IMG archive entry name encoding</param>
        /// <returns>IMG archive</returns>
        /// <exception cref="InvalidOperationException">Return value is null</exception>
        /// <exception cref="ArgumentNullException">Archive file name is null</exception>
        /// <exception cref="FileNotFoundException">Archive file not found</exception>
        /// <exception cref="InvalidDataException">Archive error</exception>
        public static IIMGArchive Open(string imgArchiveFilePath, EIMGArchiveAccessMode accessMode, Encoding entryNameEncoding)
        {
            if (imgArchiveFilePath == null)
            {
                throw new ArgumentNullException(nameof(imgArchiveFilePath));
            }
            if (entryNameEncoding == null)
            {
                throw new ArgumentNullException(nameof(entryNameEncoding));
            }
            IMGArchive ret = null;

            try
            {
                if ((accessMode != EIMGArchiveAccessMode.Create) && (!File.Exists(imgArchiveFilePath)))
                {
                    throw new FileNotFoundException("Archive not found", imgArchiveFilePath);
                }
                FileStream archive_file_stream = File.Open(imgArchiveFilePath, (accessMode == EIMGArchiveAccessMode.Create) ? FileMode.Create : FileMode.Open, (accessMode != EIMGArchiveAccessMode.Read) ? FileAccess.ReadWrite : FileAccess.Read);
                if (archive_file_stream == null)
                {
                    throw new FileNotFoundException("Archive not found", imgArchiveFilePath);
                }
                Dictionary <string, IIMGArchiveEntry> img_archive_entries = new Dictionary <string, IIMGArchiveEntry>();
                ret = new IMGArchive(archive_file_stream, accessMode, entryNameEncoding, img_archive_entries);
                if (accessMode == EIMGArchiveAccessMode.Create)
                {
                    byte[] new_data = new byte[2048];
                    new_data[0] = 0x56;
                    new_data[1] = 0x45;
                    new_data[2] = 0x52;
                    new_data[3] = 0x32;
                    archive_file_stream.Write(new_data, 0, new_data.Length);
                }
                else
                {
                    using (BinaryReader archive_file_stream_binary_reader = new BinaryReader(archive_file_stream, entryNameEncoding, true))
                    {
                        int archive_version = archive_file_stream_binary_reader.ReadInt32();
                        if (archive_version != SupportedIMGArchiveVersion)
                        {
                            throw new InvalidDataException($"Invalid IMG archive version { archive_version }.");
                        }
                        uint num_entries = archive_file_stream_binary_reader.ReadUInt32();
                        if (archive_file_stream.Length < (num_entries * 8))
                        {
                            throw new InvalidDataException($"IMG archive file size is smaller than expected.");
                        }
                        for (uint num_entry = 0U; num_entry != num_entries; num_entry++)
                        {
                            long   offset = archive_file_stream_binary_reader.ReadInt32() * 2048L;
                            int    length = archive_file_stream_binary_reader.ReadInt16() * 2048;
                            short  dummy  = archive_file_stream_binary_reader.ReadInt16();
                            byte[] full_name_bytes_raw = new byte[24];
                            if (archive_file_stream_binary_reader.Read(full_name_bytes_raw, 0, full_name_bytes_raw.Length) != full_name_bytes_raw.Length)
                            {
                                throw new InvalidDataException("IMG entry name is missing.");
                            }
                            int full_name_bytes_count = IMGUtilities.GetNullTerminatedByteStringLength(full_name_bytes_raw);
                            if (full_name_bytes_count <= 0)
                            {
                                throw new InvalidDataException("IMG entry name can't be empty.");
                            }
                            string full_name = entryNameEncoding.GetString(full_name_bytes_raw, 0, full_name_bytes_count);
                            img_archive_entries.Add(full_name.ToLower(), new IMGArchiveEntry(ret, offset, length, full_name));
                        }
                    }
                }
                if (ret == null)
                {
                    throw new InvalidOperationException("Return value is null");
                }
            }
            catch (Exception e)
            {
                ret?.Dispose();
                throw e;
            }
            return(ret);
        }