예제 #1
0
파일: DARC.cs 프로젝트: tom-overton/pk3DS
        public static bool Files2darc(string folderName, bool delete = false, string originalDARC = null, string outFile = null)
        {
            // Save all contents of a folder to a darc.
            try
            {
                byte[] darcData;
                DARC   orig;
                string root = folderName;
                if (originalDARC != null)
                {
                    // Fetch offset of DARC within file.
                    byte[] darc    = File.ReadAllBytes(originalDARC);
                    int    darcPos = GetDARCposition(darc);
                    if (darcPos < 0)
                    {
                        return(false);
                    }
                    byte[] origData = darc.Skip(darcPos).ToArray();

                    orig = new DARC(origData);
                    orig = InsertFiles(orig, folderName);
                    byte[] newDARC = SetDARC(orig);
                    darcData = darc.Take(darcPos).Concat(newDARC).ToArray();
                }
                else // no existing darc to get
                {
                    orig     = GetDARC(folderName);
                    darcData = SetDARC(orig);
                }

                // Fetch final name if not specified
                outFile ??= originalDARC ?? new DirectoryInfo(folderName).Name.Replace("_d", "") + ".darc";

                if (darcData == null)
                {
                    return(false);
                }
                File.WriteAllBytes(outFile, darcData);

                if (Directory.Exists(root) && delete)
                {
                    Directory.Delete(root, true);
                }
                return(true);
            } catch (Exception) { return(false); }
        }
예제 #2
0
파일: DARC.cs 프로젝트: tom-overton/pk3DS
        public static bool Darc2files(byte[] darc, string folderName)
        {
            // Save all contents of a DARC to a folder, assuming there's only 1 layer of folders.
            try
            {
                // Clear existing contents
                string root = folderName;
                if (Directory.Exists(root))
                {
                    Directory.Delete(root, true);
                }

                // Create new DARC object from input data
                DARC DARC = new DARC(darc);

                // Output data
                for (int i = 2; i < DARC.FileNameTable.Length;)
                {
                    bool isFolder = DARC.Entries[i].IsFolder;
                    if (!isFolder)
                    {
                        return(false);
                    }
                    // uint level = DARC.Entries[i].DataOffset; Only assuming 1 layer of folders.
                    string parentName = DARC.FileNameTable[i].FileName;
                    Directory.CreateDirectory(Path.Combine(root, parentName));

                    int nextFolder = (int)DARC.Entries[i++].DataLength;

                    // Extract all Contents of said folder
                    while (i < nextFolder)
                    {
                        string fileName = DARC.FileNameTable[i].FileName;
                        int    offset   = (int)DARC.Entries[i].DataOffset;
                        int    length   = (int)DARC.Entries[i].DataLength;
                        byte[] data     = DARC.Data.Skip((int)(offset - DARC.Header.FileDataOffset)).Take(length).ToArray();

                        string outPath = Path.Combine(root, parentName, fileName);
                        File.WriteAllBytes(outPath, data);
                        i++; // Advance to next Entry
                    }
                }
                return(true);
            }
            catch (Exception) { return(false); }
        }
예제 #3
0
        // DARC r/w
        public static byte[] setDARC(DARC darc)
        {
            // Package DARC into a writable array.
            using (MemoryStream ms = new MemoryStream())
                using (BinaryWriter bw = new BinaryWriter(ms))
                {
                    // Write Header
                    bw.Write(Encoding.ASCII.GetBytes(darc.Header.Signature));
                    bw.Write(darc.Header.Endianness);
                    bw.Write(darc.Header.HeaderSize);
                    bw.Write(darc.Header.Version);
                    bw.Write(darc.Header.FileSize);
                    bw.Write(darc.Header.FileTableOffset);
                    bw.Write(darc.Header.FileTableLength);
                    bw.Write(darc.Header.FileDataOffset);
                    // Write FileTableEntries
                    foreach (FileTableEntry entry in darc.Entries)
                    {
                        bw.Write(entry.NameOffset | (entry.IsFolder ? (uint)1 << 24 : 0));
                        bw.Write(entry.DataOffset);
                        bw.Write(entry.DataLength);
                    }
                    foreach (NameTableEntry entry in darc.FileNameTable)
                    {
                        bw.Write(Encoding.Unicode.GetBytes(entry.FileName + "\0"));
                    }
                    while (bw.BaseStream.Position < darc.Header.FileDataOffset)
                    {
                        bw.Write((byte)0);
                    }

                    // Write Data
                    bw.Write(darc.Data);

                    return(ms.ToArray());
                }
        }
예제 #4
0
파일: DARC.cs 프로젝트: tom-overton/pk3DS
 public static bool InsertFile(ref DARC orig, int index, string path)
 {
     try { return(InsertFile(ref orig, index, File.ReadAllBytes(path))); }
     catch (Exception) { return(false); }
 }
예제 #5
0
파일: DARC.cs 프로젝트: tom-overton/pk3DS
        public static DARC GetDARC(string folderName)
        {
            // Package Folder into a DARC.
            List <FileTableEntry> EntryList = new List <FileTableEntry>();
            List <NameTableEntry> NameList  = new List <NameTableEntry>();

            byte[] Data       = Array.Empty <byte>();
            uint   nameOffset = 6; // 00 00 + 00 2E 00 00

            #region Build FileTable/NameTables
            {
                // Null First File
                {
                    EntryList.Add(new FileTableEntry {
                        DataOffset = 0, DataLength = 0, IsFolder = true, NameOffset = 0
                    });
                    NameList.Add(new NameTableEntry(0, ""));
                }
                // "." Second File
                {
                    EntryList.Add(new FileTableEntry {
                        DataOffset = 0, DataLength = 0, IsFolder = true, NameOffset = 2
                    });
                    NameList.Add(new NameTableEntry(6, "."));
                }
                foreach (string folder in Directory.GetDirectories(folderName))
                {
                    string   parentName = new DirectoryInfo(folder).Name;
                    string[] files      = Directory.GetFiles(folder);
                    NameList.Add(new NameTableEntry(nameOffset, parentName));
                    EntryList.Add(new FileTableEntry
                    {
                        DataOffset = 1,
                        DataLength = (uint)(files.Length + EntryList.Count),
                        IsFolder   = true,
                        NameOffset = nameOffset
                    });
                    nameOffset += (uint)parentName.Length + 2;  // Account for null terminator

                    foreach (string file in files)
                    {
                        FileInfo fi       = new FileInfo(file);
                        string   fileName = fi.Name;
                        NameList.Add(new NameTableEntry(nameOffset, parentName));

                        EntryList.Add(new FileTableEntry
                        {
                            DataOffset = (uint)Data.Length,
                            DataLength = (uint)fi.Length,
                            IsFolder   = false,
                            NameOffset = nameOffset
                        });
                        Data        = Data.Concat(File.ReadAllBytes(file)).ToArray();
                        nameOffset += (uint)fileName.Length + 2;  // Account for null terminator
                    }
                }
            }
            #endregion

            // Compute Necessary DARC information
            int darcFileCount  = NameList.Count;
            int NameListOffset = darcFileCount * 0xC;
            int NameListLength = (int)(nameOffset + NameListOffset);
            int DataOffset     = NameListLength % 4 == 0 ? NameListLength : NameListLength + (4 - (NameListLength % 4));
            Array.Resize(ref Data, Data.Length % 4 == 0 ? Data.Length : Data.Length + 4 - (Data.Length % 4));
            int FinalSize = DataOffset + Data.Length;

            // Create New DARC
            DARC darc = new DARC
            {
                Header =
                {
                    Signature       = "darc",
                    Endianness      =               0xFEFF,
                    HeaderSize      =                 0x1C,
                    Version         =                    1,
                    FileSize        = (uint)FinalSize,
                    FileTableOffset =                 0x1C,
                    FileTableLength = (uint)NameListLength,
                    FileDataOffset  = (uint)DataOffset,
                },
                Entries       = EntryList.ToArray(),
                FileNameTable = NameList.ToArray(),
                Data          = Data,
            };
            // Fix the First two folders to specify the number of files
            darc.Entries[0].DataLength = (uint)darcFileCount;
            darc.Entries[1].DataLength = (uint)darcFileCount;

            // Fix the Data Offset of the files to point to actual destination
            foreach (FileTableEntry f in darc.Entries.Where(x => !x.IsFolder))
            {
                f.DataOffset += darc.Header.FileDataOffset;
            }
            return(darc);
        }