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) { CueNamesToWaveforms = new Dictionary <string, ushort>(); ulong referenceItemsOffset = 0; ulong referenceItemsSize = 0; ulong referenceCorrection = 0; object dummy; byte isStreaming = 0; var cueTableUtf = new CriUtfTable(); cueTableUtf.Initialize(fs, (long)CueTableOffset); var waveformTableUtf = new CriUtfTable(); waveformTableUtf.Initialize(fs, (long)WaveformTableOffset); var synthTableUtf = new CriUtfTable(); synthTableUtf.Initialize(fs, (long)SynthTableOffset); CueList = new CriAcbCueRecord[cueTableUtf.NumberOfRows]; for (var i = 0; i < cueTableUtf.NumberOfRows; i++) { CueList[i] = new CriAcbCueRecord(); CueList[i].IsWaveformIdentified = false; CueList[i].CueId = (uint)GetUtfFieldForRow(cueTableUtf, i, "CueId"); CueList[i].ReferenceType = (byte)GetUtfFieldForRow(cueTableUtf, i, "ReferenceType"); CueList[i].ReferenceIndex = (ushort)GetUtfFieldForRow(cueTableUtf, i, "ReferenceIndex"); switch (CueList[i].ReferenceType) { case 2: referenceItemsOffset = (ulong)GetOffsetForUtfFieldForRow(synthTableUtf, CueList[i].ReferenceIndex, "ReferenceItems"); referenceItemsSize = GetSizeForUtfFieldForRow(synthTableUtf, CueList[i].ReferenceIndex, "ReferenceItems"); referenceCorrection = referenceItemsSize + 2; break; case 3: case 8: if (i == 0) { referenceItemsOffset = (ulong)GetOffsetForUtfFieldForRow(synthTableUtf, 0, "ReferenceItems"); referenceItemsSize = 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.", CueList[i].ReferenceType.ToString("D"), i.ToString("D"))); } if (referenceItemsSize != 0) { // get wave form info CueList[i].WaveformIndex = ParseFile.ReadUshortBE(fs, (long)(referenceItemsOffset + referenceCorrection)); // get Streaming flag, 0 = in ACB files, 1 = in AWB file dummy = GetUtfFieldForRow(waveformTableUtf, CueList[i].WaveformIndex, "Streaming"); if (dummy != null) // check to see if this Id actually exists in the WaveformIndex { isStreaming = (byte)dummy; CueList[i].IsStreaming = isStreaming == 0 ? false : true; // get waveform id and encode type from corresponding waveform var waveformId = GetUtfFieldForRow(waveformTableUtf, CueList[i].WaveformIndex, "Id"); if (waveformId != null) { // early revisions of ACB spec used "Id" CueList[i].WaveformId = (ushort)waveformId; } else { // later versions using "MemoryAwbId" and "StreamingAwbId" if (CueList[i].IsStreaming) { CueList[i].WaveformId = (ushort)GetUtfFieldForRow(waveformTableUtf, CueList[i].WaveformIndex, "StreamAwbId"); } else { CueList[i].WaveformId = (ushort)GetUtfFieldForRow(waveformTableUtf, CueList[i].WaveformIndex, "MemoryAwbId"); } } CueList[i].EncodeType = (byte)GetUtfFieldForRow(waveformTableUtf, CueList[i].WaveformIndex, "EncodeType"); // update flag CueList[i].IsWaveformIdentified = true; } // if (dummy != null) } } }