public override void Patch(ReiPatcher.Patch.PatcherArguments args)
        {
            try
            {
                AssemblyDefinition ta = args.Assembly;
                AssemblyDefinition da = PatcherHelper.GetAssemblyDefinition(args, "CM3D2.MaidVoicePitch.Managed.dll");
                string m = "CM3D2.MaidVoicePitch.Managed.";

                // TBody.LateUpdateの処理終了後にCM3D2.MaidVoicePitch.Managed.Callbacks.TBody.LateUpdate.Invokeを呼び出す
                PatcherHelper.SetHook(PatcherHelper.HookType.PostCall, ta, "TBody", "LateUpdate", da, m + "Callbacks.TBody.LateUpdate", "Invoke");

                // TBody.MoveHeadAndEyeの処理を完全に乗っ取り、CM3D2.MaidVoicePitch.Managed.Callbacks.TBody.MoveHeadAndEye.Invokeの呼び出しに置き換える
                PatcherHelper.SetHook(PatcherHelper.HookType.PreJump, ta, "TBody", "MoveHeadAndEye", da, m + "Callbacks.TBody.MoveHeadAndEye", "Invoke");

                // BoneMorph_.Blendの処理終了後にCM3D2.MaidVoicePitch.Managed.Callbacks.BoneMorph_.Blend.Invokeを呼び出す
                PatcherHelper.SetHook(PatcherHelper.HookType.PostCall, ta, "BoneMorph_", "Blend", da, m + "Callbacks.BoneMorph_.Blend", "Invoke");

                // AudioSourceMgr.Playの処理終了後にCM3D2.MaidVoicePitch.Managed.Callbacks.AudioSourceMgr.Play.Invokeを呼び出す
                PatcherHelper.SetHook(PatcherHelper.HookType.PostCall, ta, "AudioSourceMgr", "Play", da, m + "Callbacks.AudioSourceMgr.Play", "Invoke");

                // AudioSourceMgr.PlayOneShotの処理終了後にCM3D2.MaidVoicePitch.Managed.Callbacks.AudioSourceMgr.PlayOneShot.Invokeを呼び出す
                PatcherHelper.SetHook(PatcherHelper.HookType.PostCall, ta, "AudioSourceMgr", "PlayOneShot", da, m + "Callbacks.AudioSourceMgr.PlayOneShot", "Invoke");
                SetPatchedAttribute(args.Assembly, patchTag);
            }
            catch (Exception e)
            {
                Helper.ShowException(e);
                throw;
            }
        }
        public override void Patch(ReiPatcher.Patch.PatcherArguments args)
        {
            try
            {
                AssemblyDefinition ta = args.Assembly;
                AssemblyDefinition da = PatcherHelper.GetAssemblyDefinition(args, "CM3D2.VoiceNormalizer.Managed.dll");
                string m = "CM3D2.VoiceNormalizer.Managed.";

                // 引数の型
                string[] targetArgTypes = {
                    "System.String",
                    "System.Boolean"
                };

                string[] calleeArgTypes = {
                    "AudioSourceMgr",
                    "System.String",
                    "System.Boolean"
                };

                PatcherHelper.SetHook(
                    PatcherHelper.HookType.PreCall,
                    ta, "AudioSourceMgr.LoadFromWf", targetArgTypes,
                    da, m + "Callbacks.AudioSourceMgr.LoadFromWf.Invoke", calleeArgTypes);
            }
            catch (Exception e)
            {
                Helper.ShowException(e);
                throw;
            }
        }
        public override void Patch(ReiPatcher.Patch.PatcherArguments args)
        {
            AssemblyDefinition ta = args.Assembly;
            AssemblyDefinition da = PatcherHelper.GetAssemblyDefinition(args, "CM3D2.ExternalSaveData.Managed.dll");

            // GameMain.OnInitializeの処理後、CM3D2.略.ExSaveData.DummyInitializeを呼ぶ
            PatcherHelper.SetHook(
                PatcherHelper.HookType.PostCall,
                ta, "GameMain.OnInitialize",
                da, "CM3D2.ExternalSaveData.Managed.ExSaveData.DummyInitialize");

            // GameMain.Deserializeの処理後、CM3D2.略.GameMainCallbacks.Deserialize.Invokeを呼ぶ
            PatcherHelper.SetHook(
                PatcherHelper.HookType.PostCall,
                ta, "GameMain.Deserialize",
                da, "CM3D2.ExternalSaveData.Managed.GameMainCallbacks.Deserialize.Invoke");

            // GameMain.Deserializeの処理後、CM3D2.略.GameMainCallbacks.Serialize.Invokeを呼ぶ
            PatcherHelper.SetHook(
                PatcherHelper.HookType.PostCall,
                ta, "GameMain.Serialize",
                da, "CM3D2.ExternalSaveData.Managed.GameMainCallbacks.Serialize.Invoke");

            // GameMain.DeleteSerializeDataの処理後、CM3D2.略.GameMainCallbacks.DeleteSerializeData.Invokeを呼ぶ
            PatcherHelper.SetHook(
                PatcherHelper.HookType.PostCall,
                ta, "GameMain.DeleteSerializeData",
                da, "CM3D2.ExternalSaveData.Managed.GameMainCallbacks.DeleteSerializeData.Invoke");

            SetPatchedAttribute(args.Assembly, patchTag);
        }
 public static AssemblyDefinition GetAssemblyDefinition(ReiPatcher.Patch.PatcherArguments args, string assemblyName)
 {
     var directoryName = Path.GetDirectoryName(args.Location);
     var filename = Path.Combine(directoryName, assemblyName);
     AssemblyDefinition ad = AssemblyDefinition.ReadAssembly(filename);
     if (ad == null)
     {
         throw new Exception(string.Format("{0} not found", assemblyName));
     }
     return ad;
 }
 public override void Patch(ReiPatcher.Patch.PatcherArguments args)
 {
     this.args = args;
     AssemblyDefinition ta = args.Assembly;
     AssemblyDefinition da = GetAssemblyDefinition(args, "CM3D2.ExternalSaveData.Managed.dll");
     string m = "CM3D2.ExternalSaveData.Managed.";
     SetHook(HookType.PostCall, ta, "GameMain", "OnInitialize", da, m + "ExSaveData", "DummyInitialize");
     SetHook(HookType.PostCall, ta, "GameMain", "Deserialize", da, m + "GameMainCallbacks.Deserialize", "Invoke");
     SetHook(HookType.PostCall, ta, "GameMain", "Serialize", da, m + "GameMainCallbacks.Serialize", "Invoke");
     SetHook(HookType.PostCall, ta, "GameMain", "DeleteSerializeData", da, m + "GameMainCallbacks.DeleteSerializeData", "Invoke");
     SetPatchedAttribute(args.Assembly, patchTag);
 }
        public override void Patch(ReiPatcher.Patch.PatcherArguments args)
        {
            try
            {
                AssemblyDefinition ta = args.Assembly;
                AssemblyDefinition da = PatcherHelper.GetAssemblyDefinition(args, "CM3D2.VoiceNormalizer.Managed.dll");
                string m = "CM3D2.VoiceNormalizer.Managed.";

                PatcherHelper.SetHook(
                    PatcherHelper.HookType.PreCall,
                    ta, "AudioSourceMgr.LoadFromWf",
                    da, m + "Callbacks.AudioSourceMgr.LoadFromWf.Invoke");
            }
            catch (Exception e)
            {
                Helper.ShowException(e);
                throw;
            }
        }
        public override void Patch(ReiPatcher.Patch.PatcherArguments args)
        {
            try
            {
                AssemblyDefinition ta = args.Assembly;
                AssemblyDefinition da = PatcherHelper.GetAssemblyDefinition(args, "CM3D2.ShaderWorkbench.Managed.dll");

                PatcherHelper.SetHook(
                    PatcherHelper.HookType.PostCallRet,
                    ta, "ImportCM.ReadMaterial",
                    da, "CM3D2.ShaderWorkbench.Managed.Callbacks.ImportCM.ReadMaterial.Invoke");

				SetPatchedAttribute(args.Assembly, PatchTag);
            }
            catch (Exception e)
            {
                DetailedException.Show(e);
                throw;
            }
        }
        public override void Patch(ReiPatcher.Patch.PatcherArguments args)
        {
            TypeDefinition gameuty = args.Assembly.MainModule.GetType("GameUty");
            var initmethod = gameuty.Methods.First((MethodDefinition def) => def.Name == "Init");
            foreach (var il in initmethod.Body.Instructions)
            {
                if (il.OpCode == OpCodes.Newobj)
                {
                    MethodReference oprnd = (MethodReference)il.Operand;
                    if (oprnd.DeclaringType.ToString() == "FileSystemArchive")
                    {
                        var defHook_ctor = hookdef.MainModule.GetType("CM3D2.ArchiveReplacer.Hook.HookArchive")
                                .Methods.First((MethodDefinition def) => def.Name == ".ctor");

                        il.Operand = args.Assembly.MainModule.Import(defHook_ctor);
                    }
                }
            }
            base.SetPatchedAttribute(args.Assembly, patchTag);
        }
 public override bool CanPatch(ReiPatcher.Patch.PatcherArguments args)
 {
     return args.Assembly.Name.Name == "Assembly-CSharp" && !base.GetPatchedAttributes(args.Assembly).Any(a => a.Info == patchTag);
 }
        public override void Patch(ReiPatcher.Patch.PatcherArguments args)
        {
            PatchGetAnyMouseAndKey(GetMethod(
                args.Assembly.MainModule.GetType("SceneLogo"),
                "GetAnyMouseAndKey"));

            PatchGetAnyMouseAndKey(GetMethod(
                args.Assembly.MainModule.GetType("SceneWarning"),
                "GetAnyMouseAndKey"));

            TypeDefinition tCameraMain = args.Assembly.MainModule.GetType("CameraMain");
            PatchIsForceSkip(GetMethod(tCameraMain, "FadeIn"));
            PatchIsForceSkip(GetMethod(tCameraMain, "FadeInNoUI"));
            PatchIsForceSkip(GetMethod(tCameraMain, "FadeOut"));
            PatchIsForceSkip(GetMethod(tCameraMain, "FadeOutNoUI"));

            {
                // セーブロード画面のフェードアウト
                MethodDefinition targetMethod = GetMethod(
                    args.Assembly.MainModule.GetType("TweenAlpha"), "Begin");
                Mono.Cecil.Rocks.MethodBodyRocks.SimplifyMacros(targetMethod.Body);
                foreach (Instruction inst in targetMethod.Body.Instructions)
                {
                    // 第二引数 (duration) の値の代わりに DefaultUiFadeInTime を積む
                    if (inst.OpCode == OpCodes.Ldarg && ((ParameterDefinition)inst.Operand).Index == 1)
                    {
                        inst.OpCode = OpCodes.Ldc_R4;
                        inst.Operand = DefaultUiFadeInTime;
                    }
                }
                Mono.Cecil.Rocks.MethodBodyRocks.OptimizeMacros(targetMethod.Body);
            }

            {
                // セーブロード画面のフェードイン
                //      ldc.r4 0.0
                //      stfld float32 TweenAlpha::from
                // を
                //      ldc.r4 1.0
                //      stfld float32 TweenAlpha::from
                // に書き換える
                MethodDefinition targetMethod = GetMethod(
                    args.Assembly.MainModule.GetType("BasePanelMgr"), "FadeInPanel");
                Mono.Cecil.Rocks.MethodBodyRocks.SimplifyMacros(targetMethod.Body);
                foreach (Instruction inst in targetMethod.Body.Instructions)
                {
                    if (inst.OpCode == OpCodes.Stfld && inst.Operand.ToString().Contains("TweenAlpha::from"))
                    {
                        inst.Previous.Operand = 1.0f;
                    }
                }
                Mono.Cecil.Rocks.MethodBodyRocks.OptimizeMacros(targetMethod.Body);
            }

            {
                // 日付アイキャッチ画面スキップ
                //  Input.anyKeyの戻り値を破棄して、常にtrueにする
                MethodDefinition targetMethod = GetMethod(
                    args.Assembly.MainModule.GetType("StartDailyMgr"), "Update");
                Mono.Cecil.Rocks.MethodBodyRocks.SimplifyMacros(targetMethod.Body);
                Instruction inst = targetMethod.Body.Instructions.First(
                    i => i.OpCode == OpCodes.Call && i.Operand.ToString().Contains("Input::get_anyKey"));
                ILProcessor l = targetMethod.Body.GetILProcessor();
                Instruction instInsertPoint = inst.Next;
                InsertInstDelegate o = newInst =>
                {
                    l.InsertBefore(instInsertPoint, newInst);
                };
                o(l.Create(OpCodes.Pop));
                o(l.Create(OpCodes.Ldc_I4, 1));
                Mono.Cecil.Rocks.MethodBodyRocks.OptimizeMacros(targetMethod.Body);
            }

            SetPatchedAttribute(args.Assembly, patchTag);
        }
        void Patch_SceneEdit_SlideCallback(ReiPatcher.Patch.PatcherArguments args)
        {
            // SceneEdit.SlideCallback の補間式を変更し、
            // タブ等を変更してスライダーがアクティブになる度に
            // 負の値が 0 に近づくのを抑制する
            //
            // 元の補間式は以下のようになっている
            //
            //      (int) (prop1.min + (prop1.max - prop1.min) * UIProgressBar.current.value + 0.5)
            //
            // 例えば prop1.min = -100, prop1.max = 100, UIProgressBar.current.value = 0 の場合、
            // 以下のようになる
            //
            //        (int) (-100 + (100+100) * 0 + 0.5)
            //		= (int) (-99.5)
            //		= -99
            //
            //      double -> int のキャストについては右記を参照 : https://msdn.microsoft.com/en-us/library/yht2cx7b.aspx
            //
            // この値は期待する値 -100 になっていないので、これを以下のように修正したい
            //
            //      (int) Math.Round(prop1.min + (prop1.max - prop1.min) * UIProgressBar.current.value)
            //
            // ILレベルでは、該当部分は以下のようになっているので
            //
            //      IL_004a: callvirt instance float32 UIProgressBar::get_value()
            //      IL_004f: mul
            //      IL_0050: add
            //  --> IL_0051: ldc.r4 0.5
            //  --> IL_0056: add
            //      IL_0057: conv.i4
            //
            // これを以下のように改変する
            //
            //      IL_004a: callvirt instance float32 UIProgressBar::get_value()
            //      IL_004f: mul
            //      IL_0050: add
            //  --> IL_0051: call float64 [mscorlib]System.Math::Round(float64)
            //  --> IL_0056: nop
            //      IL_0057: conv.i4

            // [Assembly-CSharp] SceneEdit.SlideCallback() を取得
            var method = GetMethod(
                args.Assembly,                      // Assembly-CSharp.dll
                "SceneEdit",                        // クラス名
                "SlideCallback",                    // メソッド名
                new string[] { }                        // メソッドの引数の型 (void)
            );

            // [mscorlib.dll] System.Math.Round(System.Double) を取得
            var methodReference = GetMethod(
                args,
                "mscorlib.dll",                     // DLL 名
                "System.Math",						// クラス名
                "Round",							// メソッド名
                new string[] { "System.Double" }	// メソッドの引数の型
            );

            Mono.Cecil.Rocks.MethodBodyRocks.SimplifyMacros(method.Body);

            // SlideCallback内で ldc.r4 0.5 (IL_0051の命令) を探す
            var inst = method.Body.Instructions.First(
                i => i.OpCode == OpCodes.Ldc_R4 &&
                (float)i.Operand == 0.5f);

            // 見つけた場所の命令を Call に書き換え
            inst.OpCode = OpCodes.Call;
            inst.Operand = args.Assembly.MainModule.Import(methodReference);

            // 次の命令を Nop に書き換え
            inst.Next.OpCode = OpCodes.Nop;

            Mono.Cecil.Rocks.MethodBodyRocks.OptimizeMacros(method.Body);
        }
 MethodDefinition GetMethod(
     ReiPatcher.Patch.PatcherArguments rpArgs, string dllFileName,
     string typeName, string methodName, params string[] args)
 {
     AssemblyDefinition ad = PatcherHelper.GetAssemblyDefinition(rpArgs, dllFileName);
     return GetMethod(ad, typeName, methodName, args);
 }
 static AssemblyDefinition GetAssemblyDefinition(ReiPatcher.Patch.PatcherArguments args, string assemblyName)
 {
     var directoryName = Path.GetDirectoryName(args.Location);
     var filename = Path.Combine(directoryName, assemblyName);
     return AssemblyDefinition.ReadAssembly(filename);
 }