public SFOData Build() { SFOData sfo = new SFOData(); sfo.Magic = 0x46535000; // _PSF sfo.Version = 0x00000101; sfo.Entries = new List <SFODir>(); var headerSize = 20; var indexTableSize = entries.Count * 16; var keyTableSize = entries.Sum(x => x.Key.Length + 1); if (keyTableSize % 4 != 0) { sfo.Padding = (uint)(4 - keyTableSize % 4); } sfo.KeyTableOffset = (uint)(headerSize + indexTableSize); sfo.DataTableOffset = sfo.KeyTableOffset + (uint)keyTableSize + sfo.Padding; ushort keyOffset = 0; uint dataOffset = 0; for (var i = 0; i < entries.Count; i++) { var entry = entries[i]; var entryLength = GetEntryLength(entry.Key, entry.Value); var maxLength = GetMaxLength(entry.Key); if (entryLength > maxLength) { throw new Exception("Value for {entry.Key} exceeds maximum allowed length"); } sfo.Entries.Add(new SFODir() { KeyOffset = keyOffset, Format = GetEntryType(entry.Key), Length = entryLength, MaxLength = maxLength, DataOffset = dataOffset, Key = entry.Key, Value = entry.Value, }); dataOffset += maxLength; keyOffset += (ushort)(entries[i].Key.Length + 1); } sfo.Size = sfo.DataTableOffset + dataOffset; return(sfo); }
/// <summary> /// /// </summary> /// <param name="sfo"></param> /// <returns></returns> private uint[] BuildHeader(SFOData sfo) { // point to the end of the header uint currentOffset = 0x28; uint[] header = new uint[0x28 / 4]; header[0] = PBPMAGIC; // Header: PBP<null> header[1] = 0x10000; header[2] = currentOffset; // Start of SFO currentOffset += sfo.Size; header[3] = currentOffset; // Start of ICON0 currentOffset += convertInfo.Icon0.Size; header[4] = currentOffset; // Start of ICON1 currentOffset += convertInfo.Icon1.Size; header[5] = currentOffset; // Start of PIC0 currentOffset += convertInfo.Pic0.Size; header[6] = currentOffset; // Start of PIC1 currentOffset += convertInfo.Pic1.Size; header[7] = currentOffset; // Start of SND0 currentOffset += convertInfo.Snd0.Size; header[8] = currentOffset; // Start of DATA.PSP var psarOffset = header[8] + convertInfo.DataPsp.Size; if ((psarOffset % 0x10000) != 0) { psarOffset = psarOffset + (0x10000 - (psarOffset % 0x10000)); } header[9] = psarOffset; // Start of DATA.PSAR return(header); }