Exemple #1
0
 public void UpdateTxm2DWithImage(TXM Txm, Bitmap Bitmap, params string[] TxmNames)
 {
     foreach (var Name in TxmNames)
     {
         Txm.Surface2DEntriesByName[Name].UpdateBitmap(Bitmap);
     }
 }
Exemple #2
0
 public void UpdateTxm2DWithEmpty(TXM Txm, params string[] TxmNames)
 {
     foreach (var Name in TxmNames)
     {
         var Entry = Txm.Surface2DEntriesByName[Name];
         Entry.UpdateBitmap(new Bitmap(Entry.Width, Entry.Height));
     }
 }
Exemple #3
0
        //private void ReduceRowColors(Bitmap Bitmap)
        //{
        //	for (int y = 0; y < Bitmap.Height; y++)
        //	{
        //		var Rle = new List<RleItem>();
        //		for (int x = 0; x < Bitmap.Width - 1; x++)
        //		{
        //			int R = Bitmap.GetPixel(x + 0, y).R;
        //			int G = Bitmap.GetPixel(x + 0, y).G;
        //			int B = Bitmap.GetPixel(x + 0, y).B;
        //			int Count = 1;
        //			while ((x < Bitmap.Width - 1) && (ColorDistance(Bitmap.GetPixel(x, y), Bitmap.GetPixel(x + 1, y)) < 6))
        //			{
        //				R += Bitmap.GetPixel(x + 1, y).R;
        //				G += Bitmap.GetPixel(x + 1, y).G;
        //				B += Bitmap.GetPixel(x + 1, y).B;
        //				Count++;
        //				x++;
        //			}
        //			var Color2 = Color.FromArgb(R / Count, G / Count, B / Count);
        //			Rle.Add(new RleItem(Color2, Count));
        //			//Console.WriteLine("{0}: {1}", Color2, Count);
        //		}
        //		int x2 = 0;
        //		ReduceRle(Rle);
        //		foreach (var Item in Rle)
        //		{
        //			var Color = Item.Color;
        //			var Count = Item.Count;
        //			while (Count-- > 0) Bitmap.SetPixel(x2++, y, Color);
        //		}
        //	}
        //}
        //
        //public void UpdateTxm2DWithPngDxt5Loosy(TXM Txm, string PatchPngPath, params string[] TxmNames)
        //{
        //	PatcherGetImage(PatchPngPath, (Bitmap) =>
        //	{
        //		//Bitmap = new DXT5().CompressColors(Bitmap);
        //		ReduceRowColors(Bitmap);
        //
        //		Bitmap.Save(@"c:\temp\temp." + TxmNames[0] + ".png");
        //		foreach (var Name in TxmNames)
        //		{
        //			Txm.Surface2DEntriesByName[Name].UpdateBitmap(Bitmap);
        //		}
        //	});
        //}

        public void UpdateTxm2DWithPng(TXM Txm, string PatchPngPath, params string[] TxmNames)
        {
            PatcherGetImage(PatchPngPath, (Bitmap) =>
            {
                foreach (var Name in TxmNames)
                {
                    Txm.Surface2DEntriesByName[Name].UpdateBitmap(Bitmap);
                }
            });
        }
 public override string ToString()
 {
     using (FPS4 fps4 = new FPS4(Stream.Duplicate()))
         using (DuplicatableStream txmvStream = fps4.GetChildByIndex(1).AsFile.DataStream.Duplicate())
             using (FPS4 txmv = new FPS4(txmvStream.Duplicate()))
                 using (DuplicatableStream txmStream = txmv.GetChildByIndex(0).AsFile.DataStream.Duplicate()) {
                     TXM txm = new TXM(txmStream.Duplicate());
                     return(txm.TXMRegulars[0].Name);
                 }
 }
Exemple #5
0
        public static Stream ProcessTexture(string name, DuplicatableStream ustream, DuplicatableStream wstream)
        {
            FPS4 w    = new FPS4(wstream.Duplicate());
            TXM  wtxm = new TXM(w.GetChildByIndex(0).AsFile.DataStream.Duplicate());
            TXV  wtxv = new TXV(wtxm, w.GetChildByIndex(1).AsFile.DataStream.Duplicate(), false);
            FPS4 u    = new FPS4(ustream.Duplicate());
            TXM  utxm = new TXM(u.GetChildByIndex(0).AsFile.DataStream.Duplicate());
            TXV  utxv = new TXV(utxm, u.GetChildByIndex(1).AsFile.DataStream.Duplicate(), false);
            List <TexConvRules> convs = new List <TexConvRules>();

            if (name == "rootR.cpk/mg/tex/karuta.tex")
            {
                convs.Add(new TexConvRules()
                {
                    WTexId = 2, UTexId = 1, Method = TexConvMethod.Delegate, Delegate = (wtex, utex) => DoKarutaHalfAndHalf(wtex, utex, 82, 134, 294)
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 4, UTexId = 3, Method = TexConvMethod.Delegate, Delegate = (wtex, utex) => DoKarutaHalfAndHalf(wtex, utex, 86, 134, 294)
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 7, UTexId = 7, Method = TexConvMethod.DownscaleTwoThirds
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 13, UTexId = 13, Method = TexConvMethod.Delegate, Delegate = (wtex, utex) => DoKaruta13(wtex, utex)
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 17, UTexId = 17, Method = TexConvMethod.DownscaleTwoThirds
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 22, UTexId = 23, Method = TexConvMethod.Delegate, Delegate = (wtex, utex) => DownscaleTwoThirds(CropExpandCanvas(utex, 2, -2, (uint)(utex.Width + 3), (uint)(utex.Height - 3)))
                });
            }
            else if (name == "rootR.cpk/mnu/tex/main.tex")
            {
                convs.Add(new TexConvRules()
                {
                    WTexId = 110, UTexId = 61, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 111, UTexId = 62, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 112, UTexId = 63, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 113, UTexId = 64, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 114, UTexId = 65, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 115, UTexId = 66, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 116, UTexId = 67, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 117, UTexId = 68, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 118, UTexId = 69, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 119, UTexId = 70, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 124, UTexId = 75, Method = TexConvMethod.Downscale2x
                });
            }
            else if (name == "rootR.cpk/mnu/tex/shop.tex")
            {
                convs.Add(new TexConvRules()
                {
                    WTexId = 1, UTexId = 1, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 2, UTexId = 2, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 3, UTexId = 3, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 4, UTexId = 4, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 5, UTexId = 5, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 6, UTexId = 6, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 7, UTexId = 7, Method = TexConvMethod.Downscale2x
                });
            }
            else if (name == "rootR.cpk/mnu/tex/skill.tex")
            {
                convs.Add(new TexConvRules()
                {
                    WTexId = 0, UTexId = 0, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 1, UTexId = 1, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 2, UTexId = 2, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 3, UTexId = 3, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 4, UTexId = 4, Method = TexConvMethod.Downscale2x
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 5, UTexId = 5, Method = TexConvMethod.Downscale2x
                });
            }
            else if (name == "rootR.cpk/mnu/tex/snd_test.tex")
            {
                convs.Add(new TexConvRules()
                {
                    WTexId = 1, UTexId = 1, Method = TexConvMethod.Downscale2x
                });
            }
            else if (name == "rootR.cpk/SysSub/JA/TitleTexture.tex")
            {
                convs.Add(new TexConvRules()
                {
                    WTexId = 1, UTexId = 1, Method = TexConvMethod.CropExpandCanvas
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 2, UTexId = 4, Method = TexConvMethod.CropExpandCanvas
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 3, UTexId = 6, Method = TexConvMethod.CropExpandCanvas
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 4, UTexId = 8, Method = TexConvMethod.CropExpandCanvas
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 6, UTexId = 12, Method = TexConvMethod.CropExpandCanvas
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 7, UTexId = 14, Method = TexConvMethod.CropExpandCanvas
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 8, UTexId = 16, Method = TexConvMethod.CropExpandCanvas
                });
            }
            else if (name.EndsWith(".CLG"))
            {
                convs.Add(new TexConvRules()
                {
                    WTexId = 0, UTexId = 0, Method = TexConvMethod.DownscaleTwoThirds
                });
                convs.Add(new TexConvRules()
                {
                    WTexId = 1, UTexId = 1, Method = TexConvMethod.Clear
                });
            }

            MemoryStream s = wstream.Duplicate().CopyToMemory();

            s.Position = 0;
            foreach (TexConvRules c in convs)
            {
                var wm = wtxm.TXMRegulars[c.WTexId];
                var um = utxm.TXMRegulars[c.UTexId];
                var wv = wtxv.textures.Where(x => x.TXM == wm).First();
                var uv = utxv.textures.Where(x => x.TXM == um).First();
                System.Drawing.Bitmap newImage = null;
                switch (c.Method)
                {
                case TexConvMethod.Downscale2x: {
                    newImage = FontProcessing.DownscaleInteger(uv.GetBitmaps()[0], 2);
                }
                break;

                case TexConvMethod.DownscaleTwoThirds: {
                    newImage = DownscaleTwoThirds(uv.GetBitmaps()[0]);
                }
                break;

                case TexConvMethod.CropExpandCanvas: {
                    newImage = DoCropExpandCanvas(uv.GetBitmaps()[0], wm.Width, wm.Height);
                }
                break;

                case TexConvMethod.Clear: {
                    newImage = new Bitmap(wv.GetBitmaps()[0]);
                    for (int y = 0; y < newImage.Height; ++y)
                    {
                        for (int x = 0; x < newImage.Width; ++x)
                        {
                            newImage.SetPixel(x, y, Color.FromArgb(0, 0, 0, 0));
                        }
                    }
                }
                break;

                case TexConvMethod.Delegate: {
                    newImage = c.Delegate(wv.GetBitmaps()[0], uv.GetBitmaps()[0]);
                }
                break;

                default: {
                    throw new Exception("don't know how to convert " + uv.TXM.Name);
                }
                }
                if (newImage != null)
                {
                    HyoutaTools.Util.Assert(newImage.Width == wm.Width);
                    HyoutaTools.Util.Assert(newImage.Height == wm.Height);
                    if (wm.Format == HyoutaTools.Tales.Vesperia.Texture.TextureFormat.Indexed8Bits_RGB5A3)
                    {
                        ChopBitsRGB5A3(newImage);
                        var palette = GeneratePalette256(newImage);

                        s.Position = w.Files[1].Location.Value + wm.TxvLocation;
                        foreach (var loc in new HyoutaTools.Textures.PixelOrderIterators.TiledPixelOrderIterator(newImage.Width, newImage.Height, 8, 4))
                        {
                            int cval = 0;
                            if (loc.X < newImage.Width && loc.Y < newImage.Height)
                            {
                                cval = palette.lookup[newImage.GetPixel(loc.X, loc.Y)];
                            }
                            s.WriteByte((byte)cval);
                        }

                        for (int ci = 0; ci < 256; ++ci)
                        {
                            ushort cval = 0;
                            if (ci < palette.colors.Count)
                            {
                                cval = HyoutaTools.Textures.ColorFetchingIterators.ColorFetcherRGB5A3.ColorToRGB5A3(palette.colors[ci]);
                            }
                            s.WriteUInt16(cval.ToEndian(EndianUtils.Endianness.BigEndian));
                        }
                    }
                    else if (wm.Format == HyoutaTools.Tales.Vesperia.Texture.TextureFormat.GamecubeRGBA8)
                    {
                        s.Position = w.Files[1].Location.Value + wm.TxvLocation;
                        byte[] tmpb = new byte[0x40];
                        int    tmpp = 0;
                        foreach (var loc in new HyoutaTools.Textures.PixelOrderIterators.TiledPixelOrderIterator(newImage.Width, newImage.Height, 4, 4))
                        {
                            Color col = newImage.GetPixel(loc.X, loc.Y);
                            tmpb[tmpp * 2 + 0]        = col.A;
                            tmpb[tmpp * 2 + 1]        = col.R;
                            tmpb[tmpp * 2 + 0 + 0x20] = col.G;
                            tmpb[tmpp * 2 + 1 + 0x20] = col.B;
                            ++tmpp;
                            if (tmpp == 16)
                            {
                                tmpp = 0;
                                s.Write(tmpb);
                            }
                        }
                        if (tmpp != 0)
                        {
                            throw new Exception("Unexpected tile size for " + wm.Name);
                        }
                    }
                    else
                    {
                        Console.WriteLine("don't know how to encode into " + wm.Format);
                    }
                }
            }

            s.Position = 0;
            return(s);
        }
Exemple #6
0
        public static (DuplicatableStream metrics, DuplicatableStream texture, Dictionary <char, (int w1, int w2)> charToWidthMap) Run(FileFetcher _fc, Config config)
        {
            bool debug         = config.DebugFontOutputPath != null;
            bool adjustMetrics = debug;

            DuplicatableStream metricsWiiStream = _fc.GetFile("rootR.cpk/sys/FontBinary2.bin", Version.W);
            DuplicatableStream textureWiiStream = _fc.GetFile("rootR.cpk/sys/FontTexture2.tex", Version.W);
            DuplicatableStream texturePs3Stream = _fc.GetFile("rootR.cpk/sys/FontTexture2.tex", Version.U);
            FPS4 metricsWiiFps4 = new FPS4(metricsWiiStream);
            DuplicatableStream metricsWiiData = metricsWiiFps4.GetChildByIndex(1).AsFile.DataStream;
            FPS4   textureWiiFps4             = new FPS4(textureWiiStream);
            FPS4   texturePs3Fps4             = new FPS4(texturePs3Stream);
            TXM    textureWiiTxm = new TXM(textureWiiFps4.GetChildByIndex(0).AsFile.DataStream);
            TXV    textureWiiTxv = new TXV(textureWiiTxm, textureWiiFps4.GetChildByIndex(1).AsFile.DataStream, false);
            TXM    texturePs3Txm = new TXM(texturePs3Fps4.GetChildByIndex(0).AsFile.DataStream);
            TXV    texturePs3Txv = new TXV(texturePs3Txm, texturePs3Fps4.GetChildByIndex(1).AsFile.DataStream, false);
            Bitmap bitmapWii     = textureWiiTxv.textures[0].GetBitmaps()[0];
            Bitmap bitmapPs3     = texturePs3Txv.textures[0].GetBitmaps()[0];

            if (debug)
            {
                Directory.CreateDirectory(config.DebugFontOutputPath);
                bitmapWii.Save(Path.Combine(config.DebugFontOutputPath, "wii.png"));
                bitmapPs3.Save(Path.Combine(config.DebugFontOutputPath, "ps3.png"));
            }

            var       img_wii = bitmapWii;
            var       img_ps3 = bitmapPs3;
            const int tile_extent_in_image = 25;
            const int tile_extent_actual   = 24;
            int       tiles_x = (img_wii.Width + 1) / tile_extent_in_image;
            int       tiles_y = (img_wii.Height + 1) / tile_extent_in_image;
            const int ps3_tile_extent_in_image = 37;
            const int ps3_tile_extent_actual   = 36;
            int       ps3_tiles_x = (img_ps3.Width + 1) / ps3_tile_extent_in_image;
            int       ps3_tiles_y = (img_ps3.Height + 1) / ps3_tile_extent_in_image;

            // split into individual tiles and extract source colors
            HashSet <Color> colors    = new HashSet <Color>();
            List <Bitmap>   tiles_wii = new List <Bitmap>();
            List <Bitmap>   tiles_ps3 = new List <Bitmap>();

            for (int ty = 0; ty < tiles_y; ++ty)
            {
                for (int tx = 0; tx < tiles_x; ++tx)
                {
                    var bmp = new Bitmap(tile_extent_actual, tile_extent_actual);
                    for (int y = 0; y < tile_extent_actual; ++y)
                    {
                        for (int x = 0; x < tile_extent_actual; ++x)
                        {
                            var px = img_wii.GetPixel(tx * tile_extent_in_image + x, ty * tile_extent_in_image + y);
                            colors.Add(px);
                            bmp.SetPixel(x, y, px);
                        }
                    }
                    tiles_wii.Add(bmp);
                }
            }
            for (int ty = 0; ty < ps3_tiles_y; ++ty)
            {
                for (int tx = 0; tx < ps3_tiles_x; ++tx)
                {
                    var bmp = new Bitmap(ps3_tile_extent_actual, ps3_tile_extent_actual);
                    for (int y = 0; y < ps3_tile_extent_actual; ++y)
                    {
                        for (int x = 0; x < ps3_tile_extent_actual; ++x)
                        {
                            var px = img_ps3.GetPixel(tx * ps3_tile_extent_in_image + x, ty * ps3_tile_extent_in_image + y);
                            bmp.SetPixel(x, y, px);
                        }
                    }
                    tiles_ps3.Add(bmp);
                }
            }

            // inject ps3 tiles over wii tiles
            List <(int where, int ps3where, string chars)> charsets = new List <(int where, int ps3where, string chars)>();

            charsets.Add((0, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"));
            charsets.Add((243, 74, ",."));
            charsets.Add((246, 77, ":;?!_"));
            charsets.Add((254, 83, "/\\~|…"));
            charsets.Add((260, 118, "‘"));
            charsets.Add((261, 118, "’"));
            charsets.Add((262, 119, "“"));
            charsets.Add((263, 119, "”"));
            charsets.Add((264, 93, "()[]{}"));
            charsets.Add((276, 105, "+"));
            charsets.Add((277, 82, "-"));             // copy the dash minus instead of the math minus, looks better in text flow
            charsets.Add((278, 107, "±×÷=≠<>≤≥"));
            charsets.Add((289, 118, "'\""));
            charsets.Add((293, 122, "$%#&*@"));

            Dictionary <char, (int w1, int w2)> charToWidthMap = new Dictionary <char, (int w1, int w2)>();

            byte[] metrics = new byte[metricsWiiData.Length];
            metricsWiiData.Read(metrics, 0, metrics.Length);

            foreach (var charset in charsets)
            {
                int where = charset.where;
                int ps3where = charset.ps3where;
                foreach (char ch in charset.chars)
                {
                    var wiitile       = tiles_wii[where];
                    var averagescaled = DownscaleTileFromPs3ToWiiWithUnweightedAverageScaling(tiles_ps3[ps3where]);
                    //var downscaled = DownscaleTileFromPs3ToWiiWithWeightedScaling(tiles_ps3[ps3where]);
                    var downscaled = averagescaled;
                    PosterizeImage(wiitile, downscaled, colors, tile_extent_actual);
                    PosterizeImage(averagescaled, averagescaled, colors, tile_extent_actual);
                    if (debug)
                    {
                        wiitile.Save(Path.Combine(config.DebugFontOutputPath, string.Format("wii_new_{0:D4}.png", where)));
                    }

                    int cutoff_1    = 180;
                    int cutoff_2    = 220;
                    int leftwhere   = where * 8 + 0;
                    int rightwhere  = where * 8 + 1;
                    int leftwhere2  = where * 8 + 4;
                    int rightwhere2 = where * 8 + 5;

                    // forcing vertical extents to be the same for all, because text looks *really weird* in english if lines have different heights
                    // for digits, forcing horizontal extents to be the same as well so they look nice in vertical lists
                    bool isDigit = ch == '0' || ch == '1' || ch == '2' || ch == '3' || ch == '4' || ch == '5' || ch == '6' || ch == '7' || ch == '8' || ch == '9';
                    if (isDigit)
                    {
                        metrics[leftwhere]  = ch == '1' ? (byte)(6) : ch == '2' ? (byte)(6) : (byte)(7);
                        metrics[rightwhere] = ch == '1' ? (byte)(8) : ch == '2' ? (byte)(8) : (byte)(7);
                        //metrics[leftwhere2] = ch == '1' ? (byte)(7) : ch == '2' ? (byte)(7) : (byte)(8);
                        //metrics[rightwhere2] = ch == '1' ? (byte)(9) : ch == '2' ? (byte)(9) : (byte)(8);
                    }
                    else
                    {
                        metrics[leftwhere]  = (byte)MeasureAlphaFromLeft(averagescaled, cutoff_1);
                        metrics[rightwhere] = (byte)MeasureAlphaFromRight(averagescaled, cutoff_1);
                        //metrics[leftwhere2] = (byte)MeasureAlphaFromLeft(averagescaled, cutoff_2);
                        //metrics[rightwhere2] = (byte)MeasureAlphaFromRight(averagescaled, cutoff_2);
                    }

                    switch (ch)
                    {
                    case 'j':
                    case ';':
                        metrics[leftwhere] += 1;
                        break;

                    case 'A':
                    case 'P':
                    case 'Q':
                    case 'T':
                    case 'Y':
                    case 'W':
                    case 'f':
                    case 's':
                    case 'w':
                    case 'y':
                    case '[':
                        metrics[rightwhere] += 1;
                        break;

                    case 't':
                        metrics[leftwhere]  += 1;
                        metrics[rightwhere] += 1;
                        break;

                    default:
                        break;
                    }

                    metrics[leftwhere2]  = metrics[leftwhere];
                    metrics[rightwhere2] = metrics[rightwhere];

                    switch (ch)
                    {
                    case '.':
                    case ',':
                        metrics[leftwhere2] += 1;
                        metrics[rightwhere] += 1;
                        break;

                    default:
                        break;
                    }

                    metrics[where * 8 + 2] = 0;                     //(byte)MeasureAlphaFromTop(test, cutoff_1);
                    metrics[where * 8 + 3] = 4;                     //(byte)MeasureAlphaFromBottom(test, cutoff_1);
                    metrics[where * 8 + 6] = 0;                     //(byte)MeasureAlphaFromTop(test, cutoff_2);
                    metrics[where * 8 + 7] = 4;                     //(byte)MeasureAlphaFromBottom(test, cutoff_2);

                    int width1 = tile_extent_actual - (metrics[leftwhere] + metrics[rightwhere]);
                    int width2 = tile_extent_actual - (metrics[leftwhere2] + metrics[rightwhere2]);
                    charToWidthMap.Add(ch, (width1, width2));

                    ++where;
                    ++ps3where;
                }
            }

            // manually generate good metrics for space; see also code patches in main.dol
            metrics[0x6F70] = 10;
            metrics[0x6F71] = 10;
            metrics[0x6F72] = 0;
            metrics[0x6F73] = 4;
            metrics[0x6F74] = 10;
            metrics[0x6F75] = 10;
            metrics[0x6F76] = 0;
            metrics[0x6F77] = 4;
            charToWidthMap.Add(' ', (tile_extent_actual - 20, tile_extent_actual - 20));

            // write out visual representation of font metrics for adjustments
            if (adjustMetrics)
            {
                foreach (var charset in charsets)
                {
                    int where = charset.where;
                    foreach (char ch in charset.chars)
                    {
                        int factor = 10;
                        var test   = PointScale(tiles_wii[where], factor);

                        for (int metricsset = 0; metricsset < 2; ++metricsset)
                        {
                            Color col = metricsset == 0 ? Color.Red : Color.Yellow;
                            int   xl  = (metrics[where * 8 + metricsset * 4] - 1) * factor + factor - 1;
                            int   xr  = (tiles_wii[where].Width - metrics[where * 8 + metricsset * 4 + 1]) * factor;
                            int   yt  = (metrics[where * 8 + metricsset * 4 + 2] - 1) * factor + factor - 1;
                            int   yb  = (tiles_wii[where].Width - metrics[where * 8 + metricsset * 4 + 3]) * factor;
                            for (int y = 0; y < test.Height; ++y)
                            {
                                if (xl >= 0 && xl < test.Width)
                                {
                                    test.SetPixel(xl, y, col);
                                }
                                if (xr >= 0 && xr < test.Width)
                                {
                                    test.SetPixel(xr, y, col);
                                }
                            }
                            for (int x = 0; x < test.Width; ++x)
                            {
                                if (yt >= 0 && yt < test.Height)
                                {
                                    test.SetPixel(x, yt, col);
                                }
                                if (yb >= 0 && yb < test.Height)
                                {
                                    test.SetPixel(x, yb, col);
                                }
                            }
                        }

                        PointScale(test, 3).Save(Path.Combine(config.DebugFontOutputPath, string.Format("metrics_view_{0:D4}.png", where)));

                        ++where;
                    }
                }
            }

            // join indvidiual tiles back into full texture
            int idx = 0;

            for (int ty = 0; ty < tiles_y; ++ty)
            {
                for (int tx = 0; tx < tiles_x; ++tx)
                {
                    var bmp = tiles_wii[idx];
                    for (int y = 0; y < tile_extent_actual; ++y)
                    {
                        for (int x = 0; x < tile_extent_actual; ++x)
                        {
                            var px = bmp.GetPixel(x, y);
                            img_wii.SetPixel(tx * tile_extent_in_image + x, ty * tile_extent_in_image + y, px);
                        }
                    }
                    ++idx;
                }
            }

            if (debug)
            {
                img_wii.Save(Path.Combine(config.DebugFontOutputPath, "wii_new.png"));
            }

            // inject metrics
            DuplicatableStream outputMetricsStream;
            {
                Stream stream = metricsWiiStream.Duplicate().CopyToMemory();
                stream.Position = 0x43E0;
                stream.Write(metrics);

                stream.Position = 0;
                byte[] data = new byte[stream.Length];
                stream.Read(data, 0, data.Length);
                outputMetricsStream = new HyoutaUtils.Streams.DuplicatableByteArrayStream(data);
            }

            // encode texture
            DuplicatableStream outputTextureStream;

            {
                Stream stream = textureWiiStream.Duplicate().CopyToMemory();
                stream.Position = 0x80100;
                List <(int idx, ushort v)> stuff = new List <(int idx, ushort v)>();
                for (int i = 0; i < 16; ++i)
                {
                    stuff.Add((i, stream.ReadUInt16().FromEndian(EndianUtils.Endianness.BigEndian)));
                }

                stream.Position = 0x100;
                var  pxit    = new HyoutaTools.Textures.PixelOrderIterators.TiledPixelOrderIterator(img_wii.Width, img_wii.Height, 8, 8);
                byte storage = 0;
                bool even    = false;
                foreach (var px in pxit)
                {
                    if (px.X < img_wii.Width && px.Y < img_wii.Height)
                    {
                        Color  col    = img_wii.GetPixel(px.X, px.Y);
                        ushort value  = HyoutaTools.Textures.ColorFetchingIterators.ColorFetcherGrey8Alpha8.ColorToGrey8Alpha8(col);
                        var    colidx = stuff.First(x => x.v == value).idx;
                        if (!even)
                        {
                            storage = (byte)colidx;
                        }
                        else
                        {
                            storage = (byte)(storage << 4 | (byte)colidx);
                            stream.WriteByte(storage);
                        }
                        even = !even;
                    }
                }

                stream.Position = 0;
                byte[] data = new byte[stream.Length];
                stream.Read(data, 0, data.Length);
                outputTextureStream = new HyoutaUtils.Streams.DuplicatableByteArrayStream(data);
            }

            return(outputMetricsStream, outputTextureStream, charToWidthMap);
        }
Exemple #7
0
        protected void Expand(string FilePath)
        {
            if (FilePath.Contains('*') || FilePath.Contains('?'))
            {
                var BasePath  = Path.GetDirectoryName(FilePath);
                var Recursive = false;
                if (BasePath == "")
                {
                    BasePath = ".";
                }
                foreach (var FileName in Directory.EnumerateFiles(BasePath, Path.GetFileName(FilePath), Recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly))
                {
                    Expand(FileName);
                }
                return;
            }


            var ListToExpand = new List <string>();

            //Console.WriteLine("Expanding '{0}'...", FilePath);

            using (var _FileStream = File.OpenRead(FilePath))
            {
                if (_FileStream.Length == 0)
                {
                    //Console.WriteLine("EMPTY: {0}", FilePath);
                    return;
                }
                var FileStream = DecompressIfCompressedStream(_FileStream);
                var MagicData  = FileStream.Slice().ReadBytesUpTo(0x100);

                if (false)
                {
                }
                else if (TO8SCEL.IsValid(MagicData))
                {
                    try
                    {
                        var To8Scel = new TO8SCEL(FileStream);
                        foreach (var Entry in To8Scel)
                        {
                            var EntryFilePath = FilePath + ".d/" + Entry.Index;
                            if (Overwrite || !File.Exists(EntryFilePath))
                            {
                                Console.WriteLine("{0}", EntryFilePath);
                                try
                                {
                                    var EntryStream = DecompressIfCompressedStream(Entry.CompressedStream);
                                    if (EntryStream.Length > 0)
                                    {
                                        EntryStream.CopyToFile(EntryFilePath);
                                    }
                                }
                                catch (Exception Exception)
                                {
                                    ShowException(Exception);
                                }
                            }
                            if (File.Exists(EntryFilePath))
                            {
                                ListToExpand.Add(EntryFilePath);
                            }
                        }
                    }
                    catch (Exception Exception)
                    {
                        ShowException(Exception);
                    }
                }
                else if (FPS4.IsValid(MagicData))
                {
                    //Console.WriteLine("FPS4");
                    try
                    {
                        var Fps4 = new FPS4(FileStream);
                        foreach (var Entry in Fps4)
                        {
                            var EntryFilePath = FilePath + ".d/" + Entry.Name;
                            if (Overwrite || !File.Exists(EntryFilePath))
                            {
                                Console.WriteLine("{0}", EntryFilePath);
                                try
                                {
                                    var EntryStream = DecompressIfCompressedStream(Entry.Open());
                                    if (EntryStream.Length > 0)
                                    {
                                        EntryStream.CopyToFile(EntryFilePath);
                                    }
                                }
                                catch (Exception Exception)
                                {
                                    ShowException(Exception);
                                }
                            }
                            if (File.Exists(EntryFilePath))
                            {
                                ListToExpand.Add(EntryFilePath);
                            }
                        }
                    }
                    catch (Exception Exception)
                    {
                        ShowException(Exception);
                    }
                }
                else if (TSS.IsValid(MagicData))
                {
                    int RoomId = 0;
                    try { RoomId = int.Parse(Path.GetFileNameWithoutExtension(FilePath)); }
                    catch { }
                    var TxtFile = FilePath + ".txt";

                    Console.WriteLine("{0}", TxtFile);
                    if (Overwrite || !File.Exists(TxtFile))
                    {
                        var Tss = new TSS().Load(FileStream.Slice());

                        using (var TxtStream = File.Open(TxtFile, FileMode.Create, FileAccess.Write))
                            using (var TextWriter = new StreamWriter(TxtStream))
                            {
                                try
                                {
                                    Tss.DumpTexts(TextWriter);
                                }
                                catch (Exception Exception)
                                {
                                    ShowException(Exception);
                                }
                            }
                    }

                    var ScrFile = FilePath + ".scr";
                    Console.WriteLine("{0}", ScrFile);
                    if (Overwrite || !File.Exists(ScrFile))
                    {
                        var Tss = new TSS().Load(FileStream.Slice());

                        using (var TxtStream = File.Open(ScrFile, FileMode.Create, FileAccess.Write))
                            using (var TextWriter = new StreamWriter(TxtStream))
                            {
                                try
                                {
                                    var ErrorString = ConsoleUtils.CaptureError(() => {
                                        Tss.DumpScript(TextWriter);
                                    });
                                }
                                catch (Exception Exception)
                                {
                                    ShowException(Exception);
                                }
                            }
                    }
                }
                else if (TO8CHTX.IsValid(MagicData))
                {
                    var Chtx    = new TO8CHTX(FileStream);
                    var TxtFile = FilePath + ".txt";
                    Console.WriteLine("{0}", TxtFile);
                    if (Overwrite || !File.Exists(TxtFile))
                    {
                        using (var TxtStream = File.Open(TxtFile, FileMode.Create, FileAccess.Write))
                            using (var TextWriter = new StreamWriter(TxtStream))
                            {
                                foreach (var Entry in Chtx.Entries)
                                {
                                    TextWriter.WriteLine("{0}", Entry.Title);
                                    TextWriter.WriteLine("{0}", Entry.TextOriginal);
                                    TextWriter.WriteLine("{0}", Entry.TextTranslated);
                                    TextWriter.WriteLine("");
                                }
                            }
                        //Chtx.Entries[0].Title
                        //Console.WriteLine("CHAT!");
                    }
                }
                else if (SE3.IsValid(MagicData))
                {
                    var Se3 = new SE3().Load(FileStream);
                    foreach (var Entry in Se3.Entries)
                    {
                        var EntryFullNameXma = FilePath + "." + Entry.Name + ".xma";
                        var EntryFullNameWav = FilePath + "." + Entry.Name + ".wav";
                        Console.WriteLine("{0}", EntryFullNameXma);
                        if (Overwrite || !File.Exists(EntryFullNameXma))
                        {
                            Entry.ToXmaWav().CopyToFile(EntryFullNameXma);
                        }
                        if (Overwrite || !File.Exists(EntryFullNameWav))
                        {
                            using (var WavOut = File.Open(EntryFullNameWav, FileMode.Create, FileAccess.Write))
                            {
                                Entry.ToWav(WavOut);
                            }
                        }
                    }
                }
                else if (TXM.IsValid(MagicData))
                {
                    string BasePath;
                    string TxmPath;
                    string TxvPath;

                    if (Path.GetExtension(FilePath).ToLower() == ".txm")
                    {
                        BasePath = Path.GetDirectoryName(FilePath) + "/" + Path.GetFileNameWithoutExtension(FilePath);
                        TxmPath  = BasePath + ".txm";
                        TxvPath  = BasePath + ".txv";
                    }
                    else
                    {
                        var DirectoryPath = Path.GetDirectoryName(FilePath);
                        TxmPath  = DirectoryPath + "/" + Path.GetFileName(FilePath);
                        TxvPath  = DirectoryPath + "/" + (int.Parse(Path.GetFileName(TxmPath)) + 1);
                        BasePath = TxmPath;
                    }

                    var Txm = TXM.FromTxmTxv(File.OpenRead(TxmPath), File.OpenRead(TxvPath));

                    /*
                     * if (Txm.Surface2DEntries.Length > 0 && Txm.Surface3DEntries.Length > 0)
                     * {
                     *      // 3D and 2D surfaces
                     *      //Console.WriteLine("ERROR 3D and 2D SURFACES! (2D: {0}, 3D: {1})", Txm.Surface2DEntries.Length, Txm.Surface3DEntries.Length);
                     * }
                     * else if (Txm.Surface2DEntries.Length > 0)
                     * {
                     *      // 2D Surfaces
                     *      //Console.WriteLine("2D SURFACES! {0}", Txm.Surface2DEntries.Length);
                     * }
                     * else if (Txm.Surface3DEntries.Length > 0)
                     * {
                     *      // 3D Surfaces
                     *      //Console.WriteLine("3D SURFACES! {0}", Txm.Surface3DEntries.Length);
                     * }
                     */

                    foreach (var Entry in Txm.Surface2DEntries)
                    {
                        var ImagePath = BasePath + "." + Entry.Name + ".png";
                        if (Overwrite || !File.Exists(ImagePath))
                        {
                            try
                            {
                                Entry.Bitmap.Save(ImagePath);
                            }
                            catch (Exception Exception)
                            {
                                ShowException(Exception);
                            }
                        }
                    }

                    foreach (var Entry in Txm.Surface3DEntries)
                    {
                        var ImagePath0 = BasePath + "." + Entry.Name + "." + 0 + ".png";
                        if (Overwrite || !File.Exists(ImagePath0))
                        {
                            try
                            {
                                var n = 0;
                                foreach (var Bitmap in Entry.Bitmaps.Bitmaps)
                                {
                                    var ImagePath = BasePath + "." + Entry.Name + "." + n + ".png";
                                    Console.WriteLine("{0}", ImagePath);
                                    if (Overwrite || !File.Exists(ImagePath))
                                    {
                                        Bitmap.Save(ImagePath);
                                    }
                                    n++;
                                }
                            }
                            catch (Exception Exception)
                            {
                                ShowException(Exception);
                            }
                        }
                    }
                }
                else
                {
                }
            }

            // Expand all the queued stuff
            foreach (var Item in ListToExpand)
            {
                try
                {
                    Expand(Item);
                }
                catch (Exception Exception)
                {
                    Console.WriteLine("  ERROR: {0}", Verbose ? Exception.ToString() : Exception.Message.ToString());
                }
            }
        }