Ejemplo n.º 1
0
        public void Extract(ref Dictionary <string, FileStream> streamCache, string destinationFolder, bool extractAsRaw)
        {
            string destinationFile = Path.Combine(Path.Combine(destinationFolder, this.ParentDirectoryName), this.FileName);

            byte[] magicBytes;

            if (!streamCache.ContainsKey(this.SourceFilePath))
            {
                streamCache[this.SourceFilePath] = File.OpenRead(this.SourceFilePath);
            }

            // check for CRILAYLA signature since file size is not always reliable,
            //    this will be a little slower, but hopefully the stream caching will minimize
            //    the impact
            magicBytes = ParseFile.ParseSimpleOffset(streamCache[this.SourceFilePath], (long)this.Offset, CriCpkArchive.CRILAYLA_SIGNATURE.Length);

            if (ParseFile.CompareSegment(magicBytes, 0, CriCpkArchive.CRILAYLA_SIGNATURE))
            {
                CriCpkArchive.Uncompress(streamCache[this.SourceFilePath], (long)this.Offset, this.Size, destinationFile);
            }
            else
            {
                ParseFile.ExtractChunkToFile64(streamCache[this.SourceFilePath], (ulong)this.Offset, (ulong)this.Size, destinationFile, false, false);
            }
        }
Ejemplo n.º 2
0
        // @TODO: Need to update this for Internal/External CPK
        protected void ExtractAwbWithCueNames(string destinationFolder, AwbToExtract whichAwb)
        {
            CriUtfTable waveformTableUtf;
            byte        encodeType;
            string      rawFileName;

            CriAfs2Archive awb;
            string         rawFileFormat = "{0}_{1}{2}";

            if (whichAwb == AwbToExtract.Internal)
            {
                awb = this.InternalAwb;
            }
            else
            {
                awb = this.ExternalAwb;
            }

            using (FileStream fs = File.Open(awb.SourceFile, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                // use files names for internal AWB
                foreach (string key in this.CueNamesToWaveforms.Keys)
                {
                    // extract file
                    ParseFile.ExtractChunkToFile64(fs,
                                                   (ulong)awb.Files[this.CueNamesToWaveforms[key]].FileOffsetByteAligned,
                                                   (ulong)awb.Files[this.CueNamesToWaveforms[key]].FileLength,
                                                   Path.Combine(destinationFolder, FileUtil.CleanFileName(key)), false, false);
                }

                //-------------------------------------
                // extract any items without a CueName
                //-------------------------------------
                using (FileStream acbStream = File.Open(this.SourceFile, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    waveformTableUtf = new CriUtfTable();
                    waveformTableUtf.Initialize(acbStream, (long)this.WaveformTableOffset);
                }

                // get list of unextracted files
                var unextractedFiles = awb.Files.Keys.Where(x => !this.CueNamesToWaveforms.ContainsValue(x));
                foreach (ushort key in unextractedFiles)
                {
                    encodeType = (byte)CriUtfTable.GetUtfFieldForRow(waveformTableUtf, key, "EncodeType");

                    rawFileName = String.Format(rawFileFormat,
                                                Path.GetFileNameWithoutExtension(awb.SourceFile), key.ToString("D5"),
                                                CriAcbFile.GetFileExtensionForEncodeType(encodeType));

                    // extract file
                    ParseFile.ExtractChunkToFile64(fs,
                                                   (ulong)awb.Files[key].FileOffsetByteAligned,
                                                   (ulong)awb.Files[key].FileLength,
                                                   Path.Combine(destinationFolder, rawFileName), false, false);
                }
            }
        }
Ejemplo n.º 3
0
        public string WriteTableToTempFile(FileStream fs, long offsetToUtfTable, int?maxTableSize = null)
        {
            string pathToUtf = null;

            int totalBytesRead = 0;
            int maxRead;

            byte[] buffer = new byte[Constants.FileReadChunkSize];

            int tableSize;

            if (maxTableSize != null) // typically used for isUtf function
            {
                tableSize = (int)maxTableSize;
            }
            else
            {
                tableSize = (int)this.UtfReader.ReadUint(fs, offsetToUtfTable, 4) + 8;
            }

            pathToUtf = Path.Combine(Path.GetTempPath(), TEMP_UTF_TABLE_FILE);

            if (this.IsEncrypted)
            {
                using (FileStream tempStream = File.Open(pathToUtf, FileMode.Create, FileAccess.Write, FileShare.Read))
                {
                    while (totalBytesRead < tableSize)
                    {
                        if ((tableSize - totalBytesRead) > buffer.Length)
                        {
                            maxRead = buffer.Length;
                        }
                        else
                        {
                            maxRead = (tableSize - totalBytesRead);
                        }

                        buffer = this.UtfReader.GetBytes(fs, offsetToUtfTable, maxRead, totalBytesRead);
                        tempStream.Write(buffer, 0, maxRead);
                        totalBytesRead += maxRead;
                    }
                }
            }
            else
            {
                if (File.Exists(pathToUtf))
                {
                    File.Delete(pathToUtf);
                }

                ParseFile.ExtractChunkToFile64(fs, (ulong)offsetToUtfTable, (ulong)tableSize, pathToUtf, false, false);
            }

            return(pathToUtf);
        }
Ejemplo n.º 4
0
        public void ExtractAllRaw(string destinationFolder)
        {
            string rawFileFormat = "{0}.{1}.bin";

            using (FileStream fs = File.Open(this.SourceFile, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                foreach (ushort key in this.Files.Keys)
                {
                    ParseFile.ExtractChunkToFile64(fs,
                                                   (ulong)this.Files[key].FileOffsetByteAligned,
                                                   (ulong)this.Files[key].FileLength,
                                                   Path.Combine(destinationFolder,
                                                                String.Format(rawFileFormat, Path.GetFileName(this.SourceFile), key.ToString("D5"))), false, false);
                }
            }
        }
Ejemplo n.º 5
0
        public static string[] SplitFile(string sourceFile, long startingOffset, ulong chunkSizeInBytes,
                                         string outputFolder)
        {
            string[] outputFileList;
            string   outputFileName;
            var      outputFiles = new ArrayList();

            long  fileLength;
            ulong currentOffset;

            int chunkCount;

            using (var sourceStream = File.OpenRead(sourceFile))
            {
                // get file length
                fileLength = sourceStream.Length;

                // init counters
                chunkCount    = 1;
                currentOffset = (ulong)startingOffset;

                while (currentOffset < (ulong)fileLength)
                {
                    // construct output file name
                    outputFileName = Path.Combine(outputFolder,
                                                  string.Format("{0}.{1}",
                                                                Path.GetFileName(sourceFile),
                                                                chunkCount.ToString("D3")));

                    ParseFile.ExtractChunkToFile64(sourceStream, currentOffset, chunkSizeInBytes,
                                                   outputFileName, true, true);


                    outputFiles.Add(outputFileName);
                    currentOffset += chunkSizeInBytes;
                    chunkCount++;
                }
            }

            outputFileList = (string[])outputFiles.ToArray(typeof(string));
            return(outputFileList);
        }
Ejemplo n.º 6
0
        public void Extract(ref Dictionary <string, FileStream> streamCache, string destinationFolder, bool extractAsRaw)
        {
            string destinationFile = Path.Combine(Path.Combine(destinationFolder, this.ParentDirectoryName), this.FileName);

            if (!streamCache.ContainsKey(this.SourceFilePath))
            {
                streamCache[this.SourceFilePath] = File.OpenRead(this.SourceFilePath);
            }

            //-----------------------------------------------------------
            // ExeFS
            //-----------------------------------------------------------
            if (this.FileSystem == Nintendo3dsCtr.FileSystemType.ExeFS)
            {
                // write file while calculating hash
                HashAlgorithm cryptoHash = SHA256.Create();
                byte[]        outputHash = ParseFile.ExtractChunkToFile64ReturningHash(streamCache[this.SourceFilePath], (ulong)this.Offset, (ulong)this.Size,
                                                                                       destinationFile, cryptoHash, false, false);

                if (!ParseFile.CompareSegment(outputHash, 0, this.Sha256Hash))
                {
                    // @TODO: only show error once per file
                    //if (!sha1ErrorDisplayed)
                    {
                        MessageBox.Show(String.Format("Warning: '{0},' failed SHA256 verification in ExeFS at offset 0x{1} during extraction.{2}",
                                                      Path.GetFileName(destinationFile), this.Offset, Environment.NewLine), "Warning - SHA256 Failure");
                    }
                }
            }
            //---------------
            // RomFS
            //---------------
            else
            {
                // @TODO: Modify to verify on extraction
                ParseFile.ExtractChunkToFile64(streamCache[this.SourceFilePath], (ulong)this.Offset,
                                               (ulong)this.Size, destinationFile, false, false);
            }
        }
Ejemplo n.º 7
0
        protected void ExtractAllUsingCueList(string destinationFolder)
        {
            CriUtfTable waveformTableUtf;
            ushort      waveformIndex;
            byte        encodeType;
            string      rawFileName;
            string      rawFileFormat = "{0}.{1}{2}";

            FileStream internalFs = null;
            FileStream externalFs = null;

            ArrayList internalIdsExtracted = new ArrayList();
            ArrayList externalIdsExtracted = new ArrayList();

            string acbAwbDestinationFolder = Path.Combine(destinationFolder, ACB_AWB_EXTRACTION_FOLDER);
            string extAwbDestinationFolder = Path.Combine(destinationFolder, EXT_AWB_EXTRACTION_FOLDER);
            string acbCpkDestinationFolder = Path.Combine(destinationFolder, ACB_CPK_EXTRACTION_FOLDER);
            string extCpkDestinationFolder = Path.Combine(destinationFolder, EXT_CPK_EXTRACTION_FOLDER);

            try
            {
                // open streams
                if (this.InternalAwb != null)
                {
                    internalFs = File.Open(this.InternalAwb.SourceFile, FileMode.Open, FileAccess.Read, FileShare.Read);
                }
                else if (this.InternalCpk != null)
                {
                    internalFs = File.Open(this.InternalCpk.SourceFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
                }

                if (this.ExternalAwb != null)
                {
                    externalFs = File.Open(this.ExternalAwb.SourceFile, FileMode.Open, FileAccess.Read, FileShare.Read);
                }
                else if (this.ExternalCpk != null)
                {
                    externalFs = File.Open(this.ExternalCpk.SourceFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
                }

                // loop through cues and extract
                for (int i = 0; i < CueList.Length; i++)
                {
                    CriAcbCueRecord cue = CueList[i];

                    if (cue.IsWaveformIdentified)
                    {
                        if (cue.IsStreaming) // external AWB file
                        {
                            if (this.ExternalAwb != null)
                            {
                                ParseFile.ExtractChunkToFile64(externalFs,
                                                               (ulong)this.ExternalAwb.Files[cue.WaveformId].FileOffsetByteAligned,
                                                               (ulong)this.ExternalAwb.Files[cue.WaveformId].FileLength,
                                                               Path.Combine(extAwbDestinationFolder, FileUtil.CleanFileName(cue.CueName)), false, false);
                            }
                            else if (this.ExternalCpk != null)
                            {
                                ParseFile.ExtractChunkToFile64(externalFs,
                                                               (ulong)this.ExternalCpk.ItocFiles[cue.WaveformId].FileOffsetByteAligned,
                                                               (ulong)this.ExternalCpk.ItocFiles[cue.WaveformId].FileLength,
                                                               Path.Combine(extCpkDestinationFolder, FileUtil.CleanFileName(cue.CueName)), false, false);
                            }

                            externalIdsExtracted.Add(cue.WaveformId);
                        }
                        else // internal AWB file (inside ACB)
                        {
                            if (this.InternalAwb != null)
                            {
                                ParseFile.ExtractChunkToFile64(internalFs,
                                                               (ulong)this.InternalAwb.Files[cue.WaveformId].FileOffsetByteAligned,
                                                               (ulong)this.InternalAwb.Files[cue.WaveformId].FileLength,
                                                               Path.Combine(acbAwbDestinationFolder, FileUtil.CleanFileName(cue.CueName)), false, false);
                            }
                            else if (this.InternalCpk != null)
                            {
                                ParseFile.ExtractChunkToFile64(internalFs,
                                                               (ulong)this.InternalCpk.ItocFiles[cue.WaveformId].FileOffsetByteAligned,
                                                               (ulong)this.InternalCpk.ItocFiles[cue.WaveformId].FileLength,
                                                               Path.Combine(acbCpkDestinationFolder, FileUtil.CleanFileName(cue.CueName)), false, false);
                            }

                            internalIdsExtracted.Add(cue.WaveformId);
                        }
                    } // if (cue.IsWaveformIdentified)
                }

                // extract leftovers
                using (FileStream acbStream = File.Open(this.SourceFile, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    waveformTableUtf = new CriUtfTable();
                    waveformTableUtf.Initialize(acbStream, (long)this.WaveformTableOffset);
                }

                if (this.ExternalAwb != null)
                {
                    var unextractedExternalFiles = this.ExternalAwb.Files.Keys.Where(x => !externalIdsExtracted.Contains(x));
                    foreach (ushort key in unextractedExternalFiles)
                    {
                        waveformIndex = GetWaveformRowIndexForWaveformId(waveformTableUtf, key, true);

                        encodeType = (byte)CriUtfTable.GetUtfFieldForRow(waveformTableUtf, waveformIndex, "EncodeType");

                        rawFileName = String.Format(rawFileFormat,
                                                    Path.GetFileName(this.ExternalAwb.SourceFile), key.ToString("D5"),
                                                    CriAcbFile.GetFileExtensionForEncodeType(encodeType));

                        // extract file
                        ParseFile.ExtractChunkToFile64(externalFs,
                                                       (ulong)this.ExternalAwb.Files[key].FileOffsetByteAligned,
                                                       (ulong)this.ExternalAwb.Files[key].FileLength,
                                                       Path.Combine(extAwbDestinationFolder, rawFileName), false, false);
                    }
                }
                else if (this.ExternalCpk != null)
                {
                    var unextractedExternalFiles = this.ExternalCpk.ItocFiles.Keys.Where(x => !externalIdsExtracted.Contains(x));
                    foreach (ushort key in unextractedExternalFiles)
                    {
                        waveformIndex = GetWaveformRowIndexForWaveformId(waveformTableUtf, key, true);

                        encodeType = (byte)CriUtfTable.GetUtfFieldForRow(waveformTableUtf, waveformIndex, "EncodeType");

                        rawFileName = String.Format(rawFileFormat,
                                                    Path.GetFileName(this.ExternalCpk.SourceFileName), key.ToString("D5"),
                                                    CriAcbFile.GetFileExtensionForEncodeType(encodeType));

                        // extract file
                        ParseFile.ExtractChunkToFile64(externalFs,
                                                       (ulong)this.ExternalCpk.ItocFiles[key].FileOffsetByteAligned,
                                                       (ulong)this.ExternalCpk.ItocFiles[key].FileLength,
                                                       Path.Combine(extCpkDestinationFolder, rawFileName), false, false);
                    }
                }

                if (this.InternalAwb != null)
                {
                    var unextractedInternalFiles = this.InternalAwb.Files.Keys.Where(x => !internalIdsExtracted.Contains(x));
                    foreach (ushort key in unextractedInternalFiles)
                    {
                        waveformIndex = GetWaveformRowIndexForWaveformId(waveformTableUtf, key, false);

                        encodeType = (byte)CriUtfTable.GetUtfFieldForRow(waveformTableUtf, waveformIndex, "EncodeType");

                        rawFileName = String.Format(rawFileFormat,
                                                    Path.GetFileName(this.InternalAwb.SourceFile), key.ToString("D5"),
                                                    CriAcbFile.GetFileExtensionForEncodeType(encodeType));

                        // extract file
                        ParseFile.ExtractChunkToFile64(internalFs,
                                                       (ulong)this.InternalAwb.Files[key].FileOffsetByteAligned,
                                                       (ulong)this.InternalAwb.Files[key].FileLength,
                                                       Path.Combine(acbAwbDestinationFolder, rawFileName), false, false);
                    }
                }
                else if (this.InternalCpk != null)
                {
                    var unextractedInternalFiles = this.InternalCpk.ItocFiles.Keys.Where(x => !internalIdsExtracted.Contains(x));
                    foreach (ushort key in unextractedInternalFiles)
                    {
                        waveformIndex = GetWaveformRowIndexForWaveformId(waveformTableUtf, key, false);

                        encodeType = (byte)CriUtfTable.GetUtfFieldForRow(waveformTableUtf, waveformIndex, "EncodeType");

                        rawFileName = String.Format(rawFileFormat,
                                                    Path.GetFileName(this.InternalCpk.SourceFileName), key.ToString("D5"),
                                                    CriAcbFile.GetFileExtensionForEncodeType(encodeType));

                        // extract file
                        ParseFile.ExtractChunkToFile64(internalFs,
                                                       (ulong)this.InternalCpk.ItocFiles[key].FileOffsetByteAligned,
                                                       (ulong)this.InternalCpk.ItocFiles[key].FileLength,
                                                       Path.Combine(acbCpkDestinationFolder, rawFileName), false, false);
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (internalFs != null)
                {
                    internalFs.Close();
                    internalFs.Dispose();
                }

                if (externalFs != null)
                {
                    externalFs.Close();
                    externalFs.Dispose();
                }
            }
        }