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 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); }