Exemplo n.º 1
0
        public void Load(string filename)
        {
            flcFile.Transparency     = TransparencyEnabled;
            flcFile.TransparentRed   = tRed;
            flcFile.TransparentGreen = tGreen;
            flcFile.TransparentBlue  = tBlue;

            string path = Path.Combine(DaggerfallUnity.Instance.Arena2Path, filename);

            if (!flcFile.Load(path))
            {
                return;
            }

            flcTexture            = TextureReader.CreateFromSolidColor(flcFile.Header.Width, flcFile.Header.Height, (TransparencyEnabled ? Color.clear : Color.black), false, false);
            flcTexture.filterMode = (FilterMode)DaggerfallUnity.Settings.MainFilterMode;
        }
Exemplo n.º 2
0
        public DaggerfallVideo()
            : base()
        {
            // Setup audio player components
            audioPlayer = new GameObject("VIDAudioPlayer");
            audioPlayer.transform.parent = DaggerfallUI.Instance.gameObject.transform;
            for (int i = 0; i < clipQueueLength; i++)
            {
                audioSources[i] = audioPlayer.AddComponent <AudioSource>();
            }
            nextEventTime = AudioSettings.dspTime;

            // Init empty texture
            vidTexture            = TextureReader.CreateFromSolidColor(1, 1, Color.black, false, false);
            vidTexture.wrapMode   = TextureWrapMode.Clamp;
            vidTexture.filterMode = (FilterMode)DaggerfallUnity.Settings.VideoFilterMode;
        }
        bool IsReady()
        {
            if (!dfUnity)
            {
                dfUnity = DaggerfallUnity.Instance;
            }

            if (!dfUnity.IsReady || string.IsNullOrEmpty(dfUnity.Arena2Path))
            {
                return(false);
            }

            if (saveGames == null || saveTrees == null || saveNames == null)
            {
                saveGames    = new SaveGames();
                saveNames    = new GUIContent[6];
                saveTrees    = new SaveTree[6];
                saveTextures = new Texture2D[6];
                if (saveGames.OpenSavesPath(Path.GetDirectoryName(DaggerfallUnity.Instance.Arena2Path)))
                {
                    for (int i = 0; i < 6; i++)
                    {
                        if (saveGames.HasSave(i))
                        {
                            saveGames.OpenSave(i);
                            saveTrees[i]               = saveGames.SaveTree;
                            saveNames[i]               = new GUIContent(saveGames.SaveName);
                            saveTextures[i]            = TextureReader.CreateFromAPIImage(saveGames.SaveImage);
                            saveTextures[i].filterMode = FilterMode.Point;
                        }
                        else
                        {
                            saveTrees[i]    = null;
                            saveTextures[i] = null;
                            saveNames[i]    = new GUIContent("Empty");
                        }
                    }
                }
            }

            return(true);
        }
        public LeftRightSpinner()
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;

            if (!dfUnity.IsReady)
            {
                return;
            }

            // Load IMG texture
            ImgFile imgFile = new ImgFile(Path.Combine(dfUnity.Arena2Path, nativeImgName), FileUsage.UseMemory, true);

            imgFile.LoadPalette(Path.Combine(dfUnity.Arena2Path, imgFile.PaletteName));
            nativeTexture            = TextureReader.CreateFromAPIImage(imgFile, 0, 0, 0);
            nativeTexture.filterMode = DaggerfallUI.Instance.GlobalFilterMode;

            // Setup spinner panel
            Size = TextureReplacement.GetSize(nativeTexture, nativeImgName);
            backgroundTexture = nativeTexture;

            // Add up/down buttons
            Components.Add(leftButton);
            Components.Add(rightButton);
            leftButton.Position       = new Vector2(0, 0);
            leftButton.Size           = new Vector2(11, 9);
            leftButton.OnMouseClick  += LeftButton_OnMouseClick;
            leftButton.OnMouseDown   += LeftButton_OnMouseDown;
            leftButton.OnMouseUp     += LeftRightButtons_OnMouseUp;
            rightButton.Position      = new Vector2(26, 0);
            rightButton.Size          = new Vector2(11, 9);
            rightButton.OnMouseClick += RightButton_OnMouseClick;
            rightButton.OnMouseDown  += RightButton_OnMouseDown;
            rightButton.OnMouseUp    += LeftRightButtons_OnMouseUp;

            // Add value label
            Components.Add(valueLabel);
            valueLabel.Position            = new Vector2(0, 2);
            valueLabel.Size                = new Vector2(15, 9);
            valueLabel.HorizontalAlignment = HorizontalAlignment.Center;
            valueLabel.ShadowColor         = DaggerfallUI.DaggerfallAlternateShadowColor1;
            SetValue(this.value);
        }
Exemplo n.º 5
0
        public UpDownSpinner()
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;

            if (!dfUnity.IsReady)
            {
                return;
            }

            // Load IMG texture
            ImgFile imgFile = new ImgFile(Path.Combine(dfUnity.Arena2Path, nativeImgName), FileUsage.UseMemory, true);

            imgFile.LoadPalette(Path.Combine(dfUnity.Arena2Path, imgFile.PaletteName));
            nativeTexture            = TextureReader.CreateFromAPIImage(imgFile, 0, 0, 0);
            nativeTexture.filterMode = DaggerfallUI.Instance.GlobalFilterMode;

            // Setup spinner panel
            Size = new Vector2(15, 20);
            backgroundTexture = nativeTexture;

            // Add up/down buttons
            Components.Add(upButton);
            Components.Add(downButton);
            upButton.Position        = new Vector2(0, 0);
            upButton.Size            = new Vector2(15, 7);
            upButton.OnMouseClick   += UpButton_OnMouseClick;
            downButton.Position      = new Vector2(0, 13);
            downButton.Size          = new Vector2(15, 7);
            downButton.OnMouseClick += DownButton_OnMouseClick;

            // Add value label
            Components.Add(valueLabel);
            valueLabel.Position            = new Vector2(0, 7);
            valueLabel.Size                = new Vector2(15, 6);
            valueLabel.HorizontalAlignment = HorizontalAlignment.Center;
            valueLabel.ShadowColor         = DaggerfallUI.DaggerfallAlternateShadowColor1;
            SetValue(this.value);
        }
Exemplo n.º 6
0
        private bool ReadyCheck()
        {
            // Ensure we have a DaggerfallUnity reference
            if (dfUnity == null)
            {
                dfUnity = DaggerfallUnity.Instance;
            }

            // Do nothing if DaggerfallUnity not ready
            if (!dfUnity.IsReady)
            {
                DaggerfallUnity.LogMessage("MaterialReader: DaggerfallUnity component is not ready. Have you set your Arena2 path?");
                return(false);
            }

            // Ensure texture reader is ready
            if (textureReader == null)
            {
                textureReader = new TextureReader(dfUnity.Arena2Path);
            }

            return(true);
        }
Exemplo n.º 7
0
        public async Task SaveTextureMaps(string filename, string baseTextureName, double reflection, double gloss, double specular)
        {
            if (Kn5 == null)
            {
                return;
            }

            MagickImage image = null;
            await Task.Run(() => {
                Format format;
                var data = TextureReader.ToPng(DeviceContextHolder, Kn5.TexturesData[baseTextureName], true, out format);

                image = new MagickImage(data);
                image.AutoLevel(Channels.Red);
                image.AutoLevel(Channels.Green);
                image.AutoLevel(Channels.Blue);

                image.Evaluate(Channels.Red, EvaluateOperator.Multiply, specular);
                image.Evaluate(Channels.Green, EvaluateOperator.Multiply, gloss);
                image.Evaluate(Channels.Blue, EvaluateOperator.Multiply, reflection);
            });

            await SaveAndDispose(filename, image);
        }
Exemplo n.º 8
0
        void SetupControl()
        {
            dfUnity = DaggerfallUnity.Instance;
            if (!dfUnity.IsReady)
            {
                return;
            }

            // Load highlight texture
            ImgFile imgFile = new ImgFile(Path.Combine(dfUnity.Arena2Path, highlightImgName), FileUsage.UseMemory, true);

            imgFile.LoadPalette(Path.Combine(dfUnity.Arena2Path, imgFile.PaletteName));
            highlightTexture            = TextureReader.CreateFromAPIImage(imgFile, 0, 0, 0);
            highlightTexture.filterMode = DaggerfallUI.Instance.GlobalFilterMode;

            // Add buttons
            Vector2 buttonPos  = new Vector2(0, 0);
            Vector2 buttonSize = new Vector2(66, 9);

            for (int i = 0; i < 5; i++)
            {
                selectButtons[i] = new Button();
                this.Components.Add(selectButtons[i]);
                selectButtons[i].Position      = buttonPos;
                selectButtons[i].Size          = buttonSize;
                selectButtons[i].Tag           = i;
                selectButtons[i].OnMouseClick += ReflexButton_OnMouseClick;
                buttonPos.y += buttonSize.y;
            }

            // Set size of this panel
            Size = new Vector2(66, 45);

            // Set starting value
            PlayerReflexes = PlayerReflexes.Average;
        }
Exemplo n.º 9
0
        /// <summary>
        /// Gets Unity Material from Daggerfall texture with more options.
        /// </summary>
        /// <param name="archive">Archive index.</param>
        /// <param name="record">Record index.</param>
        /// <param name="frame">Frame index.</param>
        /// <param name="rectOut">Receives UV rect for texture inside border.</param>
        /// <param name="borderSize">Number of pixels internal border around each texture.</param>
        /// <param name="dilate">Blend texture into surrounding empty pixels.</param>
        /// <returns>Material or null.</returns>
        public Material GetMaterial(
            int archive,
            int record,
            int frame,
            int alphaIndex,
            out Rect rectOut,
            int borderSize = 0,
            bool dilate    = false)
        {
            // Ready check
            if (!IsReady)
            {
                rectOut = new Rect();
                return(null);
            }

            // Try to retrieve from cache
            int key = MakeTextureKey((short)archive, (byte)record, (byte)frame);

            if (materialDict.ContainsKey(key))
            {
                CachedMaterial cm = materialDict[key];
                rectOut = cm.singleRect;
                return(cm.material);
            }

            // Create new texture settings
            GetTextureSettings settings = TextureReader.CreateTextureSettings(archive, record, frame, alphaIndex, borderSize, dilate);

            settings.autoEmissionForWindows = true;
            settings.sharpen = Sharpen;
            if (GenerateNormals)
            {
                settings.createNormalMap = true;
                settings.normalStrength  = NormalTextureStrength;
            }

            // Set emissive for self-illuminated textures
            if (textureReader.IsEmissive(archive, record))
            {
                settings.createEmissionMap = true;
                settings.emissionIndex     = -1;
            }

            // Get texture
            GetTextureResults results = textureReader.GetTexture2D(settings, AlphaTextureFormat, NonAlphaTextureFormat);

            rectOut = results.singleRect;

            // Setup material
            Material material = CreateStandardMaterial();

            material.name                   = FormatName(archive, record);
            material.mainTexture            = results.albedoMap;
            material.mainTexture.filterMode = MainFilterMode;

            // Setup normal map
            if (GenerateNormals && results.normalMap != null)
            {
                results.normalMap.filterMode = MainFilterMode;
                material.SetTexture("_BumpMap", results.normalMap);
                material.EnableKeyword("_NORMALMAP");
            }

            // Setup emission map
            if (results.isEmissive && !results.isWindow && results.emissionMap != null)
            {
                results.emissionMap.filterMode = MainFilterMode;
                material.SetTexture("_EmissionMap", results.emissionMap);
                material.SetColor("_EmissionColor", Color.white);
                material.EnableKeyword("_EMISSION");
            }
            else if (results.isEmissive && results.isWindow && results.emissionMap != null)
            {
                results.emissionMap.filterMode = MainFilterMode;
                material.SetTexture("_EmissionMap", results.emissionMap);
                material.SetColor("_EmissionColor", DayWindowColor * DayWindowIntensity);
                material.EnableKeyword("_EMISSION");
            }

            // Setup cached material
            DFSize     size   = results.textureFile.GetSize(record);
            DFSize     scale  = results.textureFile.GetScale(record);
            DFPosition offset = results.textureFile.GetOffset(record);

            Vector2[] recordSizes = new Vector2[1] {
                new Vector2(size.Width, size.Height)
            };
            Vector2[] recordScales = new Vector2[1] {
                new Vector2(scale.Width, scale.Height)
            };
            Vector2[] recordOffsets = new Vector2[1] {
                new Vector2(offset.X, offset.Y)
            };
            CachedMaterial newcm = new CachedMaterial()
            {
                key              = key,
                keyGroup         = 0,
                albedoMap        = results.albedoMap,
                normalMap        = results.normalMap,
                emissionMap      = results.emissionMap,
                singleRect       = rectOut,
                material         = material,
                filterMode       = MainFilterMode,
                isWindow         = results.isWindow,
                recordSizes      = recordSizes,
                recordScales     = recordScales,
                recordOffsets    = recordOffsets,
                singleFrameCount = results.textureFile.GetFrameCount(record),
            };

            materialDict.Add(key, newcm);

            return(material);
        }
Exemplo n.º 10
0
        void AddControls()
        {
            saveImageButtons = new Button[saveImageButtonDims.Length];
            saveTextButtons  = new Button[saveTextButtonDims.Length];
            for (int i = 0; i < saveImageButtonDims.Length; i++)
            {
                // Open save
                if (!saveGames.LazyOpenSave(i))
                {
                    DaggerfallUnity.LogMessage(string.Format("Could not lazy open save index {0}.", i), true);
                    continue;
                }

                // Get save texture
                Texture2D saveTexture = TextureReader.CreateFromAPIImage(saveGames.SaveImage);
                saveTexture.filterMode = DaggerfallUI.Instance.GlobalFilterMode;

                // Setup image button
                saveImageButtons[i] = DaggerfallUI.AddButton(saveImageButtonDims[i], NativePanel);
                saveImageButtons[i].BackgroundTexture       = saveTexture;
                saveImageButtons[i].BackgroundTextureLayout = TextureLayout.ScaleToFit;
                saveImageButtons[i].Tag                 = i;
                saveImageButtons[i].OnMouseClick       += SaveGame_OnMouseClick;
                saveImageButtons[i].OnMouseDoubleClick += SaveGame_OnMouseDoubleClick;

                // Setup text button
                saveTextButtons[i]                     = DaggerfallUI.AddButton(saveTextButtonDims[i], NativePanel);
                saveTextButtons[i].Label.Text          = saveGames.SaveName;
                saveTextButtons[i].Tag                 = i;
                saveTextButtons[i].OnMouseClick       += SaveGame_OnMouseClick;
                saveTextButtons[i].OnMouseDoubleClick += SaveGame_OnMouseDoubleClick;

                // Select first valid save game
                if (selectedSaveGame == -1)
                {
                    selectedSaveGame = i;
                }
            }

            // Setup outline
            outline = DaggerfallUI.AddOutline(outlineRects[0], DaggerfallUI.DaggerfallDefaultTextColor, NativePanel);
            if (selectedSaveGame == -1)
            {
                outline.Enabled = false;
            }
            else
            {
                SelectSaveGame(selectedSaveGame);
            }

            // Setup load game button
            if (selectedSaveGame >= 0)
            {
                Button loadGameButton = DaggerfallUI.AddButton(new Vector2(126, 5), new Vector2(68, 11), NativePanel);
                loadGameButton.OnMouseClick += LoadGameButton_OnMouseClick;
            }

            // Setup exit button
            DaggerfallUI.AddButton(new Vector2(133, 150), new Vector2(56, 19), WindowMessages.wmCloseWindow, NativePanel);

            // TEMP: Look for quick save and add temp button
            if (SaveLoadManager.Instance.HasQuickSave())
            {
                Button quickLoadButton = new Button();
                quickLoadButton.HorizontalAlignment   = HorizontalAlignment.Center;
                quickLoadButton.VerticalAlignment     = VerticalAlignment.Middle;
                quickLoadButton.BackgroundColor       = Color.gray;
                quickLoadButton.Label.Text            = "Quick Load";
                quickLoadButton.Label.BackgroundColor = Color.gray;
                quickLoadButton.OnMouseClick         += QuickLoadButton_OnMouseClick;
                quickLoadButton.Size = new Vector2(52, 10);
                NativePanel.Components.Add(quickLoadButton);
            }
        }
Exemplo n.º 11
0
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                Usage();
                return;
            }
            void WithIO(Action <Stream, Stream> action)
            {
                using (var fi = File.OpenRead(args[1]))
                    using (var fo = File.OpenWrite(args[2]))
                        action(fi, fo);
            }

            var makepkg = true;

            switch (args[0])
            {
            case "rbmid2mid":
                WithIO((fi, fo) =>
                {
                    var rbmid = RBMidReader.ReadStream(fi);
                    var midi  = RBMidConverter.ToMid(rbmid);
                    MidiCS.MidiFileWriter.WriteSMF(midi, fo);
                });
                break;

            case "mid2rbmid":
                WithIO((fi, fo) =>
                {
                    var mid   = MidiCS.MidiFileReader.FromStream(fi);
                    var rbmid = RBMidConverter.ToRBMid(mid);
                    RBMidWriter.WriteStream(rbmid, fo);
                });
                break;

            case "reprocess":
                WithIO((fi, fo) =>
                {
                    var rbmid     = RBMidReader.ReadStream(fi);
                    var processed = RBMidConverter.ToRBMid(RBMidConverter.ToMid(rbmid), rbmid.HopoThreshold);
                    RBMidWriter.WriteStream(processed, fo);
                });
                break;

            case "tex2png":
                WithIO((fi, fo) =>
                {
                    var tex    = TextureReader.ReadStream(fi);
                    var bitmap = TextureConverter.ToBitmap(tex, 0);
                    bitmap.Save(fo, System.Drawing.Imaging.ImageFormat.Png);
                });
                break;

            case "png2tex":
                WithIO((fi, fo) =>
                {
                    var img = System.Drawing.Image.FromStream(fi);
                    var tex = TextureConverter.ToTexture(img);
                    TextureWriter.WriteStream(tex, fo);
                });
                break;

            case "milopng2tex":
                WithIO((fi, fo) =>
                {
                    var tex = TextureConverter.MiloPngToTexture(fi);
                    TextureWriter.WriteStream(tex, fo);
                });
                break;

            case "mesh2obj":
            {
                var input  = args[1];
                var output = args[2];
                using (var fi = File.OpenRead(input))
                {
                    var mesh = HxMeshReader.ReadStream(fi);
                    var obj  = HxMeshConverter.ToObj(mesh);
                    File.WriteAllText(output, obj);
                }
                break;
            }

            case "milo2lip":
            case "milo2lips":
            case "milo2lipsync":
                WithIO((fi, fo) =>
                {
                    var milo    = MiloFile.ReadFromStream(fi);
                    var lipsync = LipsyncConverter.FromMilo(milo);
                    new LipsyncWriter(fo).WriteStream(lipsync);
                });
                break;

            case "version":
                var assembly    = System.Reflection.Assembly.GetExecutingAssembly();
                var version     = FileVersionInfo.GetVersionInfo(assembly.Location).FileVersion;
                var libAssembly = System.Reflection.Assembly.GetAssembly(typeof(RBMid));
                var libVersion  = FileVersionInfo.GetVersionInfo(libAssembly.Location).FileVersion;
                Console.WriteLine($"ForgeTool v{version}");
                Console.WriteLine($"LibForge v{libVersion}");
                break;

            case "test":
            {
                var dir = args[1];
                int succ = 0, warn = 0, fail = 0;
                var files = dir.EndsWith(".rbmid_ps4") || dir.EndsWith(".rbmid_pc") ?
                            new[] { dir } : Directory.EnumerateFiles(dir, "*.rbmid_*");
                foreach (var f in files)
                {
                    var info = new FileInfo(f);
                    var name = info.Name;
                    using (var fi = File.OpenRead(f))
                    {
                        try
                        {
                            var rbmid  = RBMidReader.ReadStream(fi);
                            var midi   = RBMidConverter.ToMid(rbmid);
                            var rbmid2 = RBMidConverter.ToRBMid(midi, rbmid.HopoThreshold);
                            using (var ms = new MemoryStream((int)fi.Length))
                            {
                                // TODO: Switch this to rbmid2 once we are generating all events
                                //       (regardless of whether the event data are all correct)
                                RBMidWriter.WriteStream(rbmid, ms);
                                ms.Position = 0;
                                if (ms.Length == fi.Length)
                                {
                                    var comparison = rbmid.Compare(rbmid2);
                                    if (comparison != null)
                                    {
                                        throw new CompareException("File comparison failed at field: " + comparison);
                                    }
                                    Console.WriteLine($"[OK] {name}");
                                    succ++;
                                }
                                else
                                {
                                    Console.Write($"[WARN] {name}:");
                                    Console.WriteLine($" Processed file had different length ({fi.Length} orig, {ms.Length} processed)");
                                    warn++;
                                }
                            }
                        } catch (CompareException e)
                        {
                            Console.WriteLine($"[WARN] {name}: {e.Message}");
                            warn++;
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine($"[ERROR] {name}: {e.Message}");
                            Console.WriteLine(e.StackTrace);
                            fail++;
                        }
                    }
                }
                Console.WriteLine($"Summary: {succ} OK, {warn} WARN, {fail} ERROR");
                if (warn > 0)
                {
                    Console.WriteLine("(a = converted file, b = original)");
                }
            }
            break;

            case "simpletest":
            {
                var dir = args[1];
                int succ = 0, warn = 0, fail = 0;
                foreach (var f in Directory.EnumerateFiles(dir, "*.rbmid_*"))
                {
                    var info = new FileInfo(f);
                    var name = info.Name;
                    using (var fi = File.OpenRead(f))
                    {
                        try
                        {
                            var rbmid = RBMidReader.ReadStream(fi);
                            using (var ms = new MemoryStream((int)fi.Length))
                            {
                                RBMidWriter.WriteStream(rbmid, ms);
                                ms.Position = 0;
                                if (ms.Length == fi.Length)
                                {
                                    succ++;
                                }
                                else
                                {
                                    Console.WriteLine($"[WARN] {name}:");
                                    Console.WriteLine($"  Processed file had different length ({fi.Length} orig, {ms.Length} processed)");
                                    warn++;
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine($"[ERROR] {name}:");
                            Console.WriteLine("  " + e.Message);
                            fail++;
                        }
                    }
                }
                Console.WriteLine($"Summary: {succ} OK, {warn} WARN, {fail} ERROR");
            }
            break;

            case "testrbsong":
            {
                var dir = args[1];
                int succ = 0, warn = 0, fail = 0;
                var files = dir.EndsWith(".rbsong") ?
                            new[] { dir } : Directory.EnumerateFiles(dir, "*.rbsong");
                foreach (var f in files)
                {
                    var info = new FileInfo(f);
                    var name = info.Name;
                    using (var fi = File.OpenRead(f))
                    {
                        try
                        {
                            var rbsong = new RBSongReader(fi).Read();
                            using (var ms = new MemoryStream((int)fi.Length))
                            {
                                new RBSongWriter(ms).WriteStream(rbsong);
                                ms.Position = 0;
                                if (ms.Length == fi.Length)
                                {
                                    succ++;
                                }
                                else
                                {
                                    Console.WriteLine($"[WARN] {name}:");
                                    Console.WriteLine($"  Processed file had different length ({fi.Length} orig, {ms.Length} processed)");
                                    warn++;
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine($"[ERROR] {name}:");
                            Console.WriteLine("  " + e.Message);
                            fail++;
                        }
                    }
                }
                Console.WriteLine($"Summary: {succ} OK, {warn} WARN, {fail} ERROR");
                if (fail > 0)
                {
                    Console.WriteLine("(a = converted file, b = original)");
                }
            }
            break;

            case "rbsong2rbsong":
                WithIO((i, o) => new RBSongWriter(o).WriteStream(new RBSongReader(i).Read()));
                break;

            case "con2gp4":
                makepkg = false;
                goto case "con2pkg";

            case "con2pkg":
            {
                var    i = 0;
                bool   eu = false;
                string pkgId = null, pkgDesc = null;
                while (++i < args.Length - 4)
                {
                    switch (args[i])
                    {
                    case "--scee":
                        eu = true;
                        continue;

                    case "--id":
                        pkgId = args[++i];
                        continue;

                    case "--desc":
                        pkgDesc = args[++i];
                        continue;
                    }
                    break;
                }
                if (makepkg)
                {
                    var cmd    = args[i++];
                    var con    = args[i++];
                    var dest   = args[i++];
                    var tmpDir = Path.Combine(Path.GetTempPath(), "forgetool_tmp_build");
                    if (!Directory.Exists(con))
                    {
                        var conFilename = Path.GetFileName(con);
                        PkgCreator.ConToGp4(con, tmpDir, eu, pkgId, pkgDesc);
                    }
                    else
                    {
                        PkgCreator.ConsToGp4(con, tmpDir, eu, pkgId, pkgDesc);
                    }
                    PkgCreator.BuildPkg(cmd, Path.Combine(tmpDir, "project.gp4"), dest);
                    Directory.Delete(tmpDir, true);
                }
                else
                {
                    var con  = args[i++];
                    var dest = args[i++];
                    PkgCreator.ConToGp4(con, dest, eu, pkgId, pkgDesc);
                }
            }
            break;

            default:
                Usage();
                break;
            }
        }
 void Start()
 {
     // AwakeからStartへ初期化を移動(TextureRender.csの初期化がStartのため)
     TextureReader = GetComponent <TextureReader>();
     TextureReader.OnImageAvailableCallback += OnImageAvailableCallbackFunc;
 }
Exemplo n.º 13
0
        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            switch (e.Node.Tag)
            {
            case null:
                break;

            case GameArchives.IFile i:
                if (i.Name.Contains(".bmp_") || i.Name.Contains(".png_"))
                {
                    using (var s = i.GetStream())
                    {
                        var tex = TextureReader.ReadStream(s);
                        pictureBox1.Width  = tex.Mipmaps[0].Width;
                        pictureBox1.Height = tex.Mipmaps[0].Height;
                        tabControl1.SelectTab(0);
                        fileTreeView.Select();
                        try
                        {
                            pictureBox1.Image = TextureConverter.ToBitmap(tex, 0);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show("Couldn't load texture: " + ex.Message);
                        }
                    }
                }
                else if (i.Name.Contains("_dta_") || i.Name.EndsWith(".dtb"))
                {
                    using (var s = i.GetStream())
                    {
                        var data = DtxCS.DTX.FromDtb(s);
                        tabControl1.SelectTab(1);
                        fileTreeView.Select();
                        var sb = new StringBuilder();
                        foreach (var x in data.Children)
                        {
                            sb.AppendLine(x.ToString(0));
                        }
                        dataTextBox.Text = sb.ToString();
                    }
                }
                else if (i.Name.EndsWith(".dta") || i.Name.EndsWith(".moggsong"))
                {
                    using (var s = i.GetStream())
                        using (var r = new System.IO.StreamReader(s))
                        {
                            tabControl1.SelectTab(1);
                            fileTreeView.Select();
                            dataTextBox.Text = r.ReadToEnd();
                        }
                }
                else if (i.Name.Contains(".songdta"))
                {
                    using (var s = i.GetStream())
                    {
                        var songData = SongDataReader.ReadStream(s);
                        songDataInspector1.UpdateValues(songData);
                        tabControl1.SelectTab(2);
                        fileTreeView.Select();
                    }
                }
                else if (i.Name.Contains(".fbx"))
                {
                    using (var s = i.GetStream())
                    {
                        var mesh = HxMeshReader.ReadStream(s);
                        meshTextBox.Text = HxMeshConverter.ToObj(mesh);
                        tabControl1.SelectTab(3);
                        fileTreeView.Select();
                    }
                }
                else if (i.Name.Contains(".rbmid_"))
                {
                    using (var s = i.GetStream())
                    {
                        var rbmid = RBMidReader.ReadStream(s);
                        ObjectPreview(rbmid);
                    }
                }
                else if (i.Name.Contains(".lipsync"))
                {
                    using (var s = i.GetStream())
                    {
                        var lipsync = new LibForge.Lipsync.LipsyncReader(s).Read();
                        ObjectPreview(lipsync);
                    }
                }
                else if (i.Name.Contains(".rbsong"))
                {
                    using (var s = i.GetStream())
                    {
                        var rbsong = new LibForge.RBSong.RBSongReader(s).Read();
                        ObjectPreview(rbsong);
                    }
                }
                break;
            }
        }
Exemplo n.º 14
0
        public Texture2D GetTexture(GraphicsDevice graphicsDevice, bool AsynchTextureLoad)
        {
            //Check if the texture's graphics device has been disposed, in which case load a new texture
            if (texture != null)
            {
                if (texture.GraphicsDevice.IsDisposed)
                {
                    texture = null;
                }
            }

            //Don't bother asking if we've already tried
            if (this.ServerTextureNotFound)
            {
                //Don't know how this could happen, but we should not have a texture if the server does not.  This indicates the code will leak resources
                Debug.Assert(TexReader == null);
                Debug.Assert(texture == null);
                return null;
            }

            //If we are trying to read a new texture, check if it is finished yet
            if (TexReader != null)
            {
                lock (this) //Don't let other threads change TexReader state
                {
                    if (TexReader != null) //In case someone freed TexReader before taking the lock
                    {
                        if (TexReader.FinishedReading)
                        {
                            TextureReader texReader = this.TexReader;

                            bool Entered = Monitor.TryEnter(texReader);
                            if (Entered)
                            {
                                //If reading the texture failed don't change our state.
                                if (texReader.FinishedReading)
                                {
                                    if (texReader.HasTexture)
                                    {
                                        this.texture = texReader.GetTexture();
                                        this.TexReader = null;
                                    }
                                    else
                                    {
                                        //We should stop asking if the server just doesn't have it.
                                        this.ServerTextureNotFound = texReader.TextureNotFound;
                                        this.TexReader.Dispose();
                                        this.TexReader = null;
                                        return null;
                                    }
                                }

                                Monitor.Exit(texReader);
                            }
                        }
                    }
                }
            }

            //If we have a texture that is what we want or better then return it and kill any requests
            if (texture != null)
            {
                //Drop any outstanding requests since we have a texture that works
                AbortRequest();

                return this.texture;
            }
            else
            {
                //In this path we either have no texture, or a low-res texture.  Ask for a new one if we haven't already
                if (this.TexReader == null)
                {
                    //If the section is read over a network provide a cache path too
                    if (State.volume.IsLocal == false)
                    {
                        this.TexReader = new TextureReader(graphicsDevice,
                                                           new Uri(this.TextureFileName),
                                                           this.TextureCachedFileName,
                                                           this.MipMapLevels);
                    }
                    else
                    {
                        this.TexReader = new TextureReader(graphicsDevice,
                                                            new Uri(this.TextureFileName),
                                                           this.MipMapLevels);
                    }

                    if (AsynchTextureLoad)
                    {
                        //TexReader.Go();

                        ThreadPool.QueueUserWorkItem(TexReader.ThreadPoolCallback);
                        //TexReader.ThreadPoolCallback(System.Threading.Thread.CurrentContext);
                    }
                    else
                    {
                        //I think reentrant paint calls make this lock useless
                        lock (this)
                        {
                            TextureReader texReader = this.TexReader;
                            this._TexReader = null;
                            texReader.ThreadPoolCallback(System.Threading.Thread.CurrentContext);

                            texReader.DoneEvent.WaitOne();

             //                           Debug.Assert(texReader.HasTexture);
                            if (texReader.HasTexture)
                            {
                                this.texture = texReader.GetTexture();
                            }
                            else
                            {
                                Trace.WriteLine("Synchronous texture reader does not have texture: " + TextureFileName);

                                this.ServerTextureNotFound = texReader.TextureNotFound;
                            }

                            texReader.Dispose();
                            texReader = null;
                        }
                    }
                }
                //We have a pending request, but we've been asked to load the texture NOW
                else if (this.TexReader != null && AsynchTextureLoad == false)
                {
                    //I think reentrant paint calls make this lock useless
                    lock (this)
                    {
                        if (this.TexReader != null)
                        {
                            TextureReader texReader = this.TexReader;
                            this._TexReader = null;
                            texReader.DoneEvent.WaitOne(); //Timeout after a minute?

                            Debug.Assert(texReader != null);
                            Debug.Assert(texReader.HasTexture);

                            if (texReader.HasTexture)
                            {
                                this.texture = texReader.GetTexture();
                            }

                            texReader.Dispose();
                            texReader = null;
                        }
                        else
                        {
                            Debug.Assert(this.texture != null, "Someone nulled out our texture reader, but didn't leave a texture during Synch texture load");
                        }
                    }
                }

                return this.texture; // Can return null or a texture with a different downsample level if we have one
            }
        }
Exemplo n.º 15
0
        protected virtual void Dispose(bool disposing)
        {
            if(disposing)
            {
                lock (this)
                {
                    //This disposes of the texture
                    //_texture = null;
                    if (this._texture != null)
                    {
                        if (!this._texture.IsDisposed)
                        {
                            this._texture.Dispose();
                            this._texture = null;
                        }
                    }

                    if (_TexReader != null)
                    {
                        _TexReader.AbortRequest();
                        _TexReader.Dispose();
                        _TexReader = null;
                    }

                    if (vbMesh != null)
                    {
                        vbMesh.Dispose();
                        vbMesh = null;
                    }

                    if (ibMesh != null)
                    {
                        ibMesh.Dispose();
                        ibMesh = null;
                    }

                    if (VertBuffer != null)
                    {
                        this.VertBuffer.Dispose();
                        this.VertBuffer = null;
                    }

                    if (IndBuffer != null)
                    {
                        this.IndBuffer.Dispose();
                        this.IndBuffer = null;
                    }
                }
            }
        }
Exemplo n.º 16
0
 /// <summary>
 /// On Awake
 /// </summary>
 private void Awake()
 {
     textureReader = GetComponent <TextureReader>();
 }
Exemplo n.º 17
0
 public void Awake()
 {
     // カメラ画像取得時に呼ばれるコールバック関数を定義
     TextureReader = GetComponent <TextureReader>();
     TextureReader.OnImageAvailableCallback += OnImageAvailableCallbackFunc;
 }
Exemplo n.º 18
0
 public static object LoadObject(GameArchives.IFile i)
 {
     if (i.Name.Contains(".bmp_") || i.Name.Contains(".png_"))
     {
         using (var s = i.GetStream())
         {
             try
             {
                 return(TextureReader.ReadStream(s));
             }
             catch (Exception ex)
             {
                 System.Windows.Forms.MessageBox.Show("Couldn't load texture: " + ex.Message);
                 return(null);
             }
         }
     }
     else if (i.Name.Contains("_dta_") || i.Name.EndsWith(".dtb"))
     {
         using (var s = i.GetStream())
         {
             var data = DtxCS.DTX.FromDtb(s);
             var sb   = new StringBuilder();
             foreach (var x in data.Children)
             {
                 sb.AppendLine(x.ToString(0));
             }
             return(sb.ToString());
         }
     }
     else if (i.Name.EndsWith(".dta") || i.Name.EndsWith(".moggsong"))
     {
         using (var s = i.GetStream())
             using (var r = new System.IO.StreamReader(s))
             {
                 return(r.ReadToEnd());
             }
     }
     else if (i.Name.Contains(".songdta"))
     {
         using (var s = i.GetStream())
         {
             var songData = SongDataReader.ReadStream(s);
             return(songData);
         }
     }
     else if (i.Name.Contains(".fbx"))
     {
         using (var s = i.GetStream())
         {
             return(HxMeshReader.ReadStream(s));
         }
     }
     else if (i.Name.Contains(".rbmid_"))
     {
         using (var s = i.GetStream())
         {
             return(RBMidReader.ReadStream(s));
         }
     }
     else if (i.Name.Contains(".lipsync"))
     {
         using (var s = i.GetStream())
         {
             return(new LipsyncReader(s).Read());
         }
     }
     else if (i.Name.Contains(".rbsong"))
     {
         using (var s = i.GetStream())
         {
             return(new RBSongReader(s).Read());
         }
     }
     else if (i.Name.Contains(".gp4"))
     {
         using (var s = i.GetStream())
         {
             return(LibOrbisPkg.GP4.Gp4Project.ReadFrom(s));
         }
     }
     else if (i.Name.Contains(".pkg"))
     {
         using (var s = i.GetStream())
         {
             return(new LibOrbisPkg.PKG.PkgReader(s).ReadHeader());
         }
     }
     else
     {
         return(null);
     }
 }
Exemplo n.º 19
0
        protected virtual void LoadGameObjectTexture(string texturePath, Size size)
        {
            TextureReader textureLOD = new TextureReader();

            TextureLOD = textureLOD.LoadTextureFromAssemblyPath(_texturePath, (int)size.Width, (int)size.Height);
        }
Exemplo n.º 20
0
        /// <summary>
        /// Parses the passed Stream into Puppet structures
        /// </summary>
        /// <param name="data">Stream containing the Puppet file data</param>
        /// <param name="catchExceptions">Flag allowing conditional exception catching</param>
        private void Parse(Stream data, bool catchExceptions = false)
        {
            using (BinaryReader reader = new BinaryReader(data))
            {
                while (reader.BaseStream.Position < reader.BaseStream.Length)
                {
                    string sectionName   = Encoding.UTF8.GetString(reader.ReadBytes(4));
                    int    sectionLength = reader.ReadInt32();
                    byte[] sectionBytes  = reader.ReadBytes(sectionLength);

                    using (BinaryReader sectionReader = new BinaryReader(new MemoryStream(sectionBytes)))
                    {
                        try
                        {
                            switch (sectionName)
                            {
                            case "VERS":
                                Version = VersionReader.ReadVersion(sectionReader);
                                break;

                            case "TEXT":
                                Textures = TextureReader.ReadAllTextures(sectionReader);
                                break;

                            case "SMTL":
                                SpecularMaterial = true;
                                break;

                            case "BONE":
                                Bones = BoneReader.ReadAllBones(sectionReader, Version);
                                break;

                            case "EXTR":
                                Extra = ExtraReader.ReadExtra(sectionReader);
                                break;

                            case "ANIM":
                                Animations = AnimationReader.ReadAllAnimations(sectionReader, Version);
                                break;

                            case "MESH":
                                Mesh = MeshReader.ReadMesh(sectionReader, Version);
                                break;

                            case "FANM":
                                // TODO: Implement parsing of FANM section
                                break;

                            case "FRAM":
                                Frames = FrameReader.ReadAllFrames(sectionReader);
                                break;

                            case "MOTI":
                                Motions = MotionReader.ReadAllMotions(sectionReader);
                                break;

                            case "COLL":
                                CollisionBoxes = CollisionBoxReader.ReadAllCollisionBoxes(sectionReader, Version);
                                break;

                            default:
                                Debug.WriteLine($"Unknown section '${sectionName}' with size of ${sectionLength.ToString()} bytes");
                                break;
                            }
                        }
                        catch (Exception e) when(catchExceptions)
                        {
                            Debug.WriteLine($"{e.Message}\n{e.StackTrace}");
                        }
                    }
                }
            }
        }
Exemplo n.º 21
0
        private static byte[] RemoveTransparencyDds(byte[] ddsImageBytes, CompressFormat?namePreferredFormat)
        {
            var format  = namePreferredFormat ?? (_dxt1Mode ? CompressFormat.DXT1 : CompressFormat.RGB);
            var dxtMode = format == CompressFormat.DXT1 || format == CompressFormat.DXT5;

            if (_textureReader == null)
            {
                _textureReader = new TextureReader();
            }

            byte[] pngImageBytes;
            if (_preserveGradients)
            {
                pngImageBytes = RemoveTransparencyBitmap(_textureReader.ToPng(ddsImageBytes), out var containsGradients);
                if (containsGradients)
                {
                    switch (format)
                    {
                    case CompressFormat.RGB:
                        format = CompressFormat.RGBA;
                        break;

                    case CompressFormat.Luminance:
                        format = CompressFormat.LuminanceAlpha;
                        break;

                    case CompressFormat.RGB565:
                        format = CompressFormat.A4R4G4B4;
                        break;

                    case CompressFormat.DXT1:
                        format = CompressFormat.DXT5;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }
                }
            }
            else
            {
                pngImageBytes = _textureReader.ToPng(ddsImageBytes, true);
            }

            if (pngImageBytes == null)
            {
                return(null);
            }

            using (var pngImageStream = new MemoryStream(pngImageBytes))
                using (var pngImage = (Bitmap)Image.FromStream(pngImageStream))
                    using (var output = new MemoryStream()) {
                        new Compressor {
                            MipmapMaxLevel = _mipMaps ? -1 : 0,
                            RoundMode      = dxtMode ? CompressRoundMode.ToNearestMultipleOfFour : CompressRoundMode.None,
                            Quality        = _productionQuality ? CompressQuality.Production : CompressQuality.Normal,
                            ResizeFilter   = CompressResizeFilter.Mitchell,
                            Format         = format
                        }.Process(pngImage.Width, pngImage.Height, CopySafe(pngImage), output, null, null);
                        return(output.ToArray());
                    }
        }
Exemplo n.º 22
0
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                Usage();
                return;
            }
            void WithIO(Action <Stream, Stream> action)
            {
                using (var fi = File.OpenRead(args[1]))
                    using (var fo = File.OpenWrite(args[2]))
                        action(fi, fo);
            }

            var makepkg = true;

            switch (args[0])
            {
            case "rbmid2mid":
                WithIO((fi, fo) =>
                {
                    var rbmid = RBMidReader.ReadStream(fi);
                    var midi  = RBMidConverter.ToMid(rbmid);
                    MidiCS.MidiFileWriter.WriteSMF(midi, fo);
                });
                break;

            case "mid2rbmid":
                WithIO((fi, fo) =>
                {
                    var mid   = MidiCS.MidiFileReader.FromStream(fi);
                    var rbmid = RBMidConverter.ToRBMid(mid);
                    RBMidWriter.WriteStream(rbmid, fo);
                });
                break;

            case "reprocess":
                WithIO((fi, fo) =>
                {
                    var rbmid     = RBMidReader.ReadStream(fi);
                    var processed = RBMidConverter.ToRBMid(RBMidConverter.ToMid(rbmid), rbmid.HopoThreshold);
                    RBMidWriter.WriteStream(processed, fo);
                });
                break;

            case "tex2png":
                WithIO((fi, fo) =>
                {
                    var tex    = TextureReader.ReadStream(fi);
                    var bitmap = TextureConverter.ToBitmap(tex, 0);
                    bitmap.Save(fo, System.Drawing.Imaging.ImageFormat.Png);
                });
                break;

            case "png2tex":
                WithIO((fi, fo) =>
                {
                    var img = System.Drawing.Image.FromStream(fi);
                    var tex = TextureConverter.ToTexture(img);
                    TextureWriter.WriteStream(tex, fo);
                });
                break;

            case "milopng2tex":
                WithIO((fi, fo) =>
                {
                    var tex = TextureConverter.MiloPngToTexture(fi);
                    TextureWriter.WriteStream(tex, fo);
                });
                break;

            case "mesh2obj":
            {
                var input  = args[1];
                var output = args[2];
                using (var fi = File.OpenRead(input))
                {
                    var mesh = HxMeshReader.ReadStream(fi);
                    var obj  = HxMeshConverter.ToObj(mesh);
                    File.WriteAllText(output, obj);
                }
                break;
            }

            case "milo2lip":
            case "milo2lips":
            case "milo2lipsync":
                WithIO((fi, fo) =>
                {
                    var milo    = MiloFile.ReadFromStream(fi);
                    var lipsync = LipsyncConverter.FromMilo(milo);
                    new LipsyncWriter(fo).WriteStream(lipsync);
                });
                break;

            case "version":
                var assembly    = System.Reflection.Assembly.GetExecutingAssembly();
                var version     = FileVersionInfo.GetVersionInfo(assembly.Location).FileVersion;
                var libAssembly = System.Reflection.Assembly.GetAssembly(typeof(RBMid));
                var libVersion  = FileVersionInfo.GetVersionInfo(libAssembly.Location).FileVersion;
                Console.WriteLine($"ForgeTool v{version}");
                Console.WriteLine($"LibForge v{libVersion}");
                break;

            case "test":
            {
                var dir = args[1];
                int succ = 0, warn = 0, fail = 0;
                var files = dir.EndsWith(".rbmid_ps4") || dir.EndsWith(".rbmid_pc") ?
                            new[] { dir } : Directory.EnumerateFiles(dir, "*.rbmid_*");
                foreach (var f in files)
                {
                    var info = new FileInfo(f);
                    var name = info.Name;
                    using (var fi = File.OpenRead(f))
                    {
                        try
                        {
                            var rbmid  = RBMidReader.ReadStream(fi);
                            var midi   = RBMidConverter.ToMid(rbmid);
                            var rbmid2 = RBMidConverter.ToRBMid(midi, rbmid.HopoThreshold);
                            using (var ms = new MemoryStream((int)fi.Length))
                            {
                                // TODO: Switch this to rbmid2 once we are generating all events
                                //       (regardless of whether the event data are all correct)
                                RBMidWriter.WriteStream(rbmid, ms);
                                ms.Position = 0;
                                if (ms.Length == fi.Length)
                                {
                                    var comparison = rbmid.Compare(rbmid2);
                                    if (comparison != null)
                                    {
                                        throw new CompareException("File comparison failed at field: " + comparison);
                                    }
                                    Console.WriteLine($"[OK] {name}");
                                    succ++;
                                }
                                else
                                {
                                    Console.Write($"[WARN] {name}:");
                                    Console.WriteLine($" Processed file had different length ({fi.Length} orig, {ms.Length} processed)");
                                    warn++;
                                }
                            }
                        } catch (CompareException e)
                        {
                            Console.WriteLine($"[WARN] {name}: {e.Message}");
                            warn++;
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine($"[ERROR] {name}: {e.Message}");
                            Console.WriteLine(e.StackTrace);
                            fail++;
                        }
                    }
                }
                Console.WriteLine($"Summary: {succ} OK, {warn} WARN, {fail} ERROR");
                if (warn > 0)
                {
                    Console.WriteLine("(a = converted file, b = original)");
                }
                if (warn > 0 || fail > 0)
                {
                    Environment.Exit(1);
                }
            }
            break;

            case "simpletest":
            {
                var dir = args[1];
                int succ = 0, warn = 0, fail = 0;
                foreach (var f in Directory.EnumerateFiles(dir, "*.rbmid_*"))
                {
                    var info = new FileInfo(f);
                    var name = info.Name;
                    using (var fi = File.OpenRead(f))
                    {
                        try
                        {
                            var rbmid = RBMidReader.ReadStream(fi);
                            using (var ms = new MemoryStream((int)fi.Length))
                            {
                                RBMidWriter.WriteStream(rbmid, ms);
                                ms.Position = 0;
                                if (ms.Length == fi.Length)
                                {
                                    succ++;
                                }
                                else
                                {
                                    Console.WriteLine($"[WARN] {name}:");
                                    Console.WriteLine($"  Processed file had different length ({fi.Length} orig, {ms.Length} processed)");
                                    warn++;
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine($"[ERROR] {name}:");
                            Console.WriteLine("  " + e.Message);
                            fail++;
                        }
                    }
                }
                Console.WriteLine($"Summary: {succ} OK, {warn} WARN, {fail} ERROR");
            }
            break;

            case "testrbsong":
            {
                var dir = args[1];
                int succ = 0, warn = 0, fail = 0;
                var files = dir.EndsWith(".rbsong") ?
                            new[] { dir } : Directory.EnumerateFiles(dir, "*.rbsong");
                foreach (var f in files)
                {
                    var info = new FileInfo(f);
                    var name = info.Name;
                    using (var fi = File.OpenRead(f))
                    {
                        try
                        {
                            var rbsong = new RBSongResource();
                            rbsong.Load(fi);
                            using (var ms = new MemoryStream((int)fi.Length))
                            {
                                new RBSongResourceWriter(ms).WriteStream(rbsong);
                                ms.Position = 0;
                                if (ms.Length == fi.Length)
                                {
                                    succ++;
                                }
                                else
                                {
                                    Console.WriteLine($"[WARN] {name}:");
                                    Console.WriteLine($"  Processed file had different length ({fi.Length} orig, {ms.Length} processed)");
                                    warn++;
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine($"[ERROR] {name}:");
                            Console.WriteLine("  " + e.Message);
                            fail++;
                        }
                    }
                }
                Console.WriteLine($"Summary: {succ} OK, {warn} WARN, {fail} ERROR");
                if (fail > 0)
                {
                    Console.WriteLine("(a = converted file, b = original)");
                }
            }
            break;

            case "rbsong2rbsong":
                WithIO((i, o) => {
                    var rbsong = new RBSongResource();
                    rbsong.Load(i);
                    new RBSongResourceWriter(o).WriteStream(rbsong);
                });
                break;

            case "con2gp4":
                makepkg = false;
                goto case "con2pkg";

            case "con2pkg":
            {
                var    i = 0;
                bool   eu = false;
                string pkgId = null, pkgDesc = null;
                while (++i < args.Length - 3)
                {
                    switch (args[i])
                    {
                    case "--scee":
                        eu = true;
                        continue;

                    case "--id":
                        pkgId = args[++i];
                        continue;

                    case "--desc":
                        pkgDesc = args[++i];
                        continue;
                    }
                    break;
                }
                if (makepkg)
                {
                    var con    = args[i++];
                    var dest   = args[i++];
                    var tmpDir = Path.Combine(Path.GetTempPath(), "forgetool_tmp_build");
                    if (!Directory.Exists(con))
                    {
                        var conFilename = Path.GetFileName(con);
                        PkgCreator.ConToGp4(con, tmpDir, eu, pkgId, pkgDesc);
                    }
                    else
                    {
                        PkgCreator.ConsToGp4(con, tmpDir, eu, pkgId, pkgDesc);
                    }
                    PkgCreator.BuildPkg(Path.Combine(tmpDir, "project.gp4"), dest);
                    Directory.Delete(tmpDir, true);
                }
                else
                {
                    var con  = args[i++];
                    var dest = args[i++];
                    PkgCreator.ConToGp4(con, dest, eu, pkgId, pkgDesc);
                }
            }
            break;

            case "csv2txt":
            {
                var input  = args[1];
                var output = args[2];
                using (var fi = File.OpenRead(input))
                {
                    var csv = CsvData.LoadFile(fi);
                    File.WriteAllText(output, csv.ToString());
                }
            }
            break;

            case "arkorder":
            {
                var input   = args[1];
                var output  = args[2];
                var sb      = new StringBuilder();
                var archive = new Archive(input);
                using (var o = File.OpenWrite(output))
                    using (var sw = new StreamWriter(o))
                    {
                        archive.WriteArkorder(sw);
                    }
            }
            break;

            case "arkbuild":
            {
                var filedir  = args[1];
                var arkorder = args[2];
                var outdir   = args[3];
                var name     = args[4];
                if (!Directory.Exists(filedir))
                {
                    Console.WriteLine($"Error: {filedir} does not exist.");
                    return;
                }
                if (!Directory.Exists(outdir))
                {
                    Console.WriteLine($"Error: {outdir} does not exist.");
                    return;
                }
                if (!File.Exists(arkorder))
                {
                    Console.WriteLine($"Error: {arkorder} not found.");
                    return;
                }
                var       arks = new List <List <Tuple <string, IFile> > >();
                DataArray arkOrder;
                using (var order = File.OpenRead(arkorder))
                    using (var reader = new StreamReader(order))
                    {
                        arkOrder = DtxCS.DTX.FromDtaStream(order);
                    }
                int arkIndex = 0;
                arks.Add(new List <Tuple <string, IFile> >());
                foreach (var x in arkOrder.Children)
                {
                    if (x is DataSymbol s)
                    {
                        var fullPath = Path.Combine(filedir, s.Name.Replace('/', Path.DirectorySeparatorChar));
                        if (!File.Exists(fullPath))
                        {
                            Console.WriteLine($"Error: {fullPath} could not be found.");
                            return;
                        }
                        IFile f = Util.LocalFile(fullPath);
                        arks[arkIndex].Add(Tuple.Create(s.Name, f));
                    }
                    else if (x is DataCommand c && c.Symbol(0).Name == "split_ark")
                    {
                        arkIndex++;
                        arks[arkIndex] = new List <Tuple <string, IFile> >();
                    }
                }
                var builder = new ArkBuilder(name, arks);
                Console.Write($"Writing {name}.hdr and ark files to {outdir}...");
                builder.Save(outdir);
            }
            break;

            default:
                Usage();
                break;
            }
        }
Exemplo n.º 23
0
        private void TextureCopy(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
        {
            CopyOperation Operation = (CopyOperation)ReadRegister(NvGpuEngine2dReg.CopyOperation);

            bool SrcLinear = ReadRegister(NvGpuEngine2dReg.SrcLinear) != 0;
            int  SrcWidth  = ReadRegister(NvGpuEngine2dReg.SrcWidth);
            int  SrcHeight = ReadRegister(NvGpuEngine2dReg.SrcHeight);
            int  SrcPitch  = ReadRegister(NvGpuEngine2dReg.SrcPitch);
            int  SrcBlkDim = ReadRegister(NvGpuEngine2dReg.SrcBlockDimensions);

            bool DstLinear = ReadRegister(NvGpuEngine2dReg.DstLinear) != 0;
            int  DstWidth  = ReadRegister(NvGpuEngine2dReg.DstWidth);
            int  DstHeight = ReadRegister(NvGpuEngine2dReg.DstHeight);
            int  DstPitch  = ReadRegister(NvGpuEngine2dReg.DstPitch);
            int  DstBlkDim = ReadRegister(NvGpuEngine2dReg.DstBlockDimensions);

            TextureSwizzle SrcSwizzle = SrcLinear
                ? TextureSwizzle.Pitch
                : TextureSwizzle.BlockLinear;

            TextureSwizzle DstSwizzle = DstLinear
                ? TextureSwizzle.Pitch
                : TextureSwizzle.BlockLinear;

            int SrcBlockHeight = 1 << ((SrcBlkDim >> 4) & 0xf);
            int DstBlockHeight = 1 << ((DstBlkDim >> 4) & 0xf);

            long SrcAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.SrcAddress);
            long DstAddress = MakeInt64From2xInt32(NvGpuEngine2dReg.DstAddress);

            long SrcKey = Vmm.GetPhysicalAddress(SrcAddress);
            long DstKey = Vmm.GetPhysicalAddress(DstAddress);

            bool IsSrcFb = Gpu.Engine3d.IsFrameBufferPosition(SrcKey);
            bool IsDstFb = Gpu.Engine3d.IsFrameBufferPosition(DstKey);

            TextureInfo SrcTexture()
            {
                return(new TextureInfo(
                           SrcAddress,
                           SrcWidth,
                           SrcHeight,
                           SrcPitch,
                           SrcBlockHeight, 1,
                           SrcSwizzle,
                           GalTextureFormat.A8B8G8R8));
            }

            TextureInfo DstTexture()
            {
                return(new TextureInfo(
                           DstAddress,
                           DstWidth,
                           DstHeight,
                           DstPitch,
                           DstBlockHeight, 1,
                           DstSwizzle,
                           GalTextureFormat.A8B8G8R8));
            }

            //TODO: fb -> fb copies, tex -> fb copies, formats other than RGBA8,
            //make it throw for unimpl stuff (like the copy mode)...
            if (IsSrcFb && IsDstFb)
            {
                //Frame Buffer -> Frame Buffer copy.
                Gpu.Renderer.FrameBuffer.Copy(
                    SrcKey,
                    DstKey,
                    0,
                    0,
                    SrcWidth,
                    SrcHeight,
                    0,
                    0,
                    DstWidth,
                    DstHeight);
            }
            if (IsSrcFb)
            {
                //Frame Buffer -> Texture copy.
                Gpu.Renderer.FrameBuffer.GetBufferData(SrcKey, (byte[] Buffer) =>
                {
                    TextureInfo Src = SrcTexture();
                    TextureInfo Dst = DstTexture();

                    if (Src.Width != Dst.Width ||
                        Src.Height != Dst.Height)
                    {
                        throw new NotImplementedException("Texture resizing is not supported");
                    }

                    TextureWriter.Write(Vmm, Dst, Buffer);
                });
            }
            else if (IsDstFb)
            {
                //Texture -> Frame Buffer copy.
                const GalTextureFormat Format = GalTextureFormat.A8B8G8R8;

                byte[] Buffer = TextureReader.Read(Vmm, SrcTexture());

                Gpu.Renderer.FrameBuffer.SetBufferData(
                    DstKey,
                    DstWidth,
                    DstHeight,
                    Format,
                    Buffer);
            }
            else
            {
                //Texture -> Texture copy.
                TextureInfo Src = SrcTexture();
                TextureInfo Dst = DstTexture();

                if (Src.Width != Dst.Width ||
                    Src.Height != Dst.Height)
                {
                    throw new NotImplementedException("Texture resizing is not supported");
                }

                TextureWriter.Write(Vmm, Dst, TextureReader.Read(Vmm, Src));
            }
        }
 public WOTerrainMaterialProvider(Mod injectedMod)
 {
     mod           = injectedMod;
     textureReader = new TextureReader(DaggerfallUnity.Instance.Arena2Path);
 }
Exemplo n.º 25
0
        protected override void Setup()
        {
            if (IsSetup)
            {
                return;
            }

            // Set background
            backgroundImg    = new ImgFile(Path.Combine(DaggerfallUnity.Arena2Path, nativeImgName), FileUsage.UseMemory, true);
            backgroundBitmap = backgroundImg.GetDFBitmap(0, 0);
            nativeTexture    = new Texture2D(backgroundBitmap.Width, backgroundBitmap.Height, TextureFormat.ARGB32, false);
            if (!nativeTexture)
            {
                throw new Exception("CreateCharClassQuestions: Could not load native texture.");
            }
            nativeTexture.SetPixels32(backgroundImg.GetColor32(backgroundBitmap, 0));
            nativeTexture.Apply(false, true);
            nativeTexture.filterMode      = DaggerfallUI.Instance.GlobalFilterMode;
            NativePanel.BackgroundTexture = nativeTexture;

            // Load both scroll images as one contiguous list of textures
            scrollFile0         = new GfxFile(Path.Combine(DaggerfallUnity.Instance.Arena2Path, scroll0FileName), FileUsage.UseMemory, true);
            scrollFile1         = new GfxFile(Path.Combine(DaggerfallUnity.Instance.Arena2Path, scroll1FileName), FileUsage.UseMemory, true);
            scrollFile0.Palette = backgroundBitmap.Palette;
            scrollFile1.Palette = backgroundBitmap.Palette;
            scrollTextures      = new List <Texture2D>();
            for (int i = 0; i < scrollFile0.frames.Length; i++)
            {
                scrollTextures.Add(TextureReader.CreateFromAPIImage(scrollFile0, 0, i, 0));
                scrollTextures.Last().filterMode = DaggerfallUI.Instance.GlobalFilterMode;
            }
            for (int i = scrollFile0.frames.Length; i < scrollFile0.frames.Length + scrollFile1.frames.Length; i++)
            {
                scrollTextures.Add(TextureReader.CreateFromAPIImage(scrollFile1, 0, i - scrollFile0.frames.Length, 0));
                scrollTextures.Last().filterMode = DaggerfallUI.Instance.GlobalFilterMode;
            }

            // Position scroll image on screen
            questionScroll.Position          = new Vector2(0, 120f);
            questionScroll.Size              = new Vector2(scrollTextures[0].width, scrollTextures[0].height);
            questionScroll.BackgroundTexture = scrollTextures[0];
            questionScroll.Parent            = NativePanel;
            textArea.Position = new Vector2(leftTextOffset, 120f + topTextOffset);
            textArea.Size     = new Vector2(scrollTextures[0].width, scrollTextures[0].height - topTextOffset * 2f);
            textArea.Parent   = NativePanel;
            NativePanel.Components.Add(textArea);
            NativePanel.Components.Add(questionScroll);

            // Setup question label
            questionIndices = GetQuestions();
            DisplayQuestion(questionIndices[questionsAnswered]);

            // Handle scrolling
            NativePanel.OnMouseScrollDown += NativePanel_OnMouseScrollDown;
            NativePanel.OnMouseScrollUp   += NativePanel_OnMouseScrollUp;
            questionScroll.OnMouseDown    += QuestionScroll_OnMouseDown;
            questionScroll.OnMouseUp      += QuestionScroll_OnMouseUp;

            // Setup animations
            rogueAnim.SetTransparentColor(0, 0, 10);
            rogueAnim.TransparencyEnabled = true;
            rogueAnim.Load("ROGUE.CEL");
            rogueAnim.Size            = new Vector2(rogueAnim.FLCFile.Header.Width, rogueAnim.FLCFile.Header.Height);
            rogueAnim.Position        = new Vector2(1f, 1f);
            rogueAnim.BackgroundColor = Color.clear;
            rogueAnim.OnAnimEnd      += CEL_OnAnimEnd;
            mageAnim.SetTransparentColor(0, 0, 10);
            mageAnim.TransparencyEnabled = true;
            mageAnim.Load("MAGE.CEL");
            mageAnim.Size            = new Vector2(mageAnim.FLCFile.Header.Width, mageAnim.FLCFile.Header.Height);
            mageAnim.Position        = new Vector2(79f, 1f);
            mageAnim.BackgroundColor = Color.clear;
            mageAnim.OnAnimEnd      += CEL_OnAnimEnd;
            warriorAnim.SetTransparentColor(0, 0, 10);
            warriorAnim.TransparencyEnabled = true;
            warriorAnim.Load("WARRIOR.CEL");
            warriorAnim.Size            = new Vector2(warriorAnim.FLCFile.Header.Width, warriorAnim.FLCFile.Header.Height);
            warriorAnim.Position        = new Vector2(110f, 1f);
            warriorAnim.BackgroundColor = Color.clear;
            warriorAnim.OnAnimEnd      += CEL_OnAnimEnd;
            rogueAnim.Loop = mageAnim.Loop = warriorAnim.Loop = false;
            NativePanel.Components.Add(rogueAnim);
            NativePanel.Components.Add(mageAnim);
            NativePanel.Components.Add(warriorAnim);

            IsSetup = true;
        }
Exemplo n.º 26
0
        /// <summary>
        /// Gets Unity Material atlas from Daggerfall texture archive.
        /// </summary>
        /// <param name="archive">Archive index to create atlas from.</param>
        /// <param name="alphaIndex">Index to receive transparent alpha.</param>
        /// <param name="rectsOut">Array of rects, one for each record sub-texture and frame.</param>
        /// <param name="padding">Number of pixels each sub-texture.</param>
        /// <param name="maxAtlasSize">Max size of atlas.</param>
        /// <param name="rectsOut">Array of rects, one for each record sub-texture and frame.</param>
        /// <param name="indicesOut">Array of record indices into rect array, accounting for animation frames.</param>
        /// <param name="border">Number of pixels internal border around each texture.</param>
        /// <param name="dilate">Blend texture into surrounding empty pixels.</param>
        /// <param name="shrinkUVs">Number of pixels to shrink UV rect.</param>
        /// <param name="copyToOppositeBorder">Copy texture edges to opposite border. Requires border, will overwrite dilate.</param>
        /// <param name="shader">Shader for material. If null, DefaultShaderName will be applied.</param>
        /// <returns>Material or null.</returns>
        public Material GetMaterialAtlas(
            int archive,
            int alphaIndex,
            int padding,
            int maxAtlasSize,
            out Rect[] rectsOut,
            out RecordIndex[] indicesOut,
            int border                = 0,
            bool dilate               = false,
            int shrinkUVs             = 0,
            bool copyToOppositeBorder = false)
        {
            // Ready check
            if (!IsReady)
            {
                rectsOut   = null;
                indicesOut = null;
                return(null);
            }

            int key = MakeTextureKey((short)archive, (byte)0, (byte)0, AtlasKeyGroup);

            if (materialDict.ContainsKey(key))
            {
                CachedMaterial cm = materialDict[key];
                if (cm.filterMode == MainFilterMode)
                {
                    // Properties are the same
                    rectsOut   = cm.atlasRects;
                    indicesOut = cm.atlasIndices;
                    return(cm.material);
                }
                else
                {
                    // Properties don't match, remove material and reload
                    materialDict.Remove(key);
                }
            }

            // Create material
            Material material = CreateStandardMaterial();

            // Create settings
            GetTextureSettings settings = TextureReader.CreateTextureSettings(archive, 0, 0, alphaIndex, border, dilate);

            settings.createNormalMap      = GenerateNormals;
            settings.autoEmission         = true;
            settings.atlasShrinkUVs       = shrinkUVs;
            settings.atlasPadding         = padding;
            settings.atlasMaxSize         = maxAtlasSize;
            settings.copyToOppositeBorder = copyToOppositeBorder;

            // Setup material
            material.name = string.Format("TEXTURE.{0:000} [Atlas]", archive);
            GetTextureResults results = textureReader.GetTexture2DAtlas(settings, AlphaTextureFormat, NonAlphaTextureFormat);

            material.mainTexture            = results.albedoMap;
            material.mainTexture.filterMode = MainFilterMode;

            // Setup normal map
            if (GenerateNormals && results.normalMap != null)
            {
                results.normalMap.filterMode = MainFilterMode;
                material.SetTexture("_BumpMap", results.normalMap);
                material.EnableKeyword("_NORMALMAP");
            }

            // Setup emission map
            if (results.isEmissive && results.emissionMap != null)
            {
                results.emissionMap.filterMode = MainFilterMode;
                material.SetTexture("_EmissionMap", results.emissionMap);
                material.SetColor("_EmissionColor", Color.white);
                material.EnableKeyword("_EMISSION");
            }

            // TEMP: Bridging between legacy material out params and GetTextureResults for now
            Vector2[] sizesOut, scalesOut, offsetsOut;
            sizesOut   = results.atlasSizes.ToArray();
            scalesOut  = results.atlasScales.ToArray();
            offsetsOut = results.atlasOffsets.ToArray();
            rectsOut   = results.atlasRects.ToArray();
            indicesOut = results.atlasIndices.ToArray();

            // Setup cached material
            CachedMaterial newcm = new CachedMaterial();

            newcm.key              = key;
            newcm.keyGroup         = AtlasKeyGroup;
            newcm.atlasRects       = rectsOut;
            newcm.atlasIndices     = indicesOut;
            newcm.material         = material;
            newcm.filterMode       = MainFilterMode;
            newcm.recordSizes      = sizesOut;
            newcm.recordScales     = scalesOut;
            newcm.recordOffsets    = offsetsOut;
            newcm.atlasFrameCounts = results.atlasFrameCounts.ToArray();
            materialDict.Add(key, newcm);

            return(material);
        }
        bool IsReady()
        {
            if (!dfUnity)
            {
                dfUnity = DaggerfallUnity.Instance;
            }

            if (itemHelper == null)
            {
                itemHelper = new ItemHelper();
            }

            if (!dfUnity.IsReady || string.IsNullOrEmpty(dfUnity.Arena2Path))
            {
                return(false);
            }

            if (factionFile == null)
            {
                factionFile = new FactionFile(dfUnity.ContentReader.GetFactionFilePath(), FileUsage.UseMemory, true);
            }

            if (saveGames == null || saveTrees == null || saveNames == null)
            {
                saveGames    = new SaveGames();
                saveNames    = new GUIContent[6];
                saveTrees    = new SaveTree[6];
                saveVars     = new SaveVars[6];
                saveTextures = new Texture2D[6];
                if (saveGames.OpenSavesPath(Path.GetDirectoryName(DaggerfallUnity.Instance.Arena2Path)))
                {
                    for (int i = 0; i < 6; i++)
                    {
                        if (saveGames.HasSave(i))
                        {
                            saveGames.OpenSave(i, false);
                            saveTrees[i]               = saveGames.SaveTree;
                            saveVars[i]                = saveGames.SaveVars;
                            saveNames[i]               = new GUIContent(saveGames.SaveName);
                            saveTextures[i]            = TextureReader.CreateFromAPIImage(saveGames.SaveImage);
                            saveTextures[i].filterMode = FilterMode.Point;
                        }
                        else
                        {
                            saveTrees[i]    = null;
                            saveVars[i]     = null;
                            saveTextures[i] = null;
                            saveNames[i]    = new GUIContent("Empty");
                        }
                    }
                }

                // Prevent duplicate names so save games aren't automatically removed from the Save Select GUI
                for (int i = 0; i < saveNames.Length; i++)
                {
                    int duplicateCount = 0;
                    for (int j = i + 1; j < saveNames.Length; j++)
                    {
                        if (saveNames[j].text == saveNames[i].text)
                        {
                            bool unique = false;
                            while (!unique)
                            {
                                unique = true;
                                string replaceText = saveNames[j].text + "(" + ++duplicateCount + ")";
                                for (int k = 0; k < saveNames.Length; k++)
                                {
                                    if (saveNames[k].text == replaceText)
                                    {
                                        unique = false;
                                        break;
                                    }
                                }

                                if (unique)
                                {
                                    saveNames[j].text = replaceText;
                                }
                            }
                        }
                    }
                }
            }

            return(true);
        }
Exemplo n.º 28
0
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                Usage();
                return;
            }
            void WithIO(Action <Stream, Stream> action)
            {
                using (var fi = File.OpenRead(args[1]))
                    using (var fo = File.OpenWrite(args[2]))
                        action(fi, fo);
            }

            switch (args[0])
            {
            case "rbmid2mid":
                WithIO((fi, fo) =>
                {
                    var rbmid = RBMidReader.ReadStream(fi);
                    var midi  = RBMidConverter.ToMid(rbmid);
                    MidiCS.MidiFileWriter.WriteSMF(midi, fo);
                });
                break;

            case "mid2rbmid":
                WithIO((fi, fo) =>
                {
                    var mid   = MidiCS.MidiFileReader.FromStream(fi);
                    var rbmid = RBMidConverter.ToRBMid(mid);
                    RBMidWriter.WriteStream(rbmid, fo);
                });
                break;

            case "reprocess":
                WithIO((fi, fo) =>
                {
                    var rbmid     = RBMidReader.ReadStream(fi);
                    var processed = RBMidConverter.ToRBMid(RBMidConverter.ToMid(rbmid));
                    RBMidWriter.WriteStream(processed, fo);
                });
                break;

            case "tex2png":
                WithIO((fi, fo) =>
                {
                    var tex    = TextureReader.ReadStream(fi);
                    var bitmap = TextureConverter.ToBitmap(tex, 0);
                    bitmap.Save(fo, System.Drawing.Imaging.ImageFormat.Png);
                });
                break;

            case "mesh2obj":
            {
                var input  = args[1];
                var output = args[2];
                using (var fi = File.OpenRead(input))
                {
                    var mesh = HxMeshReader.ReadStream(fi);
                    var obj  = HxMeshConverter.ToObj(mesh);
                    File.WriteAllText(output, obj);
                }
                break;
            }

            case "version":
                var assembly    = System.Reflection.Assembly.GetExecutingAssembly();
                var version     = FileVersionInfo.GetVersionInfo(assembly.Location).FileVersion;
                var libAssembly = System.Reflection.Assembly.GetAssembly(typeof(RBMid));
                var libVersion  = FileVersionInfo.GetVersionInfo(libAssembly.Location).FileVersion;
                Console.WriteLine($"ForgeTool v{version}");
                Console.WriteLine($"LibForge v{libVersion}");
                break;

            case "test":
            {
                var dir = args[1];
                int succ = 0, warn = 0, fail = 0;
                var files = dir.EndsWith(".rbmid_ps4") || dir.EndsWith(".rbmid_pc") ?
                            new[] { dir } : Directory.EnumerateFiles(dir, "*.rbmid_*");
                foreach (var f in files)
                {
                    var info = new FileInfo(f);
                    var name = info.Name;
                    using (var fi = File.OpenRead(f))
                    {
                        try
                        {
                            var rbmid  = RBMidReader.ReadStream(fi);
                            var midi   = RBMidConverter.ToMid(rbmid);
                            var rbmid2 = RBMidConverter.ToRBMid(midi);
                            using (var ms = new MemoryStream((int)fi.Length))
                            {
                                // TODO: Switch this to rbmid2 once we are generating all events
                                //       (regardless of whether the event data are all correct)
                                RBMidWriter.WriteStream(rbmid, ms);
                                ms.Position = 0;
                                if (ms.Length == fi.Length)
                                {
                                    var comparison = rbmid.Compare(rbmid2);
                                    if (comparison != null)
                                    {
                                        throw new Exception("File comparison failed at field: " + comparison);
                                    }
                                    succ++;
                                }
                                else
                                {
                                    Console.WriteLine($"[WARN] {name}:");
                                    Console.WriteLine($"  Processed file had different length ({fi.Length} orig, {ms.Length} processed)");
                                    warn++;
                                }
                            }
                        } catch (Exception e)
                        {
                            Console.WriteLine($"[ERROR] {name}:");
                            Console.WriteLine("  " + e.Message);
                            fail++;
                        }
                    }
                }
                Console.WriteLine($"Summary: {succ} OK, {warn} WARN, {fail} ERROR");
                if (fail > 0)
                {
                    Console.WriteLine("(a = converted file, b = original)");
                }
            }
            break;

            case "simpletest":
            {
                var dir = args[1];
                int succ = 0, warn = 0, fail = 0;
                foreach (var f in Directory.EnumerateFiles(dir, "*.rbmid_*"))
                {
                    var info = new FileInfo(f);
                    var name = info.Name;
                    using (var fi = File.OpenRead(f))
                    {
                        try
                        {
                            var rbmid = RBMidReader.ReadStream(fi);
                            using (var ms = new MemoryStream((int)fi.Length))
                            {
                                RBMidWriter.WriteStream(rbmid, ms);
                                ms.Position = 0;
                                if (ms.Length == fi.Length)
                                {
                                    succ++;
                                }
                                else
                                {
                                    Console.WriteLine($"[WARN] {name}:");
                                    Console.WriteLine($"  Processed file had different length ({fi.Length} orig, {ms.Length} processed)");
                                    warn++;
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine($"[ERROR] {name}:");
                            Console.WriteLine("  " + e.Message);
                            fail++;
                        }
                    }
                }
                Console.WriteLine($"Summary: {succ} OK, {warn} WARN, {fail} ERROR");
            }
            break;

            default:
                Usage();
                break;
            }
        }