public static async Task <bool> IsNcch(IReadOnlyBinaryDataAccessor file) { try { if (file.Length < 0x104) { return(false); } return(await file.ReadStringAsync(0x100, 4, Encoding.ASCII) == "NCCH"); } catch (Exception) { return(false); } }
public Entry(IReadOnlyBinaryDataAccessor data) { Features = (Feature)data.ReadInt32(0x00); Index = data.ReadInt32(0x04); Short08 = data.ReadInt16(0x08); Short0A = data.ReadInt16(0x0A); SortKey = data.ReadInt32(0x0C); DungeonBalanceIndex = data.ReadByte(0x12); Byte13 = data.ReadByte(0x13); MaxItems = data.ReadByte(0x14); MaxTeammates = data.ReadByte(0x15); Byte17 = data.ReadByte(0x17); Byte18 = data.ReadByte(0x18); Byte19 = data.ReadByte(0x19); // All unread bytes are zero }
private void OpenInternalNormal(IReadOnlyBinaryDataAccessor f) { BgrsName = f.ReadNullTerminatedString(0x58, Encoding.ASCII); // Max length: &H40 BgrsDevName = f.ReadNullTerminatedString(0x58 + 0x40, Encoding.ASCII); // Max length: &H80 // Yes, the counts of these two sections are in a different order than the sections themselves var animationCount = f.ReadInt32(0x118); var partCount = f.ReadInt32(0x11C); for (var partIndex = 0x140; partIndex <= 0x140 + (0x80 * partCount) - 1; partIndex += 0x80) { var partName = f.ReadNullTerminatedString(partIndex + 0x18, System.Text.Encoding.ASCII); Parts.Add(new ModelPart(f.ReadArray(partIndex, 0x80), partName)); } UnknownModelPartsFooter = f.ReadArray(0x140 + (0x80 * partCount), 0x18); OpenInternalAnimations(f, 0x140 + (0x80 * partCount) + 0x18, animationCount); }
public static async Task <bool> IsExeFs(IReadOnlyBinaryDataAccessor file) { try { if (file.Length < 0x200) { return(false); } var exefs = await ExeFs.Load(file).ConfigureAwait(false); return(exefs.Files.Any() && exefs.AreAllHashesValid()); } catch (Exception) { return(false); } }
public async Task OpenFile(IReadOnlyBinaryDataAccessor file) { // Clear virtual path if it exists if (!string.IsNullOrEmpty(VirtualPath) && CurrentFileSystem.DirectoryExists(VirtualPath)) { CurrentFileSystem.DeleteDirectory(VirtualPath); } VirtualPath = CurrentFileSystem.GetTempDirectory(); if (await NcsdFile.IsNcsd(file)) { Container = await NcsdFile.Load(file); } else if (file is BinaryFile binaryFile && await CiaFile.IsCia(binaryFile)) { Container = await CiaFile.Load(file); }
public async Task Initialize(IReadOnlyBinaryDataAccessor data) { if (Header != null && Header.RomFsSize > 0) { if (Header.ExeFsOffset > 0 && Header.ExeFsSize > 0) { ExeFs = await ExeFs.Load(data.GetReadOnlyDataReference((long)Header.ExeFsOffset *MediaUnitSize, (long)Header.ExeFsSize *MediaUnitSize)); } if (Header.RomFsOffset > 0 && Header.RomFsOffset > 0) { RomFs = await RomFs.Load(data.GetReadOnlyDataReference((long)Header.RomFsOffset *MediaUnitSize, (long)Header.RomFsSize *MediaUnitSize)); } if (Header.ExHeaderSize > 0) { ExHeader = data.GetReadOnlyDataReference(0x200, Header.ExHeaderSize); } } }
public static string ReadNullTerminatedUtf16String(this IReadOnlyBinaryDataAccessor accessor, long offset) { var encoding = Encoding.Unicode; var output = new StringBuilder(); var index = offset; Span <char> chars = stackalloc char[1]; do { var length = encoding.GetChars(accessor.ReadSpan(index, 2), chars); if (length > 0) { output.Append(chars); } index += 2; } while (chars[0] != '\0'); output.Length -= 1; // Trim the null char return(output.ToString()); }
public BGRS(IReadOnlyBinaryDataAccessor data) { Magic = data.ReadNullTerminatedString(0, System.Text.Encoding.ASCII); ReferencedBchFileName = (data.ReadNullTerminatedString(0x8, System.Text.Encoding.ASCII)).TrimEnd('0'); // Max length: 0x40 Type = (BgrsType)data.ReadInt32(0x48); switch (Type) { case BgrsType.Normal: OpenInternalNormal(data); break; case BgrsType.Extension: OpenInternalExtended(data); break; default: throw new NotSupportedException("Unsupported BGRS type: " + Type.ToString()); } }
public MessageBinEntry(IReadOnlyBinaryDataAccessor data) { var sir0 = new Sir0(data); var entryCount = sir0.SubHeader.ReadInt32(0); var entriesOffset = sir0.SubHeader.ReadInt32(4); var strings = new Dictionary <int, string>(); var hashes = new Dictionary <long, int>(); for (int i = 0; i < entryCount; i++) { var entryOffset = entriesOffset + (i * EntryLength); var stringOffset = sir0.Data.ReadInt32(entryOffset); var hash = sir0.Data.ReadInt32(entryOffset + 4); var unknown = sir0.Data.ReadInt32(entryOffset + 8); strings.Add(hash, sir0.Data.ReadNullTerminatedUnicodeString(stringOffset)); hashes.Add(stringOffset, hash); } Strings = strings; OrderedHashes = hashes.OrderBy(h => h.Key).Select(h => h.Value).ToArray(); }
public static async Task <NcchExtendedHeader> Load(IReadOnlyBinaryDataAccessor data) { var header = new NcchExtendedHeader { ApplicationTitle = await data.ReadStringAsync(0, 8, Encoding.ASCII), Reserved1 = await data.ReadArrayAsync(8, 5), Flag = await data.ReadByteAsync(0xD), RemasterVersion = await data.ReadInt16Async(0xE), TextCodeSetInfo = await CodeSetInfo.Load(data.Slice(0x10, 0xC)), StackSize = await data.ReadInt32Async(0x1C), ReadOnlyCodeSetInfo = await CodeSetInfo.Load(data.Slice(0x20, 0xC)), Reserved2 = await data.ReadInt32Async(0x2C), DataCodeSetInfo = await CodeSetInfo.Load(data.Slice(0x30, 0xC)), BssSize = await data.ReadInt32Async(0x3C) }; var moduleIds = new long[48]; await AsyncFor.For(0, 48 - 1, async i => { moduleIds[i] = await data.ReadInt64Async(0x40 + i * 8); }); header.DependencyModuleIds = moduleIds; header.SystemInformation = await SystemInfo.Load(data.Slice(0x1C0, 0x40)); header.LocalSystemCapabilities = await Arm11LocalSystemCapabilities.Load(data.Slice(0x200, 0x170)); header.KernelCapabilities = await Arm11KernelCapabilities.Load(data.Slice(0x370, 0x80)); header.AccessControl = await Arm9AccessControl.Load(data.Slice(0x3F0, 0x10)); header.AccessDescSignature = await data.ReadArrayAsync(0x400, 0x100); header.NcchHdrPublicKey = await data.ReadArrayAsync(0x500, 0x100); header.Aci = await data.ReadArrayAsync(0x600, 0x200); return(header); }
public static async Task <bool> IsExeFs(IReadOnlyBinaryDataAccessor file) { try { if (file.Length < 0x200) { return(false); } var exefsHeaders = (await ExeFs.Load(file).ConfigureAwait(false)).Headers.Where(h => !string.IsNullOrEmpty(h.Filename)); if (!exefsHeaders.Any()) { return(false); } return(exefsHeaders.All(h => h.Offset >= 0x200 && (h.Offset + h.FileSize) < file.Length)); } catch (Exception) { return(false); } }
public FloorInfoEntry(IReadOnlyBinaryDataAccessor data) { Index = data.ReadInt16(0x00); Short02 = data.ReadInt16(0x02); Event = data.ReadString(0x04, 32, Encoding.ASCII).Trim('\0'); Short24 = data.ReadInt16(0x24); Short26 = data.ReadInt16(0x26); Short28 = data.ReadInt16(0x28); Short2A = data.ReadInt16(0x2A); Byte2C = data.ReadByte(0x2C); Byte2D = data.ReadByte(0x2D); Byte2E = data.ReadByte(0x2E); Byte2F = data.ReadByte(0x2F); Short30 = data.ReadInt16(0x30); Short32 = data.ReadInt16(0x32); Byte34 = data.ReadByte(0x34); Byte35 = data.ReadByte(0x35); Byte36 = data.ReadByte(0x36); InvitationIndex = data.ReadByte(0x54); Bytes37to53 = data.ReadArray(0x37, 0x53 - 0x37 + 1); Bytes55to61 = data.ReadArray(0x55, 0x61 - 0x55 + 1); }
/// <param name="data">The raw data. Note: This will be disposed when RomFs is disposed</param> public RomFs(IReadOnlyBinaryDataAccessor data, RomFsHeader header) { Data = data ?? throw new ArgumentNullException(nameof(data)); Header = header ?? throw new ArgumentNullException(nameof(header)); LevelLocations = new IvfcLevelLocation[] { new IvfcLevelLocation { HashBlockSize = 1 << header.Level1BlockSize, HashOffset = 0x60 }, new IvfcLevelLocation { HashBlockSize = 1 << header.Level2BlockSize }, new IvfcLevelLocation { HashBlockSize = 1 << header.Level3BlockSize } }; BodyOffset = BitMath.Align(LevelLocations[0].HashOffset + header.MasterHashSize, LevelLocations[2].HashBlockSize); BodySize = header.Level3HashDataSize; LevelLocations[2].DataOffset = BodyOffset; LevelLocations[2].DataSize = BitMath.Align(BodySize, LevelLocations[2].HashBlockSize); LevelLocations[1].HashOffset = BitMath.Align(BodyOffset + BodySize, LevelLocations[2].HashBlockSize); LevelLocations[2].HashOffset = LevelLocations[1].HashOffset + header.Level2LogicalOffset - header.Level1LogicalOffset; LevelLocations[1].DataOffset = LevelLocations[2].HashOffset; LevelLocations[1].DataSize = BitMath.Align(header.Level2HashDataSize, LevelLocations[1].HashBlockSize); LevelLocations[0].DataOffset = LevelLocations[2].HashOffset; LevelLocations[0].DataSize = BitMath.Align(header.Level1HashDataSize, LevelLocations[0].HashBlockSize); // To-do: verify hashes }
public static async Task <FileMetadata> Load(IReadOnlyBinaryDataAccessor data, IvfcLevelHeader header, long offsetFromMetadataTable) { var offset = header.FileMetadataTableOffset + offsetFromMetadataTable; var metadata = new FileMetadata(data, header); metadata.ContainingDirectoryOffset = await data.ReadInt32Async(offset + 0); metadata.NextSiblingFileOffset = await data.ReadInt32Async(offset + 4); metadata.FileDataOffset = await data.ReadInt64Async(offset + 8); metadata.FileDataLength = await data.ReadInt64Async(offset + 0x10); metadata.NextFileOffset = await data.ReadInt32Async(offset + 0x18); metadata.NameLength = await data.ReadInt32Async(offset + 0x1C); if (metadata.NameLength > 0) { metadata.Name = Encoding.Unicode.GetString(await data.ReadArrayAsync(offset + 0x20, Math.Min(metadata.NameLength, MaxFilenameLength))); } return(metadata); }
public async Task Initialize(IReadOnlyBinaryDataAccessor data) { this.RawData = data; if (Header != null && Header.RomFsSize > 0) { if (Header.ExeFsOffset > 0 && Header.ExeFsSize > 0) { ExeFs = await ExeFs.Load(data.Slice((long)Header.ExeFsOffset *MediaUnitSize, (long)Header.ExeFsSize *MediaUnitSize)); } if (Header.RomFsOffset > 0 && Header.RomFsOffset > 0) { RomFs = await RomFs.Load(data.Slice((long)Header.RomFsOffset *MediaUnitSize, (long)Header.RomFsSize *MediaUnitSize)); } if (Header.ExHeaderSize > 0) { ExHeader = await NcchExtendedHeader.Load(data.Slice(0x200, Header.ExHeaderSize)); } PlainRegion = await data.ReadStringAsync(Header.PlainRegionOffset *MediaUnitSize, Header.PlainRegionSize *MediaUnitSize, Encoding.ASCII); Logo = await data.ReadArrayAsync(Header.LogoRegionOffset *MediaUnitSize, Header.LogoRegionSize *MediaUnitSize); } }
public Entry(IReadOnlyBinaryDataAccessor accessor) { var buffer = Gyu0.Decompress(accessor); Sir0 sir0 = new Sir0(buffer); var offsetHeader = sir0.SubHeader.ReadInt64(0x00); var offsetWildPokemon = sir0.SubHeader.ReadInt64(0x08); var offset3 = sir0.SubHeader.ReadInt64(0x10); var offset4 = sir0.SubHeader.ReadInt64(0x18); var lenHeader = offsetWildPokemon - offsetHeader; var lenWildPokemon = offset3 - offsetWildPokemon; var len3 = offset4 - offset3; var len4 = sir0.SubHeaderOffset - offset4; var headerEntrySize = FloorInfoEntry.Size; var entryCount = lenHeader / headerEntrySize; FloorInfos = new FloorInfoEntry[entryCount]; for (int i = 0; i < lenHeader / headerEntrySize; i++) { FloorInfos[i] = new FloorInfoEntry(sir0.Data.Slice(offsetHeader + i * headerEntrySize, headerEntrySize)); } if (lenWildPokemon > 0) { WildPokemon = new WildPokemonInfo(sir0.Data.Slice(offsetWildPokemon, lenWildPokemon)); } if (len3 > 0) { Data3 = new DungeonBalanceDataEntry3(sir0.Data.Slice(offset3, len3)); } if (len4 > 0) { Data4 = new DungeonBalanceDataEntry4(sir0.Data.Slice(offset4, len4)); } }
public override ValueTask <(int, int)?> ReadAsync(IReadOnlyBinaryDataAccessor data, long position, byte[] dest, int offset, int count) => new ValueTask <(int, int)?>(Read(data, position, dest, offset, count));
public override (byte, int)? ReadByte(IReadOnlyBinaryDataAccessor data, long position) { return((byteCount-- <= 0) ? null : ((byte, int)?)(value, 0)); }
public static async Task <byte[]> GetSuperblockHash(SHA256 sha, IReadOnlyBinaryDataAccessor data, RomFsHeader header) { var buffer = await data.ReadArrayAsync(0, header.MasterHashSize); return(sha.ComputeHash(buffer)); }
public override (int, int)? Read(IReadOnlyBinaryDataAccessor data, long position, byte[] dest, int offset, int count) => null;
public PokemonGraphicsDatabaseEntry(IReadOnlyBinaryDataAccessor entryAccessor, IReadOnlyBinaryDataAccessor rawDataAccessor) { ModelNamePointer = entryAccessor.ReadInt64(0); AnimationNamePointer = entryAccessor.ReadInt64(8); BaseFormModelNamePointer = entryAccessor.ReadInt64(16); PortraitSheetNamePointer = entryAccessor.ReadInt64(24); RescueCampSheetNamePointer = entryAccessor.ReadInt64(32); RescueCampSheetReverseNamePointer = entryAccessor.ReadInt64(40); ModelName = rawDataAccessor.ReadNullTerminatedUnicodeString(ModelNamePointer); AnimationName = rawDataAccessor.ReadNullTerminatedUnicodeString(AnimationNamePointer); BaseFormModelName = rawDataAccessor.ReadNullTerminatedUnicodeString(BaseFormModelNamePointer); PortraitSheetName = rawDataAccessor.ReadNullTerminatedUnicodeString(PortraitSheetNamePointer); RescueCampSheetName = rawDataAccessor.ReadNullTerminatedUnicodeString(RescueCampSheetNamePointer); RescueCampSheetReverseName = rawDataAccessor.ReadNullTerminatedUnicodeString(RescueCampSheetReverseNamePointer); UnkX30 = entryAccessor.ReadSingle(0x30); UnkX34 = entryAccessor.ReadSingle(0x34); UnkX38 = entryAccessor.ReadSingle(0x38); UnkX3C = entryAccessor.ReadSingle(0x3C); UnkX40 = entryAccessor.ReadSingle(0x40); UnkX44 = entryAccessor.ReadSingle(0x44); UnkX48 = entryAccessor.ReadSingle(0x48); WalkSpeedDistance = entryAccessor.ReadSingle(0x4C); // Referenced by PokemonDatabase_GetWalkSpeed() UnkX50 = entryAccessor.ReadSingle(0x50); RunSpeedRatioGround = entryAccessor.ReadSingle(0x54); // Referenced by PokemonDatabase_GetRunRateGround() UnkX58 = entryAccessor.ReadSingle(0x58); UnkX5C = entryAccessor.ReadSingle(0x5C); UnkX60 = entryAccessor.ReadSingle(0x60); UnkX64 = entryAccessor.ReadSingle(0x64); UnknownBodyType1 = (GraphicsBodySizeType)entryAccessor.ReadInt32(0x68); UnknownBodyType2 = (GraphicsBodySizeType)entryAccessor.ReadInt32(0x6C); Flags = (PokemonGraphicsDatabaseEntryFlags)entryAccessor.ReadInt32(0x70); EnabledPortraits = (EnabledPortraitsFlags)entryAccessor.ReadUInt32(0x74); // Bitmask of enabled portraits UnkX78 = entryAccessor.ReadInt32(0x78); UnkX7C = entryAccessor.ReadInt32(0x7C); UnkX80 = entryAccessor.ReadInt32(0x80); UnkX84 = entryAccessor.ReadSingle(0x84); UnkX88 = entryAccessor.ReadSingle(0x88); UnkX8C = entryAccessor.ReadSingle(0x8C); UnkX90 = entryAccessor.ReadSingle(0x90); UnkX94 = entryAccessor.ReadSingle(0x94); UnkX98 = entryAccessor.ReadSingle(0x98); UnkX9C = entryAccessor.ReadSingle(0x9C); UnkXA0 = entryAccessor.ReadSingle(0xA0); Padding1 = entryAccessor.ReadInt32(0xA4); Padding2 = entryAccessor.ReadInt32(0xA8); Padding3 = entryAccessor.ReadInt32(0xAC); }
public Sir0(IReadOnlyBinaryDataAccessor data) { Data = data; Init(); }
public DirectoryMetadata(IReadOnlyBinaryDataAccessor data, IvfcLevelHeader header) { LevelData = data ?? throw new ArgumentNullException(nameof(data)); IvfcLevelHeader = header ?? throw new ArgumentNullException(nameof(data)); }
public IvfcLevel(IReadOnlyBinaryDataAccessor data, IvfcLevelHeader header) { LevelData = data ?? throw new ArgumentNullException(nameof(data)); Header = header ?? throw new ArgumentNullException(nameof(header)); }
public TmdMetadata(IReadOnlyBinaryDataAccessor tmdData) { TmdData = tmdData ?? throw new ArgumentNullException(nameof(tmdData)); }
public Entry(IReadOnlyBinaryDataAccessor accessor) { Short00 = accessor.ReadInt16(0x00); Short02 = accessor.ReadInt16(0x02); Int04 = accessor.ReadInt16(0x04); }
public NcsdFile(IReadOnlyBinaryDataAccessor data) { NcsdData = data ?? throw new ArgumentNullException(nameof(data)); }
public override (byte, int)? ReadByte(IReadOnlyBinaryDataAccessor data, long position) => null;
public ExeFs(IReadOnlyBinaryDataAccessor exeFsData) : this() { ExeFsData = exeFsData ?? throw new ArgumentNullException(nameof(exeFsData)); }
public DungeonDataInfoEntry(IReadOnlyBinaryDataAccessor data) { Index = (DungeonIndex)data.ReadInt32(4); SortPriority = data.ReadInt32(0xC); }