private bool LoadFile(DuplicatableStream headerStream, DuplicatableStream contentStream) { DuplicatableStream infile = headerStream.Duplicate(); contentFile = contentStream.Duplicate(); infile.Seek(0x00, SeekOrigin.Begin); string magic = infile.ReadAscii(4); if (magic != "FPS4") { Console.WriteLine("Not an FPS4 file!"); return(false); } Endian = Util.Endianness.BigEndian; FileCount = infile.ReadUInt32().FromEndian(Endian); HeaderSize = infile.ReadUInt32().FromEndian(Endian); // if header seems huge then we probably have assumed the wrong endianness if (HeaderSize > 0xFFFF) { Endian = Util.Endianness.LittleEndian; FileCount = FileCount.ToEndian(Util.Endianness.BigEndian).FromEndian(Endian); HeaderSize = HeaderSize.ToEndian(Util.Endianness.BigEndian).FromEndian(Endian); } FirstFileStart = infile.ReadUInt32().FromEndian(Endian); EntrySize = infile.ReadUInt16().FromEndian(Endian); ContentBitmask = new ContentInfo(infile.ReadUInt16().FromEndian(Endian)); Unknown2 = infile.ReadUInt32().FromEndian(Endian); ArchiveNameLocation = infile.ReadUInt32().FromEndian(Endian); infile.Position = ArchiveNameLocation; if (ArchiveNameLocation > 0) { ArchiveName = infile.ReadShiftJisNullterm(); } Alignment = FirstFileStart; Console.WriteLine("Content Bitmask: 0x" + ContentBitmask.Value.ToString("X4")); if (ContentBitmask.HasUnknownDataTypes) { Console.WriteLine("WARNING: Bitmask identifies unknown data types, data interpretation will probably be incorrect."); } Files = new List <FileInfo>((int)FileCount); for (uint i = 0; i < FileCount; ++i) { infile.Position = HeaderSize + (i * EntrySize); Files.Add(new FileInfo(infile, i, ContentBitmask, Endian, Util.GameTextEncoding.ASCII)); } FileLocationMultiplier = CalculateFileLocationMultiplier(); ShouldGuessFilesizeFromNextFile = !ContentBitmask.ContainsFileSizes && !ContentBitmask.ContainsSectorSizes && CalculateIsLinear(); infile.Dispose(); return(true); }
public void PrintData(EndianUtils.Endianness endian, Dictionary <uint, TSS.TSSEntry> inGameDic, List <ItemDat.ItemDatSingle> itemDataSorted, T8BTEMST.T8BTEMST enemies) { using (DuplicatableStream stream = Stream.Duplicate()) { stream.ReadUInt32().FromEndian(endian); // ? stream.ReadUInt32().FromEndian(endian); // ? stream.ReadUInt32Array(9, endian); stream.ReadUInt32().FromEndian(endian); // play time in frames, assuming 60 frames = 1 second stream.ReadUInt32().FromEndian(endian); // gald stream.DiscardBytes(4); // ? uint[] itemCounts = stream.ReadUInt32Array(3072, endian); uint[] itemBookBitfields = stream.ReadUInt32Array(3072 / 32, endian); stream.DiscardBytes(4); // ? stream.ReadUInt32Array(4, endian); // control modes for the four active party slots stream.ReadUInt32Array(3, endian); // strategies assigned to dpad directions stream.DiscardBytes(0x40); // ?? for (int i = 0; i < 8; ++i) { // custom strategy names // game seems to read these till null byte so this could totally be abused to buffer overflow... stream.ReadAscii(0x40); } stream.DiscardBytes(0xA84D0 - 0xA7360); // ? uint[] monsterBookBitfieldsScanned = stream.ReadUInt32Array(0x48 / 4, endian); stream.DiscardBytes(0xA8680 - 0xA8518); // ? uint[] monsterBookBitfieldsSeen = stream.ReadUInt32Array(0x48 / 4, endian); stream.DiscardBytes(0xA8928 - 0xA86C8); // ? uint collectorsBookIndex = 0; foreach (var item in itemDataSorted) { uint i = item.Data[(int)ItemDat.ItemData.ID]; if (item.Data[(int)ItemDat.ItemData.InCollectorsBook] > 0) { bool haveItem = ((itemBookBitfields[i / 32] >> (int)(i % 32)) & 1) > 0; Console.WriteLine((haveItem ? "Y" : "N") + (collectorsBookIndex) + ": " + inGameDic[item.NamePointer].StringEngOrJpn); ++collectorsBookIndex; } } uint monsterBookIndex = 0; foreach (var enemy in enemies.EnemyList) { uint i = enemy.InGameID; if (enemy.InMonsterBook > 0) { bool haveSeen = ((monsterBookBitfieldsSeen[i / 32] >> (int)(i % 32)) & 1) > 0; bool haveScanned = ((monsterBookBitfieldsScanned[i / 32] >> (int)(i % 32)) & 1) > 0; Console.WriteLine((haveSeen ? "Y" : "N") + (haveScanned ? "Y" : "N") + (monsterBookIndex) + ": " + inGameDic[enemy.NameStringDicID].StringEngOrJpn); ++monsterBookIndex; } } } }
public ScenarioDatEntry(DuplicatableStream data, uint FilesOffset) { Offset = data.ReadUInt32().SwapEndian(); FilesizeCompressed = data.ReadUInt32().SwapEndian(); FilesizeUncompressed = data.ReadUInt32().SwapEndian(); if (FilesizeCompressed > 0) { DataStream = new PartialStream(data, Offset + FilesOffset, FilesizeCompressed); } else { DataStream = null; } }
public SHBP(DuplicatableStream duplicatableStream, EndianUtils.Endianness e = EndianUtils.Endianness.BigEndian) { using (DuplicatableStream s = duplicatableStream.Duplicate()) { uint magic = s.ReadUInt32(EndianUtils.Endianness.LittleEndian); if (magic != 0x50424853) { throw new Exception("wrong magic"); } uint count = s.ReadUInt32(e); Hashes = new List <uint>((int)count); for (uint i = 0; i < count; ++i) { Hashes.Add(s.ReadUInt32(e)); } } }
public TrophyTrpFile(DuplicatableStream stream, EndianUtils.Endianness endian) { Filename = stream.ReadAscii(0x20).TrimNull(); Unknown1 = stream.ReadUInt32().FromEndian(endian); Start = stream.ReadUInt32().FromEndian(endian); Unknown3 = stream.ReadUInt32().FromEndian(endian); Length = stream.ReadUInt32().FromEndian(endian); Unknown5 = stream.ReadUInt32().FromEndian(endian); Unknown6 = stream.ReadUInt32().FromEndian(endian); Unknown7 = stream.ReadUInt32().FromEndian(endian); Unknown8 = stream.ReadUInt32().FromEndian(endian); }
private bool LoadFile(DuplicatableStream inputStream, EndianUtils.Endianness?endianParam, TextUtils.GameTextEncoding encoding) { DuplicatableStream stream = inputStream.Duplicate(); stream.Position = 0; EndianUtils.Endianness endian; if (endianParam == null) { uint magic = stream.ReadUInt32().FromEndian(EndianUtils.Endianness.BigEndian); if (magic == 0x53453320) { endian = EndianUtils.Endianness.BigEndian; } else if (magic == 0x20334553) { endian = EndianUtils.Endianness.LittleEndian; } else { Console.WriteLine("Invalid magic: " + magic); return(false); } } else { endian = endianParam.Value; uint magic = stream.ReadUInt32(endian); if (magic != 0x53453320) { Console.WriteLine("Invalid magic: " + magic); return(false); } } this.Endian = endian; uint lengthOfFilenameSection = stream.ReadUInt32(endian); // probably? uint startOfFilenameSection = stream.ReadUInt32(endian); // probably? DataBegin = stream.ReadUInt32(endian); stream.Position = startOfFilenameSection; uint magicOfFilenameSection = stream.ReadUInt32(endian); FileCount = stream.ReadUInt32(endian); Filenames = new List <string>((int)FileCount); for (uint i = 0; i < FileCount; ++i) { Filenames.Add(stream.ReadSizedString(48, encoding).TrimNull()); } Data = stream; return(true); }
public EndianUtils.Endianness Endian; // not actually a field in the header, at least not here -- might be the first byte? public NubHeader(DuplicatableStream stream, EndianUtils.Endianness?endian) { Magic = stream.ReadUInt64(EndianUtils.Endianness.LittleEndian); EndianUtils.Endianness suspectedEndian; if (Magic == 0x10200) { suspectedEndian = EndianUtils.Endianness.BigEndian; } else if (Magic == 0x10201) { suspectedEndian = EndianUtils.Endianness.LittleEndian; } else { throw new Exception("unexpected magic in NUB"); } EndianUtils.Endianness e = endian ?? suspectedEndian; Fileid = stream.ReadUInt32(e); // or something like that? seems unique per archive in each game EntryCount = stream.ReadUInt32(e); StartOfFiles = stream.ReadUInt32(e); FilesSize = stream.ReadUInt32(e); StartOfEntries = stream.ReadUInt32(e); StartOfHeaders = stream.ReadUInt32(e); Endian = e; }
public iPck(DuplicatableStream duplicatableStream, EndianUtils.Endianness e = EndianUtils.Endianness.BigEndian) { using (DuplicatableStream s = duplicatableStream.Duplicate()) { uint magic = s.ReadUInt32(EndianUtils.Endianness.LittleEndian); if (magic != 0x6b635069) { throw new Exception("wrong magic"); } uint count = s.ReadUInt32(e); uint offsetsStart = s.ReadUInt32(e); uint dataStart = s.ReadUInt32(e); s.Position = offsetsStart; uint[] offsets = s.ReadUInt32Array(count, e); s.Position = dataStart; long dataEnd = s.Length - dataStart; Data = new List <byte[]>((int)count); for (uint i = 0; i < count; ++i) { long start = offsets[i]; if (start == 0xffffffffu) { Data.Add(null); } else { long end = FindFileEnd(offsets, i, dataEnd); long len = end - start; s.Position = dataStart + start; Data.Add(s.ReadUInt8Array(len)); } } } }
public SPKD(DuplicatableStream duplicatableStream, EndianUtils.Endianness e = EndianUtils.Endianness.BigEndian) { Stream = duplicatableStream.Duplicate(); Stream.Position = 4; uint fileCount = Stream.ReadUInt32(e); Stream.Position = 12; uint dataStart = Stream.ReadUInt32(e); Files = new List <SpkdFileData>((int)fileCount); Stream.Position = dataStart; for (uint i = 0; i < fileCount; ++i) { var f = new SpkdFileData(); f.Name = Stream.ReadAscii(16).TrimNull(); f.Unknown = Stream.ReadUInt32(e); f.FileStart0 = Stream.ReadUInt32(e); f.FileStart1 = Stream.ReadUInt32(e); f.FileStart2 = Stream.ReadUInt32(e); Files.Add(f); } LastFileEnd = (uint)Stream.Length; }
public Dol(DuplicatableStream stream) { Stream = stream.Duplicate(); Stream.Position = 0; FileOffsets = new List <uint>(18); LoadingAddress = new List <uint>(18); SectionSizes = new List <uint>(18); for (int i = 0; i < 18; ++i) { FileOffsets.Add(Stream.ReadUInt32().FromEndian(EndianUtils.Endianness.BigEndian)); } for (int i = 0; i < 18; ++i) { LoadingAddress.Add(Stream.ReadUInt32().FromEndian(EndianUtils.Endianness.BigEndian)); } for (int i = 0; i < 18; ++i) { SectionSizes.Add(Stream.ReadUInt32().FromEndian(EndianUtils.Endianness.BigEndian)); } BssAddress = Stream.ReadUInt32().FromEndian(EndianUtils.Endianness.BigEndian); BssSize = Stream.ReadUInt32().FromEndian(EndianUtils.Endianness.BigEndian); EntryPoint = Stream.ReadUInt32().FromEndian(EndianUtils.Endianness.BigEndian); }
// initialize from existing CPK public CpkBuilder(DuplicatableStream stream, Endianness endian = Endianness.BigEndian) { // should start with CPK and some unknown header bytes long cpkHeaderOffset = stream.Position; uint cpkMagic = stream.ReadUInt32(Endianness.LittleEndian); if (cpkMagic != 0x204B5043) { throw new Exception("wrong CPK magic"); } UnknownCpkHeaderBytes = stream.ReadBytes(12); // main UTF table should follow MainUtfTable = new UtfBuilder(stream, endian); if (MainUtfTable.Rows.Count != 1) { throw new Exception("wrong rowcount in main UTF table"); } UnknownPostCpkHeaderBytes = stream.ReadBytes(4); while (stream.ReadByte() == 0) { ; } stream.Position = stream.Position - 1; CopyrightText = stream.ReadBytes(stream.Position.Align(0x800, cpkHeaderOffset) - stream.Position); // or something ulong tocOffset = (ulong)MainUtfTable.Rows[0].Cells[MainUtfTable.FindColumnIndex("TocOffset")].Data; //ulong tocSize = (ulong)MainUtfTable.Rows[0].Cells[MainUtfTable.FindColumnIndex("TocSize")].Data; if (tocOffset != 0) { stream.Position = cpkHeaderOffset + (long)tocOffset; uint magic = stream.ReadUInt32(Endianness.LittleEndian); if (magic != 0x20434F54) { throw new Exception("wrong TOC magic"); } UnknownTocHeaderBytes = stream.ReadBytes(12); TocUtfTable = new UtfBuilder(stream, endian); } ulong itocOffset = (ulong)MainUtfTable.Rows[0].Cells[MainUtfTable.FindColumnIndex("ItocOffset")].Data; //ulong itocSize = (ulong)MainUtfTable.Rows[0].Cells[MainUtfTable.FindColumnIndex("ItocSize")].Data; if (itocOffset != 0) { stream.Position = cpkHeaderOffset + (long)itocOffset; uint magic = stream.ReadUInt32(Endianness.LittleEndian); if (magic != 0x434F5449) { throw new Exception("wrong ITOC magic"); } UnknownItocHeaderBytes = stream.ReadBytes(12); ItocUtfTable = new UtfBuilder(stream, endian); } ulong etocOffset = (ulong)MainUtfTable.Rows[0].Cells[MainUtfTable.FindColumnIndex("EtocOffset")].Data; //ulong etocSize = (ulong)MainUtfTable.Rows[0].Cells[MainUtfTable.FindColumnIndex("EtocSize")].Data; if (etocOffset != 0) { stream.Position = cpkHeaderOffset + (long)etocOffset; uint magic = stream.ReadUInt32(Endianness.LittleEndian); if (magic != 0x434F5445) { throw new Exception("wrong ETOC magic"); } UnknownEtocHeaderBytes = stream.ReadBytes(12); EtocUtfTable = new UtfBuilder(stream, endian); } ulong gtocOffset = (ulong)MainUtfTable.Rows[0].Cells[MainUtfTable.FindColumnIndex("GtocOffset")].Data; //ulong gtocSize = (ulong)MainUtfTable.Rows[0].Cells[MainUtfTable.FindColumnIndex("GtocSize")].Data; if (gtocOffset != 0) { // haven't actually seen this, but would make sense... stream.Position = cpkHeaderOffset + (long)gtocOffset; uint magic = stream.ReadUInt32(Endianness.LittleEndian); if (magic != 0x434F5447) { throw new Exception("wrong GTOC magic"); } UnknownGtocHeaderBytes = stream.ReadBytes(12); GtocUtfTable = new UtfBuilder(stream, endian); } ulong contentOffset = (ulong)MainUtfTable.Rows[0].Cells[MainUtfTable.FindColumnIndex("ContentOffset")].Data; //ulong contentSize = (ulong)MainUtfTable.Rows[0].Cells[MainUtfTable.FindColumnIndex("ContentSize")].Data; uint fileCount = (uint)MainUtfTable.Rows[0].Cells[MainUtfTable.FindColumnIndex("Files")].Data; if (TocUtfTable == null || TocUtfTable.Rows.Count != fileCount) { throw new Exception("invalid TOC?"); } Files = new List <CpkFile>((int)fileCount); int columnDirName = TocUtfTable.FindColumnIndex("DirName"); int columnFileName = TocUtfTable.FindColumnIndex("FileName"); int columnFileSize = TocUtfTable.FindColumnIndex("FileSize"); int columnExtractSize = TocUtfTable.FindColumnIndex("ExtractSize"); int columnFileOffset = TocUtfTable.FindColumnIndex("FileOffset"); int columnFileIndexId = TocUtfTable.FindColumnIndex("ID"); long baseFileOffset = cpkHeaderOffset + ((contentOffset < tocOffset) ? (long)contentOffset : (long)tocOffset); for (int i = 0; i < (int)fileCount; ++i) { var f = new CpkFile(); f.Directory = (string)TocUtfTable.Rows[i].Cells[columnDirName].Data; f.Name = (string)TocUtfTable.Rows[i].Cells[columnFileName].Data; uint fileSize = (uint)TocUtfTable.Rows[i].Cells[columnFileSize].Data; f.DecompressedSize = (uint)TocUtfTable.Rows[i].Cells[columnExtractSize].Data; ulong fileOffset = (ulong)TocUtfTable.Rows[i].Cells[columnFileOffset].Data; f.FileStream = new HyoutaUtils.Streams.PartialStream(stream, baseFileOffset + (long)fileOffset, fileSize); f.ID = (uint)TocUtfTable.Rows[i].Cells[columnFileIndexId].Data; Files.Add(f); } return; }
public UtfBuilder(DuplicatableStream stream, Endianness endian = Endianness.BigEndian) { long utfHeaderOffset = stream.Position; uint utfMagic = stream.ReadUInt32(Endianness.LittleEndian); if (utfMagic != 0x46545540) { throw new Exception("wrong UTF magic"); } uint size = stream.ReadUInt32(endian); // size of the whole UTF chunk minus the magic and this value itself // offsets are relative to here long offset = stream.Position; uint rowsLocation = stream.ReadUInt32(endian); uint stringTableLocation = stream.ReadUInt32(endian); uint dataTableLocation = stream.ReadUInt32(endian); uint tableNameLocationInStringTable = stream.ReadUInt32(endian); ushort colcount = stream.ReadUInt16(endian); ushort rowwidth = stream.ReadUInt16(endian); uint rowcount = stream.ReadUInt32(endian); string tableName = stream.ReadUTF8NulltermFromLocationAndReset(offset + stringTableLocation + tableNameLocationInStringTable); // utf_tab calls this the 'schema' List <ColumnData> columns = new List <ColumnData>(colcount); for (int i = 0; i < colcount; ++i) { ColumnData col = new ColumnData(); col.Type = stream.ReadUInt8(); uint stroffset = stream.ReadUInt32(endian); col.Name = stream.ReadUTF8NulltermFromLocationAndReset(offset + stringTableLocation + stroffset); if ((col.Type & utf_tab_sharp.UtfTab.COLUMN_STORAGE_MASK) == utf_tab_sharp.UtfTab.COLUMN_STORAGE_CONSTANT) { switch (col.Type & utf_tab_sharp.UtfTab.COLUMN_TYPE_MASK) { case utf_tab_sharp.UtfTab.COLUMN_TYPE_STRING: uint datastroffset = stream.ReadUInt32(endian); col.Data = stream.ReadUTF8NulltermFromLocationAndReset(offset + stringTableLocation + datastroffset); break; case utf_tab_sharp.UtfTab.COLUMN_TYPE_8BYTE: col.Data = stream.ReadUInt64(endian); break; case utf_tab_sharp.UtfTab.COLUMN_TYPE_DATA: uint dataOffset = stream.ReadUInt32(endian); uint dataSize = stream.ReadUInt32(endian); col.Data = stream.ReadBytesFromLocationAndReset(offset + dataTableLocation + dataOffset, dataSize); break; case utf_tab_sharp.UtfTab.COLUMN_TYPE_FLOAT: col.Data = stream.ReadUInt32(endian).UIntToFloat(); break; case utf_tab_sharp.UtfTab.COLUMN_TYPE_4BYTE2: case utf_tab_sharp.UtfTab.COLUMN_TYPE_4BYTE: col.Data = stream.ReadUInt32(endian); break; case utf_tab_sharp.UtfTab.COLUMN_TYPE_2BYTE2: case utf_tab_sharp.UtfTab.COLUMN_TYPE_2BYTE: col.Data = stream.ReadUInt16(endian); break; case utf_tab_sharp.UtfTab.COLUMN_TYPE_1BYTE2: case utf_tab_sharp.UtfTab.COLUMN_TYPE_1BYTE: col.Data = stream.ReadUInt8(); break; default: throw new Exception("unknown type for constant"); } } columns.Add(col); } List <RowData> rows = new List <RowData>((int)rowcount); for (long i = 0; i < rowcount; ++i) { stream.Position = offset + rowsLocation + (i * rowwidth); RowData row = new RowData(); row.Cells = new List <CellData>(); for (int j = 0; j < colcount; ++j) { CellData cell = new CellData(); byte type = columns[j].Type; switch ((type & utf_tab_sharp.UtfTab.COLUMN_STORAGE_MASK)) { case utf_tab_sharp.UtfTab.COLUMN_STORAGE_PERROW: switch (type & utf_tab_sharp.UtfTab.COLUMN_TYPE_MASK) { case utf_tab_sharp.UtfTab.COLUMN_TYPE_STRING: uint datastroffset = stream.ReadUInt32(endian); cell.Data = stream.ReadUTF8NulltermFromLocationAndReset(offset + stringTableLocation + datastroffset); break; case utf_tab_sharp.UtfTab.COLUMN_TYPE_8BYTE: cell.Data = stream.ReadUInt64(endian); break; case utf_tab_sharp.UtfTab.COLUMN_TYPE_DATA: uint dataOffset = stream.ReadUInt32(endian); uint dataSize = stream.ReadUInt32(endian); cell.Data = stream.ReadBytesFromLocationAndReset(offset + dataTableLocation + dataOffset, dataSize); break; case utf_tab_sharp.UtfTab.COLUMN_TYPE_FLOAT: cell.Data = stream.ReadUInt32(endian).UIntToFloat(); break; case utf_tab_sharp.UtfTab.COLUMN_TYPE_4BYTE2: case utf_tab_sharp.UtfTab.COLUMN_TYPE_4BYTE: cell.Data = stream.ReadUInt32(endian); break; case utf_tab_sharp.UtfTab.COLUMN_TYPE_2BYTE2: case utf_tab_sharp.UtfTab.COLUMN_TYPE_2BYTE: cell.Data = stream.ReadUInt16(endian); break; case utf_tab_sharp.UtfTab.COLUMN_TYPE_1BYTE2: case utf_tab_sharp.UtfTab.COLUMN_TYPE_1BYTE: cell.Data = stream.ReadUInt8(); break; default: throw new Exception("unknown type for value"); } break; case utf_tab_sharp.UtfTab.COLUMN_STORAGE_CONSTANT: cell.Data = columns[j].Data; break; case utf_tab_sharp.UtfTab.COLUMN_STORAGE_ZERO: switch (type & utf_tab_sharp.UtfTab.COLUMN_TYPE_MASK) { case utf_tab_sharp.UtfTab.COLUMN_TYPE_STRING: cell.Data = ""; break; case utf_tab_sharp.UtfTab.COLUMN_TYPE_8BYTE: cell.Data = (ulong)0; break; case utf_tab_sharp.UtfTab.COLUMN_TYPE_DATA: cell.Data = new byte[0]; break; case utf_tab_sharp.UtfTab.COLUMN_TYPE_FLOAT: cell.Data = 0.0f; break; case utf_tab_sharp.UtfTab.COLUMN_TYPE_4BYTE2: case utf_tab_sharp.UtfTab.COLUMN_TYPE_4BYTE: cell.Data = (uint)0; break; case utf_tab_sharp.UtfTab.COLUMN_TYPE_2BYTE2: case utf_tab_sharp.UtfTab.COLUMN_TYPE_2BYTE: cell.Data = (ushort)0; break; case utf_tab_sharp.UtfTab.COLUMN_TYPE_1BYTE2: case utf_tab_sharp.UtfTab.COLUMN_TYPE_1BYTE: cell.Data = (byte)0; break; default: throw new Exception("unknown type for value"); } break; default: throw new Exception("unknown storage for value"); } row.Cells.Add(cell); } rows.Add(row); } Name = tableName; Columns = columns; Rows = rows; stream.Position = utfHeaderOffset + ((long)8) + ((long)size); return; }
public override INode GetChildByIndex(long index) { if (index >= 0 && index < Entries.LongLength) { uint entryLoc = Entries[index]; Stream.Position = entryLoc; uint type = Stream.ReadUInt32(Endian); switch (type) { // PC vesperia can't agree with itself whether this is endian-agnostic or not, the JP files have it swapped compared to the EN files... case 0x69733134: case 0x34317369: { Stream.Position = entryLoc + 0x14; uint length = Stream.ReadUInt32(Endian); uint offset = Stream.ReadUInt32(Endian); Stream.Position = entryLoc + 0xbc; byte[] bnsfheader = Stream.ReadUInt8Array(0x30); Stream.Position = Header.StartOfFiles + offset; using (var ms = new MemoryStream()) { ms.Write(bnsfheader); StreamUtils.CopyStream(Stream, ms, length); return(new NubFile(ms.CopyToByteArrayStreamAndDispose(), "bnsf")); } } case 0x64737000: { Stream.Position = entryLoc + 0x14; uint length = Stream.ReadUInt32(Endian); uint offset = Stream.ReadUInt32(Endian); Stream.Position = entryLoc + 0xbc; byte[] dspheader = Stream.ReadUInt8Array(0x60); Stream.Position = Header.StartOfFiles + offset; using (var ms = new MemoryStream()) { ms.Write(dspheader); StreamUtils.CopyStream(Stream, ms, length); return(new NubFile(ms.CopyToByteArrayStreamAndDispose(), "dsp")); } } case 0x61743300: { Stream.Position = entryLoc; byte[] at3header = Stream.ReadUInt8Array(0x100); Stream.Position = entryLoc + 0x14; uint length = Stream.ReadUInt32(Endian); uint offset = Stream.ReadUInt32(Endian); Stream.Position = Header.StartOfFiles + offset; using (var ms = new MemoryStream()) { ms.Write(at3header); StreamUtils.CopyStream(Stream, ms, length); return(new NubFile(ms.CopyToByteArrayStreamAndDispose(), "at3")); } } case 0x76616700: { Stream.Position = entryLoc; byte[] vagheader = Stream.ReadUInt8Array(0xc0); Stream.Position = entryLoc + 0x14; uint length = Stream.ReadUInt32(Endian); uint offset = Stream.ReadUInt32(Endian); Stream.Position = Header.StartOfFiles + offset; using (var ms = new MemoryStream()) { if (Endian == EndianUtils.Endianness.LittleEndian) { // unclear if this needs to be all swapped or just a subset... for (int i = 0; i < 0xc0; i += 4) { ms.WriteByte(vagheader[i + 3]); ms.WriteByte(vagheader[i + 2]); ms.WriteByte(vagheader[i + 1]); ms.WriteByte(vagheader[i + 0]); } } else { ms.Write(vagheader); } ms.WriteUInt64(0); ms.WriteUInt64(0); StreamUtils.CopyStream(Stream, ms, length); return(new NubFile(ms.CopyToByteArrayStreamAndDispose(), "vag")); } } default: Console.WriteLine("Unimplemented nub subtype: 0x" + type.ToString("x8")); return(null); } } return(null); }
public TrophyTrp(HyoutaPluginBase.DuplicatableStream stream, EndianUtils.Endianness endian = EndianUtils.Endianness.BigEndian) { Stream = stream.Duplicate(); Endian = endian; try { Stream.ReStart(); Magic = Stream.ReadUInt32().FromEndian(EndianUtils.Endianness.LittleEndian); if (Magic != 0x004DA2DC) { throw new Exception("invalid magic"); } Unknown2 = Stream.ReadUInt32().FromEndian(endian); Unknown3 = Stream.ReadUInt32().FromEndian(endian); Filesize = Stream.ReadUInt32().FromEndian(endian); Filecount = Stream.ReadUInt32().FromEndian(endian); Unknown6 = Stream.ReadUInt32().FromEndian(endian); Unknown7 = Stream.ReadUInt32().FromEndian(endian); Unknown8 = Stream.ReadUInt32().FromEndian(endian); Unknown9 = Stream.ReadUInt32().FromEndian(endian); Unknown10 = Stream.ReadUInt32().FromEndian(endian); Unknown11 = Stream.ReadUInt32().FromEndian(endian); Unknown12 = Stream.ReadUInt32().FromEndian(endian); Unknown13 = Stream.ReadUInt32().FromEndian(endian); Unknown14 = Stream.ReadUInt32().FromEndian(endian); Unknown15 = Stream.ReadUInt32().FromEndian(endian); Unknown16 = Stream.ReadUInt32().FromEndian(endian); } finally { Stream.End(); } }