예제 #1
0
 // Block Layout:
 // 000-001 U16 Index
 // 002-002 U8  Type
 // 003-003 U8  List Icon ID (e.g. 40-47 for the elemental-colored dots)
 // 004-005 U16 MP Cost
 // 006-007 U16 Unknown (used to be the cooldown time)
 // 008-009 U16 Valid Targets
 // 00a-029 TXT Name
 // 02a-129 TXT Description (exact length unknown)
 // 12a-3fe U8  Padding (NULs)
 // 3ff-3ff U8  End marker (0xff)
 public bool Read(BinaryReader BR)
 {
     this.Clear();
     try
     {
         byte[] Bytes = BR.ReadBytes(0x400);
         if (Bytes[0x3ff] != 0xff || Bytes[9] != 0x00 || !FFXIEncryption.DecodeDataBlock(Bytes))
         {
             return(false);
         }
         FFXIEncoding E = new FFXIEncoding();
         BR                 = new BinaryReader(new MemoryStream(Bytes, false));
         this.ID_           = BR.ReadUInt16();
         this.Type_         = (AbilityType)BR.ReadByte();
         this.ListIconID_   = BR.ReadByte();
         this.MPCost_       = BR.ReadUInt16();
         this.Unknown1_     = BR.ReadUInt16();
         this.ValidTargets_ = (ValidTarget)BR.ReadUInt16();
         this.Name_         = E.GetString(BR.ReadBytes(32)).TrimEnd('\0');
         this.Description_  = E.GetString(BR.ReadBytes(256)).TrimEnd('\0');
         BR.Close();
         return(true);
     }
     catch
     {
         return(false);
     }
 }
예제 #2
0
 public override ThingList Load(BinaryReader BR, ProgressCallback ProgressCallback)
 {
     ThingList TL = new ThingList();
       if (ProgressCallback != null)
     ProgressCallback(I18N.GetText("FTM:CheckingFile"), 0);
       if (BR.BaseStream.Length < 0x40 || BR.BaseStream.Position != 0)
     return TL;
     FFXIEncoding E = new FFXIEncoding();
       if (E.GetString(BR.ReadBytes(8)) != "d_msg".PadRight(8, '\0'))
     return TL;
     ushort Flag1 = BR.ReadUInt16();
       if (Flag1 != 0 && Flag1 != 1)
     return TL;
     ushort Flag2 = BR.ReadUInt16();
       if (Flag2 != 0 && Flag2 != 1)
     return TL;
       if (BR.ReadUInt32() != 3 || BR.ReadUInt32() != 3)
     return TL;
     uint FileSize = BR.ReadUInt32();
       if (FileSize != BR.BaseStream.Length)
     return TL;
     uint HeaderBytes = BR.ReadUInt32();
       if (HeaderBytes != 0x40)
     return TL;
       if (BR.ReadUInt32() != 0)
     return TL;
     int BytesPerEntry = BR.ReadInt32();
       if (BytesPerEntry < 0)
     return TL;
     uint DataBytes = BR.ReadUInt32();
       if (FileSize != (HeaderBytes + DataBytes) || (DataBytes % BytesPerEntry) != 0)
     return TL;
     uint EntryCount = BR.ReadUInt32();
       if (EntryCount * BytesPerEntry != DataBytes)
     return TL;
       if (BR.ReadUInt32() != 1 || BR.ReadUInt64() != 0 || BR.ReadUInt64() != 0)
     return TL;
       if (ProgressCallback != null)
     ProgressCallback(I18N.GetText("FTM:LoadingData"), 0);
       for (uint i = 0; i < EntryCount; ++i) {
       BinaryReader EntryBR = new BinaryReader(new MemoryStream(BR.ReadBytes(BytesPerEntry)));
     EntryBR.BaseStream.Position = 0;
       bool ItemAdded = false;
     {
     Things.DMSGStringBlock SB = new Things.DMSGStringBlock();
       if (SB.Read(EntryBR, E, i)) {
     TL.Add(SB);
     ItemAdded = true;
       }
     }
     EntryBR.Close();
     if (!ItemAdded) {
       TL.Clear();
       break;
     }
     if (ProgressCallback != null)
       ProgressCallback(null, (double) (i + 1) / EntryCount);
       }
       return TL;
 }
예제 #3
0
 public override ThingList Load(BinaryReader BR, ProgressCallback ProgressCallback)
 {
     ThingList TL = new ThingList();
     if (ProgressCallback != null)
     {
         ProgressCallback(I18N.GetText("FTM:CheckingFile"), 0);
     }
     if (BR.BaseStream.Length < 0x38 || BR.BaseStream.Position != 0)
     {
         return TL;
     }
     FFXIEncoding E = new FFXIEncoding();
     // Read past the marker (32 bytes)
     if ((E.GetString(BR.ReadBytes(10)) != "XISTRING".PadRight(10, '\0')) || BR.ReadUInt16() != 2)
     {
         return TL;
     }
     foreach (byte B in BR.ReadBytes(20))
     {
         if (B != 0)
         {
             return TL;
         }
     }
     // Read The Header
     uint FileSize = BR.ReadUInt32();
     if (FileSize != BR.BaseStream.Length)
     {
         return TL;
     }
     uint EntryCount = BR.ReadUInt32();
     uint EntryBytes = BR.ReadUInt32();
     uint DataBytes = BR.ReadUInt32();
     BR.ReadUInt32(); // Unknown
     BR.ReadUInt32(); // Unknown
     if (EntryBytes != EntryCount * 12 || FileSize != 0x38 + EntryBytes + DataBytes)
     {
         return TL;
     }
     if (ProgressCallback != null)
     {
         ProgressCallback(I18N.GetText("FTM:LoadingData"), 0);
     }
     for (uint i = 0; i < EntryCount; ++i)
     {
         Things.XIStringTableEntry XSTE = new Things.XIStringTableEntry();
         if (!XSTE.Read(BR, E, i, EntryBytes, DataBytes))
         {
             TL.Clear();
             break;
         }
         if (ProgressCallback != null)
         {
             ProgressCallback(null, (double)(i + 1) / EntryCount);
         }
         TL.Add(XSTE);
     }
     return TL;
 }
예제 #4
0
 public override ThingList Load(BinaryReader BR, ProgressCallback ProgressCallback)
 {
     ThingList TL = new ThingList();
       if (ProgressCallback != null)
     ProgressCallback(I18N.GetText("FTM:CheckingFile"), 0);
       if (BR.BaseStream.Length < 0x40 || BR.BaseStream.Position != 0)
     return TL;
     FFXIEncoding E = new FFXIEncoding();
       // Skip (presumably) fixed portion of the header
       if ((E.GetString(BR.ReadBytes(8)) != "d_msg".PadRight(8, '\0')) || BR.ReadUInt16() != 1 || BR.ReadUInt16() != 1 || BR.ReadUInt32() != 3 || BR.ReadUInt32() != 3)
     return TL;
       // Read the useful header fields
     uint FileSize = BR.ReadUInt32();
       if (FileSize != BR.BaseStream.Length)
     return TL;
     uint HeaderBytes = BR.ReadUInt32();
       if (HeaderBytes != 0x40)
     return TL;
     uint EntryBytes = BR.ReadUInt32();
       if (BR.ReadUInt32() != 0)
     return TL;
     uint DataBytes  = BR.ReadUInt32();
       if (FileSize != HeaderBytes + EntryBytes + DataBytes)
     return TL;
     uint EntryCount = BR.ReadUInt32();
       if (EntryBytes != EntryCount * 8)
     return TL;
       if (BR.ReadUInt32() != 1 || BR.ReadUInt64() != 0 || BR.ReadUInt64() != 0)
     return TL;
       if (ProgressCallback != null)
     ProgressCallback(I18N.GetText("FTM:LoadingData"), 0);
       for (uint i = 0; i < EntryCount; ++i) {
     BR.BaseStream.Position = HeaderBytes + i * 8;
       int Offset = ~BR.ReadInt32();
       int Length = ~BR.ReadInt32();
     if (Length < 0 || Offset < 0 || Offset + Length > DataBytes) {
       TL.Clear();
       break;
     }
     BR.BaseStream.Position = HeaderBytes + EntryBytes + Offset;
       BinaryReader EntryBR = new BinaryReader(new MemoryStream(BR.ReadBytes(Length)));
       bool ItemAdded = false;
     {
     Things.DMSGStringBlock SB = new Things.DMSGStringBlock();
       if (SB.Read(EntryBR, E, i)) {
     TL.Add(SB);
     ItemAdded = true;
       }
     }
     EntryBR.Close();
     if (!ItemAdded) {
       TL.Clear();
       break;
     }
     if (ProgressCallback != null)
       ProgressCallback(null, (double) (i + 1) / EntryCount);
       }
       return TL;
 }
예제 #5
0
        // Block Layout:
        // 000-003 U32 Index
        // 004-007 U32 Unknown
        // 008-00b U32 Unknown
        // 00c-00f U32 Unknown
        // 010-013 U32 Unknown
        // 014-02b     Unknown
        // 02c-0ab TXT Description
        // 0ac-27f     Unknown
        // 280-281 U16 Icon Size
        // 282-bff IMG Icon (+ padding)
        public bool Read(BinaryReader BR)
        {
            this.Clear();
            try
            {
                byte[] Bytes     = BR.ReadBytes(0x280);
                byte[] IconBytes = BR.ReadBytes(0x980);
                if (!FFXIEncryption.DecodeDataBlock(Bytes))
                {
                    return(false);
                }
                if (IconBytes[0x97f] != 0xff)
                {
                    return(false);
                }
                {
                    // Verify that the icon info is valid
                    Graphic      StatusIcon = new Graphic();
                    BinaryReader IconBR     = new BinaryReader(new MemoryStream(IconBytes, false));
                    int          IconSize   = IconBR.ReadInt32();
                    if (IconSize > 0 && IconSize <= 0x97b)
                    {
                        if (!StatusIcon.Read(IconBR) || IconBR.BaseStream.Position != 4 + IconSize)
                        {
                            IconBR.Close();
                            return(false);
                        }
                    }
                    IconBR.Close();
                    if (StatusIcon == null)
                    {
                        return(false);
                    }
                    this.Icon_ = StatusIcon;
                }
                BR = new BinaryReader(new MemoryStream(Bytes, false));
            }
            catch
            {
                return(false);
            }
            FFXIEncoding E = new FFXIEncoding();

            this.ID_       = BR.ReadUInt16();
            this.Unknown1_ = BR.ReadUInt16();
            this.Unknown2_ = BR.ReadUInt32();
            this.Unknown3_ = BR.ReadUInt32();
            this.Unknown4_ = BR.ReadUInt32();
            this.Unknown4_ = BR.ReadUInt32();
            BR.ReadBytes(0x18);
            this.Description_ = E.GetString(BR.ReadBytes(128)).TrimEnd('\0');
            BR.Close();
            return(true);
        }
예제 #6
0
 public bool Read(BinaryReader BR)
 {
     this.Clear();
     try {
         FFXIEncoding E = new FFXIEncoding();
         this.Name_ = E.GetString(BR.ReadBytes(0x1C)).TrimEnd('\0');
         this.ID_   = BR.ReadUInt32();
         // ID seems to be 010 + zone id + mob id (=> there's a hard max of 0xFFF (= 4095) mobs per zone, which seems plenty :))
         // Special 'instanced' zones like MMM or Meebles use 013 + 'zone id' + mob id.
         if ((this.ID_ != 0 && (this.ID_ & 0xFFF00000) != 0x01000000) && (this.ID_ != 0 && (this.ID_ & 0xFFF00000) != 0x01300000) && (this.ID_ != 0 && (this.ID_ & 0xFFF00000) != 0x01100000))
         {
             return(false);
         }
         return(true);
     } catch { return(false); }
 }
예제 #7
0
 public override ThingList Load(BinaryReader BR, ProgressCallback ProgressCallback)
 {
     ThingList TL = new ThingList();
       if (ProgressCallback != null)
     ProgressCallback(I18N.GetText("FTM:CheckingFile"), 0);
       if (BR.BaseStream.Length < 0x38 || BR.BaseStream.Position != 0)
     return TL;
     FFXIEncoding E = new FFXIEncoding();
       // Skip (presumably) fixed portion of the header
       if ((E.GetString(BR.ReadBytes(8)) != "d_msg".PadRight(8, '\0')) || BR.ReadUInt16() != 1 || BR.ReadUInt32() != 0 || BR.ReadUInt16() != 2 || BR.ReadUInt32() != 3)
     return TL;
       // Read the useful header fields
     uint EntryCount = BR.ReadUInt32();
       if (BR.ReadUInt32() != 1)
     return TL;
     uint FileSize = BR.ReadUInt32();
       if (FileSize != BR.BaseStream.Length)
     return TL;
     uint HeaderSize = BR.ReadUInt32();
       if (HeaderSize != 0x38)
     return TL;
     uint EntryBytes = BR.ReadUInt32();
       if (EntryBytes != EntryCount * 36)
     return TL;
     uint DataBytes  = BR.ReadUInt32();
       if (FileSize != 0x38 + EntryBytes + DataBytes)
     return TL;
       // 12 NUL bytes
       if (BR.ReadUInt32() != 0 || BR.ReadUInt32() != 0 || BR.ReadUInt32() != 0)
     return TL;
       if (ProgressCallback != null)
     ProgressCallback(I18N.GetText("FTM:LoadingData"), 0);
       for (uint i = 0; i < EntryCount; ++i) {
       Things.DMSGStringTableEntry DSTE = new Things.DMSGStringTableEntry();
     if (!DSTE.Read(BR, E, i, EntryBytes, DataBytes)) {
       TL.Clear();
       break;
     }
     if (ProgressCallback != null)
       ProgressCallback(null, (double) (i + 1) / EntryCount);
     TL.Add(DSTE);
       }
       return TL;
 }
예제 #8
0
 public bool Read(BinaryReader BR)
 {
     this.Clear();
     try
     {
         FFXIEncoding E = new FFXIEncoding();
         this.Name_ = E.GetString(BR.ReadBytes(0x1C)).TrimEnd('\0');
         this.ID_ = BR.ReadUInt32();
         // ID seems to be 010 + zone id + mob id (=> there's a hard max of 0xFFF (= 4095) mobs per zone, which seems plenty :))
         // Special 'instanced' zones like MMM or Meebles use 013 + 'zone id' + mob id.
         if ((this.ID_ != 0 && (this.ID_ & 0xFFF00000) != 0x01000000) &&
             (this.ID_ != 0 && (this.ID_ & 0xFFF00000) != 0x01300000) &&
             (this.ID_ != 0 && (this.ID_ & 0xFFF00000) != 0x01100000))
         {
             return false;
         }
         return true;
     }
     catch
     {
         return false;
     }
 }
예제 #9
0
 public bool Read(BinaryReader BR)
 {
     this.Clear();
     try {
         this.ID_ = BR.ReadUInt32();
         // Read entry
         byte[] TextBytes = BR.ReadBytes(0x3b);
         this.Text_ = String.Empty;
         // Trim trailing NULs
         int ByteCount = 0x3b;
         while (TextBytes[ByteCount - 1] == 0x00)
         {
             --ByteCount;
         }
         // Process the message
         FFXIEncoding E       = new FFXIEncoding();
         int          LastPos = 0;
         for (int i = 0; i < ByteCount; ++i)
         {
             if (TextBytes[i] == 0x07) // Line Break
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += "\r\n";
                 LastPos     = i + 1;
             }
             else if (TextBytes[i] == 0x08) // Character Name (You)
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Player Name{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
                 LastPos     = i + 1;
             }
             else if (TextBytes[i] == 0x09) // Character Name (They)
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Speaker Name{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
                 LastPos     = i + 1;
             }
             else if (TextBytes[i] == 0x0a && i + 1 < TextBytes.Length)
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Numeric Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
                 LastPos     = i + 2;
                 ++i;
             }
             else if (TextBytes[i] == 0x0b) // Indicates that the lines after this are in a prompt window
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Selection Dialog{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
                 LastPos     = i + 1;
             }
             else if (TextBytes[i] == 0x0c && i + 1 < TextBytes.Length)
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Multiple Choice (Parameter {2}){1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
                 LastPos     = i + 2;
                 ++i;
             }
             else if (TextBytes[i] == 0x19 && i + 1 < TextBytes.Length)
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Item Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
                 LastPos     = i + 2;
                 ++i;
             }
             else if (TextBytes[i] == 0x1a && i + 1 < TextBytes.Length)
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Key Item Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
                 LastPos     = i + 2;
                 ++i;
             }
             else if (TextBytes[i] == 0x1c && i + 1 < TextBytes.Length) // Chocobo Name
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Player/Chocobo Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
                 LastPos     = i + 2;
                 ++i;
             }
             else if (TextBytes[i] == 0x1e && i + 1 < TextBytes.Length)
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Set Color #{2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
                 LastPos     = i + 2;
                 ++i;
             }
             else if (TextBytes[i] == 0x7f && i + 1 < TextBytes.Length) // Various stuff
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 if (TextBytes[i + 1] == 0x31 && i + 2 < TextBytes.Length) // Unknown, but seems to indicate user needs to hit RET
                 {
                     if (TextBytes[i + 2] != 0)
                     {
                         this.Text_ += String.Format("{0}{2}-Second Delay + Prompt{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
                     }
                     else
                     {
                         this.Text_ += String.Format("{0}Prompt{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
                     }
                     ++LastPos;
                     ++i;
                 }
                 else if (TextBytes[i + 1] == 0x85) // Multiple Choice: Player Gender
                 {
                     this.Text_ += String.Format("{0}Multiple Choice (Player Gender){1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
                 }
                 else if (TextBytes[i + 1] == 0x8D && i + 2 < TextBytes.Length)
                 {
                     this.Text_ += String.Format("{0}Weather Event Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
                     ++LastPos;
                     ++i;
                 }
                 else if (TextBytes[i + 1] == 0x8E && i + 2 < TextBytes.Length)
                 {
                     this.Text_ += String.Format("{0}Weather Type Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
                     ++LastPos;
                     ++i;
                 }
                 else if (TextBytes[i + 1] == 0x92 && i + 2 < TextBytes.Length)
                 {
                     this.Text_ += String.Format("{0}Singular/Plural Choice (Parameter {2}){1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
                     ++LastPos;
                     ++i;
                 }
                 else if (TextBytes[i + 1] == 0xB1 && i + 2 < TextBytes.Length) // Usually found before an item name or key item name
                 {
                     this.Text_ += String.Format("{0}Title Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
                     ++LastPos;
                     ++i;
                 }
                 else if (i + 2 < TextBytes.Length)
                 {
                     this.Text_ += String.Format("{0}Unknown Parameter (Type: {2:X2}) {3}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1], TextBytes[i + 2]);
                     ++LastPos;
                     ++i;
                 }
                 else
                 {
                     this.Text_ += String.Format("{0}Unknown Marker Type: {2:X2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
                 }
                 LastPos = i + 2;
                 ++i;
             }
             else if (TextBytes[i] == 0x7f || TextBytes[i] < 0x20)
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Possible Special Code: {2:X2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i]);
                 LastPos     = i + 1;
             }
         }
         if (LastPos < ByteCount)
         {
             this.Text_ += E.GetString(TextBytes, LastPos, ByteCount - LastPos);
         }
         return(BR.ReadByte() == 0xff);
     } catch { return(false); }
 }
예제 #10
0
        public override ThingList Load(BinaryReader BR, ProgressCallback ProgressCallback)
        {
            ThingList TL = new ThingList();

            if (ProgressCallback != null)
            {
                ProgressCallback(I18N.GetText("FTM:CheckingFile"), 0);
            }
            if (BR.BaseStream.Length < 0x40 || BR.BaseStream.Position != 0)
            {
                return(TL);
            }
            FFXIEncoding E = new FFXIEncoding();

            // Skip (presumably) fixed portion of the header
            if ((E.GetString(BR.ReadBytes(8)) != "d_msg".PadRight(8, '\0')) || BR.ReadUInt16() != 1 || BR.ReadUInt16() != 1 || BR.ReadUInt32() != 3 || BR.ReadUInt32() != 3)
            {
                return(TL);
            }
            // Read the useful header fields
            uint FileSize = BR.ReadUInt32();

            if (FileSize != BR.BaseStream.Length)
            {
                return(TL);
            }
            uint HeaderBytes = BR.ReadUInt32();

            if (HeaderBytes != 0x40)
            {
                return(TL);
            }
            uint EntryBytes = BR.ReadUInt32();

            if (BR.ReadUInt32() != 0)
            {
                return(TL);
            }
            uint DataBytes = BR.ReadUInt32();

            if (FileSize != HeaderBytes + EntryBytes + DataBytes)
            {
                return(TL);
            }
            uint EntryCount = BR.ReadUInt32();

            if (EntryBytes != EntryCount * 8)
            {
                return(TL);
            }
            if (BR.ReadUInt32() != 1 || BR.ReadUInt64() != 0 || BR.ReadUInt64() != 0)
            {
                return(TL);
            }
            if (ProgressCallback != null)
            {
                ProgressCallback(I18N.GetText("FTM:LoadingData"), 0);
            }
            for (uint i = 0; i < EntryCount; ++i)
            {
                BR.BaseStream.Position = HeaderBytes + i * 8;
                int Offset = ~BR.ReadInt32();
                int Length = ~BR.ReadInt32();
                if (Length < 0 || Offset < 0 || Offset + Length > DataBytes)
                {
                    TL.Clear();
                    break;
                }
                BR.BaseStream.Position = HeaderBytes + EntryBytes + Offset;
                BinaryReader EntryBR   = new BinaryReader(new MemoryStream(BR.ReadBytes(Length)));
                bool         ItemAdded = false;
                {
                    Things.DMSGStringBlock SB = new Things.DMSGStringBlock();
                    if (SB.Read(EntryBR, E, i))
                    {
                        TL.Add(SB);
                        ItemAdded = true;
                    }
                }
                EntryBR.Close();
                if (!ItemAdded)
                {
                    TL.Clear();
                    break;
                }
                if (ProgressCallback != null)
                {
                    ProgressCallback(null, (double)(i + 1) / EntryCount);
                }
            }
            return(TL);
        }
예제 #11
0
 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"); }
 }
예제 #12
0
        public override ThingList Load(BinaryReader BR, ProgressCallback ProgressCallback)
        {
            ThingList TL = new ThingList();

            if (ProgressCallback != null)
            {
                ProgressCallback(I18N.GetText("FTM:CheckingFile"), 0);
            }
            if (BR.BaseStream.Length < 0x38 || BR.BaseStream.Position != 0)
            {
                return(TL);
            }
            FFXIEncoding E = new FFXIEncoding();

            // Skip (presumably) fixed portion of the header
            if ((E.GetString(BR.ReadBytes(8)) != "d_msg".PadRight(8, '\0')) || BR.ReadUInt16() != 1 || BR.ReadUInt32() != 0 || BR.ReadUInt16() != 2 || BR.ReadUInt32() != 3)
            {
                return(TL);
            }
            // Read the useful header fields
            uint EntryCount = BR.ReadUInt32();

            if (BR.ReadUInt32() != 1)
            {
                return(TL);
            }
            uint FileSize = BR.ReadUInt32();

            if (FileSize != BR.BaseStream.Length)
            {
                return(TL);
            }
            uint HeaderSize = BR.ReadUInt32();

            if (HeaderSize != 0x38)
            {
                return(TL);
            }
            uint EntryBytes = BR.ReadUInt32();

            if (EntryBytes != EntryCount * 36)
            {
                return(TL);
            }
            uint DataBytes = BR.ReadUInt32();

            if (FileSize != 0x38 + EntryBytes + DataBytes)
            {
                return(TL);
            }
            // 12 NUL bytes
            if (BR.ReadUInt32() != 0 || BR.ReadUInt32() != 0 || BR.ReadUInt32() != 0)
            {
                return(TL);
            }
            if (ProgressCallback != null)
            {
                ProgressCallback(I18N.GetText("FTM:LoadingData"), 0);
            }
            for (uint i = 0; i < EntryCount; ++i)
            {
                Things.DMSGStringTableEntry DSTE = new Things.DMSGStringTableEntry();
                if (!DSTE.Read(BR, E, i, EntryBytes, DataBytes))
                {
                    TL.Clear();
                    break;
                }
                if (ProgressCallback != null)
                {
                    ProgressCallback(null, (double)(i + 1) / EntryCount);
                }
                TL.Add(DSTE);
            }
            return(TL);
        }
예제 #13
0
 // Block Layout:
 // 000-003 U32 Index
 // 004-007 U32 Unknown
 // 008-00b U32 Unknown
 // 00c-00f U32 Unknown
 // 010-013 U32 Unknown
 // 014-02b     Unknown
 // 02c-0ab TXT Description
 // 0ac-27f     Unknown
 // 280-281 U16 Icon Size
 // 282-bff IMG Icon (+ padding)
 public bool Read(BinaryReader BR)
 {
     this.Clear();
     try
     {
         byte[] Bytes = BR.ReadBytes(0x280);
         byte[] IconBytes = BR.ReadBytes(0x980);
         if (!FFXIEncryption.DecodeDataBlock(Bytes))
         {
             return false;
         }
         if (IconBytes[0x97f] != 0xff)
         {
             return false;
         }
         {
             // Verify that the icon info is valid
             Graphic StatusIcon = new Graphic();
             BinaryReader IconBR = new BinaryReader(new MemoryStream(IconBytes, false));
             int IconSize = IconBR.ReadInt32();
             if (IconSize > 0 && IconSize <= 0x97b)
             {
                 if (!StatusIcon.Read(IconBR) || IconBR.BaseStream.Position != 4 + IconSize)
                 {
                     IconBR.Close();
                     return false;
                 }
             }
             IconBR.Close();
             if (StatusIcon == null)
             {
                 return false;
             }
             this.Icon_ = StatusIcon;
         }
         BR = new BinaryReader(new MemoryStream(Bytes, false));
     }
     catch
     {
         return false;
     }
     FFXIEncoding E = new FFXIEncoding();
     this.ID_ = BR.ReadUInt16();
     this.Unknown1_ = BR.ReadUInt16();
     this.Unknown2_ = BR.ReadUInt32();
     this.Unknown3_ = BR.ReadUInt32();
     this.Unknown4_ = BR.ReadUInt32();
     this.Unknown4_ = BR.ReadUInt32();
     BR.ReadBytes(0x18);
     this.Description_ = E.GetString(BR.ReadBytes(128)).TrimEnd('\0');
     BR.Close();
     return true;
 }
예제 #14
0
 public bool Read(BinaryReader BR, uint?Index, long EntryStart, long EntryEnd)
 {
     this.Clear();
     this.Index_ = Index;
     try {
         BR.BaseStream.Seek(4 + EntryStart, SeekOrigin.Begin);
         byte[] TextBytes = BR.ReadBytes((int)(EntryEnd - EntryStart));
         for (int i = 0; i < TextBytes.Length; ++i)
         {
             TextBytes[i] ^= 0x80; // <= Evil encryption-breaking!
         }
         this.Text_ = String.Empty;
         FFXIEncoding E       = new FFXIEncoding();
         int          LastPos = 0;
         for (int i = 0; i < TextBytes.Length; ++i)
         {
             if (TextBytes[i] == 0x07) // Line Break
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += "\r\n";
                 LastPos     = i + 1;
             }
             else if (TextBytes[i] == 0x08) // Character Name (You)
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Player Name{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
                 LastPos     = i + 1;
             }
             else if (TextBytes[i] == 0x09) // Character Name (They)
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Speaker Name{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
                 LastPos     = i + 1;
             }
             else if (TextBytes[i] == 0x0a && i + 1 < TextBytes.Length)
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Numeric Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
                 LastPos     = i + 2;
                 ++i;
             }
             else if (TextBytes[i] == 0x0b) // Indicates that the lines after this are in a prompt window
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Selection Dialog{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
                 LastPos     = i + 1;
             }
             else if (TextBytes[i] == 0x0c && i + 1 < TextBytes.Length)
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Multiple Choice (Parameter {2}){1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
                 LastPos     = i + 2;
                 ++i;
             }
             else if (TextBytes[i] == 0x19 && i + 1 < TextBytes.Length)
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Item Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
                 LastPos     = i + 2;
                 ++i;
             }
             else if (TextBytes[i] == 0x1a && i + 1 < TextBytes.Length)
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Key Item Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
                 LastPos     = i + 2;
                 ++i;
             }
             else if (TextBytes[i] == 0x1c && i + 1 < TextBytes.Length) // Chocobo Name
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Player/Chocobo Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
                 LastPos     = i + 2;
                 ++i;
             }
             else if (TextBytes[i] == 0x1e && i + 1 < TextBytes.Length)
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Set Color #{2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
                 LastPos     = i + 2;
                 ++i;
             }
             else if (TextBytes[i] == 0x7f && i + 1 < TextBytes.Length) // Various stuff
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 if (TextBytes[i + 1] == 0x31 && i + 2 < TextBytes.Length) // Unknown, but seems to indicate user needs to hit RET
                 {
                     if (TextBytes[i + 2] != 0)
                     {
                         this.Text_ += String.Format("{0}{2}-Second Delay + Prompt{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
                     }
                     else
                     {
                         this.Text_ += String.Format("{0}Prompt{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
                     }
                     ++LastPos;
                     ++i;
                 }
                 else if (TextBytes[i + 1] == 0x85) // Multiple Choice: Player Gender
                 {
                     this.Text_ += String.Format("{0}Multiple Choice (Player Gender){1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
                 }
                 else if (TextBytes[i + 1] == 0x8D && i + 2 < TextBytes.Length)
                 {
                     this.Text_ += String.Format("{0}Weather Event Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
                     ++LastPos;
                     ++i;
                 }
                 else if (TextBytes[i + 1] == 0x8E && i + 2 < TextBytes.Length)
                 {
                     this.Text_ += String.Format("{0}Weather Type Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
                     ++LastPos;
                     ++i;
                 }
                 else if (TextBytes[i + 1] == 0x92 && i + 2 < TextBytes.Length)
                 {
                     this.Text_ += String.Format("{0}Singular/Plural Choice (Parameter {2}){1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
                     ++LastPos;
                     ++i;
                 }
                 else if (TextBytes[i + 1] == 0xB1 && i + 2 < TextBytes.Length) // Usually found before an item name or key item name
                 {
                     this.Text_ += String.Format("{0}Title Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
                     ++LastPos;
                     ++i;
                 }
                 else if (i + 2 < TextBytes.Length)
                 {
                     this.Text_ += String.Format("{0}Unknown Parameter (Type: {2:X2}) {3}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1], TextBytes[i + 2]);
                     ++LastPos;
                     ++i;
                 }
                 else
                 {
                     this.Text_ += String.Format("{0}Unknown Marker Type: {2:X2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
                 }
                 LastPos = i + 2;
                 ++i;
             }
             else if (TextBytes[i] == 0x7f || TextBytes[i] < 0x20)
             {
                 if (LastPos < i)
                 {
                     this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
                 }
                 this.Text_ += String.Format("{0}Possible Special Code: {2:X2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i]);
                 LastPos     = i + 1;
             }
         }
         if (LastPos < TextBytes.Length)
         {
             this.Text_ += E.GetString(TextBytes, LastPos, TextBytes.Length - LastPos);
         }
         this.Text_ = this.Text_.TrimEnd('\0');
         return(true);
     } catch { return(false); }
 }
예제 #15
0
        public override ThingList Load(BinaryReader BR, ProgressCallback ProgressCallback)
        {
            ThingList TL = new ThingList();

            if (ProgressCallback != null)
            {
                ProgressCallback(I18N.GetText("FTM:CheckingFile"), 0);
            }
            if (BR.BaseStream.Length < 0x40 || BR.BaseStream.Position != 0)
            {
                return(TL);
            }
            FFXIEncoding E = new FFXIEncoding();

            if (E.GetString(BR.ReadBytes(8)) != "d_msg".PadRight(8, '\0'))
            {
                return(TL);
            }
            ushort Flag1 = BR.ReadUInt16();

            if (Flag1 != 0 && Flag1 != 1)
            {
                return(TL);
            }
            ushort Flag2 = BR.ReadUInt16();

            if (Flag2 != 0 && Flag2 != 1)
            {
                return(TL);
            }
            if (BR.ReadUInt32() != 3 || BR.ReadUInt32() != 3)
            {
                return(TL);
            }
            uint FileSize = BR.ReadUInt32();

            if (FileSize != BR.BaseStream.Length)
            {
                return(TL);
            }
            uint HeaderBytes = BR.ReadUInt32();

            if (HeaderBytes != 0x40)
            {
                return(TL);
            }
            if (BR.ReadUInt32() != 0)
            {
                return(TL);
            }
            int BytesPerEntry = BR.ReadInt32();

            if (BytesPerEntry < 0)
            {
                return(TL);
            }
            uint DataBytes = BR.ReadUInt32();

            if (FileSize != (HeaderBytes + DataBytes) || (DataBytes % BytesPerEntry) != 0)
            {
                return(TL);
            }
            uint EntryCount = BR.ReadUInt32();

            if (EntryCount * BytesPerEntry != DataBytes)
            {
                return(TL);
            }
            if (BR.ReadUInt32() != 1 || BR.ReadUInt64() != 0 || BR.ReadUInt64() != 0)
            {
                return(TL);
            }
            if (ProgressCallback != null)
            {
                ProgressCallback(I18N.GetText("FTM:LoadingData"), 0);
            }
            for (uint i = 0; i < EntryCount; ++i)
            {
                BinaryReader EntryBR = new BinaryReader(new MemoryStream(BR.ReadBytes(BytesPerEntry)));
                EntryBR.BaseStream.Position = 0;
                bool ItemAdded = false;
                {
                    Things.DMSGStringBlock SB = new Things.DMSGStringBlock();
                    if (SB.Read(EntryBR, E, i))
                    {
                        TL.Add(SB);
                        ItemAdded = true;
                    }
                }
                EntryBR.Close();
                if (!ItemAdded)
                {
                    TL.Clear();
                    break;
                }
                if (ProgressCallback != null)
                {
                    ProgressCallback(null, (double)(i + 1) / EntryCount);
                }
            }
            return(TL);
        }
예제 #16
0
 public bool Read(BinaryReader BR)
 {
     this.Clear();
       try {
     this.ID_ = BR.ReadUInt32();
     // Read entry
       byte[] TextBytes = BR.ReadBytes(0x3b);
     this.Text_ = String.Empty;
     // Trim trailing NULs
       int ByteCount = 0x3b;
     while (TextBytes[ByteCount - 1] == 0x00)
       --ByteCount;
     // Process the message
       FFXIEncoding E = new FFXIEncoding();
       int LastPos = 0;
     for (int i = 0; i < ByteCount; ++i) {
       if (TextBytes[i] == 0x07) { // Line Break
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += "\r\n";
     LastPos = i + 1;
       }
       else if (TextBytes[i] == 0x08) { // Character Name (You)
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Player Name{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
     LastPos = i + 1;
       }
       else if (TextBytes[i] == 0x09) { // Character Name (They)
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Speaker Name{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
     LastPos = i + 1;
       }
       else if (TextBytes[i] == 0x0a && i + 1 < TextBytes.Length) {
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Numeric Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
     LastPos = i + 2;
     ++i;
       }
       else if (TextBytes[i] == 0x0b) { // Indicates that the lines after this are in a prompt window
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Selection Dialog{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
     LastPos = i + 1;
       }
       else if (TextBytes[i] == 0x0c && i + 1 < TextBytes.Length) {
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Multiple Choice (Parameter {2}){1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
     LastPos = i + 2;
     ++i;
       }
       else if (TextBytes[i] == 0x19 && i + 1 < TextBytes.Length) {
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Item Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
     LastPos = i + 2;
     ++i;
       }
       else if (TextBytes[i] == 0x1a && i + 1 < TextBytes.Length) {
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Key Item Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
     LastPos = i + 2;
     ++i;
       }
       else if (TextBytes[i] == 0x1c && i + 1 < TextBytes.Length) { // Chocobo Name
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Player/Chocobo Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
     LastPos = i + 2;
     ++i;
       }
       else if (TextBytes[i] == 0x1e && i + 1 < TextBytes.Length) {
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Set Color #{2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
     LastPos = i + 2;
     ++i;
       }
       else if (TextBytes[i] == 0x7f && i + 1 < TextBytes.Length) { // Various stuff
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     if (TextBytes[i + 1] == 0x31 && i + 2 < TextBytes.Length) { // Unknown, but seems to indicate user needs to hit RET
       if (TextBytes[i + 2] != 0)
         this.Text_ += String.Format("{0}{2}-Second Delay + Prompt{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
       else
         this.Text_ += String.Format("{0}Prompt{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
       ++LastPos;
       ++i;
     }
     else if (TextBytes[i + 1] == 0x85) // Multiple Choice: Player Gender
       this.Text_ += String.Format("{0}Multiple Choice (Player Gender){1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
     else if (TextBytes[i + 1] == 0x8D && i + 2 < TextBytes.Length) {
       this.Text_ += String.Format("{0}Weather Event Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
       ++LastPos;
       ++i;
     }
     else if (TextBytes[i + 1] == 0x8E && i + 2 < TextBytes.Length) {
       this.Text_ += String.Format("{0}Weather Type Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
       ++LastPos;
       ++i;
     }
     else if (TextBytes[i + 1] == 0x92 && i + 2 < TextBytes.Length) {
       this.Text_ += String.Format("{0}Singular/Plural Choice (Parameter {2}){1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
       ++LastPos;
       ++i;
     }
     else if (TextBytes[i + 1] == 0xB1 && i + 2 < TextBytes.Length) { // Usually found before an item name or key item name
       this.Text_ += String.Format("{0}Title Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
       ++LastPos;
       ++i;
     }
     else if (i + 2 < TextBytes.Length) {
       this.Text_ += String.Format("{0}Unknown Parameter (Type: {2:X2}) {3}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1], TextBytes[i + 2]);
       ++LastPos;
       ++i;
     }
     else
       this.Text_ += String.Format("{0}Unknown Marker Type: {2:X2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
     LastPos = i + 2;
     ++i;
       }
       else if (TextBytes[i] == 0x7f || TextBytes[i] < 0x20) {
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Possible Special Code: {2:X2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i]);
     LastPos = i + 1;
       }
     }
     if (LastPos < ByteCount)
       this.Text_ += E.GetString(TextBytes, LastPos, ByteCount - LastPos);
     return (BR.ReadByte() == 0xff);
       } catch { return false; }
 }
예제 #17
0
        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");
            }
        }
예제 #18
0
        public override ThingList Load(BinaryReader BR, ProgressCallback ProgressCallback)
        {
            ThingList TL = new ThingList();

            if (ProgressCallback != null)
            {
                ProgressCallback(I18N.GetText("FTM:CheckingFile"), 0);
            }
            if (BR.BaseStream.Length < 0x38 || BR.BaseStream.Position != 0)
            {
                return(TL);
            }
            FFXIEncoding E = new FFXIEncoding();

            // Read past the marker (32 bytes)
            if ((E.GetString(BR.ReadBytes(10)) != "XISTRING".PadRight(10, '\0')) || BR.ReadUInt16() != 2)
            {
                return(TL);
            }
            foreach (byte B in BR.ReadBytes(20))
            {
                if (B != 0)
                {
                    return(TL);
                }
            }
            // Read The Header
            uint FileSize = BR.ReadUInt32();

            if (FileSize != BR.BaseStream.Length)
            {
                return(TL);
            }
            uint EntryCount = BR.ReadUInt32();
            uint EntryBytes = BR.ReadUInt32();
            uint DataBytes  = BR.ReadUInt32();

            BR.ReadUInt32(); // Unknown
            BR.ReadUInt32(); // Unknown
            if (EntryBytes != EntryCount * 12 || FileSize != 0x38 + EntryBytes + DataBytes)
            {
                return(TL);
            }
            if (ProgressCallback != null)
            {
                ProgressCallback(I18N.GetText("FTM:LoadingData"), 0);
            }
            for (uint i = 0; i < EntryCount; ++i)
            {
                Things.XIStringTableEntry XSTE = new Things.XIStringTableEntry();
                if (!XSTE.Read(BR, E, i, EntryBytes, DataBytes))
                {
                    TL.Clear();
                    break;
                }
                if (ProgressCallback != null)
                {
                    ProgressCallback(null, (double)(i + 1) / EntryCount);
                }
                TL.Add(XSTE);
            }
            return(TL);
        }
예제 #19
0
 // Block Layout:
 // 000-001 U16 Index
 // 002-002 U8  Type
 // 003-003 U8  List Icon ID (e.g. 40-47 for the elemental-colored dots)
 // 004-005 U16 MP Cost
 // 006-007 U16 Unknown (used to be the cooldown time)
 // 008-009 U16 Valid Targets
 // 00a-029 TXT Name
 // 02a-129 TXT Description (exact length unknown)
 // 12a-3fe U8  Padding (NULs)
 // 3ff-3ff U8  End marker (0xff)
 public bool Read(BinaryReader BR)
 {
     this.Clear();
       try {
       byte[] Bytes = BR.ReadBytes(0x400);
     if (Bytes[0x3ff] != 0xff || Bytes[9] != 0x00 || !FFXIEncryption.DecodeDataBlock(Bytes))
       return false;
       FFXIEncoding E = new FFXIEncoding();
     BR = new BinaryReader(new MemoryStream(Bytes, false));
     this.ID_           = BR.ReadUInt16();
     this.Type_         = (AbilityType) BR.ReadByte();
     this.ListIconID_   = BR.ReadByte();
     this.MPCost_       = BR.ReadUInt16();
     this.Unknown1_     = BR.ReadUInt16();
     this.ValidTargets_ = (ValidTarget) BR.ReadUInt16();
     this.Name_         = E.GetString(BR.ReadBytes(32)).TrimEnd('\0');
     this.Description_  = E.GetString(BR.ReadBytes(256)).TrimEnd('\0');
     BR.Close();
     return true;
       } catch { return false; }
 }
예제 #20
0
 // Block Layout:
 // 000-001 U16 Index
 // 002-003 U16 Magic Type (1/2/3/4/5/6 - White/Black/Summon/Ninja/Bard/Blue)
 // 004-005 U16 Element
 // 006-007 U16 Valid Targets
 // 008-009 U16 Skill
 // 00a-00b U16 MP Cost
 // 00c-00c U8  Cast Time (1/4 second)
 // 00d-00d U8  Recast Delay (1/4 second)
 // 00e-025 U8  Level required (1 byte per job, 0xff if not learnable; first is for the NUL job, so always 0xff; only 24 slots despite 32 possible job flags)
 // 026-027 U16 ID (0 for "unused" spells; starts out equal to the index, but doesn't stay that way)
 // 028-028 U8  List Icon ID (not sure what this is an index of, but it seems to match differences in item icon)
 // 029-03c CHR Japanese Name (20 bytes)
 // 03d-051 CHR English Name (20 bytes)
 // 052-0d1 CHR Japanese Description (128 bytes)
 // 0d2-151 CHR English Description (128 bytes)
 // 152-3fe U8  Padding (NULs)
 // 3ff-3ff U8  End marker (0xff)
 public bool Read(BinaryReader BR)
 {
     this.Clear();
       try {
       byte[] Bytes = BR.ReadBytes(0x400);
     if (Bytes[0x3] != 0x00 || Bytes[0x5] != 0x00 || Bytes[0x7] != 0x00 || Bytes[0x9] != 0x00 || Bytes[0xf] != 0xff || Bytes[0x3ff] != 0xff)
       return false;
     if (!FFXIEncryption.DecodeDataBlock(Bytes))
       return false;
     BR = new BinaryReader(new MemoryStream(Bytes, false));
       } catch { return false; }
       this.Index_         = BR.ReadUInt16();
       this.MagicType_     = (MagicType)   BR.ReadUInt16();
       this.Element_       = (Element)     BR.ReadUInt16();
       this.ValidTargets_  = (ValidTarget) BR.ReadUInt16();
       this.Skill_         = (Skill)       BR.ReadUInt16();
       this.MPCost_        = BR.ReadUInt16();
       this.CastingTime_   = BR.ReadByte();
       this.RecastDelay_   = BR.ReadByte();
       this.LevelRequired_ = BR.ReadBytes(24);
       this.ID_            = BR.ReadUInt16();
       this.ListIconID_    = BR.ReadByte();
       FFXIEncoding E = new FFXIEncoding();
       this.JapaneseName_        = E.GetString(BR.ReadBytes( 20)).TrimEnd('\0');
       this.EnglishName_         = E.GetString(BR.ReadBytes( 20)).TrimEnd('\0');
       this.JapaneseDescription_ = E.GetString(BR.ReadBytes(128)).TrimEnd('\0');
       this.EnglishDescription_  = E.GetString(BR.ReadBytes(128)).TrimEnd('\0');
       // A slightly newer revision of this format no longer has the names, so mark them unset when empty
       if (this.JapaneseName_       .Length == 0) this.JapaneseName_        = null;
       if (this.EnglishName_        .Length == 0) this.EnglishName_         = null;
       if (this.JapaneseDescription_.Length == 0) this.JapaneseDescription_ = null;
       if (this.EnglishDescription_ .Length == 0) this.EnglishDescription_  = null;
     #if DEBUG
       { // Read the next 64 bits, and report if it's not 0 (means there's new data to identify)
       ulong Next64 = BR.ReadUInt64();
     if (Next64 != 0) {
       Console.ForegroundColor = ConsoleColor.Red;
       Console.WriteLine("Nonzero data after entry (Spell #{0}): {1:X16}", this.ID_, Next64);
       Console.ResetColor();
     }
       }
     #endif
       BR.Close();
       return true;
 }
예제 #21
0
        // Block Layout:
        // 000-001 U16 Index
        // 002-003 U16 Magic Type (1/2/3/4/5/6 - White/Black/Summon/Ninja/Bard/Blue)
        // 004-005 U16 Element
        // 006-007 U16 Valid Targets
        // 008-009 U16 Skill
        // 00a-00b U16 MP Cost
        // 00c-00c U8  Cast Time (1/4 second)
        // 00d-00d U8  Recast Delay (1/4 second)
        // 00e-025 U8  Level required (1 byte per job, 0xff if not learnable; first is for the NUL job, so always 0xff; only 24 slots despite 32 possible job flags)
        // 026-027 U16 ID (0 for "unused" spells; starts out equal to the index, but doesn't stay that way)
        // 028-028 U8  List Icon ID (not sure what this is an index of, but it seems to match differences in item icon)
        // 029-03c CHR Japanese Name (20 bytes)
        // 03d-051 CHR English Name (20 bytes)
        // 052-0d1 CHR Japanese Description (128 bytes)
        // 0d2-151 CHR English Description (128 bytes)
        // 152-3fe U8  Padding (NULs)
        // 3ff-3ff U8  End marker (0xff)
        public bool Read(BinaryReader BR)
        {
            this.Clear();
            try
            {
                byte[] Bytes = BR.ReadBytes(0x400);
                if (Bytes[0x3] != 0x00 || Bytes[0x5] != 0x00 || Bytes[0x7] != 0x00 || Bytes[0x9] != 0x00 || Bytes[0xf] != 0xff ||
                    Bytes[0x3ff] != 0xff)
                {
                    return(false);
                }
                if (!FFXIEncryption.DecodeDataBlock(Bytes))
                {
                    return(false);
                }
                BR = new BinaryReader(new MemoryStream(Bytes, false));
            }
            catch
            {
                return(false);
            }
            this.Index_         = BR.ReadUInt16();
            this.MagicType_     = (MagicType)BR.ReadUInt16();
            this.Element_       = (Element)BR.ReadUInt16();
            this.ValidTargets_  = (ValidTarget)BR.ReadUInt16();
            this.Skill_         = (Skill)BR.ReadUInt16();
            this.MPCost_        = BR.ReadUInt16();
            this.CastingTime_   = BR.ReadByte();
            this.RecastDelay_   = BR.ReadByte();
            this.LevelRequired_ = new int[0x18];
            for (var i = 0; i < 0x18; ++i)
            {
                this.LevelRequired_[i] = BR.ReadInt16();
            }
            this.ID_         = BR.ReadUInt16();
            this.ListIconID_ = BR.ReadByte();
            BR.ReadBytes(0x04);
            FFXIEncoding E = new FFXIEncoding();

            this.JapaneseName_        = E.GetString(BR.ReadBytes(20)).TrimEnd('\0');
            this.EnglishName_         = E.GetString(BR.ReadBytes(20)).TrimEnd('\0');
            this.JapaneseDescription_ = E.GetString(BR.ReadBytes(128)).TrimEnd('\0');
            this.EnglishDescription_  = E.GetString(BR.ReadBytes(128)).TrimEnd('\0');
            // A slightly newer revision of this format no longer has the names, so mark them unset when empty
            if (this.JapaneseName_.Length == 0)
            {
                this.JapaneseName_ = null;
            }
            if (this.EnglishName_.Length == 0)
            {
                this.EnglishName_ = null;
            }
            if (this.JapaneseDescription_.Length == 0)
            {
                this.JapaneseDescription_ = null;
            }
            if (this.EnglishDescription_.Length == 0)
            {
                this.EnglishDescription_ = null;
            }
#if DEBUG
            {
                // Read the next 64 bits, and report if it's not 0 (means there's new data to identify)
                ulong Next64 = BR.ReadUInt64();
                if (Next64 != 0)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Nonzero data after entry (Spell #{0}): {1:X16}", this.ID_, Next64);
                    Console.ResetColor();
                }
            }
#endif
            BR.Close();
            return(true);
        }
예제 #22
0
 public bool Read(BinaryReader BR, uint? Index, long EntryStart, long EntryEnd)
 {
     this.Clear();
       this.Index_ = Index;
       try {
     BR.BaseStream.Seek(4 + EntryStart, SeekOrigin.Begin);
       byte[] TextBytes = BR.ReadBytes((int) (EntryEnd - EntryStart));
     for (int i = 0; i < TextBytes.Length; ++i)
       TextBytes[i] ^= 0x80; // <= Evil encryption-breaking!
     this.Text_ = String.Empty;
       FFXIEncoding E = new FFXIEncoding();
       int LastPos = 0;
     for (int i = 0; i < TextBytes.Length; ++i) {
       if (TextBytes[i] == 0x07) { // Line Break
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += "\r\n";
     LastPos = i + 1;
       }
       else if (TextBytes[i] == 0x08) { // Character Name (You)
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Player Name{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
     LastPos = i + 1;
       }
       else if (TextBytes[i] == 0x09) { // Character Name (They)
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Speaker Name{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
     LastPos = i + 1;
       }
       else if (TextBytes[i] == 0x0a && i + 1 < TextBytes.Length) {
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Numeric Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
     LastPos = i + 2;
     ++i;
       }
       else if (TextBytes[i] == 0x0b) { // Indicates that the lines after this are in a prompt window
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Selection Dialog{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
     LastPos = i + 1;
       }
       else if (TextBytes[i] == 0x0c && i + 1 < TextBytes.Length) {
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Multiple Choice (Parameter {2}){1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
     LastPos = i + 2;
     ++i;
       }
       else if (TextBytes[i] == 0x19 && i + 1 < TextBytes.Length) {
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Item Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
     LastPos = i + 2;
     ++i;
       }
       else if (TextBytes[i] == 0x1a && i + 1 < TextBytes.Length) {
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Key Item Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
     LastPos = i + 2;
     ++i;
       }
       else if (TextBytes[i] == 0x1c && i + 1 < TextBytes.Length) { // Chocobo Name
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Player/Chocobo Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
     LastPos = i + 2;
     ++i;
       }
       else if (TextBytes[i] == 0x1e && i + 1 < TextBytes.Length) {
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Set Color #{2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
     LastPos = i + 2;
     ++i;
       }
       else if (TextBytes[i] == 0x7f && i + 1 < TextBytes.Length) { // Various stuff
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     if (TextBytes[i + 1] == 0x31 && i + 2 < TextBytes.Length) { // Unknown, but seems to indicate user needs to hit RET
       if (TextBytes[i + 2] != 0)
         this.Text_ += String.Format("{0}{2}-Second Delay + Prompt{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
       else
         this.Text_ += String.Format("{0}Prompt{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
       ++LastPos;
       ++i;
     }
     else if (TextBytes[i + 1] == 0x85) // Multiple Choice: Player Gender
       this.Text_ += String.Format("{0}Multiple Choice (Player Gender){1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd);
     else if (TextBytes[i + 1] == 0x8D && i + 2 < TextBytes.Length) {
       this.Text_ += String.Format("{0}Weather Event Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
       ++LastPos;
       ++i;
     }
     else if (TextBytes[i + 1] == 0x8E && i + 2 < TextBytes.Length) {
       this.Text_ += String.Format("{0}Weather Type Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
       ++LastPos;
       ++i;
     }
     else if (TextBytes[i + 1] == 0x92 && i + 2 < TextBytes.Length) {
       this.Text_ += String.Format("{0}Singular/Plural Choice (Parameter {2}){1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
       ++LastPos;
       ++i;
     }
     else if (TextBytes[i + 1] == 0xB1 && i + 2 < TextBytes.Length) { // Usually found before an item name or key item name
       this.Text_ += String.Format("{0}Title Parameter {2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 2]);
       ++LastPos;
       ++i;
     }
     else if (i + 2 < TextBytes.Length) {
       this.Text_ += String.Format("{0}Unknown Parameter (Type: {2:X2}) {3}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1], TextBytes[i + 2]);
       ++LastPos;
       ++i;
     }
     else
       this.Text_ += String.Format("{0}Unknown Marker Type: {2:X2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i + 1]);
     LastPos = i + 2;
     ++i;
       }
       else if (TextBytes[i] == 0x7f || TextBytes[i] < 0x20) {
     if (LastPos < i)
       this.Text_ += E.GetString(TextBytes, LastPos, i - LastPos);
     this.Text_ += String.Format("{0}Possible Special Code: {2:X2}{1}", FFXIEncoding.SpecialMarkerStart, FFXIEncoding.SpecialMarkerEnd, TextBytes[i]);
     LastPos = i + 1;
       }
     }
     if (LastPos < TextBytes.Length)
       this.Text_ += E.GetString(TextBytes, LastPos, TextBytes.Length - LastPos);
     this.Text_ = this.Text_.TrimEnd('\0');
     return true;
       } catch { return false; }
 }