public static void Apply(NameChange NC) { if (!NameChange.Pending.Contains(NC)) { return; } { string DATFileName = FFXI.GetFilePath(6720 + (ushort)((NC.ID_ >> 12) & 0xff)); if (DATFileName != null) { FileStream DATFile = new FileStream(DATFileName, FileMode.Open, FileAccess.ReadWrite); BinaryReader BR = new BinaryReader(DATFile, Encoding.ASCII); bool Found = false; while (DATFile.Position < DATFile.Length) { string Name = new string(BR.ReadChars(0x18)).TrimEnd('\0'); uint ID = BR.ReadUInt32(); if (ID == NC.ID_) { Found = true; if (Name != NC.Old_) { if (MessageBox.Show(String.Format(I18N.GetText("Message:OldNameMismatch"), NC.Old_, NC.New_, Name), I18N.GetText("Title:OldNameMismatch"), MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.No) { return; } } break; } } if (!Found) { MessageBox.Show(String.Format(I18N.GetText("Message:EntryNotFound"), NC.ID_, NC.Old_, NC.New_, DATFileName), I18N.GetText("Title:EntryNotFound"), MessageBoxButtons.OK, MessageBoxIcon.Error); return; } string NewName = NC.New_.PadRight(0x18, '\0'); DATFile.Position -= 0x1C; DATFile.Write(Encoding.ASCII.GetBytes(NewName), 0, 0x18); DATFile.Close(); } } NameChange.Pending.Remove(NC); foreach (NameChange ANC in NameChange.Applied) { if (ANC.ID == NC.ID) { if (ANC.Old_ == NC.New_) // Reverting existing applied change { NameChange.Applied.Remove(ANC); } else { ANC.New_ = NC.New_; } return; } } NameChange.Applied.Add(NC); }
private void TranslateAbilityFile(int JPFileNumber, int ENFileNumber) { if (!this.mnuTranslateAbilityNames.Checked && !this.mnuTranslateAbilityDescriptions.Checked) { return; } if (!this.BackupFile(JPFileNumber)) { return; } try { string JFileName = FFXI.GetFilePath(JPFileNumber); string EFileName = FFXI.GetFilePath(ENFileNumber); this.AddLogEntry(String.Format(I18N.GetText("TranslatingAbilities"), JFileName)); this.AddLogEntry(String.Format(I18N.GetText("UsingEnglishFile"), EFileName)); FileStream JFileStream = new FileStream(JFileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None); FileStream EFileStream = new FileStream(EFileName, FileMode.Open, FileAccess.Read); if ((JFileStream.Length % 0x400) != 0 || (EFileStream.Length % 0x400) != 0) { this.AddLogEntry(I18N.GetText("AbilityFileSizeBad")); goto TranslationDone; } if (JFileStream.Length != EFileStream.Length) { this.AddLogEntry(I18N.GetText("FileSizeMismatch")); goto TranslationDone; } long AbilityCount = JFileStream.Length / 0x400; byte[] JTextBlock = new byte[0x120]; byte[] ETextBlock = new byte[0x120]; for (long i = 0; i < AbilityCount; ++i) { JFileStream.Seek(i * 0x400 + 0xa, SeekOrigin.Begin); JFileStream.Read(JTextBlock, 0, 0x120); EFileStream.Seek(i * 0x400 + 0xa, SeekOrigin.Begin); EFileStream.Read(ETextBlock, 0, 0x120); if (this.mnuTranslateAbilityNames.Checked) { Array.Copy(ETextBlock, 0x00, JTextBlock, 0x00, 0x020); } if (this.mnuTranslateAbilityDescriptions.Checked) { Array.Copy(ETextBlock, 0x20, JTextBlock, 0x20, 0x100); } JFileStream.Seek(i * 0x400 + 0xa, SeekOrigin.Begin); JFileStream.Write(JTextBlock, 0, 0x120); } TranslationDone: JFileStream.Close(); EFileStream.Close(); } catch { this.LogFailure("TranslateAbilityFile"); } }
public ROMMenuItem(string Text, int FileID, EventHandler OnClick) : base(Text, OnClick) { if (FFXI.GetFilePath(FileID, out this.App_, out this.Dir_, out this.File_)) { this.UpdatePath(); } else { this.Enabled = false; } }
private static void ExtractFile(int FileNumber, string OutputFile) { string ROMPath; ROMPath = FFXI.GetFilePath(FileNumber, TargetApp); if (ROMPath == null || !File.Exists(ROMPath)) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(I18N.GetText("BadFileID"), FileNumber, OutputFile); Console.ForegroundColor = ConsoleColor.White; return; } Program.ExtractFile(ROMPath, OutputFile); }
private void SwapFile(int JPFileNumber, int ENFileNumber) { try { if (!this.BackupFile(JPFileNumber)) { return; } string SourceFile = FFXI.GetFilePath(ENFileNumber); string TargetFile = FFXI.GetFilePath(JPFileNumber); this.AddLogEntry(String.Format(I18N.GetText("ReplaceJPROM"), TargetFile)); this.AddLogEntry(String.Format(I18N.GetText("SourceENROM"), SourceFile)); File.Copy(SourceFile, TargetFile, true); } catch { this.LogFailure("SwapFile"); } }
private bool RestoreFile(int FileNumber) { try { string BackupName = Path.Combine(this.MakeBackupFolder(), String.Format("{0}.dat", FileNumber)); if (File.Exists(BackupName)) { string OriginalName = FFXI.GetFilePath(FileNumber); this.AddLogEntry(String.Format(I18N.GetText("Restoring"), OriginalName)); File.Copy(BackupName, OriginalName, true); } return(true); } catch { this.LogFailure("RestoreFile"); return(false); } }
private void TranslateSpellFile(int FileNumber) { if (!this.mnuTranslateSpellNames.Checked && !this.mnuTranslateSpellDescriptions.Checked) { return; } if (!this.BackupFile(FileNumber)) { return; } try { string FileName = FFXI.GetFilePath(FileNumber); this.AddLogEntry(String.Format(I18N.GetText("TranslatingSpells"), FileName)); FileStream SpellStream = new FileStream(FileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None); if ((SpellStream.Length % 0x400) != 0) { this.AddLogEntry(I18N.GetText("SpellFileSizeBad")); goto TranslationDone; } long SpellCount = SpellStream.Length / 0x400; byte[] TextBlock = new byte[0x128]; for (long i = 0; i < SpellCount; ++i) { SpellStream.Seek(i * 0x400 + 0x29, SeekOrigin.Begin); SpellStream.Read(TextBlock, 0, 0x128); if (this.mnuTranslateSpellNames.Checked) { Array.Copy(TextBlock, 0x14, TextBlock, 0x00, 0x14); // Copy english name } if (this.mnuTranslateSpellDescriptions.Checked) { Array.Copy(TextBlock, 0xa8, TextBlock, 0x28, 0x80); // Copy english description } SpellStream.Seek(i * 0x400 + 0x29, SeekOrigin.Begin); SpellStream.Write(TextBlock, 0, 0x128); } TranslationDone: SpellStream.Close(); } catch { this.LogFailure("TranslateSpellFile"); } }
private void UpdatePath() { this.Path_ = FFXI.GetFilePath(this.App_, this.Dir_, this.File_); this.Enabled = File.Exists(this.Path_); }
private void TranslateAutoTranslatorFile(int JPFileNumber, int ENFileNumber) { if (!this.BackupFile(JPFileNumber)) { return; } try { string JFileName = FFXI.GetFilePath(JPFileNumber); string EFileName = FFXI.GetFilePath(ENFileNumber); this.AddLogEntry(String.Format(I18N.GetText("TranslatingAutoTrans"), JFileName)); this.AddLogEntry(String.Format(I18N.GetText("UsingEnglishFile"), EFileName)); FileStream ATStream = new FileStream(JFileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None); MemoryStream NewStream = new MemoryStream(); BinaryReader JBR = new BinaryReader(ATStream); BinaryWriter JBW = new BinaryWriter(NewStream); BinaryReader EBR = new BinaryReader(new FileStream(EFileName, FileMode.Open, FileAccess.Read)); FFXIEncoding E = new FFXIEncoding(); while (ATStream.Position != ATStream.Length) { { // Validate & Copy ID uint JID = JBR.ReadUInt32(); uint EID = EBR.ReadUInt32(); if ((JID & 0xffff) != 0x102) { this.AddLogEntry(String.Format(I18N.GetText("ATBadJPID"), JID)); goto TranslationDone; } if ((EID & 0xffff) != 0x202) { this.AddLogEntry(String.Format(I18N.GetText("ATBadENID"), EID)); goto TranslationDone; } if ((EID & 0xffff0000) != (JID & 0xffff0000)) { this.AddLogEntry(String.Format(I18N.GetText("ATIDMismatch"), JID, EID)); goto TranslationDone; } JBW.Write(JID); } // Group name -> use English JBW.Write(EBR.ReadBytes(32)); JBR.BaseStream.Position += 32; // Completion Text -> based on config if (this.mnuPreserveJapaneseATCompletion.Checked) { JBW.Write(JBR.ReadBytes(32)); EBR.BaseStream.Position += 32; } else { byte[] EnglishCompletion = E.GetBytes(E.GetString(EBR.ReadBytes(32)).ToLowerInvariant()); // we want it lowercase if (EnglishCompletion.Length != 32) { this.AddLogEntry(String.Format(I18N.GetText("ATLowercaseProblem"), EnglishCompletion.Length)); goto TranslationDone; } JBW.Write(EnglishCompletion); JBR.BaseStream.Position += 32; } uint JEntryCount = JBR.ReadUInt32(); uint EEntryCount = EBR.ReadUInt32(); if (JEntryCount != EEntryCount) { this.AddLogEntry(String.Format(I18N.GetText("ATCountMismatch"), JEntryCount, EEntryCount)); goto TranslationDone; } JBW.Write(JEntryCount); long EntryBytesPos = JBW.BaseStream.Position; JBW.Write((uint)0); JBR.BaseStream.Position += 4; EBR.BaseStream.Position += 4; for (uint i = 0; i < JEntryCount; ++i) { // Validate & Copy ID uint JID = JBR.ReadUInt32(); uint EID = EBR.ReadUInt32(); if ((JID & 0xffff) != 0x102) { this.AddLogEntry(String.Format(I18N.GetText("ATBadJPID"), JID)); goto TranslationDone; } if ((EID & 0xffff) != 0x202) { this.AddLogEntry(String.Format(I18N.GetText("ATBadENID"), EID)); goto TranslationDone; } if ((EID & 0xffff0000) != (JID & 0xffff0000)) { this.AddLogEntry(String.Format(I18N.GetText("ATIDMismatch"), JID, EID)); goto TranslationDone; } JBW.Write(JID); // Display text -> use English byte[] EnglishText = EBR.ReadBytes(EBR.ReadByte()); JBW.Write((byte)EnglishText.Length); JBW.Write(EnglishText); JBR.BaseStream.Position += 1 + JBR.ReadByte(); // Completion Text -> based on config if (this.mnuPreserveJapaneseATCompletion.Checked) { byte[] JapaneseText = JBR.ReadBytes(JBR.ReadByte()); JBW.Write((byte)JapaneseText.Length); JBW.Write(JapaneseText); } else { byte[] LowerEnglishText = E.GetBytes(E.GetString(EnglishText).ToLowerInvariant()); JBW.Write((byte)LowerEnglishText.Length); JBW.Write(LowerEnglishText); JBR.BaseStream.Position += 1 + JBR.ReadByte(); } } long EndOfGroupPos = JBW.BaseStream.Position; JBW.BaseStream.Position = EntryBytesPos; JBW.Write((uint)(EndOfGroupPos - EntryBytesPos - 4)); JBW.BaseStream.Position = EndOfGroupPos; } ATStream.Seek(0, SeekOrigin.Begin); ATStream.Write(NewStream.ToArray(), 0, (int)NewStream.Length); ATStream.SetLength(NewStream.Length); TranslationDone: ATStream.Close(); NewStream.Close(); EBR.Close(); } catch { this.LogFailure("TranslateAutoTranslator"); } }
private void TranslateItemFile(int JPFileNumber, int ENFileNumber) { if (!this.mnuTranslateItemNames.Checked && !this.mnuTranslateItemDescriptions.Checked) { return; } if (!this.BackupFile(JPFileNumber)) { return; } try { string JFileName = FFXI.GetFilePath(JPFileNumber); string EFileName = FFXI.GetFilePath(ENFileNumber); this.AddLogEntry(String.Format(I18N.GetText("TranslatingItems"), JFileName)); this.AddLogEntry(String.Format(I18N.GetText("UsingEnglishFile"), EFileName)); FileStream JStream = new FileStream(JFileName, FileMode.Open, FileAccess.ReadWrite, FileShare.None); FileStream EStream = new FileStream(EFileName, FileMode.Open, FileAccess.Read, FileShare.Read); if ((JStream.Length % 0xc00) != 0) { this.AddLogEntry(I18N.GetText("ItemFileSizeBad")); goto TranslationDone; } if (JStream.Length != EStream.Length) { this.AddLogEntry(I18N.GetText("FileSizeMismatch")); goto TranslationDone; } Things.Item.Type T; { BinaryReader BR = new BinaryReader(JStream); Things.Item.DeduceType(BR, out T); BR = new BinaryReader(EStream); Things.Item.Type ET; Things.Item.DeduceType(BR, out ET); if (T != ET) { this.AddLogEntry(I18N.GetText("ItemTypeMismatch")); goto TranslationDone; } } ushort StringBase = 0; switch (T) { case Things.Item.Type.Armor: StringBase = 36; break; case Things.Item.Type.Item: StringBase = 20; break; case Things.Item.Type.PuppetItem: StringBase = 24; break; case Things.Item.Type.UsableItem: StringBase = 16; break; case Things.Item.Type.Weapon: StringBase = 44; break; case Things.Item.Type.Slip: StringBase = 80; break; default: this.AddLogEntry(I18N.GetText("ItemTypeBad")); goto TranslationDone; } long ItemCount = JStream.Length / 0xc00; byte[] JData = new byte[0x280]; byte[] EData = new byte[0x280]; MemoryStream JMemStream = new MemoryStream(JData, true); MemoryStream EMemStream = new MemoryStream(EData, false); FFXIEncoding E = new FFXIEncoding(); for (long i = 0; i < ItemCount; ++i) { JStream.Seek(i * 0xc00, SeekOrigin.Begin); JStream.Read(JData, 0, 0x280); EStream.Seek(i * 0xc00, SeekOrigin.Begin); EStream.Read(EData, 0, 0x280); FFXIEncryption.Rotate(JData, 5); FFXIEncryption.Rotate(EData, 5); // Read English or Japanese Name List <byte> Name = new List <byte>(); { MemoryStream MS = null; if (this.mnuTranslateItemNames.Checked) { MS = EMemStream; } else { MS = JMemStream; } MS.Position = StringBase + 4; BinaryReader BR = new BinaryReader(MS); MS.Position = StringBase + 0x1c + BR.ReadUInt32(); while (MS.Position < 0x280) { int B = MS.ReadByte(); if (B <= 0) { break; } Name.Add((byte)B); } Name.Add(0); while (Name.Count % 4 != 0) { Name.Add(0); } } // Read English or Japanese Description List <byte> Description = new List <byte>(); { MemoryStream MS = null; if (this.mnuTranslateItemDescriptions.Checked) { EMemStream.Position = StringBase + 4 + 8 * 4; MS = EMemStream; } else { JMemStream.Position = StringBase + 4 + 8 * 1; MS = JMemStream; } BinaryReader BR = new BinaryReader(MS); MS.Position = StringBase + 0x1c + BR.ReadUInt32(); while (MS.Position < 0x280) { int B = MS.ReadByte(); if (B <= 0) { break; } Description.Add((byte)B); } Description.Add(0); while (Description.Count % 4 != 0) { Description.Add(0); } } { // Construct a new string table BinaryWriter BW = new BinaryWriter(JMemStream); Array.Clear(JData, StringBase, 0x280 - StringBase); JMemStream.Position = StringBase; uint NameOffset = 0x14; // Right after the string table header uint DescOffset = NameOffset + (uint)Name.Count + 28; BW.Write((uint)2); // String Count BW.Write(NameOffset); // Entry #1 BW.Write((uint)0); BW.Write(DescOffset); // Entry #2 BW.Write((uint)0); // String #1 - Padding + text bytes BW.Write((uint)1); BW.Write((ulong)0); BW.Write((ulong)0); BW.Write((ulong)0); BW.Write(Name.ToArray()); // String #2 - Padding + text bytes BW.Write((uint)1); BW.Write((ulong)0); BW.Write((ulong)0); BW.Write((ulong)0); BW.Write(Description.ToArray()); // End marker BW.Write((uint)1); } // Update file data FFXIEncryption.Rotate(JData, 3); JStream.Seek(i * 0xc00, SeekOrigin.Begin); JStream.Write(JData, 0, 0x280); } TranslationDone: JStream.Close(); EStream.Close(); } catch { this.LogFailure("TranslateItemFile"); } }