Exemple #1
0
        public MtxFile(MtxSerializable mtxSerializable, MtxEncoding encoding)
        {
            this.encoding   = encoding;
            Has64BitOffsets = mtxSerializable.Has64BitOffsets;

            Entries = mtxSerializable.Sheets.Select(x =>
                                                    x.Texts.Select(x2 => new XElement("text", x2.Nodes()))
                                                    .ToList())
                      .ToList();
        }
Exemple #2
0
        public MtxFile(IEnumerable <List <XElement> >?collection, MtxEncoding encoding, bool has64BitOffsets = false)
        {
            if (collection is not null)
            {
                Entries = new List <List <XElement> >(collection);
            }
            else
            {
                Entries = new List <List <XElement> >();
            }

            this.encoding   = encoding;
            Has64BitOffsets = has64BitOffsets;
        }
Exemple #3
0
        public void OnExecute()
        {
            // Don't execute if we are showing help.
            if (ShowHelp)
            {
                return;
            }

            MtxEncoding encoding = null;
            var         version  = Version ?? "auto";

            if (version == "auto")
            {
                if (FntPath != null || FpdPath != null)
                {
                    version = "1";
                }
                else
                {
                    version = "2";
                }
            }
            if (version == "1")
            {
                if (FntPath != null)
                {
                    if (!File.Exists(FntPath))
                    {
                        Error(string.Format(ErrorMessages.FileDoesNotExist, FntPath));
                        return;
                    }

                    var fntFile = new FntFile(FntPath);
                    encoding = new CharacterMapMtxEncoding(fntFile.Characters);
                }
                else if (FpdPath != null)
                {
                    if (!File.Exists(FpdPath))
                    {
                        Error(string.Format(ErrorMessages.FileDoesNotExist, FpdPath));
                        return;
                    }

                    var fpdFile = new FpdFile(FpdPath);
                    encoding = new CharacterMapMtxEncoding(fpdFile.Characters);
                }
                else
                {
                    Error(ErrorMessages.FntOrFpdOptionMustBeSet);
                    return;
                }
            }
            else if (version == "2")
            {
                encoding = new Utf16MtxEncoding();
            }

            foreach (var file in Files)
            {
                if (!File.Exists(file))
                {
                    Error(string.Format(ErrorMessages.FileDoesNotExist, file));
                    continue;
                }

                var format = Format ?? "auto";
                if (format == "auto")
                {
                    var extension = Path.GetExtension(file);

                    if (extension.Equals(".mtx", StringComparison.OrdinalIgnoreCase))
                    {
                        format = "json";
                    }
                    else if (extension.Equals(".json", StringComparison.OrdinalIgnoreCase))
                    {
                        format = "mtx";
                    }
                    else
                    {
                        Error(string.Format(ErrorMessages.CouldNotDetermineOutputFormat, file));
                        continue;
                    }
                }

                if (format == "json")
                {
                    var outputFilename = Output ?? Path.ChangeExtension(file, ".json");

                    try
                    {
                        var mtxFile = new MtxFile(file, encoding);
                        var mtxJson = new MtxJson
                        {
                            Has64BitOffsets = mtxFile.Has64BitOffsets,
                            Entries         = mtxFile.Entries,
                        };
                        JsonFileSerializer.Serialize(outputFilename, mtxJson);
                    }
                    catch (Exception e)
                    {
                        Error(e.Message);
                    }
                }
                else if (format == "mtx")
                {
                    var outputFilename = Output ?? Path.ChangeExtension(file, ".mtx");

                    try
                    {
                        var mtxJson = JsonFileSerializer.Deserialize <MtxJson>(file);
                        var mtxFile = new MtxFile(mtxJson.Entries, encoding, mtxJson.Has64BitOffsets ? true : Has64BitOffsets);
                        mtxFile.Save(outputFilename);
                    }
                    catch (Exception e)
                    {
                        Error(e.Message);
                    }
                }
            }
        }
Exemple #4
0
        public MtxFile(string path, MtxEncoding encoding)
        {
            this.encoding = encoding;

            using (var source = new FileStream(path, FileMode.Open, FileAccess.Read))
                using (var reader = new BinaryReader(source, Encoding.Unicode))
                {
                    // The first 4 bytes in an MTX file tells us its expected file size.
                    // This value is incorrect for MTX files in the 15th Anniversary translation.
                    // Those files will be identified as being invalid.
                    var length = reader.Peek(x => x.ReadInt32());
                    if (length != source.Length)
                    {
                        throw new FileFormatException(string.Format(Resources.InvalidMtxFile, path));
                    }

                    Func <BinaryReader, int> ReadInt;
                    int intSize;

                    // MTX files used on Switch, PS4, Xbox One, and PC store their offsets as 64-bit integers
                    // On all other platforms, they are stored as 32-bit integers.
                    // We're going to test this by reading the bytes at 0x4 as a 32-bit integer to see if it returns 8.
                    // If it doesn't, we'll read bytes at 0x8 as a 64-bit integer to see if it returns 16.
                    // If it doesn't, then throw an error.

                    // This MTX file uses 32-bit offsets
                    if (reader.At(0x4, x => x.ReadInt32()) == 8)
                    {
                        Has64BitOffsets = false;
                        intSize         = 4;
                        ReadInt         = x => x.ReadInt32();
                    }

                    // This MTX file uses 64-bit offsets
                    else if (reader.At(0x8, x => x.ReadInt64()) == 16)
                    {
                        Has64BitOffsets = true;
                        intSize         = 8;
                        ReadInt         = x => (int)x.ReadInt64();
                    }

                    // Not an MTX file
                    else
                    {
                        throw new FileFormatException(string.Format(Resources.InvalidMtxFile, path));
                    }

                    source.Position += intSize;
                    var sectionsTablePosition = ReadInt(reader);
                    var sectionsCount         = (reader.Peek(ReadInt) - sectionsTablePosition) / intSize;

                    Entries = new List <List <XElement> >(sectionsCount);
                    var offsets = new Queue <int>();

                    for (var i = 0; i < sectionsCount; i++)
                    {
                        var stringsTablePosition = ReadInt(reader);
                        var stringsCount         = (reader.Peek(ReadInt) - stringsTablePosition) / intSize; // OK to do this even if it's the last entry

                        Entries.Add(new List <XElement>(stringsCount));
                    }

                    foreach (var section in Entries)
                    {
                        for (var i = 0; i < section.Capacity; i++)
                        {
                            offsets.Enqueue(ReadInt(reader));
                        }
                    }

                    foreach (var section in Entries)
                    {
                        for (var i = 0; i < section.Capacity; i++)
                        {
                            source.Position = offsets.Dequeue();
                            var s = encoding.Read(reader);
                            section.Add(s);
                        }
                    }
                }
        }
Exemple #5
0
 public MtxFile(MtxEncoding encoding, bool has64BitOffsets = false)
     : this(null, encoding, has64BitOffsets)
 {
 }
Exemple #6
0
        public MtxFile(string path, MtxEncoding encoding)
        {
            this.encoding = encoding;

            using (var source = new FileStream(path, FileMode.Open, FileAccess.Read))
                using (var reader = new BinaryReader(source, Encoding.Unicode))
                {
                    // The first 4 bytes in an MTX file tells us its expected file size.
                    // This value is incorrect for MTX files in the 15th Anniversary translation.
                    // Those files will be identified as being invalid.
                    var length = reader.PeekInt32();
                    if (length != source.Length)
                    {
                        throw new IOException(string.Format(ErrorMessages.InvalidMtxFile, path));
                    }

                    Func <int> ReadInt, PeekInt;
                    int        intSize;

                    // In the Switch version of Puyo Puyo Tetris, offsets are stored as 64-bit integers
                    // In all other versions, they are stored as 32-bit integers.
                    // We're going to test this by reading bytes 4-8 as a 32-bit integer to see if it returns 8.
                    // If it doesn't, we'll read bytes 8-16 as a 64-bit integer to see if it returns 16.
                    // If it doesn't, then throw an error.
                    source.Position += 4;
                    var testInt32 = reader.PeekInt32();
                    source.Position -= 4;

                    if (testInt32 == 8)
                    {
                        // This MTX file uses 32-bit offsets
                        Has64BitOffsets = false;
                        intSize         = 4;
                        ReadInt         = reader.ReadInt32;
                        PeekInt         = reader.PeekInt32;
                    }
                    else
                    {
                        source.Position += 8;
                        var testInt64 = reader.PeekInt64();
                        source.Position -= 8;

                        if (testInt64 == 16)
                        {
                            // This MTX file uses 64-bit offsets
                            Has64BitOffsets = true;
                            intSize         = 8;
                            ReadInt         = () => (int)reader.ReadInt64();
                            PeekInt         = () => (int)reader.PeekInt64();
                        }

                        else
                        {
                            throw new IOException(string.Format(ErrorMessages.InvalidMtxFile, path));
                        }
                    }

                    source.Position += intSize;
                    var sectionsTablePosition = ReadInt();
                    var sectionsCount         = (PeekInt() - sectionsTablePosition) / intSize;

                    Entries = new List <List <string> >(sectionsCount);
                    var offsets = new Queue <int>();

                    for (var i = 0; i < sectionsCount; i++)
                    {
                        var stringsTablePosition = ReadInt();
                        var stringsCount         = (PeekInt() - stringsTablePosition) / intSize; // OK to do this even if it's the last entry

                        Entries.Add(new List <string>(stringsCount));
                    }

                    foreach (var section in Entries)
                    {
                        for (var i = 0; i < section.Capacity; i++)
                        {
                            offsets.Enqueue(ReadInt());
                        }
                    }

                    foreach (var section in Entries)
                    {
                        for (var i = 0; i < section.Capacity; i++)
                        {
                            source.Position = offsets.Dequeue();
                            var s = encoding.Read(reader);
                            section.Add(s);
                        }
                    }
                }
        }