protected void InitializeCueNameToWaveformMap(FileStream fs, bool includeCueIdInFileName) { ushort cueIndex; string cueName; CriUtfTable cueNameTableUtf = new CriUtfTable(); cueNameTableUtf.Initialize(fs, (long)this.CueNameTableOffset); for (int i = 0; i < cueNameTableUtf.NumberOfRows; i++) { cueIndex = (ushort)CriUtfTable.GetUtfFieldForRow(cueNameTableUtf, i, "CueIndex"); // skip cues with unidentified waveforms (see 'vc05_0140.acb, vc10_0372.acb' in Kidou_Senshi_Gundam_AGE_Universe_Accel (PSP)) if (this.CueList[cueIndex].IsWaveformIdentified) { cueName = (string)CriUtfTable.GetUtfFieldForRow(cueNameTableUtf, i, "CueName"); this.CueList[cueIndex].CueName = cueName; this.CueList[cueIndex].CueName += CriAcbFile.GetFileExtensionForEncodeType(this.CueList[cueIndex].EncodeType); if (includeCueIdInFileName) { this.CueList[cueIndex].CueName = String.Format("{0}_{1}", this.CueList[cueIndex].CueId.ToString("D5"), this.CueList[cueIndex].CueName); } this.CueNamesToWaveforms.Add(this.CueList[cueIndex].CueName, this.CueList[cueIndex].WaveformId); } } }
public static ushort GetWaveformRowIndexForWaveformId(CriUtfTable utfTable, ushort waveformId, bool isStreamed) { ushort ret = ushort.MaxValue; for (int i = 0; i < utfTable.NumberOfRows; i++) { var tempId = CriUtfTable.GetUtfFieldForRow(utfTable, i, "Id"); // newer archives use different labels if (tempId == null) { if (isStreamed) { tempId = CriUtfTable.GetUtfFieldForRow(utfTable, i, "StreamAwbId"); } else { tempId = CriUtfTable.GetUtfFieldForRow(utfTable, i, "MemoryAwbId"); } } if ((ushort)tempId == waveformId) { ret = (ushort)i; } } return(ret); }
// @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); } } }
public static bool IsUtfTable(FileStream fs, long offset, bool useIncomingKeys = false, Dictionary <string, byte> incomingLcgEncryptionKeys = null) { bool ret = false; CriUtfTable utf = new CriUtfTable(); utf.SourceFile = fs.Name; utf.BaseOffset = offset; try { utf.MagicBytes = ParseFile.ParseSimpleOffset(fs, utf.BaseOffset, 4); // check if file is decrypted and get decryption keys if needed utf.checkEncryption(fs, useIncomingKeys, incomingLcgEncryptionKeys); if (utf.IsEncrypted) { // write (decrypted) utf header to file utf.UtfTableFile = utf.WriteTableToTempFile(fs, offset, 4); using (FileStream checkFs = File.Open(utf.UtfTableFile, FileMode.Open, FileAccess.Read, FileShare.Read)) { utf.MagicBytes = ParseFile.ParseSimpleOffset(checkFs, utf.BaseOffset, 4); } //utf.IsEncrypted = false; // since we've decrypted to a temp file // utf.UtfReader.IsEncrypted = false; } if (ParseFile.CompareSegment(utf.MagicBytes, 0, SIGNATURE_BYTES)) { ret = true; } else { ret = false; } } catch (Exception ex) { throw ex; } finally { if (!String.IsNullOrEmpty(utf.UtfTableFile)) { File.Delete(utf.UtfTableFile); } } return(ret); }
public static CriUtfTable InitializeToc(FileStream fs, CriUtfTable cpkUtf, string tocIdentifierString) { CriUtfTable toc = null; if (cpkUtf.Rows[0].ContainsKey(tocIdentifierString) && cpkUtf.Rows[0][tocIdentifierString].Value != null) { toc = new CriUtfTable(); toc.Initialize(fs, (long)((ulong)cpkUtf.BaseOffset + (ulong)cpkUtf.Rows[0][tocIdentifierString].Value)); } return(toc); }
public static ulong GetSizeForUtfFieldForRow(CriUtfTable utfTable, int rowIndex, string key) { ulong ret = 0; if (utfTable.Rows.GetLength(0) > rowIndex) { if (utfTable.Rows[rowIndex].ContainsKey(key)) { ret = utfTable.Rows[rowIndex][key].Size; } } return(ret); }
public static object GetUtfFieldForRow(CriUtfTable utfTable, int rowIndex, string key) { object ret = null; if (utfTable.Rows.GetLength(0) > rowIndex) { if (utfTable.Rows[rowIndex].ContainsKey(key)) { ret = utfTable.Rows[rowIndex][key].Value; } } return(ret); }
public static CriUtfTocFileInfo GetUtfItocFileInfo(CriUtfTable dataUtf, int rowIndex) { CriUtfTocFileInfo fileInfo = new CriUtfTocFileInfo(); object temp; temp = CriUtfTable.GetUtfFieldForRow(dataUtf, rowIndex, "ID"); fileInfo.FileName = temp != null ? ((ushort)temp).ToString("D5") : null; temp = CriUtfTable.GetUtfFieldForRow(dataUtf, rowIndex, "FileSize"); fileInfo.FileSize = temp != null?Convert.ToUInt32(temp) : uint.MaxValue; temp = CriUtfTable.GetUtfFieldForRow(dataUtf, rowIndex, "ExtractSize"); fileInfo.ExtractSize = temp != null?Convert.ToUInt32(temp) : uint.MaxValue; return(fileInfo); }
public static CriCpkDirectory GetGtocDirectory(CriUtfTable dataUtf, int rowIndex, string sourceFile, string parentDirectory) { CriCpkDirectory gtocDirectory; object temp; temp = CriUtfTable.GetUtfFieldForRow(dataUtf, rowIndex, "Gname"); gtocDirectory = new CriCpkDirectory(sourceFile, (string)temp, parentDirectory); temp = CriUtfTable.GetUtfFieldForRow(dataUtf, rowIndex, "Child"); if ((short)temp != -1) { // add files } return(gtocDirectory); }
public static CriUtfTocFileInfo GetUtfTocFileInfo(CriUtfTable tocUtf, int rowIndex) { CriUtfTocFileInfo fileInfo = new CriUtfTocFileInfo(); object temp; temp = CriUtfTable.GetUtfFieldForRow(tocUtf, rowIndex, "DirName"); fileInfo.DirName = temp != null ? (string)temp : null; fileInfo.DirName = fileInfo.DirName.Equals(CriCpkArchive.NULL_FILENAME) ? String.Empty : fileInfo.DirName; temp = CriUtfTable.GetUtfFieldForRow(tocUtf, rowIndex, "FileName"); fileInfo.FileName = temp != null ? (string)temp : null; fileInfo.FileName = fileInfo.FileName.Equals(CriCpkArchive.NULL_FILENAME) ? String.Format("{0}.bin", rowIndex.ToString("D5")) : fileInfo.FileName; temp = CriUtfTable.GetUtfFieldForRow(tocUtf, rowIndex, "FileOffset"); fileInfo.FileOffset = temp != null ? (ulong)temp : ulong.MaxValue; temp = CriUtfTable.GetUtfFieldForRow(tocUtf, rowIndex, "FileSize"); fileInfo.FileSize = temp != null ? (uint)temp : uint.MaxValue; temp = CriUtfTable.GetUtfFieldForRow(tocUtf, rowIndex, "ExtractSize"); fileInfo.ExtractSize = temp != null ? (uint)temp : uint.MaxValue; return(fileInfo); }
public void Initialize(FileStream fs, long offset, bool isRawDump) { FormatDescription = FORMAT_DESCRIPTION_STRING; VolumeBaseOffset = offset; IsRawDump = isRawDump; VolumeType = VolumeDataType.Data; DirectoryStructureArray = new ArrayList(); SourceFileName = fs.Name; var cpkUtf = new CriUtfTable(); cpkUtf.Initialize(fs, VolumeBaseOffset + 0x10); VolumeIdentifier = cpkUtf.TableName; ItocFiles = new Dictionary <ushort, CriAfs2File>(); TocUtf = InitializeToc(fs, cpkUtf, "TocOffset"); // this.EtocUtf = InitializeToc(fs, cpkUtf, "EtocOffset"); ItocUtf = InitializeToc(fs, cpkUtf, "ItocOffset"); // this.GtocUtf = InitializeToc(fs, cpkUtf, "GtocOffset"); var dummy = new CriCpkDirectory(SourceFileName, string.Empty, string.Empty); if (TocUtf != null) { var tocDir = GetDirectoryForToc(fs, cpkUtf, "TOC", VolumeBaseOffset); if (tocDir.FileArray.Count > 0 || tocDir.SubDirectoryArray.Count > 0) { dummy.SubDirectoryArray.Add(tocDir); } } /* * if (etocUtf != null) * { * CriCpkDirectory etocDir = this.GetDirectoryForToc(fs, cpkUtf, etocUtf, "ETOC"); * * if ((etocDir.FileArray.Count > 0) || (etocDir.SubDirectoryArray.Count > 0)) * { * dummy.SubDirectoryArray.Add(etocDir); * } * } */ if (ItocUtf != null) { var itocDir = GetDirectoryForItoc(fs, cpkUtf, "ITOC", VolumeBaseOffset); if (itocDir.FileArray.Count > 0 || itocDir.SubDirectoryArray.Count > 0) { dummy.SubDirectoryArray.Add(itocDir); } } //if (this.GtocUtf != null) //{ // CriCpkDirectory gtocDir = this.GetDirectoryForGtoc(fs, cpkUtf, "GTOC"); // if ((gtocDir.FileArray.Count > 0) || (gtocDir.SubDirectoryArray.Count > 0)) // { // dummy.SubDirectoryArray.Add(gtocDir); // } //} DirectoryStructureArray.Add(dummy); }
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(); } } }
protected void InitializeCueList(FileStream fs) { this.CueNamesToWaveforms = new Dictionary <string, ushort>(); ulong referenceItemsOffset = 0; ulong referenceItemsSize = 0; ulong referenceCorrection = 0; object dummy; byte isStreaming = 0; CriUtfTable cueTableUtf = new CriUtfTable(); cueTableUtf.Initialize(fs, (long)this.CueTableOffset); CriUtfTable waveformTableUtf = new CriUtfTable(); waveformTableUtf.Initialize(fs, (long)this.WaveformTableOffset); CriUtfTable synthTableUtf = new CriUtfTable(); synthTableUtf.Initialize(fs, (long)this.SynthTableOffset); this.CueList = new CriAcbCueRecord[cueTableUtf.NumberOfRows]; for (int i = 0; i < cueTableUtf.NumberOfRows; i++) { this.CueList[i] = new CriAcbCueRecord(); this.CueList[i].IsWaveformIdentified = false; this.CueList[i].CueId = (uint)CriUtfTable.GetUtfFieldForRow(cueTableUtf, i, "CueId"); this.CueList[i].ReferenceType = (byte)CriUtfTable.GetUtfFieldForRow(cueTableUtf, i, "ReferenceType"); this.CueList[i].ReferenceIndex = (ushort)CriUtfTable.GetUtfFieldForRow(cueTableUtf, i, "ReferenceIndex"); switch (this.CueList[i].ReferenceType) { case 2: referenceItemsOffset = (ulong)CriUtfTable.GetOffsetForUtfFieldForRow(synthTableUtf, this.CueList[i].ReferenceIndex, "ReferenceItems"); referenceItemsSize = CriUtfTable.GetSizeForUtfFieldForRow(synthTableUtf, this.CueList[i].ReferenceIndex, "ReferenceItems"); referenceCorrection = referenceItemsSize + 2; break; case 3: case 8: if (i == 0) { referenceItemsOffset = (ulong)CriUtfTable.GetOffsetForUtfFieldForRow(synthTableUtf, 0, "ReferenceItems"); referenceItemsSize = CriUtfTable.GetSizeForUtfFieldForRow(synthTableUtf, 0, "ReferenceItems"); referenceCorrection = referenceItemsSize - 2; // samples found have only had a '01 00' record => Always Waveform[0]?. } else { referenceCorrection += 4; // relative to previous offset, do not lookup // @TODO: Should this do a referenceItemsSize - 2 for the ReferenceIndex? Need to find // one where size > 4. //referenceItemsOffset = (ulong)CriUtfTable.GetOffsetForUtfFieldForRow(synthTableUtf, this.CueList[i].ReferenceIndex, "ReferenceItems"); //referenceItemsSize = CriUtfTable.GetSizeForUtfFieldForRow(synthTableUtf, this.CueList[i].ReferenceIndex, "ReferenceItems"); //referenceCorrection = referenceItemsSize - 2; } break; default: throw new FormatException(String.Format(" Unexpected ReferenceType: '{0}' for CueIndex: '{1}.' Please report to VGMToolbox thread at hcs64.com forums, see link in 'Other' menu item.", this.CueList[i].ReferenceType.ToString("D"), i.ToString("D"))); } if (referenceItemsSize != 0) { // get wave form info this.CueList[i].WaveformIndex = ParseFile.ReadUshortBE(fs, (long)(referenceItemsOffset + referenceCorrection)); // get Streaming flag, 0 = in ACB files, 1 = in AWB file dummy = CriUtfTable.GetUtfFieldForRow(waveformTableUtf, this.CueList[i].WaveformIndex, "Streaming"); if (dummy != null) // check to see if this Id actually exists in the WaveformIndex { isStreaming = (byte)dummy; this.CueList[i].IsStreaming = isStreaming == 0 ? false : true; // get waveform id and encode type from corresponding waveform var waveformId = CriUtfTable.GetUtfFieldForRow(waveformTableUtf, this.CueList[i].WaveformIndex, "Id"); if (waveformId != null) { // early revisions of ACB spec used "Id" this.CueList[i].WaveformId = (ushort)waveformId; } else { // later versions using "MemoryAwbId" and "StreamingAwbId" if (this.CueList[i].IsStreaming) { this.CueList[i].WaveformId = (ushort)CriUtfTable.GetUtfFieldForRow(waveformTableUtf, this.CueList[i].WaveformIndex, "StreamAwbId"); } else { this.CueList[i].WaveformId = (ushort)CriUtfTable.GetUtfFieldForRow(waveformTableUtf, this.CueList[i].WaveformIndex, "MemoryAwbId"); } } this.CueList[i].EncodeType = (byte)CriUtfTable.GetUtfFieldForRow(waveformTableUtf, this.CueList[i].WaveformIndex, "EncodeType"); // update flag this.CueList[i].IsWaveformIdentified = true; } // if (dummy != null) } } }
public string GetStringValue(int currentIdent, FileStream utfStream = null, bool useIncomingKeys = false, Dictionary <string, byte> lcgEncryptionKeys = null) { ulong numericValue; long signedNumericValue; byte maskedType = (byte)(this.Type & CriUtfTable.COLUMN_TYPE_MASK); string stringValue = String.Empty; string frontPad = new string(' ', currentIdent); string formattedString; switch (maskedType) { case CriUtfTable.COLUMN_TYPE_DATA: if (utfStream == null) { stringValue = this.Value.ToString(); } else if (CriUtfTable.IsUtfTable(utfStream, (long)this.Offset, useIncomingKeys, lcgEncryptionKeys)) { CriUtfTable newUtf = new CriUtfTable(); newUtf.Initialize(utfStream, (long)this.Offset); stringValue = newUtf.GetTableAsString((currentIdent + 4), true); } else { stringValue = FileUtil.GetStringFromFileChunk(utfStream, this.Offset, this.Size); if (stringValue.Length > 0x20) { formattedString = Regex.Replace(stringValue, ".{8}(?!$)", "$0 "); stringValue = Environment.NewLine + formattedString; } } break; case CriUtfTable.COLUMN_TYPE_STRING: stringValue = (string)this.Value; break; case CriUtfTable.COLUMN_TYPE_FLOAT: stringValue = Convert.ToSingle(this.Value).ToString(); break; case CriUtfTable.COLUMN_TYPE_8BYTE: case CriUtfTable.COLUMN_TYPE_4BYTE: case CriUtfTable.COLUMN_TYPE_2BYTE: case CriUtfTable.COLUMN_TYPE_1BYTE: numericValue = Convert.ToUInt64(this.Value); stringValue = String.Format("0x{0} ({1})", numericValue.ToString("X8"), numericValue.ToString()); break; case CriUtfTable.COLUMN_TYPE_4BYTE2: case CriUtfTable.COLUMN_TYPE_2BYTE2: case CriUtfTable.COLUMN_TYPE_1BYTE2: signedNumericValue = Convert.ToInt64(this.Value); stringValue = String.Format("0x{0} ({1})", signedNumericValue.ToString("X8"), signedNumericValue.ToString()); break; } return(stringValue); }
public void Initialize(FileStream fs, long offset, bool isRawDump) { this.FormatDescription = CriCpkArchive.FORMAT_DESCRIPTION_STRING; this.VolumeBaseOffset = offset; this.IsRawDump = isRawDump; this.VolumeType = VolumeDataType.Data; this.DirectoryStructureArray = new ArrayList(); this.SourceFileName = fs.Name; CriUtfTable cpkUtf = new CriUtfTable(); cpkUtf.Initialize(fs, this.VolumeBaseOffset + 0x10); this.VolumeIdentifier = cpkUtf.TableName; this.ItocFiles = new Dictionary <ushort, CriAfs2File>(); this.TocUtf = InitializeToc(fs, cpkUtf, "TocOffset"); // this.EtocUtf = InitializeToc(fs, cpkUtf, "EtocOffset"); this.ItocUtf = InitializeToc(fs, cpkUtf, "ItocOffset"); // this.GtocUtf = InitializeToc(fs, cpkUtf, "GtocOffset"); CriCpkDirectory dummy = new CriCpkDirectory(this.SourceFileName, String.Empty, String.Empty); if (this.TocUtf != null) { CriCpkDirectory tocDir = this.GetDirectoryForToc(fs, cpkUtf, "TOC", this.VolumeBaseOffset); if ((tocDir.FileArray.Count > 0) || (tocDir.SubDirectoryArray.Count > 0)) { dummy.SubDirectoryArray.Add(tocDir); } } /* * if (etocUtf != null) * { * CriCpkDirectory etocDir = this.GetDirectoryForToc(fs, cpkUtf, etocUtf, "ETOC"); * * if ((etocDir.FileArray.Count > 0) || (etocDir.SubDirectoryArray.Count > 0)) * { * dummy.SubDirectoryArray.Add(etocDir); * } * } */ if (this.ItocUtf != null) { CriCpkDirectory itocDir = this.GetDirectoryForItoc(fs, cpkUtf, "ITOC", this.VolumeBaseOffset); if ((itocDir.FileArray.Count > 0) || (itocDir.SubDirectoryArray.Count > 0)) { dummy.SubDirectoryArray.Add(itocDir); } } //if (this.GtocUtf != null) //{ // CriCpkDirectory gtocDir = this.GetDirectoryForGtoc(fs, cpkUtf, "GTOC"); // if ((gtocDir.FileArray.Count > 0) || (gtocDir.SubDirectoryArray.Count > 0)) // { // dummy.SubDirectoryArray.Add(gtocDir); // } //} this.DirectoryStructureArray.Add(dummy); }
public CriCpkDirectory GetDirectoryForItoc(FileStream fs, CriUtfTable cpkUtf, string BaseDirectoryName, long volumeBaseOffset) { ulong currentOffset = 0; CriUtfTocFileInfo fileInfo = new CriUtfTocFileInfo(); CriAfs2File afs2File = new CriAfs2File(); // get content offset and align ulong contentOffset = (ulong)CriUtfTable.GetUtfFieldForRow(cpkUtf, 0, "ContentOffset"); ushort align = (ushort)CriUtfTable.GetUtfFieldForRow(cpkUtf, 0, "Align"); // build direcory path CriCpkDirectory baseDirectory = new CriCpkDirectory(this.SourceFileName, BaseDirectoryName, String.Empty); CriCpkFile tempFile; // read file groups uint filesH = 0; uint filesL = 0; object filesHObj = CriUtfTable.GetUtfFieldForRow(this.ItocUtf, 0, "FilesH"); //count of files in DataH object filesLObj = CriUtfTable.GetUtfFieldForRow(this.ItocUtf, 0, "FilesL"); // count of files in DataL if (filesHObj != null) { filesH = (uint)filesHObj; } if (filesHObj != null) { filesL = (uint)filesLObj; } if ((filesH > 0) || (filesL > 0)) { Dictionary <string, CriUtfTocFileInfo> fileList = new Dictionary <string, CriUtfTocFileInfo>(); if (filesH > 0) { // read DataH group CriUtfTable dataH = new CriUtfTable(); dataH.Initialize(fs, (long)CriUtfTable.GetOffsetForUtfFieldForRow(this.ItocUtf, 0, "DataH")); for (int i = 0; i < dataH.Rows.GetLength(0); i++) { fileInfo = GetUtfItocFileInfo(dataH, i); fileList.Add(fileInfo.FileName, fileInfo); } } if (filesL > 0) { // read DataL group CriUtfTable dataL = new CriUtfTable(); dataL.Initialize(fs, (long)CriUtfTable.GetOffsetForUtfFieldForRow(this.ItocUtf, 0, "DataL")); for (int i = 0; i < dataL.Rows.GetLength(0); i++) { fileInfo = GetUtfItocFileInfo(dataL, i); fileList.Add(fileInfo.FileName, fileInfo); } } // initialize current offset currentOffset = contentOffset; // populate offsets for files var keys = fileList.Keys.ToList(); keys.Sort(); foreach (string key in keys) { // afs2 file for ACB extraction afs2File = new CriAfs2File(); afs2File.CueId = Convert.ToUInt16(fileList[key].FileName); // ??? @TODO maybe key is enough? need to check. afs2File.FileOffsetRaw = volumeBaseOffset + (long)currentOffset; // align offset if (currentOffset % align != 0) { currentOffset = MathUtil.RoundUpToByteAlignment(currentOffset, align); } // update file info fileList[key].FileOffset = (ulong)volumeBaseOffset + currentOffset; fileList[key].FileName += ".bin"; // afs2 file for ACB extraction afs2File.FileOffsetByteAligned = (long)fileList[key].FileOffset; afs2File.FileLength = fileList[key].FileSize; // increment current offset currentOffset += fileList[key].FileSize; // create file and add to base directory tempFile = new CriCpkFile(BaseDirectoryName, this.SourceFileName, fileList[key].FileName, (long)fileList[key].FileOffset, this.VolumeBaseOffset, (long)fileList[key].FileOffset, fileList[key].FileSize, fileList[key].ExtractSize); baseDirectory.FileArray.Add(tempFile); // add afs2 file to ItocFiles for ACB extraction this.ItocFiles.Add(afs2File.CueId, afs2File); } // foreach (string key in keys) } // if ((filesH > 0) || (filesL > 0)) return(baseDirectory); }
public CriCpkDirectory GetDirectoryForToc(FileStream fs, CriUtfTable cpkUtf, string BaseDirectoryName, long volumeBaseOffset) { CriUtfTocFileInfo fileInfo = new CriUtfTocFileInfo(); long trueTocBaseOffset; ulong contentOffset = (ulong)CriUtfTable.GetUtfFieldForRow(cpkUtf, 0, "ContentOffset"); ushort align = (ushort)CriUtfTable.GetUtfFieldForRow(cpkUtf, 0, "Align"); char[] separators = new char[] { '/', '\\' }; ArrayList allDirectories = new ArrayList(); CriCpkDirectory baseDirectory = new CriCpkDirectory(this.SourceFileName, BaseDirectoryName, String.Empty); CriCpkDirectory newDirectory; CriCpkDirectory currentDirectory; int indexOfNewDirectory; CriCpkFile tempFile; Dictionary <string, ArrayList> fileListDictionary = new Dictionary <string, ArrayList>(); string parentName; // loop over files to get unique dirs for (int i = 0; i < this.TocUtf.Rows.GetLength(0); i++) { fileInfo = GetUtfTocFileInfo(this.TocUtf, i); if (fileInfo.FileName != null) { //--------------- // get directory //--------------- if (!fileListDictionary.ContainsKey(fileInfo.DirName)) { fileListDictionary.Add(fileInfo.DirName, new ArrayList()); } //-------------- // create file //-------------- // set true base offset, since UTF header starts at 0x10 of a container type trueTocBaseOffset = this.TocUtf.BaseOffset - 0x10; // get absolute offset if (contentOffset < (ulong)trueTocBaseOffset) { fileInfo.FileOffset += contentOffset; } else { fileInfo.FileOffset += (ulong)trueTocBaseOffset; } if (fileInfo.FileOffset % align != 0) { fileInfo.FileOffset = MathUtil.RoundUpToByteAlignment(fileInfo.FileOffset, align); } parentName = BaseDirectoryName + Path.DirectorySeparatorChar + fileInfo.DirName; parentName = parentName.Replace('/', Path.DirectorySeparatorChar); tempFile = new CriCpkFile(parentName, this.SourceFileName, fileInfo.FileName, (long)fileInfo.FileOffset, this.VolumeBaseOffset, (long)fileInfo.FileOffset, fileInfo.FileSize, fileInfo.ExtractSize); // add to Dictionary fileListDictionary[fileInfo.DirName].Add(tempFile); } } foreach (var path in fileListDictionary.Keys) { currentDirectory = baseDirectory; var pathItems = path.Split(separators); parentName = BaseDirectoryName; for (int i = 0; i < pathItems.Count(); i++) { var item = pathItems[i]; var tmp = currentDirectory.SubDirectoryArray.Cast <CriCpkDirectory>().Where(x => x.DirectoryName.Equals(item)); if (tmp.Count() > 0) { currentDirectory = tmp.Single(); } else { newDirectory = new CriCpkDirectory(this.SourceFileName, item, parentName); indexOfNewDirectory = currentDirectory.SubDirectoryArray.Add(newDirectory); currentDirectory = (CriCpkDirectory)currentDirectory.SubDirectoryArray[indexOfNewDirectory]; } if (i == pathItems.GetUpperBound(0)) { foreach (CriCpkFile f in fileListDictionary[path]) { currentDirectory.FileArray.Add(f); } } parentName += Path.DirectorySeparatorChar + item; } } return(baseDirectory); }