public override void Read(DataStream strIn) { DataReader reader = new DataReader(strIn, EndiannessMode.LittleEndian, Encoding.GetEncoding("shift_jis")); uint numBlocks = reader.ReadUInt32(); this.entries = new Entry[numBlocks]; for (int i = 0; i < numBlocks; i++) { uint idx = reader.ReadUInt32(); int textSize = reader.ReadInt32(); string text = reader.ReadString(textSize); this.entries[i] = new Entry(idx, text.ApplyTable("replace", false)); } }
public override void Read(DataStream strIn) { DataReader reader = new DataReader(strIn, EndiannessMode.LittleEndian, Encoding.GetEncoding("shift_jis")); this.id = reader.ReadUInt32(); this.startBlocks = new string[4]; for (int i = 0; i < this.startBlocks.Length; i++) { ushort textSize = reader.ReadUInt16(); this.startBlocks[i] = reader.ReadString(textSize).ApplyTable("replace", false); } this.unknown = reader.ReadBytes(0x0D); byte numEndBlocks = reader.ReadByte(); this.endBlocks = new string[numEndBlocks]; for (int i = 0; i < this.endBlocks.Length; i++) { ushort size = reader.ReadUInt16(); this.endBlocks[i] = reader.ReadString(size).ApplyTable("replace", false); } byte numUnknown = reader.ReadByte(); this.unknown2 = new byte[numUnknown][]; for (int i = 0; i < this.unknown2.Length; i++) { byte dataSize = reader.ReadByte(); this.unknown2[i] = reader.ReadBytes(dataSize + 4); } }
public override void Read(DataStream strIn) { DataReader reader = new DataReader(strIn); this.type = reader.ReadUInt32(); this.blocks = new Block[3]; this.blocks[0] = Block.FromStream(strIn, typeof(Entry1)); this.blocks[1] = Block.FromStream(strIn, typeof(Entry2)); this.blocks[2] = Block.FromStream(strIn, typeof(Entry3)); }
public override void Read(DataStream strIn) { DataReader reader = new DataReader(strIn, EndiannessMode.LittleEndian, Encoding.GetEncoding("shift_jis")); ushort numEntries = reader.ReadUInt16(); this.entries = new Entry[numEntries]; for (int i = 0; i < numEntries; i++) { this.entries[i] = new Entry(); this.entries[i].Id = reader.ReadUInt32(); this.entries[i].Text = reader.ReadString(typeof(ushort), "replace", false); } }
public override void Read(DataStream strIn) { DataReader reader = new DataReader(strIn, EndiannessMode.LittleEndian, Encoding.GetEncoding("shift_jis")); ushort numBlocks = reader.ReadUInt16(); this.blocks = new Block[numBlocks]; for (int i = 0; i < numBlocks; i++) { reader.ReadUInt16(); // Block size this.blocks[i] = new Block(); this.blocks[i].Id = reader.ReadUInt32(); this.blocks[i].Elements = new string[3]; for (int j = 0; j < 3; j++) this.blocks[i].Elements[j] = reader.ReadString(typeof(ushort), "replace", false); reader.ReadByte(); // 0x00 } }
/// <summary> /// Read a Fat section from a stream. /// </summary> /// <param name="str">Stream to read from.</param> public override void Read(DataStream str) { this.files = new GameFile[str.Length / FatEntrySize]; DataReader dr = new DataReader(str); uint startOffset, endOffset; for (ushort i = 0; i < this.files.Length; i++) { startOffset = dr.ReadUInt32(); endOffset = dr.ReadUInt32(); this.files[i] = new GameFile( string.Empty, // Name will be added later in FNT new DataStream(str.BaseStream, startOffset, endOffset - startOffset)); // TODO: FIX this.files[i].Tags["Id"] = i; } if (this.files.Length > 0) { if (this.files[0].Stream.Offset > str.Position - this.Size) this.firstOffset = (uint)(this.files[0].Stream.Offset - (str.Position - this.Size)); else this.firstOffset = (uint)((str.Position - this.Size) - this.files[0].Stream.Offset); } else { this.firstOffset = 0xFFFFFFFF; } }
/// <summary> /// Read a the header from a NDS game ROM. /// </summary> /// <param name="str">Stream with the ROM. Must be at the correct position.</param> public override void Read(DataStream str) { long startPosition = str.Position; DataReader dr = new DataReader(str); this.gameTitle = dr.ReadChars(12); this.gameCode = dr.ReadChars(4); this.makerCode = dr.ReadChars(2); this.unitCode = dr.ReadByte(); this.encryptionSeed = dr.ReadByte(); this.cartridgeSize = (uint)(1 << (MinCartridge + dr.ReadByte())); this.reserved = dr.ReadBytes(9); this.RomVersion = dr.ReadByte(); this.internalFlags = dr.ReadByte(); this.Arm9Offset = dr.ReadUInt32(); this.Arm9EntryAddress = dr.ReadUInt32(); this.Arm9RamAddress = dr.ReadUInt32(); this.Arm9Size = dr.ReadUInt32(); this.Arm7Offset = dr.ReadUInt32(); this.Arm7EntryAddress = dr.ReadUInt32(); this.Arm7RamAddress = dr.ReadUInt32(); this.Arm7Size = dr.ReadUInt32(); this.fntOffset = dr.ReadUInt32(); this.fntSize = dr.ReadUInt32(); this.FatOffset = dr.ReadUInt32(); this.FatSize = dr.ReadUInt32(); this.Ov9TableOffset = dr.ReadUInt32(); this.Ov9TableSize = dr.ReadUInt32(); this.Ov7TableOffset = dr.ReadUInt32(); this.Ov7TableSize = dr.ReadUInt32(); this.flagsRead = dr.ReadUInt32(); this.flagsInit = dr.ReadUInt32(); this.bannerOffset = dr.ReadUInt32(); this.secureCRC16 = dr.ReadUInt16(); this.RomTimeout = dr.ReadUInt16(); this.Arm9Autoload = dr.ReadUInt32(); this.Arm7Autoload = dr.ReadUInt32(); this.secureDisable = dr.ReadUInt64(); this.RomSize = dr.ReadUInt32(); this.headerSize = dr.ReadUInt32(); this.reserved2 = dr.ReadBytes(56); this.nintendoLogo = dr.ReadBytes(156); this.logoCRC16 = dr.ReadUInt16(); this.headerCRC16 = dr.ReadUInt16(); this.debugRomOffset = dr.ReadUInt32(); this.debugSize = dr.ReadUInt32(); this.debugRamAddress = dr.ReadUInt32(); this.reserved3 = dr.ReadUInt32(); int unknownSize = (int)(this.headerSize - (str.Position - startPosition)); this.unknown = dr.ReadBytes(unknownSize); }
/// <summary> /// Searchs the encoded size address. /// </summary> /// <returns>The encoded size address. 0 if not found. 1 if game is homebrew.</returns> private uint SearchEncodedSizeAddress() { /* * Steps to find the ARM9 size address that we need to change * in order to fix the BLZ decoded error. * * 0º Check the game is not homebrew. * 1º Get ARM9 entry address. * 2º From that point and while we're in the secure zone, * search the decode_BLZ routine. * 3º Search previous BL (jump) instruction that call the decoder. * 4º Search instructions before it that loads R0 (parameter of decode_BLZ). */ DataReader reader = new DataReader(this.Stream); // 0º if (this.Tags.ContainsKey("_GameCode_") && (string)this.Tags["_GameCode_"] == "####") return 0x01; // 1º uint entryAddress = this.EntryAddress - this.RamAddress; // 2º this.Stream.Seek(entryAddress, SeekMode.Origin); uint decoderAddress = SearchDecoder(); if (decoderAddress == 0x00) { Console.WriteLine("INVALID decoder address."); return 0x00; } // 3º & 4º this.Stream.Seek(entryAddress, SeekMode.Origin); uint baseOffset = SearchBaseOffset(decoderAddress); if (baseOffset == 0x00) { Console.WriteLine("INVALID base offset."); return 0x00; } // Get relative address (not RAM address) this.Stream.Seek(baseOffset, SeekMode.Origin); uint sizeAddress = reader.ReadUInt32() + 0x14; // Size is at 0x14 from that address sizeAddress -= this.RamAddress; return sizeAddress; }
private uint SearchDecoder() { DataReader reader = new DataReader(this.Stream); long startPosition = this.Stream.Position; uint decoderAddress = 0x00; while (this.Stream.Position - startPosition < SecureAreaSize && decoderAddress == 0x00) { long loopPosition = this.Stream.RelativePosition; // Compare instructions to see if it's the routing we want bool found = true; for (int i = 0; i < DecoderOps.Length && found; i++) { if (reader.ReadUInt32() != DecoderOps[i]) { found = false; } } if (found) decoderAddress = (uint)loopPosition - DecoderShift; // Get start of routine else this.Stream.Seek(loopPosition + 4, SeekMode.Origin); // Go to next instruction } return decoderAddress; }
private uint SearchBaseOffset(uint decoderAddress) { DataReader reader = new DataReader(this.Stream); uint instr; // Search the instruction: BL DecoderAddress // Where DecoderAddress=(PC+8+nn*4) bool found = false; while (this.Stream.RelativePosition < decoderAddress && !found) { instr = reader.ReadUInt32(); if ((instr & 0xFF000000) == 0xEB000000) { uint shift = instr & 0x00FFFFFF; shift = 4 + shift * 4; // Check if that jump goes to the correct routine if (this.Stream.RelativePosition + shift == decoderAddress) found = true; } } // Search for the Load instruction, btw LDR R1=[PC+ZZ]. // Usually two instruction before. this.Stream.Seek(-0x0C, SeekMode.Current); uint baseOffset = 0x00; instr = reader.ReadUInt32(); if ((instr & 0xFFFF0000) == 0xE59F0000) baseOffset = (uint)this.Stream.RelativePosition + (instr & 0xFFF) + 4; // If not found... Should we continue looking above instructions? // I run a test with > 500 games and at the moment it is always there return baseOffset; }
public virtual void Read(DataStream stream) { DataReader reader = new DataReader(stream); this.Id = reader.ReadUInt32(); }
public static Block FromStream(DataStream stream, Type entryType) { Block b = new Block(); DataReader reader = new DataReader(stream); reader.ReadUInt32(); // Block size b.Entries = new List<Entry>(); while (true) { uint id = reader.ReadUInt32(); if (id == 0xFFFFFFFF) break; else stream.Seek(-0x04, SeekMode.Current); Entry entry = (Entry)Activator.CreateInstance(entryType); entry.Read(stream); b.Entries.Add(entry); } return b; }
/// <summary> /// Read a FNT section from a stream. /// </summary> /// <param name="str">Stream to read from.</param> public override void Read(DataStream str) { DataReader dr = new DataReader(str); uint fntOffset = (uint)str.Position; // Get the number of directories and the offset to subtables // from the main table. uint subtablesOffset = dr.ReadUInt32() + fntOffset; dr.ReadUInt16(); ushort numDirs = dr.ReadUInt16(); this.tables = new Fnt.FntTable[numDirs]; for (int i = 0; i < numDirs; i++) { str.Seek(fntOffset + (i * FntEntrySize), SeekMode.Origin); // Error, in some cases the number of directories is wrong. // Found in FF Four Heroes of Light, Tetris Party deluxe. if (str.Position > subtablesOffset) { numDirs = (ushort)i; Array.Resize(ref this.tables, numDirs); break; } FntTable table = new FntTable( dr.ReadUInt32(), // Offset dr.ReadUInt16(), // Id First File dr.ReadUInt16()); // Id Parent Folder // Read subtable str.Seek(fntOffset + table.Offset, SeekMode.Origin); table.Read(str); this.tables[i] = table; } }
/// <summary> /// Create a new overlay file from the info in the overlay table. /// </summary> /// <param name="str">Stream to read the table.</param> /// <param name="listFiles">List of files where the overlay must be.</param> /// <returns>Overlay file.</returns> public static OverlayFile FromTable(DataStream str, bool isArm9, GameFile[] listFiles) { DataReader dr = new DataReader(str); str.Seek(0x18, SeekMode.Current); uint fileId = dr.ReadUInt32(); str.Seek(-0x1C, SeekMode.Current); OverlayFile overlay = new OverlayFile(listFiles[fileId], isArm9); overlay.OverlayId = dr.ReadUInt32(); overlay.RamAddress = dr.ReadUInt32(); overlay.RamSize = dr.ReadUInt32(); overlay.BssSize = dr.ReadUInt32(); overlay.StaticInitStart = dr.ReadUInt32(); overlay.StaticInitEnd = dr.ReadUInt32(); dr.ReadUInt32(); // File ID again uint encodingInfo = dr.ReadUInt32(); overlay.EncodedSize = encodingInfo & 0x00FFFFFF; overlay.IsEncoded = ((encodingInfo >> 24) & 0x01) == 1; overlay.IsSigned = ((encodingInfo >> 24) & 0x02) == 2; return overlay; }