[
  {
    "path": ".gitattributes",
    "content": "###############################################################################\n# Set default behavior to automatically normalize line endings.\n###############################################################################\n* text=auto\n\n###############################################################################\n# Set default behavior for command prompt diff.\n#\n# This is need for earlier builds of msysgit that does not have it on by\n# default for csharp files.\n# Note: This is only used by command line\n###############################################################################\n#*.cs     diff=csharp\n\n###############################################################################\n# Set the merge driver for project and solution files\n#\n# Merging from the command prompt will add diff markers to the files if there\n# are conflicts (Merging from VS is not affected by the settings below, in VS\n# the diff markers are never inserted). Diff markers may cause the following \n# file extensions to fail to load in VS. An alternative would be to treat\n# these files as binary and thus will always conflict and require user\n# intervention with every merge. To do so, just uncomment the entries below\n###############################################################################\n#*.sln       merge=binary\n#*.csproj    merge=binary\n#*.vbproj    merge=binary\n#*.vcxproj   merge=binary\n#*.vcproj    merge=binary\n#*.dbproj    merge=binary\n#*.fsproj    merge=binary\n#*.lsproj    merge=binary\n#*.wixproj   merge=binary\n#*.modelproj merge=binary\n#*.sqlproj   merge=binary\n#*.wwaproj   merge=binary\n\n###############################################################################\n# behavior for image files\n#\n# image files are treated as binary by default.\n###############################################################################\n#*.jpg   binary\n#*.png   binary\n#*.gif   binary\n\n###############################################################################\n# diff behavior for common document formats\n# \n# Convert binary document formats to text before diffing them. This feature\n# is only available from the command line. Turn it on by uncommenting the \n# entries below.\n###############################################################################\n#*.doc   diff=astextplain\n#*.DOC   diff=astextplain\n#*.docx  diff=astextplain\n#*.DOCX  diff=astextplain\n#*.dot   diff=astextplain\n#*.DOT   diff=astextplain\n#*.pdf   diff=astextplain\n#*.PDF   diff=astextplain\n#*.rtf   diff=astextplain\n#*.RTF   diff=astextplain\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/------.md",
    "content": "---\nname: 新機能の提案\nabout: 既存の挙動を変更する/新しい機能の追加\ntitle: \"+〇〇〇〇〇〇\"\nlabels: enhancement\nassignees: ''\n\n---\n\n**背景**\nどのような理由でこの機能を提案するかの説明\n\n**概要**\n提案する機能はどのようなものなのかの説明\n物によっては画像があると分かりやすい\n\n**没案**\n他に検討した案\n\n**その他**\n他に書きたいことがあれば\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/aviutl--------------.md",
    "content": "---\nname: AviUtl/周辺プラグインのバグの報告\nabout: patch.aulに直してほしいバグ\ntitle: \"*〇〇〇〇〇〇\"\nlabels: enhancement\nassignees: ''\n\n---\n\n【！】報告の前に必ずこの挙動がpatch.aulを導入していない状態で引き起こされる事象であることを確認してください\npatch.aulを導入した結果期待していない挙動になるのであれば、これはpatch.aulのバグとして扱い、別のテンプレートが用意されています\n\n**概要**\n起こってしまうことの説明を簡単に\n何かメッセージが表示されるのであれば、全文を正確にコピーする\n\n**再現手順**\nどのような操作をするとこのバグを観測できるのか\n(例)\n1. XXXプラグイン version XXXを導入する\n2. 新規プロジェクトにXXXオブジェクトを配置する\n3. XXXオブジェクトの設定を開く\n\n**起こってほしかったこと**\nバグが起きなければどうなるのか\n\n**スクリーンショット**\n必要だと思えば添付する\n\n**環境**\nAviUtl/拡張編集のバージョンは一応書いておく\n導入しているフィルタ/入力/出力/色変換/その他のプラグインの情報をバージョンを添えて正確に書く\nもし例外が発生しているのであれば、詳細情報が書かれたファイルを添付することでも環境の説明になる\n\n**その他**\nもし他に何か書きたいことがあれば\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/patch-aul------.md",
    "content": "---\nname: patch.aulのバグの報告\nabout: patch.aulが起因であるバグはここから\ntitle: \"/〇〇〇〇〇〇\"\nlabels: bug\nassignees: ''\n\n---\n\n【！】報告の前に必ずこの挙動がpatch.aulを導入したことにより引き起こされる事象であることを確認してください\nAviUtl/拡張編集/その他プラグインのバグの報告には別のテンプレートが用意されています\n\n**概要**\n起こってしまうことの説明を簡単に\n何かメッセージが表示されるのであれば、全文を正確にコピーする\n\n**再現手順**\nどのような操作をするとこのバグを観測できるのか\n(例)\n1. XXXプラグイン version XXXを導入する\n2. 新規プロジェクトにXXXオブジェクトを配置する\n3. XXXオブジェクトの設定を開く\n\n**起こってほしかったこと**\nバグが起きなければどうなるのか\n\n**スクリーンショット**\n必要だと思えば添付する\n\n**環境**\nAviUtl/拡張編集のバージョンは自明なので省略できる\n導入しているフィルタ/入力/出力/色変換/その他のプラグインの情報をバージョンを添えて正確に書く\nもし例外が発生しているのであれば、詳細情報が書かれたファイルを添付することでも環境の説明になる\n\n**その他**\nもし他に何か書きたいことがあれば\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "<!-- \nPR を作成する前に、以下の点について確認してください。\n1. 誰が見ても分かりやすいタイトル/説明が書かれていること。\n2. 1つの変更点に対して1つの PR が立てられていること。\n-->\n\n**関係する Issue**\n関係する Issue の番号を以下に書いてください。\n- #0 を閉じる\n- #0 に関連\n\n**変更点**\nこの PR での変更点について教えてください。\n- ○○の追加\n- ○○の修正\n\n**内容の精査**\n以下の点について教えてください。\n- [ ] コードにおかしな点がないことを確認しました。\n- [ ] 実際にビルドして試しました。\n\n**スクリーンショット(任意)**\nスクリーンショットを Ctrl+V で追加できます。\n"
  },
  {
    "path": ".github/workflows/CI.yml",
    "content": "name: CI\n\non:\n  push:\n  pull_request:\n\njobs:\n  build:\n    runs-on: windows-2022\n    strategy:\n      matrix:\n        configuration: [Debug, Release]\n\n    steps:\n    - name: Checkout repository\n      uses: actions/checkout@v2\n      with:\n        submodules: recursive\n    - name: Use Developer Command Prompt\n      uses: ilammy/msvc-dev-cmd@v1\n    - name: Install CUDA Toolkit\n      uses: Jimver/cuda-toolkit@v0.2.7\n    - name: Setup NuGet\n      uses: nuget/setup-nuget@v1\n    - name: Restore NuGet package\n      run : nuget restore patch.sln\n    - name: Create Directories\n      run : |\n        mkdir pack\n        mkdir test\n    - name: Build patch.aul\n      run : devenv patch.sln /Build \"${{ matrix.configuration }}|x86\"\n"
  },
  {
    "path": ".gitignore",
    "content": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore\n\n# User-specific files\n*.rsuser\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Mono auto generated files\nmono_crash.*\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\n[Ww][Ii][Nn]32/\n[Aa][Rr][Mm]/\n[Aa][Rr][Mm]64/\nbld/\n[Bb]in/\n[Oo]bj/\n[Oo]ut/\n[Ll]og/\n[Ll]ogs/\n\n# Visual Studio 2015/2017 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# Visual Studio 2017 auto generated files\nGenerated\\ Files/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUnit\n*.VisualState.xml\nTestResult.xml\nnunit-*.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# Benchmark Results\nBenchmarkDotNet.Artifacts/\n\n# .NET Core\nproject.lock.json\nproject.fragment.lock.json\nartifacts/\n\n# ASP.NET Scaffolding\nScaffoldingReadMe.txt\n\n# StyleCop\nStyleCopReport.xml\n\n# Files built by Visual Studio\n*_i.c\n*_p.c\n*_h.h\n*.ilk\n*.meta\n*.obj\n*.iobj\n*.pch\n*.pdb\n*.ipdb\n*.pgc\n*.pgd\n*.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*_wpftmp.csproj\n*.log\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n*.VC.db\n*.VC.VC.opendb\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# Visual Studio Trace Files\n*.e2e\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# AxoCover is a Code Coverage Tool\n.axoCover/*\n!.axoCover/settings.json\n\n# Coverlet is a free, cross platform Code Coverage Tool\ncoverage*.json\ncoverage*.xml\ncoverage*.info\n\n# Visual Studio code coverage results\n*.coverage\n*.coveragexml\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# Note: Comment the next line if you want to checkin your web deploy settings,\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# Microsoft Azure Web App publish settings. Comment the next line if you want to\n# checkin your Azure Web App publish settings, but sensitive information contained\n# in these scripts will be unencrypted\nPublishScripts/\n\n# NuGet Packages\n*.nupkg\n# NuGet Symbol Packages\n*.snupkg\n# The packages folder can be ignored because of Package Restore\n**/[Pp]ackages/*\n# except build/, which is used as an MSBuild target.\n!**/[Pp]ackages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/[Pp]ackages/repositories.config\n# NuGet v3's project.json files produces more ignorable files\n*.nuget.props\n*.nuget.targets\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Windows Store app package directories and files\nAppPackages/\nBundleArtifacts/\nPackage.StoreAssociation.xml\n_pkginfo.txt\n*.appx\n*.appxbundle\n*.appxupload\n\n# Visual Studio cache files\n# files ending in .cache can be ignored\n*.[Cc]ache\n# but keep track of directories ending in .cache\n!?*.[Cc]ache/\n\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.jfm\n*.pfx\n*.publishsettings\norleans.codegen.cs\n\n# Including strong name files can present a security risk\n# (https://github.com/github/gitignore/pull/2483#issue-259490424)\n#*.snk\n\n# Since there are multiple workflows, uncomment next line to ignore bower_components\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\n#bower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\nServiceFabricBackup/\n*.rptproj.bak\n\n# SQL Server files\n*.mdf\n*.ldf\n*.ndf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n*.rptproj.rsuser\n*- [Bb]ackup.rdl\n*- [Bb]ackup ([0-9]).rdl\n*- [Bb]ackup ([0-9][0-9]).rdl\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\nnode_modules/\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)\n*.vbw\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\npaket-files/\n\n# FAKE - F# Make\n.fake/\n\n# CodeRush personal settings\n.cr/personal\n\n# Python Tools for Visual Studio (PTVS)\n__pycache__/\n*.pyc\n\n# Cake - Uncomment if you are using it\n# tools/**\n# !tools/packages.config\n\n# Tabs Studio\n*.tss\n\n# Telerik's JustMock configuration file\n*.jmconfig\n\n# BizTalk build output\n*.btp.cs\n*.btm.cs\n*.odx.cs\n*.xsd.cs\n\n# OpenCover UI analysis results\nOpenCover/\n\n# Azure Stream Analytics local run output\nASALocalRun/\n\n# MSBuild Binary and Structured Log\n*.binlog\n\n# NVidia Nsight GPU debugger configuration file\n*.nvuser\n\n# MFractors (Xamarin productivity tool) working folder\n.mfractor/\n\n# Local History for Visual Studio\n.localhistory/\n\n# BeatPulse healthcheck temp database\nhealthchecksdb\n\n# Backup folder for Package Reference Convert tool in Visual Studio 2017\nMigrationBackup/\n\n# Ionide (cross platform F# VS Code tools) working folder\n.ionide/\n\n# Fody - auto-generated XML schema\nFodyWeavers.xsd\n\n\n# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #\n.vscode/\ntest/\npack/\nRelease_PDB/\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"patch/aviutl_exedit_sdk\"]\n\tpath = patch/aviutl_exedit_sdk\n\turl = https://github.com/ePi5131/aviutl_exedit_sdk\n[submodule \"patch/winwrap\"]\n\tpath = patch/winwrap\n\turl = https://github.com/ePi5131/winwrap\n"
  },
  {
    "path": "COPYING",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "COPYING.LESSER",
    "content": "                   GNU LESSER GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n\n  This version of the GNU Lesser General Public License incorporates\nthe terms and conditions of version 3 of the GNU General Public\nLicense, supplemented by the additional permissions listed below.\n\n  0. Additional Definitions.\n\n  As used herein, \"this License\" refers to version 3 of the GNU Lesser\nGeneral Public License, and the \"GNU GPL\" refers to version 3 of the GNU\nGeneral Public License.\n\n  \"The Library\" refers to a covered work governed by this License,\nother than an Application or a Combined Work as defined below.\n\n  An \"Application\" is any work that makes use of an interface provided\nby the Library, but which is not otherwise based on the Library.\nDefining a subclass of a class defined by the Library is deemed a mode\nof using an interface provided by the Library.\n\n  A \"Combined Work\" is a work produced by combining or linking an\nApplication with the Library.  The particular version of the Library\nwith which the Combined Work was made is also called the \"Linked\nVersion\".\n\n  The \"Minimal Corresponding Source\" for a Combined Work means the\nCorresponding Source for the Combined Work, excluding any source code\nfor portions of the Combined Work that, considered in isolation, are\nbased on the Application, and not on the Linked Version.\n\n  The \"Corresponding Application Code\" for a Combined Work means the\nobject code and/or source code for the Application, including any data\nand utility programs needed for reproducing the Combined Work from the\nApplication, but excluding the System Libraries of the Combined Work.\n\n  1. Exception to Section 3 of the GNU GPL.\n\n  You may convey a covered work under sections 3 and 4 of this License\nwithout being bound by section 3 of the GNU GPL.\n\n  2. Conveying Modified Versions.\n\n  If you modify a copy of the Library, and, in your modifications, a\nfacility refers to a function or data to be supplied by an Application\nthat uses the facility (other than as an argument passed when the\nfacility is invoked), then you may convey a copy of the modified\nversion:\n\n   a) under this License, provided that you make a good faith effort to\n   ensure that, in the event an Application does not supply the\n   function or data, the facility still operates, and performs\n   whatever part of its purpose remains meaningful, or\n\n   b) under the GNU GPL, with none of the additional permissions of\n   this License applicable to that copy.\n\n  3. Object Code Incorporating Material from Library Header Files.\n\n  The object code form of an Application may incorporate material from\na header file that is part of the Library.  You may convey such object\ncode under terms of your choice, provided that, if the incorporated\nmaterial is not limited to numerical parameters, data structure\nlayouts and accessors, or small macros, inline functions and templates\n(ten or fewer lines in length), you do both of the following:\n\n   a) Give prominent notice with each copy of the object code that the\n   Library is used in it and that the Library and its use are\n   covered by this License.\n\n   b) Accompany the object code with a copy of the GNU GPL and this license\n   document.\n\n  4. Combined Works.\n\n  You may convey a Combined Work under terms of your choice that,\ntaken together, effectively do not restrict modification of the\nportions of the Library contained in the Combined Work and reverse\nengineering for debugging such modifications, if you also do each of\nthe following:\n\n   a) Give prominent notice with each copy of the Combined Work that\n   the Library is used in it and that the Library and its use are\n   covered by this License.\n\n   b) Accompany the Combined Work with a copy of the GNU GPL and this license\n   document.\n\n   c) For a Combined Work that displays copyright notices during\n   execution, include the copyright notice for the Library among\n   these notices, as well as a reference directing the user to the\n   copies of the GNU GPL and this license document.\n\n   d) Do one of the following:\n\n       0) Convey the Minimal Corresponding Source under the terms of this\n       License, and the Corresponding Application Code in a form\n       suitable for, and under terms that permit, the user to\n       recombine or relink the Application with a modified version of\n       the Linked Version to produce a modified Combined Work, in the\n       manner specified by section 6 of the GNU GPL for conveying\n       Corresponding Source.\n\n       1) Use a suitable shared library mechanism for linking with the\n       Library.  A suitable mechanism is one that (a) uses at run time\n       a copy of the Library already present on the user's computer\n       system, and (b) will operate properly with a modified version\n       of the Library that is interface-compatible with the Linked\n       Version.\n\n   e) Provide Installation Information, but only if you would otherwise\n   be required to provide such information under section 6 of the\n   GNU GPL, and only to the extent that such information is\n   necessary to install and execute a modified version of the\n   Combined Work produced by recombining or relinking the\n   Application with a modified version of the Linked Version. (If\n   you use option 4d0, the Installation Information must accompany\n   the Minimal Corresponding Source and Corresponding Application\n   Code. If you use option 4d1, you must provide the Installation\n   Information in the manner specified by section 6 of the GNU GPL\n   for conveying Corresponding Source.)\n\n  5. Combined Libraries.\n\n  You may place library facilities that are a work based on the\nLibrary side by side in a single library together with other library\nfacilities that are not Applications and are not covered by this\nLicense, and convey such a combined library under terms of your\nchoice, if you do both of the following:\n\n   a) Accompany the combined library with a copy of the same work based\n   on the Library, uncombined with any other library facilities,\n   conveyed under the terms of this License.\n\n   b) Give prominent notice with the combined library that part of it\n   is a work based on the Library, and explaining where to find the\n   accompanying uncombined form of the same work.\n\n  6. Revised Versions of the GNU Lesser General Public License.\n\n  The Free Software Foundation may publish revised and/or new versions\nof the GNU Lesser General Public License from time to time. Such new\nversions will be similar in spirit to the present version, but may\ndiffer in detail to address new problems or concerns.\n\n  Each version is given a distinguishing version number. If the\nLibrary as you received it specifies that a certain numbered version\nof the GNU Lesser General Public License \"or any later version\"\napplies to it, you have the option of following the terms and\nconditions either of that published version or of any later version\npublished by the Free Software Foundation. If the Library as you\nreceived it does not specify a version number of the GNU Lesser\nGeneral Public License, you may choose any version of the GNU Lesser\nGeneral Public License ever published by the Free Software Foundation.\n\n  If the Library as you received it specifies that a proxy can decide\nwhether future versions of the GNU Lesser General Public License shall\napply, that proxy's public statement of acceptance of any version is\npermanent authorization for you to choose that version for the\nLibrary.\n"
  },
  {
    "path": "LICENSE",
    "content": "© 2022-2023 ePi\n\npatch.aulはLGPLv3の元ライセンスする。ライセンスの詳細はCOPYING,COPYING.LESSERファイルを参照すること。\n"
  },
  {
    "path": "credits.md",
    "content": "# 使用したライブラリについて\n## Boost\n> Boost Software License - Version 1.0 - August 17th, 2003\n>\n> Permission is hereby granted, free of charge, to any person or organization\n> obtaining a copy of the software and accompanying documentation covered by\n> this license (the \"Software\") to use, reproduce, display, distribute,\n> execute, and transmit the Software, and to prepare derivative works of the\n> Software, and to permit third-parties to whom the Software is furnished to\n> do so, all subject to the following:\n>\n> The copyright notices in the Software and this entire statement, including\n> the above license grant, this restriction and the following disclaimer,\n> must be included in all copies of the Software, in whole or in part, and\n> all derivative works of the Software, unless such copies or derivative\n> works are solely in the form of machine-executable object code generated by\n> a source language processor.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n> FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\n> SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\n> FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\n> ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n> DEALINGS IN THE SOFTWARE.\n## aviutl_exedit_sdk\n## winwrap\nこれらは私が書いたライブラリであり、1条項BSDライセンスの下頒布している。文面は以下の通り。\n\n> Copyright (c) 2022\n> ePi All rights reserved.\n> \n> Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n> \n> Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n> THIS SOFTWARE IS PROVIDED BY ePi “AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ePi BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n## json.h\nこのプログラムはUnlicenseで頒布されているが、ここに使用したことを記述しておく。\n"
  },
  {
    "path": "patch/.editorconfig",
    "content": "# Rules in this file were initially inferred by Visual Studio IntelliCode from the D:\\dev\\patch\\patch\\ codebase based on best match to current usage at 2021/08/07\n# You can modify the rules from these initially generated values to suit your own policies\n# You can learn more about editorconfig here: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference\n[*.{cpp,hpp}]\n\ncharset = utf-8\n"
  },
  {
    "path": "patch/add_dll_ref.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include <Windows.h>\n\n#include \"global.hpp\"\n\n// 自身の参照カウントを増やす\ninline class add_dll_ref_t {\n\tinline static bool loading_self = false;\npublic:\n\tbool dllmain_if_break() noexcept {\n\t\treturn loading_self;\n\t}\n\n\tvoid add_ref() noexcept {\n\t\tloading_self = true;\n\t\tLoadLibraryW(GLOBAL::patchaul_path.c_str());\n\t\tloading_self = false;\n\t}\n} add_dll_ref;\n"
  },
  {
    "path": "patch/clprogram.cl",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tThis program is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\nkernel void PolorTransform(global short* dst, global short* src, int obj_w, int obj_h, int obj_line,\n\tint center_length, int radius, float angle, float uzu, float uzu_a){\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\t\n\tint x_dist = x - radius;\n\tint y_dist = y - radius;\n\tfloat dist = sqrt((float)(x_dist * x_dist + y_dist * y_dist));\n\n\tint range = (int)round((float)obj_w / max(dist, 1.0f) * 57.6115417480468f + uzu_a);\n\t\t\t\t\n\tint yy_t256 = (int)round((float)(((obj_h + center_length) << 8) / radius) * dist);\n\tint yy_range_fr = 0x100 - (yy_t256 & 0xff);\n\tint yy_begin = (yy_t256 >> 8) - center_length;\n\t\t\t\t\n\tint xx_t256 = (int)round((((float)radius - dist) * uzu + angle - atan2((float)y_dist, (float)x_dist)) * (float)obj_w * 40.7436637878417f) - range / 2;\n\tint xx_range_fr = 0x100 - (xx_t256 & 0xff);\n\tint xx_begin = (xx_t256 >> 8) % obj_w;\n\t\t\t\t\n\trange = max(0x100,range);\n\tint yy = yy_begin;\n\n\tint sum_y = 0;\n\tint sum_cb = 0;\n\tint sum_cr = 0;\n\tint sum_a = 0;\n\n\tglobal short* pix;\n\tint src_a;\n\n\tif (0 <= yy && yy < obj_h) {\n\t\tint range_remain = range;\n\t\tint xx = xx_begin;\n\t\tif (xx_range_fr) {\n\t\t\tpix = src + (xx + yy * obj_line) * 4;\n\t\t\tsum_a = pix[3] * xx_range_fr * yy_range_fr >> 16;\n\t\t\tsum_y = pix[0] * sum_a >> 12;\n\t\t\tsum_cb = pix[1] * sum_a >> 12;\n\t\t\tsum_cr = pix[2] * sum_a >> 12;\n\t\t\trange_remain -= xx_range_fr;\n\t\t\txx++;\n\t\t\txx %= obj_w;\n\t\t}\n\t\tint pix_range = range_remain >> 8;\n\t\tfor(int i=0;i<pix_range;i++){\n\t\t\tpix = src + (xx + yy * obj_line) * 4;\n\t\t\tsrc_a = pix[3] * yy_range_fr >> 8;\n\t\t\tsum_y += pix[0] * src_a >> 12;\n\t\t\tsum_cb += pix[1] * src_a >> 12;\n\t\t\tsum_cr += pix[2] * src_a >> 12;\n\t\t\tsum_a += src_a;\n\t\t\txx++;\n\t\t\txx %= obj_w;\n\t\t}\n\t\trange_remain &= 0xff;\n\t\tif (range_remain) {\n\t\t\tpix = src + (xx + yy * obj_line) * 4;\n\t\t\tsrc_a = pix[3] * range_remain * yy_range_fr >> 16;\n\t\t\tsum_y += pix[0] * src_a >> 12;\n\t\t\tsum_cb += pix[1] * src_a >> 12;\n\t\t\tsum_cr += pix[2] * src_a >> 12;\n\t\t\tsum_a += src_a;\n\t\t}\n\t}\n\tyy++;\n\tyy_range_fr = 0x100 - yy_range_fr;\n\tif (0 <= yy && yy < obj_h) {\n\t\tint range_remain = range;\n\t\tint xx = xx_begin;\n\t\tif (xx_range_fr != 0x100) {\n\t\t\tpix = src + (xx + yy * obj_line) * 4;\n\t\t\tsrc_a = pix[3] * xx_range_fr * yy_range_fr >> 16;\n\t\t\tsum_y += pix[0] * src_a >> 12;\n\t\t\tsum_cb += pix[1] * src_a >> 12;\n\t\t\tsum_cr += pix[2] * src_a >> 12;\n\t\t\tsum_a += src_a;\n\t\t\trange_remain -= xx_range_fr;\n\t\t\txx++;\n\t\t\txx %= obj_w;\n\t\t}\n\t\tint pix_range = range_remain >> 8;\n\t\tfor(int i=0;i<pix_range;i++){\n\t\t\tpix = src + (xx + yy * obj_line) * 4;\n\t\t\tsrc_a = pix[3] * yy_range_fr >> 8;\n\t\t\tsum_y += pix[0] * src_a>> 12;\n\t\t\tsum_cb += pix[1] * src_a >> 12;\n\t\t\tsum_cr += pix[2] * src_a >> 12;\n\t\t\tsum_a += src_a;\n\t\t\txx++;\n\t\t\txx %= obj_w;\n\t\t}\n\t\trange_remain &= 0xff;\n\t\tif (range_remain) {\n\t\t\tpix = src + (xx + yy * obj_line) * 4;\n\t\t\tsrc_a = pix[3] * range_remain * yy_range_fr >> 16;\n\t\t\tsum_y += pix[0] * src_a >> 12;\n\t\t\tsum_cb += pix[1] * src_a >> 12;\n\t\t\tsum_cr += pix[2] * src_a >> 12;\n\t\t\tsum_a += src_a;\n\t\t}\n\t}\n\tdst += (x + y * obj_line) * 4;\n\tif (sum_a) {\n\t\tfloat a_float = 4096.0f / (float)sum_a;\n\t\tdst[0] = (short)round((float)sum_y * a_float);\n\t\tdst[1] = (short)round((float)sum_cb * a_float);\n\t\tdst[2] = (short)round((float)sum_cr * a_float);\n\t\tdst[3] = (short)((sum_a << 8) / range);\n\t} else {\n\t\tdst[0] = dst[1] = dst[2] = dst[3] = 0;\n\t}\n}\n\nkernel void DisplacementMap_move(global short* dst, global short* src, global short* mem,\n\tint obj_w, int obj_h, int obj_line, int param0, int param1, int ox, int oy) {\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\n\tdst += (x + y * obj_line) * 4;\n\tmem += (x + y * obj_line) * 4;\n\n\tint p0 = min(mem[0], mem[obj_line * 4]);\n\tint p1 = max(mem[4], mem[obj_line * 4 + 4]);\n\tp0 = (p0 - 0x800) * param0 / 5;\n\tp1 = (p1 - 0x800) * param0 / 5 + 0x1000;\n\tif (p1 < p0) {\n\t\tint tmp = p0;\n\t\tp0 = p1;\n\t\tp1 = tmp;\n\t}\n\tint xx_range = p1 - p0;\n\tint xx_begin = p0 + (x << 12);\n\tint xx_end = xx_range + xx_begin;\n\n\tp0 = min(mem[1], mem[5]);\n\tp1 = max(mem[obj_line * 4 + 1], mem[obj_line * 4 + 5]);\n\tp0 = (p0 - 0x800) * param1 / 5;\n\tp1 = (p1 - 0x800) * param1 / 5 + 0x1000;\n\tif (p1 < p0) {\n\t\tint tmp = p0;\n\t\tp0 = p1;\n\t\tp1 = tmp;\n\t}\n\tint yy_range = p1 - p0;\n\tint yy_begin = p0 + (y << 12);\n\tint yy_end = yy_range + yy_begin;\n\n\tif (xx_range < 0x1000) {\n\t\txx_begin += (xx_range - 0x1000) >> 1;\n\t\txx_end = xx_begin + 0x1000;\n\t\txx_range = 0x1000;\n\t}\n\tif (yy_range < 0x1000) {\n\t\tyy_begin += (yy_range - 0x1000) >> 1;\n\t\tyy_end = yy_begin + 0x1000;\n\t\tyy_range = 0x1000;\n\t}\n\n\tint xx_level = 12;\n\tint yy_level = 12;\n\twhile (0x20000 < xx_range) {\n\t\txx_begin >>= 1;\n\t\txx_end++;\n\t\txx_end >>= 1;\n\t\txx_range = xx_end - xx_begin;\n\t\txx_level--;\n\t}\n\twhile (0x20000 < yy_range) {\n\t\tyy_begin >>= 1;\n\t\tyy_end++;\n\t\tyy_end >>= 1;\n\t\tyy_range = yy_end - yy_begin;\n\t\tyy_level--;\n\t}\n\txx_level &= 0x1f;\n\tyy_level &= 0x1f;\n\n\txx_begin = max(xx_begin, 0);\n\txx_end = min(xx_end, obj_w << xx_level);\n\tyy_begin = max(yy_begin, 0);\n\tyy_end = min(yy_end, obj_h << yy_level);\n\n\tfloat dsum_y = 0.0f;\n\tfloat dsum_cb = 0.0f;\n\tfloat dsum_cr = 0.0f;\n\tfloat dsum_a = 0.0f;\n\tint yy = yy_begin;\n\twhile (yy < yy_end) {\n\t\tint yy_itr = yy >> yy_level;\n\t\tint sum_y = 0;\n\t\tint sum_cb = 0;\n\t\tint sum_cr = 0;\n\t\tint sum_a = 0;\n\t\tint xx = xx_begin;\n\t\twhile (xx < xx_end) {\n\t\t\tint xx_itr = xx >> xx_level;\n\t\t\tint fraction;\n\t\t\tif (xx & 0xfff) {\n\t\t\t\tfraction = -xx & 0xfff;\n\t\t\t} else {\n\t\t\t\tfraction = min(xx_end - xx, 0x1000);\n\t\t\t}\n\n\t\t\tglobal short* srct = src + (xx_itr + yy_itr * obj_line) * 4;\n\t\t\tint src_a = srct[3] * fraction >> 8;\n\t\t\tsum_y += srct[0] * src_a >> 16;\n\t\t\tsum_cb += srct[1] * src_a >> 16;\n\t\t\tsum_cr += srct[2] * src_a >> 16;\n\t\t\tsum_a += src_a;\n\t\t\txx += fraction;\n\t\t}\n\t\tint fraction;\n\t\tif (yy & 0xfff) {\n\t\t\tfraction = -yy & 0xfff;\n\t\t} else {\n\t\t\tfraction = min(yy_end - yy, 0x1000);\n\t\t}\n\t\tfloat fraction_rate = (float)fraction * 0.000244140625f;\n\t\tdsum_y += (float)sum_y * fraction_rate;\n\t\tdsum_cb += (float)sum_cb * fraction_rate;\n\t\tdsum_cr += (float)sum_cr * fraction_rate;\n\t\tdsum_a += (float)sum_a * fraction_rate;\n\t\tyy += fraction;\n\t}\n\n\tif (256.0f <= dsum_a) {\n\t\tfloat inv_a = 65536.0f / dsum_a;\n\t\tdst[0] = (short)round(dsum_y * inv_a);\n\t\tdst[1] = (short)round(dsum_cb * inv_a);\n\t\tdst[2] = (short)round(dsum_cr * inv_a);\n\t\tdst[3] = (short)round(dsum_a / ((float)yy_range / 1024.0f) / ((float)xx_range / 1024.0f));\n\t} else {\n\t\tdst[0] = dst[1] = dst[2] = dst[3] = 0;\n\t}\n}\nkernel void DisplacementMap_zoom(global short* dst, global short* src, global short* mem,\n\tint obj_w, int obj_h, int obj_line, int param0, int param1, int ox, int oy){\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\n\tdst += (x + y * obj_line) * 4;\n\tmem += (x + y * obj_line) * 4;\n\n\tint xx_min, xx_max, yy_min, yy_max;\n\tint xx_temp, yy_temp;\n\n\tfloat zoom;\n\tfloat xxd = (float)(x * 0x1000 - ox);\n\tif (0 < param0) {\n\t\tzoom = (1024.0f / (float)(param0 + 1000) - 1.0) * 0.00048828125f;\n\t} else {\n\t\tzoom = (float)param0 * -0.00000048828125f;\n\t}\n\tfloat temp = xxd * zoom;\n\txx_min = xx_max = x * 0x1000 + (int)((float)(mem[0] - 0x800) * temp);\n\n\txx_temp = x * 0x1000 + (int)((float)(mem[obj_line * 4] - 0x800) * temp);\n\txx_min = min(xx_min, xx_temp);\n\txx_max = max(xx_max, xx_temp);\n\n\ttemp = (xxd + 4096.0f) * zoom;\n\txx_temp = (x + 1) * 0x1000 + (int)((float)(mem[4] - 0x800) * temp);\n\txx_min = min(xx_min, xx_temp);\n\txx_max = max(xx_max, xx_temp);\n\n\txx_temp = (x + 1) * 0x1000 + (int)((float)(mem[(obj_line + 1) * 4] - 0x800) * temp);\n\tint xx_begin = min(xx_min, xx_temp);\n\tint xx_end = max(xx_max, xx_temp);\n\n\n\tfloat yyd = (float)(y * 0x1000 - oy);\n\tif (0 < param1) {\n\t\tzoom = (1024.0f / (float)(param1 + 1000) - 1.0) * 0.00048828125f;\n\t} else {\n\t\tzoom = (float)param1 * -0.00000048828125f;\n\t}\n\ttemp = yyd * zoom;\n\tyy_min = yy_max = y * 0x1000 + (int)((float)(mem[1] - 0x800) * temp);\n\n\tyy_temp = y * 0x1000 + (int)((float)(mem[5] - 0x800) * temp);\n\tyy_min = min(yy_min, yy_temp);\n\tyy_max = max(yy_max, yy_temp);\n\n\ttemp = (yyd + 4096.0f) * zoom;\n\tyy_temp = (y + 1) * 0x1000 + (int)((float)(mem[(obj_line + 1) * 4] - 0x800) * temp);\n\tyy_min = min(yy_min, yy_temp);\n\tyy_max = max(yy_max, yy_temp);\n\n\tyy_temp = (y + 1) * 0x1000 + (int)((float)(mem[obj_line * 4 + 5] - 0x800) * temp);\n\tint yy_begin = min(yy_min, yy_temp);\n\tint yy_end = max(yy_max, yy_temp);\n\n\tint xx_range = xx_end - xx_begin;\n\tint yy_range = yy_end - yy_begin;\n\n\tif (xx_range < 0x1000) {\n\t\txx_begin += (xx_range - 0x1000) >> 1;\n\t\txx_end = xx_begin + 0x1000;\n\t\txx_range = 0x1000;\n\t}\n\tif (yy_range < 0x1000) {\n\t\tyy_begin += (yy_range - 0x1000) >> 1;\n\t\tyy_end = yy_begin + 0x1000;\n\t\tyy_range = 0x1000;\n\t}\n\n\tint xx_level = 12;\n\tint yy_level = 12;\n\twhile (0x20000 < xx_range) {\n\t\txx_begin >>= 1;\n\t\txx_end++;\n\t\txx_end >>= 1;\n\t\txx_range = xx_end - xx_begin;\n\t\txx_level--;\n\t}\n\twhile (0x20000 < yy_range) {\n\t\tyy_begin >>= 1;\n\t\tyy_end++;\n\t\tyy_end >>= 1;\n\t\tyy_range = yy_end - yy_begin;\n\t\tyy_level--;\n\t}\n\txx_level &= 0x1f;\n\tyy_level &= 0x1f;\n\n\txx_begin = max(xx_begin, 0);\n\txx_end = min(xx_end, obj_w << xx_level);\n\tyy_begin = max(yy_begin, 0);\n\tyy_end = min(yy_end, obj_h << yy_level);\n\n\tfloat dsum_y = 0.0f;\n\tfloat dsum_cb = 0.0f;\n\tfloat dsum_cr = 0.0f;\n\tfloat dsum_a = 0.0f;\n\tint yy = yy_begin;\n\twhile (yy < yy_end) {\n\t\tint yy_itr = yy >> yy_level;\n\t\tint sum_y = 0;\n\t\tint sum_cb = 0;\n\t\tint sum_cr = 0;\n\t\tint sum_a = 0;\n\t\tint xx = xx_begin;\n\t\twhile (xx < xx_end) {\n\t\t\tint xx_itr = xx >> xx_level;\n\t\t\tint fraction;\n\t\t\tif (xx & 0xfff) {\n\t\t\t\tfraction = -xx & 0xfff;\n\t\t\t} else {\n\t\t\t\tfraction = min(xx_end - xx, 0x1000);\n\t\t\t}\n\n\t\t\tglobal short* srct = src + (xx_itr + yy_itr * obj_line) * 4;\n\t\t\tint src_a = srct[3] * fraction >> 8;\n\t\t\tsum_y += srct[0] * src_a >> 16;\n\t\t\tsum_cb += srct[1] * src_a >> 16;\n\t\t\tsum_cr += srct[2] * src_a >> 16;\n\t\t\tsum_a += src_a;\n\t\t\txx += fraction;\n\t\t}\n\t\tint fraction;\n\t\tif (yy & 0xfff) {\n\t\t\tfraction = -yy & 0xfff;\n\t\t} else {\n\t\t\tfraction = min(yy_end - yy, 0x1000);\n\t\t}\n\t\tfloat fraction_rate = (float)fraction * 0.000244140625f;\n\t\tdsum_y += (float)sum_y * fraction_rate;\n\t\tdsum_cb += (float)sum_cb * fraction_rate;\n\t\tdsum_cr += (float)sum_cr * fraction_rate;\n\t\tdsum_a += (float)sum_a * fraction_rate;\n\t\tyy += fraction;\n\t}\n\n\tif (256.0f <= dsum_a) {\n\t\tfloat inv_a = 65536.0f / dsum_a;\n\t\tdst[0] = (short)round(dsum_y * inv_a);\n\t\tdst[1] = (short)round(dsum_cb * inv_a);\n\t\tdst[2] = (short)round(dsum_cr * inv_a);\n\t\tdst[3] = (short)round(dsum_a / ((float)yy_range / 1024.0f) / ((float)xx_range / 1024.0f));\n\t} else {\n\t\tdst[0] = dst[1] = dst[2] = dst[3] = 0;\n\t}\n}\nkernel void DisplacementMap_rot(global short* dst, global short* src, global short* mem,\n\tint obj_w, int obj_h, int obj_line, int param0, int param1, int ox, int oy){\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\n\tdst += (x + y * obj_line) * 4;\n\tmem += (x + y * obj_line) * 4;\n\n\tint xx_min, xx_max, yy_min, yy_max;\n\tint xx_temp, yy_temp;\n\n\tfloat xxd = (float)((x << 12) - ox);\n\tfloat yyd = (float)((y << 12) - oy);\n\tfloat xxd_next = xxd + 4096.0f;\n\tfloat yyd_next = yyd + 4096.0f;\n\tfloat paramrad = (float)param0 * (float)-0.000003067961642955197f;\n\n\tfloat rad = (float)(mem[0] - 0x800) * paramrad;\n\tfloat sinv = sin(rad);\n\tfloat cosv = cos(rad);\n\txx_min = xx_max = (int)(xxd * cosv - yyd * sinv);\n\tyy_min = yy_max = (int)(xxd * sinv + yyd * cosv);\n\n\trad = (float)(mem[4] - 0x800) * paramrad;\n\tsinv = sin(rad);\n\tcosv = cos(rad);\n\txx_temp = (int)(xxd_next * cosv - yyd * sinv);\n\tyy_temp = (int)(xxd_next * sinv + yyd * cosv);\n\txx_min = min(xx_min, xx_temp);\n\txx_max = max(xx_max, xx_temp);\n\tyy_min = min(yy_min, yy_temp);\n\tyy_max = max(yy_max, yy_temp);\n\n\trad = (float)(mem[obj_line * 4] - 0x800) * paramrad;\n\tsinv = sin(rad);\n\tcosv = cos(rad);\n\txx_temp = (int)(xxd * cosv - yyd_next * sinv);\n\tyy_temp = (int)(xxd * sinv + yyd_next * cosv);\n\txx_min = min(xx_min, xx_temp);\n\txx_max = max(xx_max, xx_temp);\n\tyy_min = min(yy_min, yy_temp);\n\tyy_max = max(yy_max, yy_temp);\n\n\trad = (float)(mem[(obj_line + 1) * 4] - 0x800) * paramrad;\n\tsinv = sin(rad);\n\tcosv = cos(rad);\n\txx_temp = (int)(xxd_next * cosv - yyd_next * sinv);\n\tyy_temp = (int)(xxd_next * sinv + yyd_next * cosv);\n\tint xx_begin = min(xx_min, xx_temp) + ox;\n\tint xx_end = max(xx_max, xx_temp) + ox;\n\tint yy_begin = min(yy_min, yy_temp) + oy;\n\tint yy_end = max(yy_max, yy_temp) + oy;\n\n\tint xx_range = xx_end - xx_begin;\n\tint yy_range = yy_end - yy_begin;\n\n\tif (xx_range < 0x1000) {\n\t\txx_begin += (xx_range - 0x1000) >> 1;\n\t\txx_end = xx_begin + 0x1000;\n\t\txx_range = 0x1000;\n\t}\n\tif (yy_range < 0x1000) {\n\t\tyy_begin += (yy_range - 0x1000) >> 1;\n\t\tyy_end = yy_begin + 0x1000;\n\t\tyy_range = 0x1000;\n\t}\n\n\tint xx_level = 12;\n\tint yy_level = 12;\n\twhile (0x20000 < xx_range) {\n\t\txx_begin >>= 1;\n\t\txx_end++;\n\t\txx_end >>= 1;\n\t\txx_range = xx_end - xx_begin;\n\t\txx_level--;\n\t}\n\twhile (0x20000 < yy_range) {\n\t\tyy_begin >>= 1;\n\t\tyy_end++;\n\t\tyy_end >>= 1;\n\t\tyy_range = yy_end - yy_begin;\n\t\tyy_level--;\n\t}\n\txx_level &= 0x1f;\n\tyy_level &= 0x1f;\n\n\txx_begin = max(xx_begin, 0);\n\txx_end = min(xx_end, obj_w << xx_level);\n\tyy_begin = max(yy_begin, 0);\n\tyy_end = min(yy_end, obj_h << yy_level);\n\n\tfloat dsum_y = 0.0f;\n\tfloat dsum_cb = 0.0f;\n\tfloat dsum_cr = 0.0f;\n\tfloat dsum_a = 0.0f;\n\tint yy = yy_begin;\n\twhile (yy < yy_end) {\n\t\tint yy_itr = yy >> yy_level;\n\t\tint sum_y = 0;\n\t\tint sum_cb = 0;\n\t\tint sum_cr = 0;\n\t\tint sum_a = 0;\n\t\tint xx = xx_begin;\n\t\twhile (xx < xx_end) {\n\t\t\tint xx_itr = xx >> xx_level;\n\t\t\tint fraction;\n\t\t\tif (xx & 0xfff) {\n\t\t\t\tfraction = -xx & 0xfff;\n\t\t\t} else {\n\t\t\t\tfraction = min(xx_end - xx, 0x1000);\n\t\t\t}\n\n\t\t\tglobal short* srct = src + (xx_itr + yy_itr * obj_line) * 4;\n\t\t\tint src_a = srct[3] * fraction >> 8;\n\t\t\tsum_y += srct[0] * src_a >> 16;\n\t\t\tsum_cb += srct[1] * src_a >> 16;\n\t\t\tsum_cr += srct[2] * src_a >> 16;\n\t\t\tsum_a += src_a;\n\t\t\txx += fraction;\n\t\t}\n\t\tint fraction;\n\t\tif (yy & 0xfff) {\n\t\t\tfraction = -yy & 0xfff;\n\t\t} else {\n\t\t\tfraction = min(yy_end - yy, 0x1000);\n\t\t}\n\t\tfloat fraction_rate = (float)fraction * 0.000244140625f;\n\t\tdsum_y += (float)sum_y * fraction_rate;\n\t\tdsum_cb += (float)sum_cb * fraction_rate;\n\t\tdsum_cr += (float)sum_cr * fraction_rate;\n\t\tdsum_a += (float)sum_a * fraction_rate;\n\t\tyy += fraction;\n\t}\n\n\tif (256.0f <= dsum_a) {\n\t\tfloat inv_a = 65536.0f / dsum_a;\n\t\tdst[0] = (short)round(dsum_y * inv_a);\n\t\tdst[1] = (short)round(dsum_cb * inv_a);\n\t\tdst[2] = (short)round(dsum_cr * inv_a);\n\t\tdst[3] = (short)round(dsum_a / ((float)yy_range / 1024.0f) / ((float)xx_range / 1024.0f));\n\t} else {\n\t\tdst[0] = dst[1] = dst[2] = dst[3] = 0;\n\t}\n}\n\nkernel void RadiationalBlur_Media(\n\tglobal short* dst, global short* src, int src_w, int src_h, int buffer_line,\n\tint rb_blur_cx, int rb_blur_cy, int rb_obj_cx, int rb_obj_cy, int rb_range, int rb_pixel_range) {\n\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\tint pixel_itr = x + y * buffer_line;\n\n\tx += rb_obj_cx;\n\ty += rb_obj_cy;\n\tint cx = rb_blur_cx - x;\n\tint cy = rb_blur_cy - y;\n\tint c_dist_times8 = (int)round(sqrt((float)(cx * cx + cy * cy)) * 8.0f);\n\tint range = rb_range * c_dist_times8 / 1000;\n\n\tif (rb_pixel_range < c_dist_times8) {\n\t\trange = rb_pixel_range * rb_range / 1000;\n\t\tc_dist_times8 = rb_pixel_range;\n\t} else if (8 < c_dist_times8) {\n\t\tc_dist_times8 *= 8;\n\t\trange *= 8;\n\t} else if (4 < c_dist_times8) {\n\t\tc_dist_times8 *= 4;\n\t\trange *= 4;\n\t} else if (2 < c_dist_times8) {\n\t\tc_dist_times8 *= 2;\n\t\trange *= 2;\n\t}\n\n\tif (2 <= c_dist_times8 && 2 <= range) {\n\t\tint sum_a = 0;\n\t\tint sum_cr = 0;\n\t\tint sum_cb = 0;\n\t\tint sum_y = 0;\n\n\t\tfor (int i = 0; i < range; i++) {\n\t\t\tint x_itr = x + i * cx / c_dist_times8;\n\t\t\tint y_itr = y + i * cy / c_dist_times8;\n\t\t\tif (0 <= x_itr && x_itr < src_w && 0 <= y_itr && y_itr < src_h) {\n\t\t\t\tshort4 itr = vload4(x_itr + y_itr * buffer_line, src);\n\t\t\t\tint itr_a = itr.w;\n\t\t\t\tsum_a += itr_a;\n\t\t\t\tif (0x1000 < itr_a) {\n\t\t\t\t\titr_a = 0x1000;\n\t\t\t\t}\n\t\t\t\tsum_y += itr.x * itr_a / 4096;\n\t\t\t\tsum_cb += itr.y * itr_a / 4096;\n\t\t\t\tsum_cr += itr.z * itr_a / 4096;\n\t\t\t\t\n\t\t\t}\n\t\t}\n\t\tif (sum_a != 0) {\n\t\t\tvstore4(\n\t\t\t\t(short4)(\n\t\t\t\t\tround(sum_y * 4096.0f / sum_a),\n\t\t\t\t\tround(sum_cb * 4096.0f / sum_a),\n\t\t\t\t\tround(sum_cr * 4096.0f / sum_a),\n\t\t\t\t\tsum_a / range\n\t\t\t\t\t),\n\t\t\t\tpixel_itr, dst\n\t\t\t);\n\t\t} else {\n\t\t\tdst[pixel_itr * 4 + 3] = 0;\n\t\t}\n\t} else {\n\t\tif (x < 0 || y < 0 || src_w <= x || src_h <= y) {\n\t\t\tvstore4((short4)(0, 0, 0, 0), pixel_itr, dst);\n\t\t} else {\n\t\t\tvstore4(vload4(x + y * buffer_line, src), pixel_itr, dst);\n\t\t}\n\t}\n}\n\nkernel void RadiationalBlur_Filter(\n\tglobal short* dst, global short* src, int buffer_line,\n\tint rb_blur_cx, int rb_blur_cy, int rb_range, int rb_pixel_range) {\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\n\tint cx = rb_blur_cx - x;\n\tint cy = rb_blur_cy - y;\n\tint c_dist_times8 = (int)round(sqrt((float)(cx * cx + cy * cy)) * 8.0f);\n\tint range = rb_range * c_dist_times8 / 1000;\n\tif (rb_pixel_range < c_dist_times8) {\n\t\trange = (rb_pixel_range * rb_range) / 1000;\n\t\tc_dist_times8 = rb_pixel_range;\n\t} else if (8 < c_dist_times8) {\n\t\tc_dist_times8 *= 8;\n\t\trange *= 8;\n\t} else if (4 < c_dist_times8) {\n\t\tc_dist_times8 *= 4;\n\t\trange *= 4;\n\t} else if (2 < c_dist_times8) {\n\t\tc_dist_times8 *= 2;\n\t\trange *= 2;\n\t}\n\n\tint offset = (x + y * buffer_line) * 3;\n\tif (2 <= c_dist_times8 && 2 <= range) {\n\t\tint sum_y = 0;\n\t\tint sum_cb = 0;\n\t\tint sum_cr = 0;\n\t\tfor (int i = 0; i < range; i++) {\n\t\t\tint x_itr = x + i * cx / c_dist_times8;\n\t\t\tint y_itr = y + i * cy / c_dist_times8;\n\t\t\tint pix_offset = (x_itr + y_itr * buffer_line) * 3;\n\t\t\tsum_y += src[pix_offset];\n\t\t\tsum_cb += src[++pix_offset];\n\t\t\tsum_cr += src[++pix_offset];\n\t\t}\n\n\t\tdst[offset] = (short)(sum_y / range);\n\t\tdst[++offset] = (short)(sum_cb / range);\n\t\tdst[++offset] = (short)(sum_cr / range);\n\t} else {\n\t\tdst[offset] = src[offset];\n\t\tdst[offset + 1] = src[offset + 1];\n\t\tdst[offset + 2] = src[offset + 2];\n\t}\n}\n\nkernel void RadiationalBlur_Filter_Far(\n\tglobal short* dst, global short* src, int scene_w, int scene_h, int buffer_line,\n\tint rb_blur_cx, int rb_blur_cy, int rb_range, int rb_pixel_range) {\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\n\tint cx = rb_blur_cx - x;\n\tint cy = rb_blur_cy - y;\n\tint c_dist_times8 = (int)round(sqrt((float)(cx * cx + cy * cy)) * 8.0f);\n\tint range = rb_range * c_dist_times8 / 1000;\n\tif (rb_pixel_range < c_dist_times8) {\n\t\trange = (rb_pixel_range * rb_range) / 1000;\n\t\tc_dist_times8 = rb_pixel_range;\n\t} else if (8 < c_dist_times8) {\n\t\tc_dist_times8 *= 8;\n\t\trange *= 8;\n\t} else if (4 < c_dist_times8) {\n\t\tc_dist_times8 *= 4;\n\t\trange *= 4;\n\t} else if (2 < c_dist_times8) {\n\t\tc_dist_times8 *= 2;\n\t\trange *= 2;\n\t}\n\n\tint offset = (x + y * buffer_line) * 3;\n\tif (2 <= c_dist_times8 && 2 <= range) {\n\t\tint sum_y = 0;\n\t\tint sum_cb = 0;\n\t\tint sum_cr = 0;\n\t\tfor (int i = 0; i < range; i++) {\n\t\t\tint x_itr = x + i * cx / c_dist_times8;\n\t\t\tint y_itr = y + i * cy / c_dist_times8;\n\t\t\tif (0 <= x_itr && 0 <= y_itr && x_itr < scene_w && y_itr < scene_h) {\n\t\t\t\tint pix_offset = (x_itr + y_itr * buffer_line) * 3;\n\t\t\t\tsum_y += src[pix_offset];\n\t\t\t\tsum_cb += src[++pix_offset];\n\t\t\t\tsum_cr += src[++pix_offset];\n\t\t\t}\n\t\t}\n\n\t\tdst[offset] = (short)(sum_y / range);\n\t\tdst[++offset] = (short)(sum_cb / range);\n\t\tdst[++offset] = (short)(sum_cr / range);\n\t} else {\n\t\tdst[offset] = src[offset];\n\t\tdst[offset + 1] = src[offset + 1];\n\t\tdst[offset + 2] = src[offset + 2];\n\t}\n}\n\nkernel void Flash(global short* dst, global short* src, int src_w, int src_h, int exedit_buffer_line,\n\tint g_cx,\n\tint g_cy,\n\tint g_range,\n\tint g_pixel_range,\n\tint g_temp_x,\n\tint g_temp_y,\n\tint g_r_intensity\n) {\n\n\tint xi = get_global_id(0);\n\tint yi = get_global_id(1);\n\n\tint x = xi + g_temp_x;\n\tint y = yi + g_temp_y;\n\n\tint pixel_itr = xi + yi * exedit_buffer_line;\n\n\tint cx = g_cx - x;\n\tint cy = g_cy - y;\n\tint c_dist_times8 = (int)round(sqrt((float)(cx * cx + cy * cy)) * 8.0f);\n\tint range = g_range * c_dist_times8 / 1000;\n\n\tif (g_pixel_range < c_dist_times8) {\n\t\trange = g_pixel_range * g_range / 1000;\n\t\tc_dist_times8 = g_pixel_range;\n\t} else if (8 < c_dist_times8) {\n\t\tc_dist_times8 *= 8;\n\t\trange *= 8;\n\t} else if (4 < c_dist_times8) {\n\t\tc_dist_times8 *= 4;\n\t\trange *= 4;\n\t} else if (2 < c_dist_times8) {\n\t\tc_dist_times8 *= 2;\n\t\trange *= 2;\n\t}\n\n\tint sum_y, sum_cb, sum_cr;\n\n\tif (2 <= c_dist_times8 && 2 <= range) {\n\t\tsum_y = sum_cb = sum_cr = 0;\n\t\tfor (int i = 0; i < range; i++) {\n\t\t\tint x_itr = x + i * cx / c_dist_times8;\n\t\t\tint y_itr = y + i * cy / c_dist_times8;\n\n\t\t\tif (0 <= x_itr && 0 <= y_itr && x_itr < src_w && y_itr < src_h) {\n\t\t\t\tshort4 itr = vload4(x_itr + y_itr * exedit_buffer_line, src);\n\t\t\t\tif (itr.w != 0) {\n\t\t\t\t\tif (itr.w < 4096) {\n\t\t\t\t\t\tsum_y += itr.x * itr.w / 4096;\n\t\t\t\t\t\tsum_cb += itr.y * itr.w / 4096;\n\t\t\t\t\t\tsum_cr += itr.z * itr.w / 4096;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsum_y += itr.x;\n\t\t\t\t\t\tsum_cb += itr.y;\n\t\t\t\t\t\tsum_cr += itr.z;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tsum_y /= range;\n\t\tsum_cb /= range;\n\t\tsum_cr /= range;\n\t} else {\n\t\tif (x < 0 || y < 0 || src_w <= x || src_h <= y) {\n\t\t\tvstore4((short4)(0, 0, 0, 0), pixel_itr, dst);\n\t\t\treturn;\n\t\t} else {\n\t\t\tshort4 itr = vload4(x + y * exedit_buffer_line, src);\n\t\t\tsum_y = itr.x * itr.w / 4096;\n\t\t\tsum_cb = itr.y * itr.w / 4096;\n\t\t\tsum_cr = itr.z * itr.w / 4096;\n\t\t}\n\t}\n\n\tint ya = sum_y - g_r_intensity;\n\tif (ya < 1) {\n\t\tvstore4((short4)(0, 0, 0, 0), pixel_itr, dst);\n\t} else {\n\t\tsum_cb -= g_r_intensity * sum_cb / sum_y;\n\t\tsum_cr -= g_r_intensity * sum_cr / sum_y;\n\t\tif (ya < 4096) {\n\t\t\tvstore4(\n\t\t\t\t(short4)(\n\t\t\t\t\t4096,\n\t\t\t\t\tsum_cb * 4096 / ya,\n\t\t\t\t\tsum_cr * 4096 / ya,\n\t\t\t\t\tya\n\t\t\t\t\t),\n\t\t\t\tpixel_itr, dst\n\t\t\t);\n\t\t} else {\n\t\t\tvstore4(\n\t\t\t\t(short4)(\n\t\t\t\t\tya,\n\t\t\t\t\tsum_cb,\n\t\t\t\t\tsum_cr,\n\t\t\t\t\t4096\n\t\t\t\t\t),\n\t\t\t\tpixel_itr, dst\n\t\t\t);\n\t\t}\n\t}\n}\nkernel void FlashColor(global short* dst, global short* src, int src_w, int src_h, int exedit_buffer_line,\n\tint g_cx,\n\tint g_cy,\n\tint g_range,\n\tint g_pixel_range,\n\tint g_temp_x,\n\tint g_temp_y,\n\tint g_r_intensity,\n\tshort g_color_y,\n\tshort g_color_cb,\n\tshort g_color_cr\n) {\n\n\tint xi = get_global_id(0);\n\tint yi = get_global_id(1);\n\n\tint x = xi + g_temp_x;\n\tint y = yi + g_temp_y;\n\n\tint pixel_itr = xi + yi * exedit_buffer_line;\n\n\tint cx = g_cx - x;\n\tint cy = g_cy - y;\n\tint c_dist_times8 = (int)round(sqrt((float)(cx * cx + cy * cy)) * 8.0f);\n\tint range = g_range * c_dist_times8 / 1000;\n\tif (g_pixel_range < c_dist_times8) {\n\t\trange = g_pixel_range * g_range / 1000;\n\t\tc_dist_times8 = g_pixel_range;\n\t} else if (8 < c_dist_times8) {\n\t\tc_dist_times8 *= 8;\n\t\trange *= 8;\n\t} else if (4 < c_dist_times8) {\n\t\tc_dist_times8 *= 4;\n\t\trange *= 4;\n\t} else if (2 < c_dist_times8) {\n\t\tc_dist_times8 *= 2;\n\t\trange *= 2;\n\t}\n\tint itr_y, itr_cb, itr_cr;\n\n\tif (2 <= c_dist_times8 && 2 <= range) {\n\t\tint sum_a = 0;\n\t\tfor (int i = 0; i < range; i++) {\n\t\t\tint x_itr = x + i * cx / c_dist_times8;\n\t\t\tint y_itr = y + i * cy / c_dist_times8;\n\n\t\t\tif (0 <= x_itr && 0 <= y_itr && x_itr < src_w && y_itr < src_h) {\n\t\t\t\tshort4 itr = vload4(x_itr + y_itr * exedit_buffer_line, src);\n\t\t\t\tint itr_a = itr.w;\n\t\t\t\tif (itr_a != 0) {\n\t\t\t\t\tif (itr_a < 4096) {\n\t\t\t\t\t\tsum_a += itr_a;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsum_a += 4096;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tsum_a /= range;\n\t\titr_y = g_color_y * sum_a / 4096;\n\t\titr_cb = g_color_cb * sum_a / 4096;\n\t\titr_cr = g_color_cr * sum_a / 4096;\n\t} else {\n\t\tif (x < 0 || y < 0 || src_w <= x || src_h <= y) {\n\t\t\tvstore4((short4)(0, 0, 0, 0), pixel_itr, dst);\n\t\t\treturn;\n\t\t} else {\n\t\t\tshort4 itr = vload4(x + y * exedit_buffer_line, src);\n\t\t\tint itr_a = itr.w;\n\t\t\titr_y = g_color_y * itr_a / 4096;\n\t\t\titr_cb = g_color_cb * itr_a / 4096;\n\t\t\titr_cr = g_color_cr * itr_a / 4096;\n\t\t}\n\t}\n\n\tint ya = itr_y - g_r_intensity;\n\tif (ya < 1) {\n\t\tvstore4((short4)(0, 0, 0, 0), pixel_itr, dst);\n\t} else {\n\t\titr_cb -= g_r_intensity * itr_cb / itr_y;\n\t\titr_cr -= g_r_intensity * itr_cr / itr_y;\n\t\tif (ya < 4096) {\n\t\t\tvstore4(\n\t\t\t\t(short4)(\n\t\t\t\t\t4096,\n\t\t\t\t\titr_cb * 4096 / ya,\n\t\t\t\t\titr_cr * 4096 / ya,\n\t\t\t\t\tya\n\t\t\t\t\t),\n\t\t\t\tpixel_itr, dst\n\t\t\t);\n\t\t} else {\n\t\t\tvstore4(\n\t\t\t\t(short4)(\n\t\t\t\t\tya,\n\t\t\t\t\titr_cb,\n\t\t\t\t\titr_cr,\n\t\t\t\t\t4096\n\t\t\t\t\t),\n\t\t\t\tpixel_itr, dst\n\t\t\t);\n\t\t}\n\t}\n}\nkernel void DirectionalBlur_Media(global short* dst, global short* src, int obj_w, int obj_h, int obj_line,\n\tint x_begin, int x_end, int x_step, int y_begin, int y_end, int y_step, int range) {\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\tint pix_range = range * 2 + 1;\n\n\tdst += (x + y * obj_line) * 4;\n\n\tint sum_y = 0;\n\tint sum_cb = 0;\n\tint sum_cr = 0;\n\tint sum_a = 0;\n\n\tint x_itr = ((x + x_begin) << 16) + 0x8000 - range * x_step;\n\tint y_itr = ((y + y_begin) << 16) + 0x8000 - range * y_step;\n\n\tfor (int n = 0; n < pix_range; n++) {\n\t\tint xx = x_itr >> 16;\n\t\tint yy = y_itr >> 16;\n\t\tif (0 <= xx && xx < obj_w && 0 <= yy && yy < obj_h) {\n\t\t\tglobal short* pix = src + (xx + yy * obj_line) * 4;\n\t\t\tint src_a = min((int)pix[3], 0x1000);\n\t\t\tsum_y += pix[0] * src_a >> 12;\n\t\t\tsum_cb += pix[1] * src_a >> 12;\n\t\t\tsum_cr += pix[2] * src_a >> 12;\n\t\t\tsum_a += src_a;\n\t\t}\n\t\tx_itr += x_step;\n\t\ty_itr += y_step;\n\t}\n\tif (0 < sum_a) {\n\t\tfloat a_float = 4096.0f / (float)sum_a;\n\t\tdst[0] = (short)round((float)sum_y * a_float);\n\t\tdst[1] = (short)round((float)sum_cb * a_float);\n\t\tdst[2] = (short)round((float)sum_cr * a_float);\n\t} else {\n\t\tdst[0] = dst[1] = dst[2] = 0;\n\t}\n\tdst[3] = (short)(sum_a / pix_range);\n}\nkernel void DirectionalBlur_original_size(global short* dst, global short* src, int obj_w, int obj_h, int obj_line,\n\tint x_step, int y_step, int range) {\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\tint pix_range = range * 2 + 1;\n\n\tdst += (x + y * obj_line) * 4;\n\n\tint x_itr = (x << 16) + 0x8000 - range * x_step;\n\tint y_itr = (y << 16) + 0x8000 - range * y_step;\n\n\tint sum_y = 0;\n\tint sum_cb = 0;\n\tint sum_cr = 0;\n\tint sum_a = 0;\n\tint cnt = 0;\n\n\tfor (int n = 0; n < pix_range; n++) {\n\t\tint xx = x_itr >> 16;\n\t\tint yy = y_itr >> 16;\n\t\tif (0 <= xx && xx < obj_w && 0 <= yy && yy < obj_h) {\n\t\t\tglobal short* pix = src + (xx + yy * obj_line) * 4;\n\t\t\tint src_a = min((int)pix[3], 0x1000);\n\t\t\tsum_y += pix[0] * src_a >> 12;\n\t\t\tsum_cb += pix[1] * src_a >> 12;\n\t\t\tsum_cr += pix[2] * src_a >> 12;\n\t\t\tsum_a += src_a;\n\t\t\tcnt++;\n\t\t}\n\t\tx_itr += x_step;\n\t\ty_itr += y_step;\n\t}\n\tif(cnt == 0) cnt = 0xffffff;\n\tif (0 < sum_a) {\n\t\tfloat a_float = 4096.0f / (float)sum_a;\n\t\tdst[0] = (short)round((float)sum_y * a_float);\n\t\tdst[1] = (short)round((float)sum_cb * a_float);\n\t\tdst[2] = (short)round((float)sum_cr * a_float);\n\t} else {\n\t\tdst[0] = dst[1] = dst[2] = 0;\n\t}\n\tdst[3] = (short)(sum_a / cnt);\n}\nkernel void DirectionalBlur_Filter(global short* dst, global short* src, int scene_w, int scene_h, int scene_line,\n\tint x_step, int y_step, int range) {\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\tint pix_range = range * 2 + 1;\n\n\tdst += (x + y * scene_line) * 3;\n\n\tint x_itr = (x << 16) + 0x8000 - range * x_step;\n\tint y_itr = (y << 16) + 0x8000 - range * y_step;\n\n\tint sum_y = 0;\n\tint sum_cb = 0;\n\tint sum_cr = 0;\n\tint cnt = 0;\n\tfor (int n = 0; n < pix_range; n++) {\n\t\tint xx = x_itr >> 16;\n\t\tint yy = y_itr >> 16;\n\t\tif (0 <= xx && xx < scene_w && 0 <= yy && yy < scene_h) {\n\t\t\tglobal short* pix = src + (xx + yy * scene_line) * 3;\n\t\t\tsum_y += pix[0];\n\t\t\tsum_cb += pix[1];\n\t\t\tsum_cr += pix[2];\n\t\t\tcnt++;\n\t\t}\n\t\tx_itr += x_step;\n\t\ty_itr += y_step;\n\t}\n\tif(cnt == 0) cnt = 0xffffff;\n\tdst[0] = (short)(sum_y / cnt);\n\tdst[1] = (short)(sum_cb / cnt);\n\tdst[2] = (short)(sum_cr / cnt);\n}\nkernel void LensBlur_Media(global char* dst, global char* src, int obj_w, int obj_h, int obj_line,\n\tint range, int rangep05_sqr, int range_t3m1, int rangem1_sqr) {\n\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\n\tint top = -min(y, range);\n\tint bottom = min(obj_h - y - 1, range);\n\tint left = -min(x, range);\n\tint right = min(obj_w - x - 1, range);\n\n\tfloat sum_y = 0.0f;\n\tint sum_cb = 0;\n\tint sum_cr = 0;\n\tint sum_a = 0;\n\n\tint cor_sum = 0;\n\n\tint offset = (x + left + (y + top) * obj_line) * 8;\n\n\tfor (int yy = top; yy <= bottom; yy++) {\n\t\tint sqr = yy * yy + left * left;\n\t\tint offset2 = offset;\n\t\tfor (int xx = left; xx <= right; xx++) {\n\t\t\tif (sqr < rangep05_sqr) {\n\t\t\t\tint cor_a;\n\t\t\t\tif (rangem1_sqr < sqr) {\n\t\t\t\t\tcor_a = ((rangep05_sqr - sqr) << 12) / range_t3m1;\n\t\t\t\t} else {\n\t\t\t\t\tcor_a = 4096;\n\t\t\t\t}\n\t\t\t\tcor_sum += cor_a;\n\t\t\t\tcor_a = *(global short*)&src[offset2 + 6] * cor_a >> 12;\n\t\t\t\tsum_y += *(global float*)&src[offset2] * (float)cor_a;\n\t\t\t\tsum_cb += src[offset2 + 4] * cor_a;\n\t\t\t\tsum_cr += src[offset2 + 5] * cor_a;\n\t\t\t\tsum_a += cor_a;\n\t\t\t}\n\t\t\tsqr += 1 + xx * 2;\n\t\t\toffset2 += 8;\n\t\t}\n\t\toffset += obj_line * 8;\n\t}\n\n\tdst += (x + y * obj_line) * 8;\n\tif (0 < sum_a) {\n\t\t*(global float*)dst = sum_y / (float)sum_a;\n\t\tdst[4] = (char)(((sum_a >> 1) + sum_cb) / sum_a);\n\t\tdst[5] = (char)(((sum_a >> 1) + sum_cr) / sum_a);\n\t\t*(global short*)&dst[6] = (short)round((float)sum_a * (4096.0f / (float)cor_sum));\n\t} else {\n\t\t*(global int*)dst = 0;\n\t\t*(global int*)&dst[4] = 0;\n\t}\n}\n\nkernel void LensBlur_Filter(global char* dst, global char* src, int scene_w, int scene_h, int scene_line,\n\tint range, int rangep05_sqr, int range_t3m1, int rangem1_sqr) {\n\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\n\tint top = -min(y, range);\n\tint bottom = min(scene_h - y - 1, range);\n\tint left = -min(x, range);\n\tint right = min(scene_w - x - 1, range);\n\n\tshort tofloat[2];\n\tfloat sum_y = 0.0f;\n\tint sum_cb = 0;\n\tint sum_cr = 0;\n\tint sum_a = 0;\n\n\tint offset = (x + left + (y + top) * scene_line) * 6;\n\n\tfor (int yy = top; yy <= bottom; yy++) {\n\n\t\tint sqr = yy * yy + left * left;\n\t\tint offset2 = offset;\n\n\t\tfor (int xx = left; xx <= right; xx++) {\n\t\t\tif (sqr < rangep05_sqr) {\n\t\t\t\tint cor_a;\n\t\t\t\tif (rangem1_sqr < sqr) {\n\t\t\t\t\tcor_a = ((rangep05_sqr - sqr) << 12) / range_t3m1;\n\t\t\t\t} else {\n\t\t\t\t\tcor_a = 4096;\n\t\t\t\t}\n\t\t\t\ttofloat[0] = *(global short*)&src[offset2];\n\t\t\t\ttofloat[1] = *(global short*)&src[offset2 + 2];\n\t\t\t\tsum_y += *(float*)tofloat * (float)cor_a;\n\t\t\t\tsum_cb += src[offset2 + 4] * cor_a;\n\t\t\t\tsum_cr += src[offset2 + 5] * cor_a;\n\t\t\t\tsum_a += cor_a;\n\t\t\t}\n\t\t\tsqr += 1 + xx * 2;\n\t\t\toffset2 += 6;\n\t\t}\n\t\toffset += scene_line * 6;\n\t}\n\n\tdst += (x + y * scene_line) * 6;\n\t*(float*)tofloat = sum_y / (float)sum_a;\n\t*(global short*)&dst[0] = tofloat[0];\n\t*(global short*)&dst[2] = tofloat[1];\n\tdst[4] = (char)(((sum_a >> 1) + sum_cb) / sum_a);\n\tdst[5] = (char)(((sum_a >> 1) + sum_cr) / sum_a);\n}\n"
  },
  {
    "path": "patch/config.hpp",
    "content": "/*\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n\n#include <Windows.h>\n#include <boost/scope_exit.hpp>\n\n#include \"macro.h\"\n#include \"util_resource.hpp\"\n#include \"config_rw.hpp\"\n\n#include \"patch.hpp\"\n\n\nclass Config2 {\n    bool invalid_json;\n\npublic:\n    void load(std::wstring_view path) {\n        auto hFile = CreateFileW(path.data(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);\n        if (hFile == INVALID_HANDLE_VALUE) return;\n        DWORD ignore;\n        auto size_low = GetFileSize(hFile, &ignore);\n        auto file = std::make_unique<byte[]>(size_low);\n        if (ReadFile(hFile, file.get(), size_low, &ignore, NULL) == FALSE) {\n            patch_resource_message_stack.emplace_back(new patch_resource_message_class_w(PATCH_RS_PATCH_FAILED_TO_LOAD_SETTING, MB_TASKMODAL | MB_ICONEXCLAMATION));\n            return;\n        }\n        CloseHandle(hFile);\n\n        json_value_s* root = nullptr;\n        BOOST_SCOPE_EXIT_ALL(&root) { free(root); };\n\n        root = json_parse(file.get(), size_low);\n        if (root == nullptr) {\n            patch_resource_message_stack.emplace_back(new patch_resource_message_class_w(PATCH_RS_PATCH_INVALID_SETTING_JSON, MB_TASKMODAL | MB_ICONEXCLAMATION));\n            invalid_json = true;\n            return;\n        }\n\n        ConfigReader cr(root);\n\n        cr.regist(\"switch\", [](json_value_s* value) {\n            ConfigReader cr(value);\n            \n\t\t    #ifdef PATCH_SWITCH_ACCESS_KEY\n                patch::access_key.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_COLORPALETTE_CACHE\n                patch::colorpalette_cache.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_FILEINFO\n                patch::fileinfo.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_SUSIE_LOAD\n                patch::susie_load.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_SPLASH\n                patch::splash.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_AUP_SCENE_SETTING\n                patch::aup_scene_setting.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_AUP_LAYER_SETTING\n                patch::aup_layer_setting.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_EXO_AVIUTL_FILTER\n                patch::exo_aviutlfilter.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_EXO_SCENEIDX\n                patch::exo_sceneidx.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_EXO_TRACKPARAM\n                patch::exo_trackparam.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_EXO_TRACK_MINUSVAL\n                patch::exo_trackminusval.switch_load(cr);\n\t\t    #endif\n            #ifdef PATCH_SWITCH_EXO_MIDPT_AND_TRA\n                patch::exo_midpt_and_tra.switch_load(cr);\n            #endif\n\t\t    #ifdef PATCH_SWITCH_EXO_SPECIALCOLORCONV\n                patch::exo_specialcolorconv.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_EXO_FOLD_GUI\n                patch::exo_fold_gui.switch_load(cr);\n\t\t    #endif\n            #ifdef PATCH_SWITCH_TRA_AVIUTL_FILTER\n                patch::tra_aviutlfilter.switch_load(cr);\n            #endif\n            #ifdef PATCH_SWITCH_TRA_CHANGE_DRAWFILTER\n                patch::tra_change_drawfilter.switch_load(cr);\n            #endif\n            #ifdef PATCH_SWITCH_TRA_SPECIFIED_SPEED\n                patch::tra_specified_speed.switch_load(cr);\n            #endif\n            #ifdef PATCH_SWITCH_SETTING_NEW_PROJECT\n                patch::setting_new_project.switch_load(cr);\n            #endif\n\t\t    #ifdef PATCH_SWITCH_TEXT_OP_SIZE\n                patch::text_op_size.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_IGNORE_MEDIA_PARAM_RESET\n                patch::ignore_media_param_reset.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_FONT_DIALOG\n                patch::font_dialog.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_SCROLL_OBJDLG\n                patch::scroll_objdlg.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_ALPHA_BG\n                patch::alpha_bg.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_HELPFUL_MSGBOX\n                patch::helpful_msgbox.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_FAILED_SJIS_MSGBOX\n                patch::failed_sjis_msgbox.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_FAILED_LONGER_PATH\n\t\tpatch::failed_longer_path.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_FAILED_FILE_DROP\n\t\tpatch::failed_file_drop.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_THEME_CC\n                patch::theme_cc.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_EXEDITWINDOW_SIZING\n                patch::exeditwindow_sizing.switch_load(cr);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_SETTINGDIALOG_MOVE\n                patch::setting_dialog_move.switch_load(cr);\n\t\t    #endif\n            #ifdef PATCH_SWITCH_OBJ_COLORCORRECTION\n                patch::ColorCorrection.switch_load(cr);\n            #endif\n            #ifdef PATCH_SWITCH_OBJ_GLOW\n                patch::Glow.switch_load(cr);\n            #endif\n            #ifdef PATCH_SWITCH_OBJ_LENSBLUR\n                patch::LensBlur.switch_load(cr);\n            #endif\n            #ifdef PATCH_SWITCH_OBJ_NOISE\n                patch::Noise.switch_load(cr);\n            #endif\n            #ifdef PATCH_SWITCH_OBJ_SPECIALCOLORCONV\n                patch::obj_specialcolorconv.switch_load(cr);\n            #endif\n            #ifdef PATCH_SWITCH_SETTINGDIALOG_EXCOLORCONFIG\n                patch::excolorconfig.switch_load(cr);\n\t\t    #endif\n            #ifdef PATCH_SWITCH_RCLICKMENU_SPLIT\n                patch::rclickmenu_split.switch_load(cr);\n            #endif\n            #ifdef PATCH_SWITCH_RCLICKMENU_DELETE\n                patch::rclickmenu_delete.switch_load(cr);\n            #endif\n            #ifdef PATCH_SWITCH_BLEND\n                patch::blend.switch_load(cr);\n            #endif\n            #ifdef PATCH_SWITCH_ADD_EXTENSION\n                patch::add_extension.switch_load(cr);\n            #endif\n            #ifdef PATCH_SWITCH_DIALOG_NEW_FILE\n                patch::dialog_new_file.switch_load(cr);\n            #endif\n            #ifdef PATCH_SWITCH_PLAYBACK_SPEED\n                patch::playback_speed.switch_load(cr);\n            #endif\n\t\t\n\t\t    #ifdef PATCH_SWITCH_UNDO\n                patch::undo.switch_load(cr);\n                #ifdef PATCH_SWITCH_UNDO_REDO\n                    patch::redo.switch_load(cr);\n                #endif\n\t\t    #endif\n\n\t\t    #ifdef PATCH_SWITCH_CONSOLE\n                patch::console.switch_load(cr);\n\t\t    #endif\n\t\t\t\t\n\t\t    #ifdef PATCH_SWITCH_LUA\n                patch::lua.switch_load(cr);\n                #ifdef PATCH_SWITCH_LUA_GETVALUE\n                    patch::lua_getvalueex.switch_load(cr);\n                #endif\n\n                #ifdef PATCH_SWITCH_LUA_RAND\n                    patch::lua_rand.switch_load(cr);\n                #endif\n\n                #ifdef PATCH_SWITCH_LUA_RANDEX\n                    patch::lua_randex.switch_load(cr);\n                #endif\n\t\t    #endif\n\n\t\t    #ifdef PATCH_SWITCH_FAST\n                patch::fast::fast.switch_load(cr);\n\t\t\t    \n\t\t\t    #ifdef PATCH_SWITCH_FAST_EXEDITWINDOW\n                    patch::fast_exeditwindow.switch_load(cr);\n\t\t\t    #endif\n\t\t\t    #ifdef PATCH_SWITCH_FAST_SETTINGDIALOG\n                    patch::fast_setting_dialog.switch_load(cr);\n\t\t\t    #endif\n                #ifdef PATCH_SWITCH_FAST_TEXT\n                    patch::fast::text.switch_load(cr);\n                #endif\n                #ifdef PATCH_SWITCH_FAST_CREATE_FIGURE\n                    patch::fast::create_figure.switch_load(cr);\n                #endif\n                #ifdef PATCH_SWITCH_FAST_BORDER\n                    patch::fast::Border.switch_load(cr);\n                #endif\n                #ifdef PATCH_SWITCH_FAST_GLOW\n                    patch::fast::Glow.switch_load(cr);\n                #endif\n\t\t\n                #ifdef PATCH_SWITCH_CL\n                    patch::fast::cl.switch_load(cr);\n                    \n\t\t\t\t    #ifdef PATCH_SWITCH_FAST_RADIATIONALBLUR\n\t\t\t\t\t    patch::fast::RadiationalBlur.switch_load(cr);\n\t\t\t\t    #endif\n\t\t\t\t    #ifdef PATCH_SWITCH_FAST_POLORTRANSFORM\n                        patch::fast::PolorTransform.switch_load(cr);\n\t\t\t\t    #endif\n\t\t\t\t    #ifdef PATCH_SWITCH_FAST_DISPLACEMENTMAP\n                        patch::fast::DisplacementMap.switch_load(cr);\n\t\t\t\t    #endif\n                    #ifdef PATCH_SWITCH_FAST_FLASH\n                        patch::fast::Flash.switch_load(cr);\n                    #endif\n                    #ifdef PATCH_SWITCH_FAST_DIRECTIONALBLUR\n                        patch::fast::DirectionalBlur.switch_load(cr);\n                    #endif\n\t\t\t\t    #ifdef PATCH_SWITCH_FAST_LENSBLUR\n\t\t\t\t\t    patch::fast::LensBlur.switch_load(cr);\n\t\t\t\t    #endif\n                #endif\n\t\t    #endif\n\n            cr.load();\n        });\n\n#ifdef PATCH_SWITCH_CONSOLE\n        cr.regist(\"console\", [](json_value_s* value) {\n            ConfigReader cr(value);\n            patch::console.config_load(cr);\n            cr.load();\n        });\n#endif\n#ifdef PATCH_SWITCH_THEME_CC\n        cr.regist(\"theme_cc\", [](json_value_s* value) {\n            ConfigReader cr(value);\n            patch::theme_cc.config_load(cr);\n            cr.load();\n        });\n#endif\n#ifdef PATCH_SWITCH_UNDO_REDO\n        cr.regist(\"redo\", [](json_value_s* value) {\n            ConfigReader cr(value);\n            patch::redo.config_load(cr);\n            cr.load();\n        });\n#endif\n#ifdef PATCH_SWITCH_FAST_EXEDITWINDOW\n        cr.regist(\"fast_exeditwindow\", [](json_value_s* value) {\n            ConfigReader cr(value);\n            patch::fast_exeditwindow.config_load(cr);\n            cr.load();\n        });\n#endif\n#ifdef PATCH_SWITCH_FAST_TEXT\n        cr.regist(\"fast_text\", [](json_value_s* value) {\n            ConfigReader cr(value);\n            patch::fast::text.config_load(cr);\n            cr.load();\n        });\n#endif\n\n        cr.load();\n    }\n\n    void store(std::wstring_view path) {\n        if (invalid_json)return;\n\n        auto hFile = CreateFileW(path.data(), GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);\n        if (hFile == INVALID_HANDLE_VALUE) {\n            patch_resource_message_w(PATCH_RS_PATCH_FAILED_TO_SAVE_SETTING, MB_TASKMODAL | MB_ICONEXCLAMATION);\n            return;\n        }\n        BOOST_SCOPE_EXIT_ALL(&hFile) {\n            CloseHandle(hFile);\n        };\n\n        int level = 0;\n        ConfigWriter cw(level);\n\n#ifdef PATCH_SWITCH_CONSOLE\n        {\n            ConfigWriter console(++level);\n\n            patch::console.config_store(console);\n\n            std::stringstream ss;\n            console.write(ss);\n\n            cw.append(\"console\", ss.str());\n            --level;\n        }\n#endif\n\n#ifdef PATCH_SWITCH_THEME_CC\n        {\n            ConfigWriter theme_cc(++level);\n\n            patch::theme_cc.config_store(theme_cc);\n\n            std::stringstream ss;\n            theme_cc.write(ss);\n\n            cw.append(\"theme_cc\", ss.str());\n            --level;\n        }\n#endif\n\n#ifdef PATCH_SWITCH_UNDO_REDO\n        {\n            ConfigWriter redo(++level);\n\n            patch::redo.config_store(redo);\n\n            std::stringstream ss;\n            redo.write(ss);\n\n            cw.append(\"redo\", ss.str());\n            --level;\n        }\n#endif\n\n#ifdef PATCH_SWITCH_FAST_EXEDITWINDOW\n        {\n            ConfigWriter fast_exeditwindow(++level);\n            \n            patch::fast_exeditwindow.config_store(fast_exeditwindow);\n\n            std::stringstream ss;\n            fast_exeditwindow.write(ss);\n\n            cw.append(\"fast_exeditwindow\", ss.str());\n            --level;\n        }\n#endif\n\n#ifdef PATCH_SWITCH_FAST_TEXT\n        {\n            ConfigWriter fast_text(++level);\n\n            patch::fast::text.config_store(fast_text);\n\n            std::stringstream ss;\n            fast_text.write(ss);\n\n            cw.append(\"fast_text\", ss.str());\n            --level;\n        }\n#endif\n\n        {\n            ConfigWriter switch_(++level);\n            \n\t\t    #ifdef PATCH_SWITCH_ACCESS_KEY\n                patch::access_key.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_COLORPALETTE_CACHE\n                patch::colorpalette_cache.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_FILEINFO\n                patch::fileinfo.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_SUSIE_LOAD\n                patch::susie_load.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_SPLASH\n                patch::splash.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_AUP_SCENE_SETTING\n                patch::aup_scene_setting.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_AUP_LAYER_SETTING\n                patch::aup_layer_setting.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_EXO_AVIUTL_FILTER\n                patch::exo_aviutlfilter.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_EXO_SCENEIDX\n                patch::exo_sceneidx.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_EXO_TRACKPARAM\n                patch::exo_trackparam.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_EXO_TRACK_MINUSVAL\n                patch::exo_trackminusval.switch_store(switch_);\n\t\t    #endif\n            #ifdef PATCH_SWITCH_EXO_MIDPT_AND_TRA\n                patch::exo_midpt_and_tra.switch_store(switch_);\n            #endif\n\t\t    #ifdef PATCH_SWITCH_EXO_SPECIALCOLORCONV\n                patch::exo_specialcolorconv.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_EXO_FOLD_GUI\n                patch::exo_fold_gui.switch_store(switch_);\n\t\t    #endif\n            #ifdef PATCH_SWITCH_TRA_AVIUTL_FILTER\n                patch::tra_aviutlfilter.switch_store(switch_);\n            #endif\n            #ifdef PATCH_SWITCH_TRA_CHANGE_DRAWFILTER\n                patch::tra_change_drawfilter.switch_store(switch_);\n            #endif\n            #ifdef PATCH_SWITCH_TRA_SPECIFIED_SPEED\n                patch::tra_specified_speed.switch_store(switch_);\n            #endif\n            #ifdef PATCH_SWITCH_SETTING_NEW_PROJECT\n                patch::setting_new_project.switch_store(switch_);\n            #endif\n\t\t    #ifdef PATCH_SWITCH_TEXT_OP_SIZE\n                patch::text_op_size.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_IGNORE_MEDIA_PARAM_RESET\n                patch::ignore_media_param_reset.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_FONT_DIALOG\n                patch::font_dialog.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_SCROLL_OBJDLG\n                patch::scroll_objdlg.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_ALPHA_BG\n                patch::alpha_bg.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_HELPFUL_MSGBOX\n                patch::helpful_msgbox.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_FAILED_SJIS_MSGBOX\n                patch::failed_sjis_msgbox.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_FAILED_LONGER_PATH\n\t\tpatch::failed_longer_path.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_FAILED_FILE_DROP\n\t\tpatch::failed_file_drop.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_THEME_CC\n                patch::theme_cc.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_EXEDITWINDOW_SIZING\n                patch::exeditwindow_sizing.switch_store(switch_);\n\t\t    #endif\n\t\t    #ifdef PATCH_SWITCH_SETTINGDIALOG_MOVE\n                patch::setting_dialog_move.switch_store(switch_);\n\t\t    #endif\n            #ifdef PATCH_SWITCH_OBJ_COLORCORRECTION\n                patch::ColorCorrection.switch_store(switch_);\n            #endif\n            #ifdef PATCH_SWITCH_OBJ_GLOW\n                patch::Glow.switch_store(switch_);\n            #endif\n            #ifdef PATCH_SWITCH_OBJ_LENSBLUR\n                patch::LensBlur.switch_store(switch_);\n            #endif\n            #ifdef PATCH_SWITCH_OBJ_NOISE\n                patch::Noise.switch_store(switch_);\n            #endif\n            #ifdef PATCH_SWITCH_OBJ_SPECIALCOLORCONV\n                patch::obj_specialcolorconv.switch_store(switch_);\n            #endif\n\t\t    #ifdef PATCH_SWITCH_SETTINGDIALOG_EXCOLORCONFIG\n                patch::excolorconfig.switch_store(switch_);\n\t\t    #endif\n            #ifdef PATCH_SWITCH_RCLICKMENU_SPLIT\n                patch::rclickmenu_split.switch_store(switch_);\n            #endif\n            #ifdef PATCH_SWITCH_RCLICKMENU_DELETE\n                patch::rclickmenu_delete.switch_store(switch_);\n            #endif\n            #ifdef PATCH_SWITCH_BLEND\n                patch::blend.switch_store(switch_);\n            #endif\n            #ifdef PATCH_SWITCH_ADD_EXTENSION\n                patch::add_extension.switch_store(switch_);\n            #endif\n            #ifdef PATCH_SWITCH_DIALOG_NEW_FILE\n                patch::dialog_new_file .switch_store(switch_);\n            #endif\n            #ifdef PATCH_SWITCH_PLAYBACK_SPEED\n                patch::playback_speed.switch_store(switch_);\n            #endif\n\n\t\t    #ifdef PATCH_SWITCH_UNDO\n                patch::undo.switch_store(switch_);\n                #ifdef PATCH_SWITCH_UNDO_REDO\n                    patch::redo.switch_store(switch_);\n                #endif\n\t\t    #endif\n\n\t\t    #ifdef PATCH_SWITCH_CONSOLE\n                patch::console.switch_store(switch_);\n\t\t    #endif\n\t\t\t\t\n\t\t    #ifdef PATCH_SWITCH_LUA\n                patch::lua.switch_store(switch_);\n                #ifdef PATCH_SWITCH_LUA_GETVALUE\n                    patch::lua_getvalueex.switch_store(switch_);\n                #endif\n\n                #ifdef PATCH_SWITCH_LUA_RAND\n                    patch::lua_rand.switch_store(switch_);\n                #endif\n\n                #ifdef PATCH_SWITCH_LUA_RANDEX\n                    patch::lua_randex.switch_store(switch_);\n                #endif\n\t\t    #endif\n\n\t\t    #ifdef PATCH_SWITCH_FAST\n                patch::fast::fast.switch_store(switch_);\n\t\t\t    \n\t\t\t    #ifdef PATCH_SWITCH_FAST_EXEDITWINDOW\n                    patch::fast_exeditwindow.switch_store(switch_);\n\t\t\t    #endif\n\t\t\t    #ifdef PATCH_SWITCH_FAST_SETTINGDIALOG\n                    patch::fast_setting_dialog.switch_store(switch_);\n\t\t\t    #endif\n                #ifdef PATCH_SWITCH_FAST_TEXT\n                    patch::fast::text.switch_store(switch_);\n                #endif\n                #ifdef PATCH_SWITCH_FAST_CREATE_FIGURE\n                    patch::fast::create_figure.switch_store(switch_);\n                #endif\n                #ifdef PATCH_SWITCH_FAST_BORDER\n                    patch::fast::Border.switch_store(switch_);\n                #endif\n                #ifdef PATCH_SWITCH_FAST_GLOW\n                    patch::fast::Glow.switch_store(switch_);\n                #endif\n\t\t\n                #ifdef PATCH_SWITCH_CL\n                    patch::fast::cl.switch_store(switch_);\n                    \n\t\t\t\t    #ifdef PATCH_SWITCH_FAST_RADIATIONALBLUR\n\t\t\t\t\t    patch::fast::RadiationalBlur.switch_store(switch_);\n\t\t\t\t    #endif\n\t\t\t\t    #ifdef PATCH_SWITCH_FAST_POLORTRANSFORM\n                        patch::fast::PolorTransform.switch_store(switch_);\n\t\t\t\t    #endif\n\t\t\t\t    #ifdef PATCH_SWITCH_FAST_DISPLACEMENTMAP\n                        patch::fast::DisplacementMap.switch_store(switch_);\n\t\t\t\t    #endif\n                    #ifdef PATCH_SWITCH_FAST_FLASH\n                        patch::fast::Flash.switch_store(switch_);\n                    #endif\n                    #ifdef PATCH_SWITCH_FAST_DIRECTIONALBLUR\n                        patch::fast::DirectionalBlur.switch_store(switch_);\n                    #endif\n\t\t\t\t    #ifdef PATCH_SWITCH_FAST_LENSBLUR\n\t\t\t\t\t    patch::fast::LensBlur.switch_store(switch_);\n\t\t\t\t    #endif\n                #endif\n\t\t    #endif\n\n            std::stringstream ss;\n            switch_.write(ss);\n\n            cw.append(\"switch\", ss.str());\n            --level;\n        }\n        std::stringstream ss;\n        cw.write(ss);\n        auto s = ss.str();\n\n        DWORD ignore;\n        WriteFile(hFile, s.c_str(), s.size(), &ignore, nullptr);\n    }\n};\ninline Config2 config2;\n"
  },
  {
    "path": "patch/config_rw.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tThis program is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n\n#include <string>\n#include <string_view>\n#include <sstream>\n#include <vector>\n#include <utility>\n#include <array>\n#include <unordered_map>\n#include <functional>\n#include <optional>\n#include <charconv>\n\n#include \"json.h\"\n\n#include \"util_others.hpp\"\n\nnamespace config_type {\n\n\tstruct ColorBGR {\n\t\tunion {\n\t\t\tstruct {\n\t\t\t\tuint8_t b, g, r;\n\t\t\t\tuint8_t valid;\n\t\t\t};\n\t\t\tuint32_t val;\n\t\t};\n\t\tColorBGR() : val{} {}\n\n\t\tColorBGR(uint32_t x) : val(x) {\n\t\t\tval = x;\n\t\t\tvalid = 1;\n\t\t}\n\t\tColorBGR(int b, int g, int r) :b(b), g(g), r(r), valid(1) {}\n\t\tColorBGR(std::string_view x) {\n\t\t\tif (x.size() < 6) {\n\t\t\t\tb = g = r = valid = 0;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tauto itr = x.data();\n\t\t\tstd::from_chars(itr, itr + 2, r, 16);\n\t\t\titr += 2;\n\t\t\tstd::from_chars(itr, itr + 2, g, 16);\n\t\t\titr += 2;\n\t\t\tstd::from_chars(itr, itr + 2, b, 16);\n\t\t\tvalid = 1;\n\t\t}\n\t\tinline static ColorBGR from_rgb(uint32_t x) {\n\t\t\tif (std::is_constant_evaluated()) {\n\t\t\t\treturn (x >> 16 & 0xff) || (x & 0xff00) || (x << 16 & 0xff0000);\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn _byteswap_ulong(x << 8);\n\t\t\t}\n\t\t}\n\n\t\tconstexpr uint32_t to_col() const noexcept {\n\t\t\treturn val & 0xffffff;\n\t\t}\n\t\tconstexpr uint32_t to_col_rgb() const noexcept {\n\t\t\tif (std::is_constant_evaluated()) {\n\t\t\t\treturn b << 16 | g << 8 | r;\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn _byteswap_ulong(val) >> 8;\n\t\t\t}\n\t\t}\n\t\tstd::string to_string() const {\n\t\t\treturn \"{:02x}{:02x}{:02x}\"_fmt(r, g, b);\n\t\t}\n\t\tstd::string to_jsonstring() const {\n\t\t\tif(valid) return \"\\\"{:02x}{:02x}{:02x}\\\"\"_fmt(r, g, b);\n\t\t\treturn std::string{};\n\t\t}\n\t\tconstexpr bool is_valid() const noexcept {\n\t\t\treturn valid;\n\t\t}\n\t\tbool operator==(ColorBGR x) const {\n\t\t\tif (this->valid) {\n\t\t\t\tif (!x.valid)return false;\n\t\t\t\telse return (this->val & 0xffffff) == (x.val & 0xffffff);\n\t\t\t}\n\t\t\telse return !x.valid;\n\t\t}\n\t};\n\n\t// ColorBGR2つの配列、またはColorBGR1つ、またはnulloptを表す\n\t// [ \"ffffff\", \"ffffff\" ] や [\"ffffff\"]、\"ffffff\" など\n\tstruct ColorBGR2_Opt {\n\t\tstd::array<ColorBGR, 2> ary{};\n\t\tColorBGR2_Opt() : ary{} {}\n\t\tColorBGR2_Opt(ColorBGR c1, ColorBGR c2) : ary{ c1,c2 } {}\n\n\t\tinline void load(json_value_s* value) {\n\t\t\tif (auto js = json_value_as_string(value)) {\n\t\t\t\tary[0] = std::string_view(js->string, js->string_size);\n\t\t\t\tary[1].valid = 0;\n\t\t\t}\n\t\t\telse if (auto ja = json_value_as_array(value)) {\n\t\t\t\tif (ja->length == 0) {\n\t\t\t\t\tary[0].valid = 0;\n\t\t\t\t}\n\t\t\t\telse if (ja->length == 1) {\n\t\t\t\t\tif (auto js = json_value_as_string(ja->start->value)) {\n\t\t\t\t\t\tary[0] = std::string_view(js->string, js->string_size);\n\t\t\t\t\t\tary[1].valid = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tauto v = ja->start;\n\t\t\t\t\tbool valid = true;\n\t\t\t\t\tfor (size_t i = 0; i < 2; i++) {\n\t\t\t\t\t\tif (auto js = json_value_as_string(v->value)) {\n\t\t\t\t\t\t\tary[i] = std::string_view(js->string, js->string_size);\n\t\t\t\t\t\t\tif (!ary[i].is_valid()) {\n\t\t\t\t\t\t\t\tvalid = false;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tv = v->next;\n\t\t\t\t\t}\n\t\t\t\t\tif (!valid) ary[0].valid = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tstd::string to_jsonstring() const {\n\t\t\tif (ary[0].is_valid()) {\n\t\t\t\tif (ary[1].is_valid())\n\t\t\t\t\treturn \"[ {}, {} ]\"_fmt(ary[0].to_jsonstring(), ary[1].to_jsonstring());\n\t\t\t\telse\n\t\t\t\t\treturn ary[0].to_jsonstring();\n\t\t\t}\n\t\t\treturn std::string{};\n\t\t}\n\n\t\tconstexpr bool has_value() const {\n\t\t\treturn ary[0].is_valid();\n\t\t}\n\n\t\tconstexpr int count() const {\n\t\t\tif (!ary[0].is_valid()) return 0;\n\t\t\treturn 1 + ary[1].is_valid();\n\t\t}\n\t};\n\n\t// ColorBGRを2つ持つかnullopt\n\tstruct ColorBGR2 {\n\t\tstd::array<ColorBGR, 2> ary;\n\t\tColorBGR2() : ary{} {}\n\t\tColorBGR2(ColorBGR c1, ColorBGR c2) : ary{ c1,c2 } {}\n\n\t\tinline void load(json_value_s* value) {\n\t\t\tif (auto ja = json_value_as_array(value)) {\n\t\t\t\tif (ja->length > 1) {\n\t\t\t\t\tauto v = ja->start;\n\t\t\t\t\tbool valid = true;\n\t\t\t\t\tfor (size_t i = 0; i < 2; i++) {\n\t\t\t\t\t\tif (auto js = json_value_as_string(v->value)) {\n\t\t\t\t\t\t\tary[i] = std::string_view(js->string, js->string_size);\n\t\t\t\t\t\t\tif (!ary[i].is_valid()) {\n\t\t\t\t\t\t\t\tvalid = false;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tv = v->next;\n\t\t\t\t\t}\n\t\t\t\t\tif (!valid) ary[0].valid = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tstd::string to_jsonstring() const {\n\t\t\tif (ary[0].is_valid())\n\t\t\t\treturn \"[ {}, {} ]\"_fmt(ary[0].to_jsonstring(), ary[1].to_jsonstring());\n\t\t\treturn std::string{};\n\t\t}\n\n\t\tconstexpr bool has_value() const {\n\t\t\treturn ary[0].is_valid();\n\t\t}\n\n\t\tconstexpr int count() const {\n\t\t\tif (!ary[0].is_valid()) return 0;\n\t\t\treturn 1 + ary[1].is_valid();\n\t\t}\n\t};\n\n\tstruct ColorBGR3 {\n\t\tstd::array<ColorBGR, 3> ary;\n\t\tColorBGR3() : ary{} {}\n\t\tColorBGR3(ColorBGR c1, ColorBGR c2, ColorBGR c3) : ary{ c1,c2,c3 } {}\n\n\t\tinline void load(json_value_s* value) {\n\t\t\tif (auto ja = json_value_as_array(value)) {\n\t\t\t\tif (ja->length > 2) {\n\t\t\t\t\tauto v = ja->start;\n\t\t\t\t\tbool valid = true;\n\t\t\t\t\tfor (size_t i = 0; i < 3; i++) {\n\t\t\t\t\t\tif (auto js = json_value_as_string(v->value)) {\n\t\t\t\t\t\t\tary[i] = std::string_view(js->string, js->string_size);\n\t\t\t\t\t\t\tif (!ary[i].is_valid()) {\n\t\t\t\t\t\t\t\tvalid = false;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tv = v->next;\n\t\t\t\t\t}\n\t\t\t\t\tif (!valid) ary[0].valid = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tconstexpr bool has_value() const {\n\t\t\treturn ary[0].is_valid();\n\t\t}\n\t\tstd::string to_jsonstring() const {\n\t\t\tif (has_value())\n\t\t\t\treturn \"[ {}, {}, {} ]\"_fmt(ary[0].to_jsonstring(), ary[1].to_jsonstring(), ary[2].to_jsonstring());\n\t\t\treturn std::string{};\n\t\t}\n\t};\n\n}\n\ntemplate<class T>\nconcept ConfigWriterHasToJsonString = requires (T x) {\n\tx.to_jsonstring();\n};\n\ninline std::string mytostring(int x) {\n\tstd::string ret(std::numeric_limits<int>::digits10 + 2, '\\0');\n\tstd::to_chars(ret.data(), ret.data() + ret.size(), x);\n\tret.resize(ret.find_first_of('\\0'));\n\treturn ret;\n}\n\ninline std::string mytostring(double x) {\n\tstd::string ret(std::numeric_limits<double>::max_exponent10 + 9, '\\0');\n\tstd::to_chars(ret.data(), ret.data() + ret.size(), x);\n\tret.resize(ret.find_first_of('\\0'));\n\treturn ret;\n}\n\ntemplate<class T>\nconcept ConfigWriterCanToChars = requires(T x) {\n\tmytostring(x);\n};\n\ntemplate<class T>\nconcept ConfigReaderHasLoad = requires(T x) {\n\tx.load(std::declval<json_value_s*>());\n};\n\nclass ConfigWriter {\n\tstd::stringstream ss;\n\n\tstruct KeyAndValue {\n\t\tstd::string key, value;\n\t};\n\n\tstd::vector<KeyAndValue> vkv;\n\n\tint level;\n\n\tinline static void WriteLevel(std::stringstream& ss, int level) {\n\t\tfor (int i = 0; i < level; i++) ss << '\\t';\n\t}\n\t// {\\n を書く\n\tinline static void WriteBlockBegin(std::stringstream& ss) {\n\t\tss << \"{\\n\";\n\t}\n\t// } を書く\n\tinline static void WriteBlockEnd(std::stringstream& ss) {\n\t\tss << \"}\";\n\t}\n\t// [[\"key\" : ]] を書く\n\tinline static void WriteKey(std::stringstream& ss, std::string_view key) {\n\t\tss << \"\\\"\" << key << \"\\\" : \";\n\t}\n\ttemplate <bool comma = false>\n\tinline static void WriteReturn(std::stringstream& ss) {\n\t\tif constexpr (comma) ss << \",\\n\";\n\t\telse ss << \"\\n\";\n\t}\n\npublic:\n\tConfigWriter(int level) : level(level) {}\n\n\tvoid append(std::string_view key, std::string_view value) {\n\t\tif(value.size() && value[0] != '\\0') vkv.emplace_back(std::string(key), std::string(value));\n\t}\n\n\ttemplate<ConfigWriterHasToJsonString T>\n\tvoid append(std::string_view key, const T& value) {\n\t\tauto result = value.to_jsonstring();\n\t\tif(result[0] != '\\0') vkv.emplace_back(std::string(key), result);\n\t}\n\n\tvoid append(std::string_view key, bool value) {\n\t\tvkv.emplace_back(std::string(key), value ? \"true\" : \"false\");\n\t}\n\n\tvoid append(std::string_view key, const RECT& value) {\n\t\tvkv.emplace_back(std::string(key), \"[ {}, {}, {}, {} ]\"_fmt(value.left, value.top, value.right, value.bottom));\n\t}\n\n\ttemplate<size_t N>\n\tvoid append(std::string_view key, const std::array<int, N>& value) {\n\t\tif (value.size() > 0) {\n\t\t\tstd::stringstream ss;\n\t\t\tss << \"[ \";\n\t\t\tconst auto last = value.size() - 1;\n\t\t\tfor (size_t i = 0; i < last; i++) {\n\t\t\t\tss << value[i] << \", \";\n\t\t\t}\n\t\t\tss << value[last] << \" ]\";\n\t\t\tvkv.emplace_back(std::string(key), ss.str());\n\t\t}\n\t\telse {\n\t\t\tvkv.emplace_back(std::string(key), \"[]\");\n\t\t}\n\t}\n\n\ttemplate<ConfigWriterCanToChars T>\n\tvoid append(std::string_view key, const T& value) {\n\t\tvkv.emplace_back(std::string(key), mytostring(value));\n\t}\n\n\ttemplate<class T>\n\tvoid append(std::string_view key, const std::optional<T>& value) {\n\t\tif (value) {\n\t\t\tappend(key, *value);\n\t\t}\n\t}\n\n\tvoid write(std::stringstream& ss) const {\n\t\tauto s = vkv.size();\n\t\tif (s == 0)return;\n\n\t\tWriteBlockBegin(ss);\n\n\t\tfor (size_t i = 0; i < s - 1; i++) {\n\t\t\tWriteLevel(ss, level + 1);\n\t\t\tWriteKey(ss, vkv[i].key);\n\t\t\tss << vkv[i].value;\n\t\t\tWriteReturn<true>(ss);\n\t\t}\n\t\tWriteLevel(ss, level + 1);\n\t\tWriteKey(ss, vkv[s - 1].key);\n\t\tss << vkv[s - 1].value;\n\t\tWriteReturn<false>(ss);\n\n\t\tWriteLevel(ss, level);\n\t\tWriteBlockEnd(ss);\n\t}\n\n\tint get_level() const { return level; }\n};\n\nclass ConfigReader {\n\tjson_value_s* value;\n\n\tusing RegisterFunction = std::function<void(json_value_s*)>;\n\tusing MapType = std::unordered_map<std::string, RegisterFunction>;\n\n\tMapType map;\n\n\npublic:\n\tConfigReader(json_value_s* value) : value(value) {}\n\n\tvoid load() {\n\t\tauto obj = json_value_as_object(value);\n\t\tif (obj == nullptr)return;\n\n\t\tfor (auto elm = obj->start; elm != nullptr; elm = elm->next) {\n\t\t\tif (auto itr = map.find(elm->name->string); itr != map.end()) {\n\t\t\t\titr->second(elm->value);\n\t\t\t}\n\t\t}\n\t}\n\n\ttemplate<class T>\n\tvoid regist(const std::string& str, T func) {\n\t\tmap.try_emplace(str, func);\n\t}\n\n\n\tinline static bool load_variable(json_value_s* jv, bool& value) {\n\t\tif (json_value_is_false(jv)) {\n\t\t\tvalue = false;\n\t\t\treturn true;\n\t\t}\n\t\telse if (json_value_is_true(jv)) {\n\t\t\tvalue = true;\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\ttemplate<std::integral Int>\n\tinline static bool load_variable(json_value_s* jv, Int& value) {\n\t\tif (auto n = json_value_as_number(jv); n) {\n\t\t\tInt ret{};\n\t\t\tstd::from_chars(n->number, n->number + n->number_size, ret);\n\t\t\tvalue = ret;\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\ttemplate<std::floating_point Float>\n\tinline static bool load_variable(json_value_s* jv, Float& value) {\n\t\tif (auto n = json_value_as_number(jv); n) {\n\t\t\tFloat ret;\n\t\t\tstd::from_chars(n->number, n->number + n->number_size, ret);\n\t\t\tvalue = ret;\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\tinline static void load_variable(json_value_s* jv, config_type::ColorBGR& value) {\n\t\tif (auto s = json_value_as_string(jv); s) {\n\t\t\tvalue = config_type::ColorBGR(std::string_view(s->string, s->string_size));\n\t\t}\n\t\telse {\n\t\t\tvalue.valid = 0;\n\t\t}\n\t}\n\n\tinline static void load_variable(json_value_s* jv, std::optional<RECT>& value) {\n\t\tif (auto ja = json_value_as_array(jv); ja) {\n\t\t\tif (ja->length >= 4) {\n\t\t\t\tauto itr = ja->start;\n\t\t\t\tstd::array<LONG, 4> buf;\n\t\t\t\tfor (size_t i = 0; i < 4; i++, itr = itr->next) {\n\t\t\t\t\tif (auto jn = json_value_as_number(itr->value); jn) {\n\t\t\t\t\t\tstd::from_chars(jn->number, jn->number + jn->number_size, buf[i]);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tvalue = std::nullopt;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tvalue.emplace(RECT{\n\t\t\t\t\t.left = buf[0],\n\t\t\t\t\t.top = buf[1],\n\t\t\t\t\t.right = buf[2],\n\t\t\t\t\t.bottom = buf[3]\n\t\t\t\t});\n\t\t\t}\n\t\t\telse {\n\t\t\t\tvalue = std::nullopt;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tvalue = std::nullopt;\n\t\t}\n\t}\n\n\ttemplate<size_t N>\n\tinline static void load_variable(json_value_s* jv, std::optional<std::array<int, N>>& value) {\n\t\tif (auto ja = json_value_as_array(jv); ja) {\n\t\t\tif (ja->length >= N) {\n\t\t\t\tauto itr = ja->start;\n\t\t\t\tstd::array<int, N> buf;\n\t\t\t\tfor (size_t i = 0; i < N; i++, itr = itr->next) {\n\t\t\t\t\tif (auto jn = json_value_as_number(itr->value); jn) {\n\t\t\t\t\t\tstd::from_chars(jn->number, jn->number + jn->number_size, buf[i]);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tvalue = std::nullopt;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tvalue = buf;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tvalue = std::nullopt;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tint buf;\n\t\t\tif (auto jn = json_value_as_number(jv); jn) {\n\t\t\t\tstd::from_chars(jn->number, jn->number + jn->number_size, buf);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tvalue = std::nullopt;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvalue.emplace();\n\t\t\tauto& v = value.value();\n\t\t\tfor (size_t i = 0; i < N; i++) {\n\t\t\t\tv[i] = buf;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t}\n\n\ttemplate<ConfigReaderHasLoad T>\n\tinline static void load_variable(json_value_s* jv, T& value) {\n\t\tvalue.load(jv);\n\t}\n\n\ttemplate<class T>\n\tinline static void load_variable(json_value_s* jv, std::optional<T>& value) {\n\t\tT t;\n\t\tif (load_variable(jv, t)) {\n\t\t\tvalue.emplace(std::move(t));\n\t\t}\n\t\telse {\n\t\t\tvalue = std::nullopt;\n\t\t}\n\t}\n\n};\n\n"
  },
  {
    "path": "patch/cryptostring.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include <cstdint>\n#include <bit>\n#include <vector>\n#include <array>\n#include <concepts>\n\n/// <summary>\n/// バイナリに生の文字列を残さないためのクラス\n/// </summary>\ntemplate <class CharT, size_t N>\nclass cryptostring {\n\ttemplate<class CharT> struct KeyV {};\n\ttemplate<> struct KeyV<char> { inline static constexpr char value = 0b00101101i8; };\n\ttemplate<> struct KeyV<wchar_t> { inline static constexpr wchar_t value = 0b1001010110001100i16; };\n\n\ttemplate<std::integral T>\n\t[[nodiscard]] constexpr static T bit_rotate_l(const T x, size_t a) {\n\t\tauto ux = std::bit_cast<std::make_unsigned_t<T>>(x);\n\t\treturn std::bit_cast<T>(std::rotl(ux, a));\n\t}\n\n\ttemplate<std::integral T>\n\t[[nodiscard]] constexpr static T bit_rotate_r(const T x, size_t a) {\n\t\tauto ux = std::bit_cast<std::make_unsigned_t<T>>(x);\n\t\treturn std::bit_cast<T>(std::rotr(ux, a));\n\t}\n\n\tstd::array<CharT, N> ary;\n\tbool decrypted = false;\npublic:\n\tconstexpr cryptostring(const CharT(&str)[N]) {\n\t\tfor (size_t i = 0; i < N; i++) ary[i] = str[i] ^ bit_rotate_l(KeyV<CharT>::value, (i * 3) % (CHAR_BIT * sizeof(CharT)));\n\t}\n\n\t[[nodiscard]] CharT* get() {\n\t\tif (!decrypted) [[unlikely]] {\n\t\t\tfor (size_t i = 0; i < N; i++) ary[i] ^= bit_rotate_l(KeyV<CharT>::value, (i * 3) % (CHAR_BIT * sizeof(CharT)));\n\t\t\tdecrypted = true;\n\t\t}\n\t\treturn ary.data();\n\t}\n\n\tvoid re_encrypt() {\n\t\tif (decrypted) [[likely]] {\n\t\t\tfor (size_t i = 0; i < N; i++) ary[i] ^= bit_rotate_l(KeyV<CharT>::value, (i * 3) % (CHAR_BIT * sizeof(CharT)));\n\t\t\tdecrypted = false;\n\t\t}\n\t}\n};\n\ntemplate <class CharT, size_t N>\ninline constexpr cryptostring<CharT, N> make_cryptostring(const CharT(&str)[N]) {\n\treturn cryptostring<CharT, N>(str);\n}\n\ninline cryptostring cstr_kernel32_dll(\"KERNEL32.DLL\");\ninline cryptostring cstr_user32_dll(\"USER32.DLL\");\ninline cryptostring cstr_EnumResourceLanguagesA(\"EnumResourceLanguagesA\");\ninline cryptostring cstr_LoadLibraryA(\"LoadLibraryA\");\ninline cryptostring cstr_LoadLibraryW(\"LoadLibraryW\");\ninline cryptostring cstr_MessageBoxA(\"MessageBoxA\");\ninline cryptostring cstr_gdi32_dll(\"GDI32.DLL\");\ninline cryptostring cstr_GetGlyphOutlineW(\"GetGlyphOutlineW\");\ninline cryptostring cstr_DeleteObject(\"DeleteObject\");\ninline cryptostring cstr_CreateFontIndirectW(\"CreateFontIndirectW\");\ninline cryptostring cstr_GetModuleHandleA(\"GetModuleHandleA\");\ninline cryptostring cstr_GetModuleHandleW(\"GetModuleHandleW\");\ninline cryptostring cstr_Module32First(\"Module32First\");\ninline cryptostring cstr_Module32FirstW(\"Module32FirstW\");\ninline cryptostring cstr_Module32Next(\"Module32Next\");\ninline cryptostring cstr_Module32NextW(\"Module32NextW\");\n"
  },
  {
    "path": "patch/debug_log.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include <iostream>\n#include <mutex>\n\n#include \"util_others.hpp\"\n\ninline class debug_log_t {\nprivate:\n\tstd::mutex mtx;\n\npublic:\n\ttemplate<class T>\n\tvoid operator()(const T& v) {\n\t\tstd::lock_guard lock(mtx);\n\t\tstd::cout << v << std::endl;\n\t}\n\n\ttemplate<class... Args>\n\tvoid operator()(Args... args) {\n\t\tstd::lock_guard lock(mtx);\n\t\tformat_to_os(std::cout, args...);\n\t\tstd::endl(std::cout);\n\t}\n} debug_log;\n"
  },
  {
    "path": "patch/gate.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include <mutex>\n#include <condition_variable>\n\nclass Gate {\n    std::mutex mtx;\n    std::condition_variable cond;\n    bool flag;\n\npublic:\n    Gate() :mtx{}, cond{}, flag{} {}\n\n    Gate(bool opened) :mtx{}, cond{}, flag{opened} {}\n\n    void open() {\n        {\n            std::lock_guard lock(mtx);\n            flag = true;\n        }\n\n        cond.notify_one();\n    }\n\n    void wait() {\n        std::unique_lock lock(mtx);\n        cond.wait(lock, [this] { return flag; });\n        flag = false;\n    }\n};\n"
  },
  {
    "path": "patch/global.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include <cstdint>\n#include <bit>\n#include <string>\n#include <Windows.h>\n\n#include \"global_minimum.hpp\"\n\nnamespace GLOBAL {\n\tinline HMODULE exedit_hmod;\n\tinline uint32_t& exedit_base = (uint32_t&)exedit_hmod;\n\tinline std::byte executable_memory[USN_PAGE_SIZE * 16];\n\tinline std::byte* executable_memory_cursor = executable_memory;\n\tinline std::wstring patchaul_path;\n\tinline std::wstring patchaul_config_path;\n\tinline std::string patchaul_path_a;\n}\n"
  },
  {
    "path": "patch/global_minimum.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include <bit>\n#include <cstdint>\n#include <Windows.h>\n\nnamespace GLOBAL {\n\tinline HMODULE aviutl_hmod;\n\tinline uint32_t& aviutl_base = (uint32_t&)aviutl_hmod;\n\tinline HINSTANCE patchaul_hinst;\n\n\tinline void init_minimum(HINSTANCE patch_hmod) {\n\t\tGLOBAL::patchaul_hinst = patch_hmod;\n\t\tGLOBAL::aviutl_base = std::bit_cast<uint32_t>(GetModuleHandleA(NULL));\n\t}\n}\n"
  },
  {
    "path": "patch/hash.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include <optional>\n#include <bit>\n#include <concepts>\n#include <type_traits>\n\n#include <boost/scope_exit.hpp>\n\n#include <Windows.h>\n\nstruct SHA256 {\nprivate:\n\tinline constexpr static uint32_t K[] = {\n\t\t0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n\t\t0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n\t\t0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n\t\t0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n\t\t0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n\t\t0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n\t\t0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n\t\t0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\n\t};\n\n\tinline constexpr static uint32_t H0[] = { 0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19 };\n\n\tstatic uint32_t Sigma0(uint32_t x) {\n\t\treturn std::rotr(x, 2) ^ std::rotr(x, 13) ^ std::rotr(x, 22);\n\t}\n\n\tstatic uint32_t Sigma1(uint32_t x) {\n\t\treturn std::rotr(x, 6) ^ std::rotr(x, 11) ^ std::rotr(x, 25);\n\t}\n\n\tstatic uint32_t sigma0(uint32_t x) {\n\t\treturn std::rotr(x, 7) ^ std::rotr(x, 18) ^ (x >> 3);\n\t}\n\n\tstatic uint32_t sigma1(uint32_t x) {\n\t\treturn std::rotr(x, 17) ^ std::rotr(x, 19) ^ (x >> 10);\n\t}\n\n\tstatic uint32_t Ch(uint32_t x, uint32_t y, uint32_t z) {\n\t\treturn (x & y) ^ (~x & z);\n\t}\n\n\tstatic uint32_t Maj(uint32_t x, uint32_t y, uint32_t z) {\n\t\treturn (x & y) ^ (y & z) ^ (z & x);\n\t}\n\npublic:\n\n\tstd::byte data[32];\n\n\tSHA256(std::string_view filename) {\n#if _DEBUG && 1 // 重いので\n\t\tstd::fill(std::begin(data), std::end(data), std::byte{});\n#else\n\t\tstd::vector<uint8_t> buf;\n\t\t{\n\t\t\tauto hFile = CreateFileA(filename.data(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);\n\t\t\tif (hFile == INVALID_HANDLE_VALUE) throw std::runtime_error(\"Failed to open file.\");\n\t\t\tBOOST_SCOPE_EXIT_ALL(hFile) {\n\t\t\t\tCloseHandle(hFile);\n\t\t\t};\n\n\t\t\tDWORD sizehigh;\n\t\t\tauto sizelow = GetFileSize(hFile, &sizehigh);\n\n\t\t\tbuf.resize(sizelow);\n\t\t\tDWORD read;\n\t\t\tif (!ReadFile(hFile, buf.data(), sizelow, &read, nullptr)) throw std::runtime_error(\"Failed to read file.\");\n\t\t}\n\t\tuint32_t H[8];\n\t\tstd::memcpy(H, H0, sizeof(H0));\n\n\t\tauto process = [&](const byte* msg) {\n\t\t\tuint32_t W[64];\n\t\t\tfor (size_t t = 0; t < 16; t++) {\n\t\t\t\tW[t] = _byteswap_ulong(*reinterpret_cast<const unsigned long*>(msg + t * 4));\n\t\t\t}\n\t\t\tfor (size_t t = 16; t < 64; t++) {\n\t\t\t\tW[t] = sigma1(W[t - 2]) + W[t - 7] + sigma0(W[t - 15]) + W[t - 16];\n\t\t\t}\n\t\t\tauto a = H[0];\n\t\t\tauto b = H[1];\n\t\t\tauto c = H[2];\n\t\t\tauto d = H[3];\n\t\t\tauto e = H[4];\n\t\t\tauto f = H[5];\n\t\t\tauto g = H[6];\n\t\t\tauto h = H[7];\n\t\t\tfor (size_t t = 0; t < 64; t++) {\n\t\t\t\tauto T1 = h + Sigma1(e) + Ch(e, f, g) + K[t] + W[t];\n\t\t\t\tauto T2 = Sigma0(a) + Maj(a, b, c);\n\t\t\t\th = g;\n\t\t\t\tg = f;\n\t\t\t\tf = e;\n\t\t\t\te = d + T1;\n\t\t\t\td = c;\n\t\t\t\tc = b;\n\t\t\t\tb = a;\n\t\t\t\ta = T1 + T2;\n\t\t\t}\n\t\t\tH[0] += a;\n\t\t\tH[1] += b;\n\t\t\tH[2] += c;\n\t\t\tH[3] += d;\n\t\t\tH[4] += e;\n\t\t\tH[5] += f;\n\t\t\tH[6] += g;\n\t\t\tH[7] += h;\n\t\t};\n\n\t\tauto buf_size_d64 = buf.size() / 64;\n\t\tauto buf_size_m64 = buf.size() % 64;\n\t\tfor (size_t i = 0; i < buf_size_d64; i++) process(&buf[i * 64]);\n\n\t\tuint8_t last_msg[64];\n\t\tstd::memcpy(last_msg, buf.data() + buf_size_d64 * 64, buf_size_m64);\n\t\tlast_msg[buf_size_m64] = 0x80;\n\t\tif (buf_size_m64 < 56) {\n\t\t\tstd::memset(last_msg + buf_size_m64 + 1, 0, 58 - buf_size_m64);\n\t\t\tauto size = buf.size();\n\t\t\tlast_msg[59] = static_cast<uint8_t>(size >> 29);\n\t\t\tlast_msg[60] = static_cast<uint8_t>(size >> 21);\n\t\t\tlast_msg[61] = static_cast<uint8_t>(size >> 13);\n\t\t\tlast_msg[62] = static_cast<uint8_t>(size >>  5);\n\t\t\tlast_msg[63] = static_cast<uint8_t>(size <<  3);\n\t\t\tprocess(last_msg);\n\t\t}\n\t\telse {\n\t\t\tstd::memset(last_msg + buf_size_m64 + 1, 0, 63 - buf_size_m64);\n\t\t\tprocess(last_msg);\n\n\t\t\tstd::memset(last_msg, 0, 59);\n\t\t\tauto size = buf.size();\n\t\t\tlast_msg[59] = static_cast<uint8_t>(size >> 29);\n\t\t\tlast_msg[60] = static_cast<uint8_t>(size >> 21);\n\t\t\tlast_msg[61] = static_cast<uint8_t>(size >> 13);\n\t\t\tlast_msg[62] = static_cast<uint8_t>(size >>  5);\n\t\t\tlast_msg[63] = static_cast<uint8_t>(size <<  3);\n\t\t\tprocess(last_msg);\n\t\t}\n\t\tfor (size_t i = 0; i < 8; i++) {\n\t\t\t*reinterpret_cast<unsigned long*>(data + i * 4) = _byteswap_ulong(H[i]);\n\t\t}\n#endif\n\t}\n\n\ttemplate<std::integral... T> requires(sizeof...(T) == std::extent_v<decltype(data)>)\n\tconstexpr SHA256(T&&... list) noexcept : data{ static_cast<std::byte>(std::forward<T>(list))... } {}\n\n\tstatic std::optional<SHA256> make_opt(std::string_view filename) {\n\t\ttry {\n\t\t\treturn SHA256(filename);\n\t\t}\n\t\tcatch (const std::runtime_error&) {\n\t\t\treturn std::nullopt;\n\t\t}\n\t}\n\n\tstd::string tostring() const {\n\t\tstd::string ret;\n\t\tret.reserve(64);\n\n\t\tstatic const char chs[] = \"0123456789ABCDEF\";\n\n\t\tfor (auto b : data) {\n\t\t\tret.append(1, chs[(std::to_integer<uint32_t>(b) >> 4) & 0xf]);\n\t\t\tret.append(1, chs[std::to_integer<uint32_t>(b) & 0xf]);\n\t\t}\n\n\t\treturn ret;\n\t}\n};\n\ninline bool operator==(const SHA256& a, const SHA256& b) {\n\treturn std::equal(std::begin(a.data), std::end(a.data), std::begin(b.data));\n}\n"
  },
  {
    "path": "patch/init.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"init.hpp\"\n\n#include <set>\n#include <string>\n\n#include \"cryptostring.hpp\"\n#include \"util_others.hpp\"\n#include \"util_resource.hpp\"\n\n#include \"config.hpp\"\n\n\nvoid init_t::InitAtDllMain() {\n\tExchangeFunction(GLOBAL::aviutl_hmod, cstr_kernel32_dll.get(), cstr_EnumResourceLanguagesA.get(), EnumResourceLanguagesA_Wrap);\n}\n\nvoid init_t::InitAtPatchLoaded() {\n\t{\n\t\tstatic const char aviutl_version_str[] = {\n\t\t\t'1','.','1','0','\\0','\\0','\\0','\\0'\n\t\t};\n\t\tif (memcmp(reinterpret_cast<void*>(GLOBAL::aviutl_base + OFS::AviUtl::VersionString), aviutl_version_str, sizeof(aviutl_version_str)) != 0) {\n\t\t\tMessageBoxW(NULL, L\"patch.aul requires AviUtl *1.10*.\\nAviUtl version 1.10以外では動作しません．\", L\"patch.aul\", MB_ICONEXCLAMATION);\n\t\t\treturn;\n\t\t}\n\t}\n\tGLOBAL::patchaul_path = WinWrap::Module{ GLOBAL::patchaul_hinst }.getFileNameW();\n\tGLOBAL::patchaul_path_a = WinWrap::Module{ GLOBAL::patchaul_hinst }.getFileNameA();\n\n\tGLOBAL::patchaul_config_path = GLOBAL::patchaul_path + L\".json\";\n\n\t//GLOBAL::config.load(GLOBAL::patchaul_config_path);\n\tconfig2.load(GLOBAL::patchaul_config_path);\n\n\tadd_dll_ref.add_ref();\n\n\tModulesData::update();\n\n\t{\n\t\tDWORD oldProtect;\n\t\tVirtualProtect(GLOBAL::executable_memory, sizeof(GLOBAL::executable_memory), PAGE_EXECUTE_READWRITE, &oldProtect);\n\t}\n\t\n\tInjectFunction_fastcall(GLOBAL::aviutl_base + OFS::AviUtl::InitAuf, InitAufBefore, 10);\n\n\tExchangeFunction(GLOBAL::aviutl_hmod, cstr_kernel32_dll.get(), cstr_LoadLibraryA.get(), LoadLibraryAWrap);\n\n\toverwrite_resource();\n\n\n#ifdef PATCH_SWITCH_SPLASH\n\tif (PATCH_SWITCHER_MEMBER(PATCH_SWITCH_SPLASH)) {\n\t\tpatch::splash.init();\n\n\t\tpatch::splash.set_phase(L\"patch.aulの準備中\", L\"\");\n\t\tpatch::splash.start();\n\t}\n#endif\n\n#ifdef PATCH_SWITCH_CONSOLE\n\tpatch::console.init();\n#endif\n\n#ifdef PATCH_SWITCH_EXCEPTION_LOG\n\tpatch::exception_log();\n#endif\n\n#ifdef PATCH_SWITCH_SYSINFO_MODIFY\n\tpatch::sysinfo_info_write();\n#endif\n\n#ifdef PATCH_SWITCH_ACCESS_KEY\n\tpatch::access_key.init();\n#endif\n\n#ifdef PATCH_SWITCH_COLORPALETTE_CACHE\n\tpatch::colorpalette_cache.init();\n#endif\n\n#ifdef PATCH_SWITCH_FILEINFO\n\tpatch::fileinfo.init();\n#endif\n\n}\n\nvoid init_t::InitAtExeditLoad() {\n\tmywindow.init();\n\n#ifdef PATCH_SWITCH_THEME_CC\n\tpatch::theme_cc.init();\n#endif\n\n#ifdef PATCH_SWITCH_AUP_SCENE_SETTING\n\tpatch::aup_scene_setting.init();\n#endif\n#ifdef PATCH_SWITCH_TRA_AVIUTL_FILTER\n\tpatch::tra_aviutlfilter.init();\n#endif\n#ifdef PATCH_SWITCH_TRA_CHANGE_DRAWFILTER\n\tpatch::tra_change_drawfilter.init();\n#endif\n#ifdef PATCH_SWITCH_TRA_SPECIFIED_SPEED\n\tpatch::tra_specified_speed.init();\n#endif\n#ifdef PATCH_SWITCH_SETTING_NEW_PROJECT\n\tpatch::setting_new_project.init();\n#endif\n\n\n#ifdef PATCH_SWITCH_AUP_LAYER_SETTING\n\tpatch::aup_layer_setting.init();\n#endif\n#ifdef PATCH_SWITCH_EXO_AVIUTL_FILTER\n\tpatch::exo_aviutlfilter.init();\n#endif\n\n#ifdef PATCH_SWITCH_EXO_SCENEIDX\n\tpatch::exo_sceneidx.init();\n#endif\n\n#ifdef PATCH_SWITCH_EXO_TRACKPARAM\n\tpatch::exo_trackparam.init();\n#endif\n\n#ifdef PATCH_SWITCH_EXO_TRACK_MINUSVAL\n\tpatch::exo_trackminusval.init();\n#endif\n\n#ifdef PATCH_SWITCH_EXO_MIDPT_AND_TRA\n\tpatch::exo_midpt_and_tra.init();\n#endif\n\n#ifdef PATCH_SWITCH_EXO_SPECIALCOLORCONV\n\tpatch::exo_specialcolorconv.init();\n#endif\n\n#ifdef PATCH_SWITCH_EXO_FOLD_GUI\n\tpatch::exo_fold_gui.init();\n#endif\n\n#ifdef PATCH_SWITCH_CONSOLE\n\tpatch::console.init_at_exedit_init();\n#endif\n\n#ifdef PATCH_SWITCH_TEXT_OP_SIZE\n\tpatch::text_op_size.init();\n#endif\n\t\n#ifdef PATCH_SWITCH_IGNORE_MEDIA_PARAM_RESET\n\tpatch::ignore_media_param_reset.init();\n#endif\n\n#ifdef PATCH_SWITCH_SCROLL_OBJDLG\n\tpatch::scroll_objdlg.init();\n#endif\n\n#ifdef PATCH_SWITCH_SUSIE_LOAD\n\tpatch::susie_load.init();\n#endif\n\n#ifdef PATCH_SWITCH_HELPFUL_MSGBOX\n\tpatch::helpful_msgbox.init();\n#endif\n\n#ifdef PATCH_SWITCH_FAILED_SJIS_MSGBOX\n\tpatch::failed_sjis_msgbox.init();\n#endif\n#ifdef PATCH_SWITCH_FAILED_LONGER_PATH\n\tpatch::failed_longer_path.init();\n#endif\n#ifdef PATCH_SWITCH_FAILED_FILE_DROP\n\tpatch::failed_file_drop.init();\n#endif\n\n#ifdef PATCH_SWITCH_OBJ_COLORCORRECTION\n\tpatch::ColorCorrection.init();\n#endif\n#ifdef PATCH_SWITCH_OBJ_GLOW\n\tpatch::Glow.init();\n#endif\n#ifdef PATCH_SWITCH_OBJ_LENSBLUR\n\tpatch::LensBlur.init();\n#endif\n#ifdef PATCH_SWITCH_OBJ_NOISE\n\tpatch::Noise.init();\n#endif\n#ifdef PATCH_SWITCH_OBJ_SPECIALCOLORCONV\n\tpatch::obj_specialcolorconv.init();\n#endif\n\n#ifdef PATCH_SWITCH_SETTINGDIALOG_EXCOLORCONFIG\n\tpatch::excolorconfig.init();\n#endif\n\n#ifdef PATCH_SWITCH_RCLICKMENU_SPLIT\n\tpatch::rclickmenu_split.init();\n#endif\n#ifdef PATCH_SWITCH_RCLICKMENU_DELETE\n\tpatch::rclickmenu_delete.init();\n#endif\n#ifdef PATCH_SWITCH_BLEND\n\tpatch::blend.init();\n#endif\n#ifdef PATCH_SWITCH_ADD_EXTENSION\n\tpatch::add_extension.init();\n#endif\n#ifdef PATCH_SWITCH_DIALOG_NEW_FILE\n\tpatch::dialog_new_file.init();\n#endif\n#ifdef PATCH_SWITCH_PLAYBACK_SPEED\n\tpatch::playback_speed.init();\n#endif\n\t\n\tpatch::setting_dialog();\n\n\t#ifdef PATCH_SWITCH_FAST\n\tpatch::fast::fast.init();\n\tif (patch::fast::fast.is_enabled_i()) {\n\t\t#ifdef PATCH_SWITCH_FAST_GETPUTPIXELDATA\n\t\t\tpatch::fast::getputpixeldata();\n\t\t#endif\n\n\t\t#ifdef PATCH_SWITCH_FAST_SETTINGDIALOG\n\t\t\tpatch::fast_setting_dialog.init();\n\t\t#endif\n\n\t\t#ifdef PATCH_SWITCH_FAST_EXEDITWINDOW\n\t\t\tpatch::fast_exeditwindow.init();\n\t\t#endif\n\n\t\t#ifdef PATCH_SWITCH_FAST_TEXT\n\t\t\tpatch::fast::text.init();\n\t\t#endif\n\t\t#ifdef PATCH_SWITCH_FAST_CREATE_FIGURE\n\t\t\tpatch::fast::create_figure.init();\n\t\t#endif\n\t\t#ifdef PATCH_SWITCH_FAST_BORDER\n\t\t\tpatch::fast::Border.init();\n\t\t#endif\n\t\t#ifdef PATCH_SWITCH_FAST_GLOW\n\t\t\tpatch::fast::Glow.init();\n\t\t#endif\n\t\t\n\t\t#ifdef PATCH_SWITCH_CL\n\t\t\tif (patch::fast::cl.init()) {\n\t\t\t\tif (patch::fast::cl.is_enabled_i()) {\n\t\t\t\t\t#ifdef PATCH_SWITCH_FAST_POLORTRANSFORM\n\t\t\t\t\t\tpatch::fast::PolorTransform.init();\n\t\t\t\t\t#endif\n\t\t\t\t\t#ifdef PATCH_SWITCH_FAST_DISPLACEMENTMAP\n\t\t\t\t\t\tpatch::fast::DisplacementMap.init();\n\t\t\t\t\t#endif\n\t\t\t\t\t#ifdef PATCH_SWITCH_FAST_RADIATIONALBLUR\n\t\t\t\t\t\tpatch::fast::RadiationalBlur.init();\n\t\t\t\t\t#endif\n\t\t\t\t\t#ifdef PATCH_SWITCH_FAST_FLASH\n\t\t\t\t\t\tpatch::fast::Flash.init();\n\t\t\t\t\t#endif\n\t\t\t\t\t#ifdef PATCH_SWITCH_FAST_DIRECTIONALBLUR\n\t\t\t\t\t\tpatch::fast::DirectionalBlur.init();\n\t\t\t\t\t#endif\n\t\t\t\t\t#ifdef PATCH_SWITCH_FAST_LENSBLUR\n\t\t\t\t\t\tpatch::fast::LensBlur.init();\n\t\t\t\t\t#endif\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tpatch_resource_message_w(PATCH_RS_PATCH_CANT_USE_CL, MB_TASKMODAL | MB_ICONEXCLAMATION);\n\t\t\t}\n\t\t#endif\n\t}\n\t#endif\n\n#ifdef PATCH_SWITCH_UNDO\n\tpatch::undo.init();\n\tif (patch::undo.is_enabled_i()) {\n\t\t#ifdef PATCH_SWITCH_UNDO_REDO\n\t\t\tpatch::redo.init();\n\t\t#endif\n\t}\n#endif\n\n\t//GLOBAL::config.store(GLOBAL::patchaul_config_path);\n\tconfig2.store(GLOBAL::patchaul_config_path);\n}\n\t\t\nvoid init_t::InitAufBefore() {\n\tpatch::aviutl_wndproc_override.go();\n}\n\nBOOL WINAPI init_t::EnumResourceLanguagesA_Wrap(HMODULE hModule, LPCSTR lpType, LPCSTR lpName, ENUMRESLANGPROCA lpEnumFunc, LONG_PTR lParam) {\n\tExchangeFunction((HMODULE)GLOBAL::aviutl_base, cstr_kernel32_dll.get(), cstr_EnumResourceLanguagesA.get(), EnumResourceLanguagesA);\n\n\tInitAtPatchLoaded();\n\n\treturn FALSE;\n}\n\nHMODULE WINAPI init_t::LoadLibraryAWrap(LPCSTR lpLibFileName) {\n\tHMODULE ret = LoadLibraryA(lpLibFileName);\n\tif (ret == NULL)return NULL;\n\n\tLPCSTR filename = PathFindFileNameA(lpLibFileName);\n\tif (lstrcmpiA(filename, \"exedit.auf\") == 0) {\n\t\tGLOBAL::exedit_hmod = ret;\n\t\tauto filters = reinterpret_cast<AviUtl::GetFilterTableList_t>(GetProcAddress(ret, AviUtl::GetFilterTableListName))();\n\t\tif (strcmp(filters[0]->information, \"拡張編集(exedit) version 0.92 by ＫＥＮくん\") != 0) {\n\t\t\tMessageBoxW(NULL, L\"patch.aul requires Exedit version *0.92*.\\n拡張編集 version 0.92以外では動作しません．\", L\"patch.aul\", MB_ICONEXCLAMATION);\n\t\t\treturn ret;\n\t\t}\n\t\toriginal_func_init = std::exchange(filters[0]->func_init, func_initWrap);\n\t\toriginal_func_WndProc = std::exchange(filters[0]->func_WndProc, func_WndProcWrap);\n#ifdef _DEBUG\n\t\toriginal_func_proc = std::exchange(filters[0]->func_proc, func_procWrap);\n#endif\n\t\tInitAtExeditLoad();\n\t}\n#ifdef PATCH_SWITCH_CANCEL_BOOST_CONFLICT\n\telse if (lstrcmpiA(filename, \"Boost.auf\") == 0) {\n\t\tif (auto ptr = search_import(ret, cstr_kernel32_dll.get(), cstr_GetModuleHandleA.get())) {\n\t\t\tOverWriteOnProtectHelper(ptr, 4).store_i32(0, &init_t::Boost_GetModuleHandleA_Wrap);\n\t\t}\n\t\tif (auto ptr = search_import(ret, cstr_kernel32_dll.get(), cstr_GetModuleHandleW.get())) {\n\t\t\tOverWriteOnProtectHelper(ptr, 4).store_i32(0, &init_t::Boost_GetModuleHandleW_Wrap);\n\t\t}\n\t\tif (auto ptr = search_import(ret, cstr_kernel32_dll.get(), cstr_LoadLibraryA.get())) {\n\t\t\tOverWriteOnProtectHelper(ptr, 4).store_i32(0, &init_t::Boost_LoadLibraryA_Wrap);\n\t\t}\n\t\tif (auto ptr = search_import(ret, cstr_kernel32_dll.get(), cstr_LoadLibraryW.get())) {\n\t\t\tOverWriteOnProtectHelper(ptr, 4).store_i32(0, &init_t::Boost_LoadLibraryW_Wrap);\n\t\t}\n\t\tif (auto ptr = search_import(ret, cstr_kernel32_dll.get(), cstr_Module32First.get())) {\n\t\t\tOverWriteOnProtectHelper(ptr, 4).store_i32(0, &init_t::Boost_Module32First_Wrap);\n\t\t}\n\t\tif (auto ptr = search_import(ret, cstr_kernel32_dll.get(), cstr_Module32FirstW.get())) {\n\t\t\tOverWriteOnProtectHelper(ptr, 4).store_i32(0, &init_t::Boost_Module32FirstW_Wrap);\n\t\t}\n\t\tif (auto ptr = search_import(ret, cstr_kernel32_dll.get(), cstr_Module32Next.get())) {\n\t\t\tOverWriteOnProtectHelper(ptr, 4).store_i32(0, &init_t::Boost_Module32Next_Wrap);\n\t\t}\n\t\tif (auto ptr = search_import(ret, cstr_kernel32_dll.get(), cstr_Module32NextW.get())) {\n\t\t\tOverWriteOnProtectHelper(ptr, 4).store_i32(0, &init_t::Boost_Module32NextW_Wrap);\n\t\t}\n\t}\n#endif\n#ifdef PATCH_SWITCH_WARNING_OLD_LSW\n\telse if (lstrcmpiA(filename, \"lwcolor.auc\") == 0) {\n\t\tstatic const SHA256 r940_hash(0xc7, 0xe2, 0x51, 0xde, 0xd2, 0xf8, 0x21, 0xcb, 0x1b, 0xc6, 0xb1, 0x9a, 0x66, 0x43, 0xd3, 0x0d, 0xa4, 0xeb, 0xd6, 0x97, 0x1e, 0x34, 0x1a, 0xb2, 0x11, 0xd9, 0x41, 0x1d, 0xcc, 0xbf, 0x9a, 0x18);\n\t\tSHA256 hash(lpLibFileName);\n\t\tif (hash == r940_hash) {\n\t\t\tauto ret = patch_resource_message_w(PATCH_RS_PATCH_OLD_LSW, MB_ICONEXCLAMATION | MB_YESNO);\n\t\t\tif (ret == IDYES) {\n\t\t\t\tstatic cryptostring lsw_url(L\"https://scrapbox.io/aviutl/L-SMASH_Works\");\n\t\t\t\tweb_confirm(lsw_url.get());\n\t\t\t}\n\t\t}\n\t}\n#endif\n\telse {\n\t\tstatic std::set<std::string> list = {\n\t\t\t\"bakusoku.auf\",\n\t\t\t\"eclipse_fast.auf\",\n\t\t\t\"redo.auf\",\n\t\t};\n\n\t\tstd::string check = filename;\n\t\tstd::transform(check.begin(), check.end(), check.begin(), [](auto c) { return std::tolower(c); });\n\n\t\tif (list.find(check) != list.end()) {\n\t\t\tFreeLibrary(ret);\n\t\t\t\n\t\t\tauto ret = patch_resource_message_w(PATCH_RS_PATCH_CONFLICT_PLUGIN, MB_TASKMODAL | MB_ICONINFORMATION | MB_YESNO, string_convert_A2W(filename));\n\n\t\t\tif (ret) {\n\t\t\t\tswitch (*ret) {\n\t\t\t\tcase IDYES:\n\t\t\t\t\tDeleteFileA(lpLibFileName);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn NULL;\n\t\t}\n\t}\n\treturn ret;\n}\n\t\nBOOL __cdecl init_t::func_WndProcWrap(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, AviUtl::EditHandle* editp, AviUtl::FilterPlugin* fp) {\n\tswitch (message) {\n\t\t#ifdef PATCH_SWITCH_EXEDITWINDOW_SIZING\n\t\tcase WM_SIZING:\n\t\t\tif (auto ret = patch::exeditwindow_sizing.wndproc(wparam, lparam) == -1) break;\n\t\t\telse return ret;\n\t\t#endif\n\t\tcase AviUtl::FilterPlugin::WindowMessage::Command:\n\t\t\t#ifdef PATCH_SWITCH_UNDO_REDO\n\t\t\tif (wparam == PATCH_EXEDITMENU_REDO) {\n\t\t\t\tif (patch::redo.is_enabled_i()) {\n\t\t\t\t\tpatch::redo.run_redo();\n\t\t\t\t}\n\t\t\t\treturn TRUE;\n\t\t\t}\n\t\t\t#endif\n\n\t}\n\treturn original_func_WndProc(hwnd, message, wparam, lparam, editp, fp);\n}\n\nBOOL __cdecl init_t::func_initWrap(AviUtl::FilterPlugin* fp) {\n\tif (original_func_init(fp) == FALSE) return FALSE;\n\t\n\t#ifdef PATCH_SWITCH_UNDO_REDO\n\t\tfp->exfunc->add_menu_item(fp, \"やり直す\", fp->hwnd, PATCH_EXEDITMENU_REDO, 'Y', AviUtl::ExFunc::AddMenuItemFlag::Ctrl);\n\t#endif\n\n#ifdef PATCH_SWITCH_LUA\n\tpatch::lua.init();\n\n\t#ifdef PATCH_SWITCH_LUA_RAND\n\t\tpatch::lua_rand.init();\n\t#endif\n\n\t#ifdef PATCH_SWITCH_LUA_RANDEX\n\t\tpatch::lua_randex.init();\n\t#endif\n\n\t#ifdef PATCH_SWITCH_LUA_GETVALUE\n\t\tpatch::lua_getvalueex.init();\n\t#endif\n\n#endif\n\t\n\treturn TRUE;\n}\n\nBOOL __cdecl init_t::func_procWrap(AviUtl::FilterPlugin* fp, AviUtl::FilterProcInfo* fpip) {\n\t//std::cout << \" = = = = = = \" << std::endl;\n\t#ifdef PATCH_SWITCH_ALPHA_BG\n\t\tpatch::alpha_bg.func_proc(fp, fpip);\n\t#endif\n\treturn original_func_proc(fp, fpip);\n}\n\n#ifdef PATCH_SWITCH_CANCEL_BOOST_CONFLICT\nHMODULE WINAPI init_t::Boost_GetModuleHandleA_Wrap(LPCSTR lpModuleName) {\n\tauto filename = PathFindFileNameA(lpModuleName);\n\tif (lstrcmpiA(filename, \"patch.aul\") == 0) {\n\t\treturn NULL;\n\t}\n\treturn GetModuleHandleA(lpModuleName);\n}\n\nHMODULE WINAPI init_t::Boost_GetModuleHandleW_Wrap(LPCWSTR lpModuleName) {\n\tauto filename = PathFindFileNameW(lpModuleName);\n\tif (lstrcmpiW(filename, L\"patch.aul\") == 0) {\n\t\treturn NULL;\n\t}\n\treturn GetModuleHandleW(lpModuleName);\n}\n\nHMODULE WINAPI init_t::Boost_LoadLibraryA_Wrap(LPCSTR lpLibFileName) {\n\tauto filename = PathFindFileNameA(lpLibFileName);\n\tif (lstrcmpiA(filename, \"patch.aul\") == 0) {\n\t\treturn NULL;\n\t}\n\treturn LoadLibraryA(lpLibFileName);\n}\n\nHMODULE WINAPI init_t::Boost_LoadLibraryW_Wrap(LPCWSTR lpLibFileName) {\n\tauto filename = PathFindFileNameW(lpLibFileName);\n\tif (lstrcmpiW(filename, L\"patch.aul\") == 0) {\n\t\treturn NULL;\n\t}\n\treturn LoadLibraryW(lpLibFileName);\n}\n\nBOOL WINAPI init_t::Boost_Module32First_Wrap(HANDLE hSnapshot, LPMODULEENTRY32 lpme) {\n\tauto ret = Module32First(hSnapshot, lpme);\n\tif (ret && lstrcmpiA(lpme->szModule, \"patch.aul\") == 0) {\n\t\treturn Module32Next(hSnapshot, lpme);\n\t}\n\treturn ret;\n}\n\nBOOL WINAPI init_t::Boost_Module32FirstW_Wrap(HANDLE hSnapshot, LPMODULEENTRY32W lpme) {\n\tauto ret = Module32FirstW(hSnapshot, lpme);\n\tif (ret && lstrcmpiW(lpme->szModule, L\"patch.aul\") == 0) {\n\t\treturn Module32NextW(hSnapshot, lpme);\n\t}\n\treturn ret;\n}\n\nBOOL WINAPI init_t::Boost_Module32Next_Wrap(HANDLE hSnapshot, LPMODULEENTRY32 lpme) {\n\tauto ret = Module32Next(hSnapshot, lpme);\n\tif (ret && lstrcmpiA(lpme->szModule, \"patch.aul\") == 0) {\n\t\treturn Module32Next(hSnapshot, lpme);\n\t}\n\treturn ret;\n}\n\nBOOL WINAPI init_t::Boost_Module32NextW_Wrap(HANDLE hSnapshot, LPMODULEENTRY32W lpme) {\n\tauto ret = Module32NextW(hSnapshot, lpme);\n\tif (ret && lstrcmpiW(lpme->szModule, L\"patch.aul\") == 0) {\n\t\treturn Module32NextW(hSnapshot, lpme);\n\t}\n\treturn ret;\n}\n#endif\n"
  },
  {
    "path": "patch/init.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include <winwrap.hpp>\n\n#include \"cryptostring.hpp\"\n#include \"add_dll_ref.hpp\"\n#include \"util.hpp\"\n#include \"global.hpp\"\n#include \"offset_address.hpp\"\n#include \"util.hpp\"\n#include \"patch.hpp\"\n#include \"debug_log.hpp\"\n\n#include \"overwrite_resource.hpp\"\n#include \"patch_exception_log.hpp\"\n\n#include \"mywindow.hpp\"\n\ninline class init_t {\npublic:\n\n\tinline static BOOL(__cdecl* original_func_WndProc)(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, AviUtl::EditHandle* editp, AviUtl::FilterPlugin* fp);\n\tinline static BOOL(__cdecl* original_func_init)(AviUtl::FilterPlugin* fp);\n\tinline static BOOL(__cdecl* original_func_proc)(AviUtl::FilterPlugin* fp, AviUtl::FilterProcInfo* fpip);\n\n\tstatic BOOL __cdecl func_WndProcWrap(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, AviUtl::EditHandle* editp, AviUtl::FilterPlugin* fp);\n\tstatic BOOL __cdecl func_initWrap(AviUtl::FilterPlugin* fp);\n\tstatic BOOL __cdecl func_procWrap(AviUtl::FilterPlugin* fp, AviUtl::FilterProcInfo* fpip);\n\tstatic BOOL WINAPI EnumResourceLanguagesA_Wrap(HMODULE hModule, LPCSTR lpType, LPCSTR lpName, ENUMRESLANGPROCA lpEnumFunc, LONG_PTR lParam);\n\tstatic HMODULE WINAPI LoadLibraryAWrap(LPCSTR lpLibFileName);\n\n#ifdef PATCH_SWITCH_CANCEL_BOOST_CONFLICT\n\tstatic HMODULE WINAPI Boost_GetModuleHandleA_Wrap(LPCSTR lpModuleName);\n\tstatic HMODULE WINAPI Boost_GetModuleHandleW_Wrap(LPCWSTR lpModuleName);\n\tstatic HMODULE WINAPI Boost_LoadLibraryA_Wrap(LPCSTR lpLibFileName);\n\tstatic HMODULE WINAPI Boost_LoadLibraryW_Wrap(LPCWSTR lpLibFileName);\n\tstatic BOOL WINAPI Boost_Module32First_Wrap(HANDLE hSnapshot, LPMODULEENTRY32 lpme);\n\tstatic BOOL WINAPI Boost_Module32FirstW_Wrap(HANDLE hSnapshot, LPMODULEENTRY32W lpme);\n\tstatic BOOL WINAPI Boost_Module32Next_Wrap(HANDLE hSnapshot, LPMODULEENTRY32 lpme);\n\tstatic BOOL WINAPI Boost_Module32NextW_Wrap(HANDLE hSnapshot, LPMODULEENTRY32W lpme);\n#endif\n\n\n\t// DllMain呼び出しのタイミングでやる処理\n\t// できるだけ少なくしたい\n\tstatic void InitAtDllMain();\n\n\t// LoadLibrary(\"patch.aul\")直後にやる処理\n\t// EnumResourceLanguagesAの乗っ取りで実現\n\t// EnumResourceLanguagesAが失敗したことにして，patch.aulは正しい言語拡張リソースではないことにする\n\tstatic void InitAtPatchLoaded();\n\n\t// exedit.aufのLoadLibrary直後にやる処理\n\t// 拡張編集へのインジェクションはここでやる\n\tstatic void InitAtExeditLoad();\n\n\t// フィルタプラグインの読み込みを開始するタイミングでやる処理\n\tstatic void InitAufBefore();\n\n\n} init;\n"
  },
  {
    "path": "patch/json.h",
    "content": "/*\n   The latest version of this library is available on GitHub;\n   https://github.com/sheredom/json.h.\n*/\n\n/*\n   This is free and unencumbered software released into the public domain.\n\n   Anyone is free to copy, modify, publish, use, compile, sell, or\n   distribute this software, either in source code form or as a compiled\n   binary, for any purpose, commercial or non-commercial, and by any\n   means.\n\n   In jurisdictions that recognize copyright laws, the author or authors\n   of this software dedicate any and all copyright interest in the\n   software to the public domain. We make this dedication for the benefit\n   of the public at large and to the detriment of our heirs and\n   successors. We intend this dedication to be an overt act of\n   relinquishment in perpetuity of all present and future rights to this\n   software under copyright law.\n\n   THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\n   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n   OTHER DEALINGS IN THE SOFTWARE.\n\n   For more information, please refer to <http://unlicense.org/>.\n*/\n\n#ifndef SHEREDOM_JSON_H_INCLUDED\n#define SHEREDOM_JSON_H_INCLUDED\n\n#if defined(_MSC_VER)\n#pragma warning(push)\n\n/* disable warning: no function prototype given: converting '()' to '(void)' */\n#pragma warning(disable : 4255)\n\n/* disable warning: '__cplusplus' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */\n#pragma warning(disable : 4668)\n\n/* disable warning: 'bytes padding added after construct' */\n#pragma warning(disable : 4820)\n#endif\n\n#include <stddef.h>\n#include <string.h>\n\n#if defined(_MSC_VER)\n#define json_weak __inline\n#elif defined(__clang__) || defined(__GNUC__)\n#define json_weak __attribute__((weak))\n#else\n#error Non clang, non gcc, non MSVC compiler found!\n#endif\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\nstruct json_value_s;\nstruct json_parse_result_s;\n\nenum json_parse_flags_e {\n  json_parse_flags_default = 0,\n\n  /* allow trailing commas in objects and arrays. For example, both [true,] and\n     {\"a\" : null,} would be allowed with this option on. */\n  json_parse_flags_allow_trailing_comma = 0x1,\n\n  /* allow unquoted keys for objects. For example, {a : null} would be allowed\n     with this option on. */\n  json_parse_flags_allow_unquoted_keys = 0x2,\n\n  /* allow a global unbracketed object. For example, a : null, b : true, c : {}\n     would be allowed with this option on. */\n  json_parse_flags_allow_global_object = 0x4,\n\n  /* allow objects to use '=' instead of ':' between key/value pairs. For\n     example, a = null, b : true would be allowed with this option on. */\n  json_parse_flags_allow_equals_in_object = 0x8,\n\n  /* allow that objects don't have to have comma separators between key/value\n     pairs. */\n  json_parse_flags_allow_no_commas = 0x10,\n\n  /* allow c-style comments (either variants) to be ignored in the input JSON\n     file. */\n  json_parse_flags_allow_c_style_comments = 0x20,\n\n  /* deprecated flag, unused. */\n  json_parse_flags_deprecated = 0x40,\n\n  /* record location information for each value. */\n  json_parse_flags_allow_location_information = 0x80,\n\n  /* allow strings to be 'single quoted'. */\n  json_parse_flags_allow_single_quoted_strings = 0x100,\n\n  /* allow numbers to be hexadecimal. */\n  json_parse_flags_allow_hexadecimal_numbers = 0x200,\n\n  /* allow numbers like +123 to be parsed. */\n  json_parse_flags_allow_leading_plus_sign = 0x400,\n\n  /* allow numbers like .0123 or 123. to be parsed. */\n  json_parse_flags_allow_leading_or_trailing_decimal_point = 0x800,\n\n  /* allow Infinity, -Infinity, NaN, -NaN. */\n  json_parse_flags_allow_inf_and_nan = 0x1000,\n\n  /* allow multi line string values. */\n  json_parse_flags_allow_multi_line_strings = 0x2000,\n\n  /* allow simplified JSON to be parsed. Simplified JSON is an enabling of a set\n     of other parsing options. */\n  json_parse_flags_allow_simplified_json =\n      (json_parse_flags_allow_trailing_comma |\n       json_parse_flags_allow_unquoted_keys |\n       json_parse_flags_allow_global_object |\n       json_parse_flags_allow_equals_in_object |\n       json_parse_flags_allow_no_commas),\n\n  /* allow JSON5 to be parsed. JSON5 is an enabling of a set of other parsing\n     options. */\n  json_parse_flags_allow_json5 =\n      (json_parse_flags_allow_trailing_comma |\n       json_parse_flags_allow_unquoted_keys |\n       json_parse_flags_allow_c_style_comments |\n       json_parse_flags_allow_single_quoted_strings |\n       json_parse_flags_allow_hexadecimal_numbers |\n       json_parse_flags_allow_leading_plus_sign |\n       json_parse_flags_allow_leading_or_trailing_decimal_point |\n       json_parse_flags_allow_inf_and_nan |\n       json_parse_flags_allow_multi_line_strings)\n};\n\n/* Parse a JSON text file, returning a pointer to the root of the JSON\n * structure. json_parse performs 1 call to malloc for the entire encoding.\n * Returns 0 if an error occurred (malformed JSON input, or malloc failed). */\njson_weak struct json_value_s *json_parse(const void *src, size_t src_size);\n\n/* Parse a JSON text file, returning a pointer to the root of the JSON\n * structure. json_parse performs 1 call to alloc_func_ptr for the entire\n * encoding. Returns 0 if an error occurred (malformed JSON input, or malloc\n * failed). If an error occurred, the result struct (if not NULL) will explain\n * the type of error, and the location in the input it occurred. If\n * alloc_func_ptr is null then malloc is used. */\njson_weak struct json_value_s *\njson_parse_ex(const void *src, size_t src_size, size_t flags_bitset,\n              void *(*alloc_func_ptr)(void *, size_t), void *user_data,\n              struct json_parse_result_s *result);\n\n/* Extracts a value and all the data that makes it up into a newly created\n * value. json_extract_value performs 1 call to malloc for the entire encoding.\n */\njson_weak struct json_value_s *\njson_extract_value(const struct json_value_s *value);\n\n/* Extracts a value and all the data that makes it up into a newly created\n * value. json_extract_value performs 1 call to alloc_func_ptr for the entire\n * encoding. If alloc_func_ptr is null then malloc is used. */\njson_weak struct json_value_s *\njson_extract_value_ex(const struct json_value_s *value,\n                      void *(*alloc_func_ptr)(void *, size_t), void *user_data);\n\n/* Write out a minified JSON utf-8 string. This string is an encoding of the\n * minimal string characters required to still encode the same data.\n * json_write_minified performs 1 call to malloc for the entire encoding. Return\n * 0 if an error occurred (malformed JSON input, or malloc failed). The out_size\n * parameter is optional as the utf-8 string is null terminated. */\njson_weak void *json_write_minified(const struct json_value_s *value,\n                                    size_t *out_size);\n\n/* Write out a pretty JSON utf-8 string. This string is encoded such that the\n * resultant JSON is pretty in that it is easily human readable. The indent and\n * newline parameters allow a user to specify what kind of indentation and\n * newline they want (two spaces / three spaces / tabs? \\r, \\n, \\r\\n ?). Both\n * indent and newline can be NULL, indent defaults to two spaces (\"  \"), and\n * newline defaults to linux newlines ('\\n' as the newline character).\n * json_write_pretty performs 1 call to malloc for the entire encoding. Return 0\n * if an error occurred (malformed JSON input, or malloc failed). The out_size\n * parameter is optional as the utf-8 string is null terminated. */\njson_weak void *json_write_pretty(const struct json_value_s *value,\n                                  const char *indent, const char *newline,\n                                  size_t *out_size);\n\n/* Reinterpret a JSON value as a string. Returns null is the value was not a\n * string. */\njson_weak struct json_string_s *\njson_value_as_string(struct json_value_s *const value);\n\n/* Reinterpret a JSON value as a number. Returns null is the value was not a\n * number. */\njson_weak struct json_number_s *\njson_value_as_number(struct json_value_s *const value);\n\n/* Reinterpret a JSON value as an object. Returns null is the value was not an\n * object. */\njson_weak struct json_object_s *\njson_value_as_object(struct json_value_s *const value);\n\n/* Reinterpret a JSON value as an array. Returns null is the value was not an\n * array. */\njson_weak struct json_array_s *\njson_value_as_array(struct json_value_s *const value);\n\n/* Whether the value is true. */\njson_weak int json_value_is_true(const struct json_value_s *const value);\n\n/* Whether the value is false. */\njson_weak int json_value_is_false(const struct json_value_s *const value);\n\n/* Whether the value is null. */\njson_weak int json_value_is_null(const struct json_value_s *const value);\n\n/* The various types JSON values can be. Used to identify what a value is. */\nenum json_type_e {\n  json_type_string,\n  json_type_number,\n  json_type_object,\n  json_type_array,\n  json_type_true,\n  json_type_false,\n  json_type_null\n};\n\n/* A JSON string value. */\nstruct json_string_s {\n  /* utf-8 string */\n  const char *string;\n  /* The size (in bytes) of the string */\n  size_t string_size;\n};\n\n/* A JSON string value (extended). */\nstruct json_string_ex_s {\n  /* The JSON string this extends. */\n  struct json_string_s string;\n\n  /* The character offset for the value in the JSON input. */\n  size_t offset;\n\n  /* The line number for the value in the JSON input. */\n  size_t line_no;\n\n  /* The row number for the value in the JSON input, in bytes. */\n  size_t row_no;\n};\n\n/* A JSON number value. */\nstruct json_number_s {\n  /* ASCII string containing representation of the number. */\n  const char *number;\n  /* the size (in bytes) of the number. */\n  size_t number_size;\n};\n\n/* an element of a JSON object. */\nstruct json_object_element_s {\n  /* the name of this element. */\n  struct json_string_s *name;\n  /* the value of this element. */\n  struct json_value_s *value;\n  /* the next object element (can be NULL if the last element in the object). */\n  struct json_object_element_s *next;\n};\n\n/* a JSON object value. */\nstruct json_object_s {\n  /* a linked list of the elements in the object. */\n  struct json_object_element_s *start;\n  /* the number of elements in the object. */\n  size_t length;\n};\n\n/* an element of a JSON array. */\nstruct json_array_element_s {\n  /* the value of this element. */\n  struct json_value_s *value;\n  /* the next array element (can be NULL if the last element in the array). */\n  struct json_array_element_s *next;\n};\n\n/* a JSON array value. */\nstruct json_array_s {\n  /* a linked list of the elements in the array. */\n  struct json_array_element_s *start;\n  /* the number of elements in the array. */\n  size_t length;\n};\n\n/* a JSON value. */\nstruct json_value_s {\n  /* a pointer to either a json_string_s, json_number_s, json_object_s, or. */\n  /* json_array_s. Should be cast to the appropriate struct type based on what.\n   */\n  /* the type of this value is. */\n  void *payload;\n  /* must be one of json_type_e. If type is json_type_true, json_type_false, or.\n   */\n  /* json_type_null, payload will be NULL. */\n  size_t type;\n};\n\n/* a JSON value (extended). */\nstruct json_value_ex_s {\n  /* the JSON value this extends. */\n  struct json_value_s value;\n\n  /* the character offset for the value in the JSON input. */\n  size_t offset;\n\n  /* the line number for the value in the JSON input. */\n  size_t line_no;\n\n  /* the row number for the value in the JSON input, in bytes. */\n  size_t row_no;\n};\n\n/* a parsing error code. */\nenum json_parse_error_e {\n  /* no error occurred (huzzah!). */\n  json_parse_error_none = 0,\n\n  /* expected either a comma or a closing '}' or ']' to close an object or. */\n  /* array! */\n  json_parse_error_expected_comma_or_closing_bracket,\n\n  /* colon separating name/value pair was missing! */\n  json_parse_error_expected_colon,\n\n  /* expected string to begin with '\"'! */\n  json_parse_error_expected_opening_quote,\n\n  /* invalid escaped sequence in string! */\n  json_parse_error_invalid_string_escape_sequence,\n\n  /* invalid number format! */\n  json_parse_error_invalid_number_format,\n\n  /* invalid value! */\n  json_parse_error_invalid_value,\n\n  /* reached end of buffer before object/array was complete! */\n  json_parse_error_premature_end_of_buffer,\n\n  /* string was malformed! */\n  json_parse_error_invalid_string,\n\n  /* a call to malloc, or a user provider allocator, failed. */\n  json_parse_error_allocator_failed,\n\n  /* the JSON input had unexpected trailing characters that weren't part of the.\n   */\n  /* JSON value. */\n  json_parse_error_unexpected_trailing_characters,\n\n  /* catch-all error for everything else that exploded (real bad chi!). */\n  json_parse_error_unknown\n};\n\n/* error report from json_parse_ex(). */\nstruct json_parse_result_s {\n  /* the error code (one of json_parse_error_e). */\n  size_t error;\n\n  /* the character offset for the error in the JSON input. */\n  size_t error_offset;\n\n  /* the line number for the error in the JSON input. */\n  size_t error_line_no;\n\n  /* the row number for the error, in bytes. */\n  size_t error_row_no;\n};\n\n#ifdef __cplusplus\n} /* extern \"C\". */\n#endif\n\n#include <stdlib.h>\n\n#if defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n#if defined(_MSC_VER) && (_MSC_VER < 1920)\n#define json_uintmax_t unsigned __int64\n#else\n#include <inttypes.h>\n#define json_uintmax_t uintmax_t\n#endif\n\n#if defined(_MSC_VER)\n#define json_strtoumax _strtoui64\n#else\n#define json_strtoumax strtoumax\n#endif\n\n#if defined(__cplusplus) && (__cplusplus >= 201103L)\n#define json_null nullptr\n#else\n#define json_null 0\n#endif\n\n#if defined(__clang__)\n#pragma clang diagnostic push\n\n/* we do one big allocation via malloc, then cast aligned slices of this for. */\n/* our structures - we don't have a way to tell the compiler we know what we. */\n/* are doing, so disable the warning instead! */\n#pragma clang diagnostic ignored \"-Wcast-align\"\n\n/* We use C style casts everywhere. */\n#pragma clang diagnostic ignored \"-Wold-style-cast\"\n\n/* We need long long for strtoull. */\n#pragma clang diagnostic ignored \"-Wc++11-long-long\"\n\n/* Who cares if nullptr doesn't work with C++98, we don't use it there! */\n#pragma clang diagnostic ignored \"-Wc++98-compat\"\n#pragma clang diagnostic ignored \"-Wc++98-compat-pedantic\"\n#elif defined(_MSC_VER)\n#pragma warning(push)\n\n/* disable 'function selected for inline expansion' warning. */\n#pragma warning(disable : 4711)\n\n/* disable '#pragma warning: there is no warning number' warning. */\n#pragma warning(disable : 4619)\n\n/* disable 'warning number not a valid compiler warning' warning. */\n#pragma warning(disable : 4616)\n\n/* disable 'Compiler will insert Spectre mitigation for memory load if\n * /Qspectre. */\n/* switch specified' warning. */\n#pragma warning(disable : 5045)\n#endif\n\nstruct json_parse_state_s {\n  const char *src;\n  size_t size;\n  size_t offset;\n  size_t flags_bitset;\n  char *data;\n  char *dom;\n  size_t dom_size;\n  size_t data_size;\n  size_t line_no;     /* line counter for error reporting. */\n  size_t line_offset; /* (offset-line_offset) is the character number (in\n                         bytes). */\n  size_t error;\n};\n\njson_weak int json_hexadecimal_digit(const char c);\nint json_hexadecimal_digit(const char c) {\n  if ('0' <= c && c <= '9') {\n    return c - '0';\n  }\n  if ('a' <= c && c <= 'f') {\n    return c - 'a' + 10;\n  }\n  if ('A' <= c && c <= 'F') {\n    return c - 'A' + 10;\n  }\n  return -1;\n}\n\njson_weak int json_hexadecimal_value(const char *c, const unsigned long size,\n                                     unsigned long *result);\nint json_hexadecimal_value(const char *c, const unsigned long size,\n                           unsigned long *result) {\n  const char *p;\n  int digit;\n\n  if (size > sizeof(unsigned long) * 2) {\n    return 0;\n  }\n\n  *result = 0;\n  for (p = c; (unsigned long)(p - c) < size; ++p) {\n    *result <<= 4;\n    digit = json_hexadecimal_digit(*p);\n    if (digit < 0 || digit > 15) {\n      return 0;\n    }\n    *result |= (unsigned char)digit;\n  }\n  return 1;\n}\n\njson_weak int json_skip_whitespace(struct json_parse_state_s *state);\nint json_skip_whitespace(struct json_parse_state_s *state) {\n  size_t offset = state->offset;\n  const size_t size = state->size;\n  const char *const src = state->src;\n\n  /* the only valid whitespace according to ECMA-404 is ' ', '\\n', '\\r' and\n   * '\\t'. */\n  switch (src[offset]) {\n  default:\n    return 0;\n  case ' ':\n  case '\\r':\n  case '\\t':\n  case '\\n':\n    break;\n  }\n\n  do {\n    switch (src[offset]) {\n    default:\n      /* Update offset. */\n      state->offset = offset;\n      return 1;\n    case ' ':\n    case '\\r':\n    case '\\t':\n      break;\n    case '\\n':\n      state->line_no++;\n      state->line_offset = offset;\n      break;\n    }\n\n    offset++;\n  } while (offset < size);\n\n  /* Update offset. */\n  state->offset = offset;\n  return 1;\n}\n\njson_weak int json_skip_c_style_comments(struct json_parse_state_s *state);\nint json_skip_c_style_comments(struct json_parse_state_s *state) {\n  /* do we have a comment?. */\n  if ('/' == state->src[state->offset]) {\n    /* skip '/'. */\n    state->offset++;\n\n    if ('/' == state->src[state->offset]) {\n      /* we had a comment of the form //. */\n\n      /* skip second '/'. */\n      state->offset++;\n\n      while (state->offset < state->size) {\n        switch (state->src[state->offset]) {\n        default:\n          /* skip the character in the comment. */\n          state->offset++;\n          break;\n        case '\\n':\n          /* if we have a newline, our comment has ended! Skip the newline. */\n          state->offset++;\n\n          /* we entered a newline, so move our line info forward. */\n          state->line_no++;\n          state->line_offset = state->offset;\n          return 1;\n        }\n      }\n\n      /* we reached the end of the JSON file! */\n      return 1;\n    } else if ('*' == state->src[state->offset]) {\n      /* we had a comment in the C-style long form. */\n\n      /* skip '*'. */\n      state->offset++;\n\n      while (state->offset + 1 < state->size) {\n        if (('*' == state->src[state->offset]) &&\n            ('/' == state->src[state->offset + 1])) {\n          /* we reached the end of our comment! */\n          state->offset += 2;\n          return 1;\n        } else if ('\\n' == state->src[state->offset]) {\n          /* we entered a newline, so move our line info forward. */\n          state->line_no++;\n          state->line_offset = state->offset;\n        }\n\n        /* skip character within comment. */\n        state->offset++;\n      }\n\n      /* Comment wasn't ended correctly which is a failure. */\n      return 1;\n    }\n  }\n\n  /* we didn't have any comment, which is ok too! */\n  return 0;\n}\n\njson_weak int json_skip_all_skippables(struct json_parse_state_s *state);\nint json_skip_all_skippables(struct json_parse_state_s *state) {\n  /* skip all whitespace and other skippables until there are none left. note\n   * that the previous version suffered from read past errors should. the\n   * stream end on json_skip_c_style_comments eg. '{\"a\" ' with comments flag.\n   */\n\n  int did_consume = 0;\n  const size_t size = state->size;\n\n  if (json_parse_flags_allow_c_style_comments & state->flags_bitset) {\n    do {\n      if (state->offset == size) {\n        state->error = json_parse_error_premature_end_of_buffer;\n        return 1;\n      }\n\n      did_consume = json_skip_whitespace(state);\n\n      /* This should really be checked on access, not in front of every call.\n       */\n      if (state->offset == size) {\n        state->error = json_parse_error_premature_end_of_buffer;\n        return 1;\n      }\n\n      did_consume |= json_skip_c_style_comments(state);\n    } while (0 != did_consume);\n  } else {\n    do {\n      if (state->offset == size) {\n        state->error = json_parse_error_premature_end_of_buffer;\n        return 1;\n      }\n\n      did_consume = json_skip_whitespace(state);\n    } while (0 != did_consume);\n  }\n\n  if (state->offset == size) {\n    state->error = json_parse_error_premature_end_of_buffer;\n    return 1;\n  }\n\n  return 0;\n}\n\njson_weak int json_get_value_size(struct json_parse_state_s *state,\n                                  int is_global_object);\n\njson_weak int json_get_string_size(struct json_parse_state_s *state,\n                                   size_t is_key);\nint json_get_string_size(struct json_parse_state_s *state, size_t is_key) {\n  size_t offset = state->offset;\n  const size_t size = state->size;\n  size_t data_size = 0;\n  const char *const src = state->src;\n  const int is_single_quote = '\\'' == src[offset];\n  const char quote_to_use = is_single_quote ? '\\'' : '\"';\n  const size_t flags_bitset = state->flags_bitset;\n  unsigned long codepoint;\n  unsigned long high_surrogate = 0;\n\n  if ((json_parse_flags_allow_location_information & flags_bitset) != 0 &&\n      is_key != 0) {\n    state->dom_size += sizeof(struct json_string_ex_s);\n  } else {\n    state->dom_size += sizeof(struct json_string_s);\n  }\n\n  if ('\"' != src[offset]) {\n    /* if we are allowed single quoted strings check for that too. */\n    if (!((json_parse_flags_allow_single_quoted_strings & flags_bitset) &&\n          is_single_quote)) {\n      state->error = json_parse_error_expected_opening_quote;\n      state->offset = offset;\n      return 1;\n    }\n  }\n\n  /* skip leading '\"' or '\\''. */\n  offset++;\n\n  while ((offset < size) && (quote_to_use != src[offset])) {\n    /* add space for the character. */\n    data_size++;\n\n    switch (src[offset]) {\n    default:\n      break;\n    case '\\0':\n    case '\\t':\n      state->error = json_parse_error_invalid_string;\n      state->offset = offset;\n      return 1;\n    }\n\n    if ('\\\\' == src[offset]) {\n      /* skip reverse solidus character. */\n      offset++;\n\n      if (offset == size) {\n        state->error = json_parse_error_premature_end_of_buffer;\n        state->offset = offset;\n        return 1;\n      }\n\n      switch (src[offset]) {\n      default:\n        state->error = json_parse_error_invalid_string_escape_sequence;\n        state->offset = offset;\n        return 1;\n      case '\"':\n      case '\\\\':\n      case '/':\n      case 'b':\n      case 'f':\n      case 'n':\n      case 'r':\n      case 't':\n        /* all valid characters! */\n        offset++;\n        break;\n      case 'u':\n        if (!(offset + 5 < size)) {\n          /* invalid escaped unicode sequence! */\n          state->error = json_parse_error_invalid_string_escape_sequence;\n          state->offset = offset;\n          return 1;\n        }\n\n        codepoint = 0;\n        if (!json_hexadecimal_value(&src[offset + 1], 4, &codepoint)) {\n          /* escaped unicode sequences must contain 4 hexadecimal digits! */\n          state->error = json_parse_error_invalid_string_escape_sequence;\n          state->offset = offset;\n          return 1;\n        }\n\n        /* Valid sequence!\n         * see: https://en.wikipedia.org/wiki/UTF-8#Invalid_code_points.\n         *      1       7       U + 0000        U + 007F        0xxxxxxx.\n         *      2       11      U + 0080        U + 07FF        110xxxxx\n         * 10xxxxxx.\n         *      3       16      U + 0800        U + FFFF        1110xxxx\n         * 10xxxxxx        10xxxxxx.\n         *      4       21      U + 10000       U + 10FFFF      11110xxx\n         * 10xxxxxx        10xxxxxx        10xxxxxx.\n         * Note: the high and low surrogate halves used by UTF-16 (U+D800\n         * through U+DFFF) and code points not encodable by UTF-16 (those after\n         * U+10FFFF) are not legal Unicode values, and their UTF-8 encoding must\n         * be treated as an invalid byte sequence. */\n\n        if (high_surrogate != 0) {\n          /* we previously read the high half of the \\uxxxx\\uxxxx pair, so now\n           * we expect the low half. */\n          if (codepoint >= 0xdc00 &&\n              codepoint <= 0xdfff) { /* low surrogate range. */\n            data_size += 3;\n            high_surrogate = 0;\n          } else {\n            state->error = json_parse_error_invalid_string_escape_sequence;\n            state->offset = offset;\n            return 1;\n          }\n        } else if (codepoint <= 0x7f) {\n          data_size += 0;\n        } else if (codepoint <= 0x7ff) {\n          data_size += 1;\n        } else if (codepoint >= 0xd800 &&\n                   codepoint <= 0xdbff) { /* high surrogate range. */\n          /* The codepoint is the first half of a \"utf-16 surrogate pair\". so we\n           * need the other half for it to be valid: \\uHHHH\\uLLLL. */\n          if (offset + 11 > size || '\\\\' != src[offset + 5] ||\n              'u' != src[offset + 6]) {\n            state->error = json_parse_error_invalid_string_escape_sequence;\n            state->offset = offset;\n            return 1;\n          }\n          high_surrogate = codepoint;\n        } else if (codepoint >= 0xd800 &&\n                   codepoint <= 0xdfff) { /* low surrogate range. */\n          /* we did not read the other half before. */\n          state->error = json_parse_error_invalid_string_escape_sequence;\n          state->offset = offset;\n          return 1;\n        } else {\n          data_size += 2;\n        }\n        /* escaped codepoints after 0xffff are supported in json through utf-16\n         * surrogate pairs: \\uD83D\\uDD25 for U+1F525. */\n\n        offset += 5;\n        break;\n      }\n    } else if (('\\r' == src[offset]) || ('\\n' == src[offset])) {\n      if (!(json_parse_flags_allow_multi_line_strings & flags_bitset)) {\n        /* invalid escaped unicode sequence! */\n        state->error = json_parse_error_invalid_string_escape_sequence;\n        state->offset = offset;\n        return 1;\n      }\n\n      offset++;\n    } else {\n      /* skip character (valid part of sequence). */\n      offset++;\n    }\n  }\n\n  /* If the offset is equal to the size, we had a non-terminated string! */\n  if (offset == size) {\n    state->error = json_parse_error_premature_end_of_buffer;\n    state->offset = offset - 1;\n    return 1;\n  }\n\n  /* skip trailing '\"' or '\\''. */\n  offset++;\n\n  /* add enough space to store the string. */\n  state->data_size += data_size;\n\n  /* one more byte for null terminator ending the string! */\n  state->data_size++;\n\n  /* update offset. */\n  state->offset = offset;\n\n  return 0;\n}\n\njson_weak int is_valid_unquoted_key_char(const char c);\nint is_valid_unquoted_key_char(const char c) {\n  return (('0' <= c && c <= '9') || ('a' <= c && c <= 'z') ||\n          ('A' <= c && c <= 'Z') || ('_' == c));\n}\n\njson_weak int json_get_key_size(struct json_parse_state_s *state);\nint json_get_key_size(struct json_parse_state_s *state) {\n  const size_t flags_bitset = state->flags_bitset;\n\n  if (json_parse_flags_allow_unquoted_keys & flags_bitset) {\n    size_t offset = state->offset;\n    const size_t size = state->size;\n    const char *const src = state->src;\n    size_t data_size = state->data_size;\n\n    /* if we are allowing unquoted keys, first grok for a quote... */\n    if ('\"' == src[offset]) {\n      /* ... if we got a comma, just parse the key as a string as normal. */\n      return json_get_string_size(state, 1);\n    } else if ((json_parse_flags_allow_single_quoted_strings & flags_bitset) &&\n               ('\\'' == src[offset])) {\n      /* ... if we got a comma, just parse the key as a string as normal. */\n      return json_get_string_size(state, 1);\n    } else {\n      while ((offset < size) && is_valid_unquoted_key_char(src[offset])) {\n        offset++;\n        data_size++;\n      }\n\n      /* one more byte for null terminator ending the string! */\n      data_size++;\n\n      if (json_parse_flags_allow_location_information & flags_bitset) {\n        state->dom_size += sizeof(struct json_string_ex_s);\n      } else {\n        state->dom_size += sizeof(struct json_string_s);\n      }\n\n      /* update offset. */\n      state->offset = offset;\n\n      /* update data_size. */\n      state->data_size = data_size;\n\n      return 0;\n    }\n  } else {\n    /* we are only allowed to have quoted keys, so just parse a string! */\n    return json_get_string_size(state, 1);\n  }\n}\n\njson_weak int json_get_object_size(struct json_parse_state_s *state,\n                                   int is_global_object);\nint json_get_object_size(struct json_parse_state_s *state,\n                         int is_global_object) {\n  const size_t flags_bitset = state->flags_bitset;\n  const char *const src = state->src;\n  const size_t size = state->size;\n  size_t elements = 0;\n  int allow_comma = 0;\n  int found_closing_brace = 0;\n\n  if (is_global_object) {\n    /* if we found an opening '{' of an object, we actually have a normal JSON\n     * object at the root of the DOM... */\n    if (!json_skip_all_skippables(state) && '{' == state->src[state->offset]) {\n      /* . and we don't actually have a global object after all! */\n      is_global_object = 0;\n    }\n  }\n\n  if (!is_global_object) {\n    if ('{' != src[state->offset]) {\n      state->error = json_parse_error_unknown;\n      return 1;\n    }\n\n    /* skip leading '{'. */\n    state->offset++;\n  }\n\n  state->dom_size += sizeof(struct json_object_s);\n\n  if ((state->offset == size) && !is_global_object) {\n    state->error = json_parse_error_premature_end_of_buffer;\n    return 1;\n  }\n\n  do {\n    if (!is_global_object) {\n      if (json_skip_all_skippables(state)) {\n        state->error = json_parse_error_premature_end_of_buffer;\n        return 1;\n      }\n\n      if ('}' == src[state->offset]) {\n        /* skip trailing '}'. */\n        state->offset++;\n\n        found_closing_brace = 1;\n\n        /* finished the object! */\n        break;\n      }\n    } else {\n      /* we don't require brackets, so that means the object ends when the input\n       * stream ends! */\n      if (json_skip_all_skippables(state)) {\n        break;\n      }\n    }\n\n    /* if we parsed at least once element previously, grok for a comma. */\n    if (allow_comma) {\n      if (',' == src[state->offset]) {\n        /* skip comma. */\n        state->offset++;\n        allow_comma = 0;\n      } else if (json_parse_flags_allow_no_commas & flags_bitset) {\n        /* we don't require a comma, and we didn't find one, which is ok! */\n        allow_comma = 0;\n      } else {\n        /* otherwise we are required to have a comma, and we found none. */\n        state->error = json_parse_error_expected_comma_or_closing_bracket;\n        return 1;\n      }\n\n      if (json_parse_flags_allow_trailing_comma & flags_bitset) {\n        continue;\n      } else {\n        if (json_skip_all_skippables(state)) {\n          state->error = json_parse_error_premature_end_of_buffer;\n          return 1;\n        }\n      }\n    }\n\n    if (json_get_key_size(state)) {\n      /* key parsing failed! */\n      state->error = json_parse_error_invalid_string;\n      return 1;\n    }\n\n    if (json_skip_all_skippables(state)) {\n      state->error = json_parse_error_premature_end_of_buffer;\n      return 1;\n    }\n\n    if (json_parse_flags_allow_equals_in_object & flags_bitset) {\n      const char current = src[state->offset];\n      if ((':' != current) && ('=' != current)) {\n        state->error = json_parse_error_expected_colon;\n        return 1;\n      }\n    } else {\n      if (':' != src[state->offset]) {\n        state->error = json_parse_error_expected_colon;\n        return 1;\n      }\n    }\n\n    /* skip colon. */\n    state->offset++;\n\n    if (json_skip_all_skippables(state)) {\n      state->error = json_parse_error_premature_end_of_buffer;\n      return 1;\n    }\n\n    if (json_get_value_size(state, /* is_global_object = */ 0)) {\n      /* value parsing failed! */\n      return 1;\n    }\n\n    /* successfully parsed a name/value pair! */\n    elements++;\n    allow_comma = 1;\n  } while (state->offset < size);\n\n  if ((state->offset == size) && !is_global_object && !found_closing_brace) {\n    state->error = json_parse_error_premature_end_of_buffer;\n    return 1;\n  }\n\n  state->dom_size += sizeof(struct json_object_element_s) * elements;\n\n  return 0;\n}\n\njson_weak int json_get_array_size(struct json_parse_state_s *state);\nint json_get_array_size(struct json_parse_state_s *state) {\n  const size_t flags_bitset = state->flags_bitset;\n  size_t elements = 0;\n  int allow_comma = 0;\n  const char *const src = state->src;\n  const size_t size = state->size;\n\n  if ('[' != src[state->offset]) {\n    /* expected array to begin with leading '['. */\n    state->error = json_parse_error_unknown;\n    return 1;\n  }\n\n  /* skip leading '['. */\n  state->offset++;\n\n  state->dom_size += sizeof(struct json_array_s);\n\n  while (state->offset < size) {\n    if (json_skip_all_skippables(state)) {\n      state->error = json_parse_error_premature_end_of_buffer;\n      return 1;\n    }\n\n    if (']' == src[state->offset]) {\n      /* skip trailing ']'. */\n      state->offset++;\n\n      state->dom_size += sizeof(struct json_array_element_s) * elements;\n\n      /* finished the object! */\n      return 0;\n    }\n\n    /* if we parsed at least once element previously, grok for a comma. */\n    if (allow_comma) {\n      if (',' == src[state->offset]) {\n        /* skip comma. */\n        state->offset++;\n        allow_comma = 0;\n      } else if (!(json_parse_flags_allow_no_commas & flags_bitset)) {\n        state->error = json_parse_error_expected_comma_or_closing_bracket;\n        return 1;\n      }\n\n      if (json_parse_flags_allow_trailing_comma & flags_bitset) {\n        allow_comma = 0;\n        continue;\n      } else {\n        if (json_skip_all_skippables(state)) {\n          state->error = json_parse_error_premature_end_of_buffer;\n          return 1;\n        }\n      }\n    }\n\n    if (json_get_value_size(state, /* is_global_object = */ 0)) {\n      /* value parsing failed! */\n      return 1;\n    }\n\n    /* successfully parsed an array element! */\n    elements++;\n    allow_comma = 1;\n  }\n\n  /* we consumed the entire input before finding the closing ']' of the array!\n   */\n  state->error = json_parse_error_premature_end_of_buffer;\n  return 1;\n}\n\njson_weak int json_get_number_size(struct json_parse_state_s *state);\nint json_get_number_size(struct json_parse_state_s *state) {\n  const size_t flags_bitset = state->flags_bitset;\n  size_t offset = state->offset;\n  const size_t size = state->size;\n  int had_leading_digits = 0;\n  const char *const src = state->src;\n\n  state->dom_size += sizeof(struct json_number_s);\n\n  if ((json_parse_flags_allow_hexadecimal_numbers & flags_bitset) &&\n      (offset + 1 < size) && ('0' == src[offset]) &&\n      (('x' == src[offset + 1]) || ('X' == src[offset + 1]))) {\n    /* skip the leading 0x that identifies a hexadecimal number. */\n    offset += 2;\n\n    /* consume hexadecimal digits. */\n    while ((offset < size) && (('0' <= src[offset] && src[offset] <= '9') ||\n                               ('a' <= src[offset] && src[offset] <= 'f') ||\n                               ('A' <= src[offset] && src[offset] <= 'F'))) {\n      offset++;\n    }\n  } else {\n    int found_sign = 0;\n    int inf_or_nan = 0;\n\n    if ((offset < size) &&\n        (('-' == src[offset]) ||\n         ((json_parse_flags_allow_leading_plus_sign & flags_bitset) &&\n          ('+' == src[offset])))) {\n      /* skip valid leading '-' or '+'. */\n      offset++;\n\n      found_sign = 1;\n    }\n\n    if (json_parse_flags_allow_inf_and_nan & flags_bitset) {\n      const char inf[9] = \"Infinity\";\n      const size_t inf_strlen = sizeof(inf) - 1;\n      const char nan[4] = \"NaN\";\n      const size_t nan_strlen = sizeof(nan) - 1;\n\n      if (offset + inf_strlen < size) {\n        int found = 1;\n        size_t i;\n        for (i = 0; i < inf_strlen; i++) {\n          if (inf[i] != src[offset + i]) {\n            found = 0;\n            break;\n          }\n        }\n\n        if (found) {\n          /* We found our special 'Infinity' keyword! */\n          offset += inf_strlen;\n\n          inf_or_nan = 1;\n        }\n      }\n\n      if (offset + nan_strlen < size) {\n        int found = 1;\n        size_t i;\n        for (i = 0; i < nan_strlen; i++) {\n          if (nan[i] != src[offset + i]) {\n            found = 0;\n            break;\n          }\n        }\n\n        if (found) {\n          /* We found our special 'NaN' keyword! */\n          offset += nan_strlen;\n\n          inf_or_nan = 1;\n        }\n      }\n    }\n\n    if (found_sign && !inf_or_nan && (offset < size) &&\n        !('0' <= src[offset] && src[offset] <= '9')) {\n      /* check if we are allowing leading '.'. */\n      if (!(json_parse_flags_allow_leading_or_trailing_decimal_point &\n            flags_bitset) ||\n          ('.' != src[offset])) {\n        /* a leading '-' must be immediately followed by any digit! */\n        state->error = json_parse_error_invalid_number_format;\n        state->offset = offset;\n        return 1;\n      }\n    }\n\n    if ((offset < size) && ('0' == src[offset])) {\n      /* skip valid '0'. */\n      offset++;\n\n      /* we need to record whether we had any leading digits for checks later.\n       */\n      had_leading_digits = 1;\n\n      if ((offset < size) && ('0' <= src[offset] && src[offset] <= '9')) {\n        /* a leading '0' must not be immediately followed by any digit! */\n        state->error = json_parse_error_invalid_number_format;\n        state->offset = offset;\n        return 1;\n      }\n    }\n\n    /* the main digits of our number next. */\n    while ((offset < size) && ('0' <= src[offset] && src[offset] <= '9')) {\n      offset++;\n\n      /* we need to record whether we had any leading digits for checks later.\n       */\n      had_leading_digits = 1;\n    }\n\n    if ((offset < size) && ('.' == src[offset])) {\n      offset++;\n\n      if (!('0' <= src[offset] && src[offset] <= '9')) {\n        if (!(json_parse_flags_allow_leading_or_trailing_decimal_point &\n              flags_bitset) ||\n            !had_leading_digits) {\n          /* a decimal point must be followed by at least one digit. */\n          state->error = json_parse_error_invalid_number_format;\n          state->offset = offset;\n          return 1;\n        }\n      }\n\n      /* a decimal point can be followed by more digits of course! */\n      while ((offset < size) && ('0' <= src[offset] && src[offset] <= '9')) {\n        offset++;\n      }\n    }\n\n    if ((offset < size) && ('e' == src[offset] || 'E' == src[offset])) {\n      /* our number has an exponent! Skip 'e' or 'E'. */\n      offset++;\n\n      if ((offset < size) && ('-' == src[offset] || '+' == src[offset])) {\n        /* skip optional '-' or '+'. */\n        offset++;\n      }\n\n      if ((offset < size) && !('0' <= src[offset] && src[offset] <= '9')) {\n        /* an exponent must have at least one digit! */\n        state->error = json_parse_error_invalid_number_format;\n        state->offset = offset;\n        return 1;\n      }\n\n      /* consume exponent digits. */\n      do {\n        offset++;\n      } while ((offset < size) && ('0' <= src[offset] && src[offset] <= '9'));\n    }\n  }\n\n  if (offset < size) {\n    switch (src[offset]) {\n    case ' ':\n    case '\\t':\n    case '\\r':\n    case '\\n':\n    case '}':\n    case ',':\n    case ']':\n      /* all of the above are ok. */\n      break;\n    case '=':\n      if (json_parse_flags_allow_equals_in_object & flags_bitset) {\n        break;\n      }\n\n      state->error = json_parse_error_invalid_number_format;\n      state->offset = offset;\n      return 1;\n    default:\n      state->error = json_parse_error_invalid_number_format;\n      state->offset = offset;\n      return 1;\n    }\n  }\n\n  state->data_size += offset - state->offset;\n\n  /* one more byte for null terminator ending the number string! */\n  state->data_size++;\n\n  /* update offset. */\n  state->offset = offset;\n\n  return 0;\n}\n\njson_weak int json_get_value_size(struct json_parse_state_s *state,\n                                  int is_global_object);\nint json_get_value_size(struct json_parse_state_s *state,\n                        int is_global_object) {\n  const size_t flags_bitset = state->flags_bitset;\n  const char *const src = state->src;\n  size_t offset;\n  const size_t size = state->size;\n\n  if (json_parse_flags_allow_location_information & flags_bitset) {\n    state->dom_size += sizeof(struct json_value_ex_s);\n  } else {\n    state->dom_size += sizeof(struct json_value_s);\n  }\n\n  if (is_global_object) {\n    return json_get_object_size(state, /* is_global_object = */ 1);\n  } else {\n    if (json_skip_all_skippables(state)) {\n      state->error = json_parse_error_premature_end_of_buffer;\n      return 1;\n    }\n\n    /* can cache offset now. */\n    offset = state->offset;\n\n    switch (src[offset]) {\n    case '\"':\n      return json_get_string_size(state, 0);\n    case '\\'':\n      if (json_parse_flags_allow_single_quoted_strings & flags_bitset) {\n        return json_get_string_size(state, 0);\n      } else {\n        /* invalid value! */\n        state->error = json_parse_error_invalid_value;\n        return 1;\n      }\n    case '{':\n      return json_get_object_size(state, /* is_global_object = */ 0);\n    case '[':\n      return json_get_array_size(state);\n    case '-':\n    case '0':\n    case '1':\n    case '2':\n    case '3':\n    case '4':\n    case '5':\n    case '6':\n    case '7':\n    case '8':\n    case '9':\n      return json_get_number_size(state);\n    case '+':\n      if (json_parse_flags_allow_leading_plus_sign & flags_bitset) {\n        return json_get_number_size(state);\n      } else {\n        /* invalid value! */\n        state->error = json_parse_error_invalid_number_format;\n        return 1;\n      }\n    case '.':\n      if (json_parse_flags_allow_leading_or_trailing_decimal_point &\n          flags_bitset) {\n        return json_get_number_size(state);\n      } else {\n        /* invalid value! */\n        state->error = json_parse_error_invalid_number_format;\n        return 1;\n      }\n    default:\n      if ((offset + 4) <= size && 't' == src[offset + 0] &&\n          'r' == src[offset + 1] && 'u' == src[offset + 2] &&\n          'e' == src[offset + 3]) {\n        state->offset += 4;\n        return 0;\n      } else if ((offset + 5) <= size && 'f' == src[offset + 0] &&\n                 'a' == src[offset + 1] && 'l' == src[offset + 2] &&\n                 's' == src[offset + 3] && 'e' == src[offset + 4]) {\n        state->offset += 5;\n        return 0;\n      } else if ((offset + 4) <= size && 'n' == state->src[offset + 0] &&\n                 'u' == state->src[offset + 1] &&\n                 'l' == state->src[offset + 2] &&\n                 'l' == state->src[offset + 3]) {\n        state->offset += 4;\n        return 0;\n      } else if ((json_parse_flags_allow_inf_and_nan & flags_bitset) &&\n                 (offset + 3) <= size && 'N' == src[offset + 0] &&\n                 'a' == src[offset + 1] && 'N' == src[offset + 2]) {\n        return json_get_number_size(state);\n      } else if ((json_parse_flags_allow_inf_and_nan & flags_bitset) &&\n                 (offset + 8) <= size && 'I' == src[offset + 0] &&\n                 'n' == src[offset + 1] && 'f' == src[offset + 2] &&\n                 'i' == src[offset + 3] && 'n' == src[offset + 4] &&\n                 'i' == src[offset + 5] && 't' == src[offset + 6] &&\n                 'y' == src[offset + 7]) {\n        return json_get_number_size(state);\n      }\n\n      /* invalid value! */\n      state->error = json_parse_error_invalid_value;\n      return 1;\n    }\n  }\n}\n\njson_weak void json_parse_value(struct json_parse_state_s *state,\n                                int is_global_object,\n                                struct json_value_s *value);\n\njson_weak void json_parse_string(struct json_parse_state_s *state,\n                                 struct json_string_s *string);\nvoid json_parse_string(struct json_parse_state_s *state,\n                       struct json_string_s *string) {\n  size_t offset = state->offset;\n  size_t bytes_written = 0;\n  const char *const src = state->src;\n  const char quote_to_use = '\\'' == src[offset] ? '\\'' : '\"';\n  char *data = state->data;\n  unsigned long high_surrogate = 0;\n  unsigned long codepoint;\n\n  string->string = data;\n\n  /* skip leading '\"' or '\\''. */\n  offset++;\n\n  while (quote_to_use != src[offset]) {\n    if ('\\\\' == src[offset]) {\n      /* skip the reverse solidus. */\n      offset++;\n\n      switch (src[offset++]) {\n      default:\n        return; /* we cannot ever reach here. */\n      case 'u': {\n        codepoint = 0;\n        if (!json_hexadecimal_value(&src[offset], 4, &codepoint)) {\n          return; /* this shouldn't happen as the value was already validated.\n                   */\n        }\n\n        offset += 4;\n\n        if (codepoint <= 0x7fu) {\n          data[bytes_written++] = (char)codepoint; /* 0xxxxxxx. */\n        } else if (codepoint <= 0x7ffu) {\n          data[bytes_written++] =\n              (char)(0xc0u | (codepoint >> 6)); /* 110xxxxx. */\n          data[bytes_written++] =\n              (char)(0x80u | (codepoint & 0x3fu)); /* 10xxxxxx. */\n        } else if (codepoint >= 0xd800 &&\n                   codepoint <= 0xdbff) { /* high surrogate. */\n          high_surrogate = codepoint;\n          continue; /* we need the low half to form a complete codepoint. */\n        } else if (codepoint >= 0xdc00 &&\n                   codepoint <= 0xdfff) { /* low surrogate. */\n          /* combine with the previously read half to obtain the complete\n           * codepoint. */\n          const unsigned long surrogate_offset =\n              0x10000u - (0xD800u << 10) - 0xDC00u;\n          codepoint = (high_surrogate << 10) + codepoint + surrogate_offset;\n          high_surrogate = 0;\n          data[bytes_written++] =\n              (char)(0xF0u | (codepoint >> 18)); /* 11110xxx. */\n          data[bytes_written++] =\n              (char)(0x80u | ((codepoint >> 12) & 0x3fu)); /* 10xxxxxx. */\n          data[bytes_written++] =\n              (char)(0x80u | ((codepoint >> 6) & 0x3fu)); /* 10xxxxxx. */\n          data[bytes_written++] =\n              (char)(0x80u | (codepoint & 0x3fu)); /* 10xxxxxx. */\n        } else {\n          /* we assume the value was validated and thus is within the valid\n           * range. */\n          data[bytes_written++] =\n              (char)(0xe0u | (codepoint >> 12)); /* 1110xxxx. */\n          data[bytes_written++] =\n              (char)(0x80u | ((codepoint >> 6) & 0x3fu)); /* 10xxxxxx. */\n          data[bytes_written++] =\n              (char)(0x80u | (codepoint & 0x3fu)); /* 10xxxxxx. */\n        }\n      } break;\n      case '\"':\n        data[bytes_written++] = '\"';\n        break;\n      case '\\\\':\n        data[bytes_written++] = '\\\\';\n        break;\n      case '/':\n        data[bytes_written++] = '/';\n        break;\n      case 'b':\n        data[bytes_written++] = '\\b';\n        break;\n      case 'f':\n        data[bytes_written++] = '\\f';\n        break;\n      case 'n':\n        data[bytes_written++] = '\\n';\n        break;\n      case 'r':\n        data[bytes_written++] = '\\r';\n        break;\n      case 't':\n        data[bytes_written++] = '\\t';\n        break;\n      case '\\r':\n        data[bytes_written++] = '\\r';\n\n        /* check if we have a \"\\r\\n\" sequence. */\n        if ('\\n' == src[offset]) {\n          data[bytes_written++] = '\\n';\n          offset++;\n        }\n\n        break;\n      case '\\n':\n        data[bytes_written++] = '\\n';\n        break;\n      }\n    } else {\n      /* copy the character. */\n      data[bytes_written++] = src[offset++];\n    }\n  }\n\n  /* skip trailing '\"' or '\\''. */\n  offset++;\n\n  /* record the size of the string. */\n  string->string_size = bytes_written;\n\n  /* add null terminator to string. */\n  data[bytes_written++] = '\\0';\n\n  /* move data along. */\n  state->data += bytes_written;\n\n  /* update offset. */\n  state->offset = offset;\n}\n\njson_weak void json_parse_key(struct json_parse_state_s *state,\n                              struct json_string_s *string);\nvoid json_parse_key(struct json_parse_state_s *state,\n                    struct json_string_s *string) {\n  if (json_parse_flags_allow_unquoted_keys & state->flags_bitset) {\n    const char *const src = state->src;\n    char *const data = state->data;\n    size_t offset = state->offset;\n\n    /* if we are allowing unquoted keys, check for quoted anyway... */\n    if (('\"' == src[offset]) || ('\\'' == src[offset])) {\n      /* ... if we got a quote, just parse the key as a string as normal. */\n      json_parse_string(state, string);\n    } else {\n      size_t size = 0;\n\n      string->string = state->data;\n\n      while (is_valid_unquoted_key_char(src[offset])) {\n        data[size++] = src[offset++];\n      }\n\n      /* add null terminator to string. */\n      data[size] = '\\0';\n\n      /* record the size of the string. */\n      string->string_size = size++;\n\n      /* move data along. */\n      state->data += size;\n\n      /* update offset. */\n      state->offset = offset;\n    }\n  } else {\n    /* we are only allowed to have quoted keys, so just parse a string! */\n    json_parse_string(state, string);\n  }\n}\n\njson_weak void json_parse_object(struct json_parse_state_s *state,\n                                 int is_global_object,\n                                 struct json_object_s *object);\nvoid json_parse_object(struct json_parse_state_s *state, int is_global_object,\n                       struct json_object_s *object) {\n  const size_t flags_bitset = state->flags_bitset;\n  const size_t size = state->size;\n  const char *const src = state->src;\n  size_t elements = 0;\n  int allow_comma = 0;\n  struct json_object_element_s *previous = json_null;\n\n  if (is_global_object) {\n    /* if we skipped some whitespace, and then found an opening '{' of an. */\n    /* object, we actually have a normal JSON object at the root of the DOM...\n     */\n    if ('{' == src[state->offset]) {\n      /* . and we don't actually have a global object after all! */\n      is_global_object = 0;\n    }\n  }\n\n  if (!is_global_object) {\n    /* skip leading '{'. */\n    state->offset++;\n  }\n\n  (void)json_skip_all_skippables(state);\n\n  /* reset elements. */\n  elements = 0;\n\n  while (state->offset < size) {\n    struct json_object_element_s *element = json_null;\n    struct json_string_s *string = json_null;\n    struct json_value_s *value = json_null;\n\n    if (!is_global_object) {\n      (void)json_skip_all_skippables(state);\n\n      if ('}' == src[state->offset]) {\n        /* skip trailing '}'. */\n        state->offset++;\n\n        /* finished the object! */\n        break;\n      }\n    } else {\n      if (json_skip_all_skippables(state)) {\n        /* global object ends when the file ends! */\n        break;\n      }\n    }\n\n    /* if we parsed at least one element previously, grok for a comma. */\n    if (allow_comma) {\n      if (',' == src[state->offset]) {\n        /* skip comma. */\n        state->offset++;\n        allow_comma = 0;\n        continue;\n      }\n    }\n\n    element = (struct json_object_element_s *)state->dom;\n\n    state->dom += sizeof(struct json_object_element_s);\n\n    if (json_null == previous) {\n      /* this is our first element, so record it in our object. */\n      object->start = element;\n    } else {\n      previous->next = element;\n    }\n\n    previous = element;\n\n    if (json_parse_flags_allow_location_information & flags_bitset) {\n      struct json_string_ex_s *string_ex =\n          (struct json_string_ex_s *)state->dom;\n      state->dom += sizeof(struct json_string_ex_s);\n\n      string_ex->offset = state->offset;\n      string_ex->line_no = state->line_no;\n      string_ex->row_no = state->offset - state->line_offset;\n\n      string = &(string_ex->string);\n    } else {\n      string = (struct json_string_s *)state->dom;\n      state->dom += sizeof(struct json_string_s);\n    }\n\n    element->name = string;\n\n    (void)json_parse_key(state, string);\n\n    (void)json_skip_all_skippables(state);\n\n    /* skip colon or equals. */\n    state->offset++;\n\n    (void)json_skip_all_skippables(state);\n\n    if (json_parse_flags_allow_location_information & flags_bitset) {\n      struct json_value_ex_s *value_ex = (struct json_value_ex_s *)state->dom;\n      state->dom += sizeof(struct json_value_ex_s);\n\n      value_ex->offset = state->offset;\n      value_ex->line_no = state->line_no;\n      value_ex->row_no = state->offset - state->line_offset;\n\n      value = &(value_ex->value);\n    } else {\n      value = (struct json_value_s *)state->dom;\n      state->dom += sizeof(struct json_value_s);\n    }\n\n    element->value = value;\n\n    json_parse_value(state, /* is_global_object = */ 0, value);\n\n    /* successfully parsed a name/value pair! */\n    elements++;\n    allow_comma = 1;\n  }\n\n  /* if we had at least one element, end the linked list. */\n  if (previous) {\n    previous->next = json_null;\n  }\n\n  if (0 == elements) {\n    object->start = json_null;\n  }\n\n  object->length = elements;\n}\n\njson_weak void json_parse_array(struct json_parse_state_s *state,\n                                struct json_array_s *array);\nvoid json_parse_array(struct json_parse_state_s *state,\n                      struct json_array_s *array) {\n  const char *const src = state->src;\n  const size_t size = state->size;\n  size_t elements = 0;\n  int allow_comma = 0;\n  struct json_array_element_s *previous = json_null;\n\n  /* skip leading '['. */\n  state->offset++;\n\n  (void)json_skip_all_skippables(state);\n\n  /* reset elements. */\n  elements = 0;\n\n  do {\n    struct json_array_element_s *element = json_null;\n    struct json_value_s *value = json_null;\n\n    (void)json_skip_all_skippables(state);\n\n    if (']' == src[state->offset]) {\n      /* skip trailing ']'. */\n      state->offset++;\n\n      /* finished the array! */\n      break;\n    }\n\n    /* if we parsed at least one element previously, grok for a comma. */\n    if (allow_comma) {\n      if (',' == src[state->offset]) {\n        /* skip comma. */\n        state->offset++;\n        allow_comma = 0;\n        continue;\n      }\n    }\n\n    element = (struct json_array_element_s *)state->dom;\n\n    state->dom += sizeof(struct json_array_element_s);\n\n    if (json_null == previous) {\n      /* this is our first element, so record it in our array. */\n      array->start = element;\n    } else {\n      previous->next = element;\n    }\n\n    previous = element;\n\n    if (json_parse_flags_allow_location_information & state->flags_bitset) {\n      struct json_value_ex_s *value_ex = (struct json_value_ex_s *)state->dom;\n      state->dom += sizeof(struct json_value_ex_s);\n\n      value_ex->offset = state->offset;\n      value_ex->line_no = state->line_no;\n      value_ex->row_no = state->offset - state->line_offset;\n\n      value = &(value_ex->value);\n    } else {\n      value = (struct json_value_s *)state->dom;\n      state->dom += sizeof(struct json_value_s);\n    }\n\n    element->value = value;\n\n    json_parse_value(state, /* is_global_object = */ 0, value);\n\n    /* successfully parsed an array element! */\n    elements++;\n    allow_comma = 1;\n  } while (state->offset < size);\n\n  /* end the linked list. */\n  if (previous) {\n    previous->next = json_null;\n  }\n\n  if (0 == elements) {\n    array->start = json_null;\n  }\n\n  array->length = elements;\n}\n\njson_weak void json_parse_number(struct json_parse_state_s *state,\n                                 struct json_number_s *number);\nvoid json_parse_number(struct json_parse_state_s *state,\n                       struct json_number_s *number) {\n  const size_t flags_bitset = state->flags_bitset;\n  size_t offset = state->offset;\n  const size_t size = state->size;\n  size_t bytes_written = 0;\n  const char *const src = state->src;\n  char *data = state->data;\n\n  number->number = data;\n\n  if (json_parse_flags_allow_hexadecimal_numbers & flags_bitset) {\n    if (('0' == src[offset]) &&\n        (('x' == src[offset + 1]) || ('X' == src[offset + 1]))) {\n      /* consume hexadecimal digits. */\n      while ((offset < size) &&\n             (('0' <= src[offset] && src[offset] <= '9') ||\n              ('a' <= src[offset] && src[offset] <= 'f') ||\n              ('A' <= src[offset] && src[offset] <= 'F') ||\n              ('x' == src[offset]) || ('X' == src[offset]))) {\n        data[bytes_written++] = src[offset++];\n      }\n    }\n  }\n\n  while (offset < size) {\n    int end = 0;\n\n    switch (src[offset]) {\n    case '0':\n    case '1':\n    case '2':\n    case '3':\n    case '4':\n    case '5':\n    case '6':\n    case '7':\n    case '8':\n    case '9':\n    case '.':\n    case 'e':\n    case 'E':\n    case '+':\n    case '-':\n      data[bytes_written++] = src[offset++];\n      break;\n    default:\n      end = 1;\n      break;\n    }\n\n    if (0 != end) {\n      break;\n    }\n  }\n\n  if (json_parse_flags_allow_inf_and_nan & flags_bitset) {\n    const size_t inf_strlen = 8; /* = strlen(\"Infinity\");. */\n    const size_t nan_strlen = 3; /* = strlen(\"NaN\");. */\n\n    if (offset + inf_strlen < size) {\n      if ('I' == src[offset]) {\n        size_t i;\n        /* We found our special 'Infinity' keyword! */\n        for (i = 0; i < inf_strlen; i++) {\n          data[bytes_written++] = src[offset++];\n        }\n      }\n    }\n\n    if (offset + nan_strlen < size) {\n      if ('N' == src[offset]) {\n        size_t i;\n        /* We found our special 'NaN' keyword! */\n        for (i = 0; i < nan_strlen; i++) {\n          data[bytes_written++] = src[offset++];\n        }\n      }\n    }\n  }\n\n  /* record the size of the number. */\n  number->number_size = bytes_written;\n  /* add null terminator to number string. */\n  data[bytes_written++] = '\\0';\n  /* move data along. */\n  state->data += bytes_written;\n  /* update offset. */\n  state->offset = offset;\n}\n\njson_weak void json_parse_value(struct json_parse_state_s *state,\n                                int is_global_object,\n                                struct json_value_s *value);\nvoid json_parse_value(struct json_parse_state_s *state, int is_global_object,\n                      struct json_value_s *value) {\n  const size_t flags_bitset = state->flags_bitset;\n  const char *const src = state->src;\n  const size_t size = state->size;\n  size_t offset;\n\n  (void)json_skip_all_skippables(state);\n\n  /* cache offset now. */\n  offset = state->offset;\n\n  if (is_global_object) {\n    value->type = json_type_object;\n    value->payload = state->dom;\n    state->dom += sizeof(struct json_object_s);\n    json_parse_object(state, /* is_global_object = */ 1,\n                      (struct json_object_s *)value->payload);\n  } else {\n    switch (src[offset]) {\n    case '\"':\n    case '\\'':\n      value->type = json_type_string;\n      value->payload = state->dom;\n      state->dom += sizeof(struct json_string_s);\n      json_parse_string(state, (struct json_string_s *)value->payload);\n      break;\n    case '{':\n      value->type = json_type_object;\n      value->payload = state->dom;\n      state->dom += sizeof(struct json_object_s);\n      json_parse_object(state, /* is_global_object = */ 0,\n                        (struct json_object_s *)value->payload);\n      break;\n    case '[':\n      value->type = json_type_array;\n      value->payload = state->dom;\n      state->dom += sizeof(struct json_array_s);\n      json_parse_array(state, (struct json_array_s *)value->payload);\n      break;\n    case '-':\n    case '+':\n    case '0':\n    case '1':\n    case '2':\n    case '3':\n    case '4':\n    case '5':\n    case '6':\n    case '7':\n    case '8':\n    case '9':\n    case '.':\n      value->type = json_type_number;\n      value->payload = state->dom;\n      state->dom += sizeof(struct json_number_s);\n      json_parse_number(state, (struct json_number_s *)value->payload);\n      break;\n    default:\n      if ((offset + 4) <= size && 't' == src[offset + 0] &&\n          'r' == src[offset + 1] && 'u' == src[offset + 2] &&\n          'e' == src[offset + 3]) {\n        value->type = json_type_true;\n        value->payload = json_null;\n        state->offset += 4;\n      } else if ((offset + 5) <= size && 'f' == src[offset + 0] &&\n                 'a' == src[offset + 1] && 'l' == src[offset + 2] &&\n                 's' == src[offset + 3] && 'e' == src[offset + 4]) {\n        value->type = json_type_false;\n        value->payload = json_null;\n        state->offset += 5;\n      } else if ((offset + 4) <= size && 'n' == src[offset + 0] &&\n                 'u' == src[offset + 1] && 'l' == src[offset + 2] &&\n                 'l' == src[offset + 3]) {\n        value->type = json_type_null;\n        value->payload = json_null;\n        state->offset += 4;\n      } else if ((json_parse_flags_allow_inf_and_nan & flags_bitset) &&\n                 (offset + 3) <= size && 'N' == src[offset + 0] &&\n                 'a' == src[offset + 1] && 'N' == src[offset + 2]) {\n        value->type = json_type_number;\n        value->payload = state->dom;\n        state->dom += sizeof(struct json_number_s);\n        json_parse_number(state, (struct json_number_s *)value->payload);\n      } else if ((json_parse_flags_allow_inf_and_nan & flags_bitset) &&\n                 (offset + 8) <= size && 'I' == src[offset + 0] &&\n                 'n' == src[offset + 1] && 'f' == src[offset + 2] &&\n                 'i' == src[offset + 3] && 'n' == src[offset + 4] &&\n                 'i' == src[offset + 5] && 't' == src[offset + 6] &&\n                 'y' == src[offset + 7]) {\n        value->type = json_type_number;\n        value->payload = state->dom;\n        state->dom += sizeof(struct json_number_s);\n        json_parse_number(state, (struct json_number_s *)value->payload);\n      }\n      break;\n    }\n  }\n}\n\nstruct json_value_s *\njson_parse_ex(const void *src, size_t src_size, size_t flags_bitset,\n              void *(*alloc_func_ptr)(void *user_data, size_t size),\n              void *user_data, struct json_parse_result_s *result) {\n  struct json_parse_state_s state;\n  void *allocation;\n  struct json_value_s *value;\n  size_t total_size;\n  int input_error;\n\n  if (result) {\n    result->error = json_parse_error_none;\n    result->error_offset = 0;\n    result->error_line_no = 0;\n    result->error_row_no = 0;\n  }\n\n  if (json_null == src) {\n    /* invalid src pointer was null! */\n    return json_null;\n  }\n\n  state.src = (const char *)src;\n  state.size = src_size;\n  state.offset = 0;\n  state.line_no = 1;\n  state.line_offset = 0;\n  state.error = json_parse_error_none;\n  state.dom_size = 0;\n  state.data_size = 0;\n  state.flags_bitset = flags_bitset;\n\n  input_error = json_get_value_size(\n      &state, (int)(json_parse_flags_allow_global_object & state.flags_bitset));\n\n  if (0 == input_error) {\n    json_skip_all_skippables(&state);\n\n    if (state.offset != state.size) {\n      /* our parsing didn't have an error, but there are characters remaining in\n       * the input that weren't part of the JSON! */\n\n      state.error = json_parse_error_unexpected_trailing_characters;\n      input_error = 1;\n    }\n  }\n\n  if (input_error) {\n    /* parsing value's size failed (most likely an invalid JSON DOM!). */\n    if (result) {\n      result->error = state.error;\n      result->error_offset = state.offset;\n      result->error_line_no = state.line_no;\n      result->error_row_no = state.offset - state.line_offset;\n    }\n    return json_null;\n  }\n\n  /* our total allocation is the combination of the dom and data sizes (we. */\n  /* first encode the structure of the JSON, and then the data referenced by. */\n  /* the JSON values). */\n  total_size = state.dom_size + state.data_size;\n\n  if (json_null == alloc_func_ptr) {\n    allocation = malloc(total_size);\n  } else {\n    allocation = alloc_func_ptr(user_data, total_size);\n  }\n\n  if (json_null == allocation) {\n    /* malloc failed! */\n    if (result) {\n      result->error = json_parse_error_allocator_failed;\n      result->error_offset = 0;\n      result->error_line_no = 0;\n      result->error_row_no = 0;\n    }\n\n    return json_null;\n  }\n\n  /* reset offset so we can reuse it. */\n  state.offset = 0;\n\n  /* reset the line information so we can reuse it. */\n  state.line_no = 1;\n  state.line_offset = 0;\n\n  state.dom = (char *)allocation;\n  state.data = state.dom + state.dom_size;\n\n  if (json_parse_flags_allow_location_information & state.flags_bitset) {\n    struct json_value_ex_s *value_ex = (struct json_value_ex_s *)state.dom;\n    state.dom += sizeof(struct json_value_ex_s);\n\n    value_ex->offset = state.offset;\n    value_ex->line_no = state.line_no;\n    value_ex->row_no = state.offset - state.line_offset;\n\n    value = &(value_ex->value);\n  } else {\n    value = (struct json_value_s *)state.dom;\n    state.dom += sizeof(struct json_value_s);\n  }\n\n  json_parse_value(\n      &state, (int)(json_parse_flags_allow_global_object & state.flags_bitset),\n      value);\n\n  return (struct json_value_s *)allocation;\n}\n\nstruct json_value_s *json_parse(const void *src, size_t src_size) {\n  return json_parse_ex(src, src_size, json_parse_flags_default, json_null,\n                       json_null, json_null);\n}\n\nstruct json_extract_result_s {\n  size_t dom_size;\n  size_t data_size;\n};\n\nstruct json_value_s *json_extract_value(const struct json_value_s *value) {\n  return json_extract_value_ex(value, json_null, json_null);\n}\n\njson_weak struct json_extract_result_s\njson_extract_get_number_size(const struct json_number_s *const number);\njson_weak struct json_extract_result_s\njson_extract_get_string_size(const struct json_string_s *const string);\njson_weak struct json_extract_result_s\njson_extract_get_object_size(const struct json_object_s *const object);\njson_weak struct json_extract_result_s\njson_extract_get_array_size(const struct json_array_s *const array);\njson_weak struct json_extract_result_s\njson_extract_get_value_size(const struct json_value_s *const value);\n\nstruct json_extract_result_s\njson_extract_get_number_size(const struct json_number_s *const number) {\n  struct json_extract_result_s result;\n  result.dom_size = sizeof(struct json_number_s);\n  result.data_size = number->number_size;\n  return result;\n}\n\nstruct json_extract_result_s\njson_extract_get_string_size(const struct json_string_s *const string) {\n  struct json_extract_result_s result;\n  result.dom_size = sizeof(struct json_string_s);\n  result.data_size = string->string_size + 1;\n  return result;\n}\n\nstruct json_extract_result_s\njson_extract_get_object_size(const struct json_object_s *const object) {\n  struct json_extract_result_s result;\n  size_t i;\n  const struct json_object_element_s *element = object->start;\n\n  result.dom_size = sizeof(struct json_object_s) +\n                    (sizeof(struct json_object_element_s) * object->length);\n  result.data_size = 0;\n\n  for (i = 0; i < object->length; i++) {\n    const struct json_extract_result_s string_result =\n        json_extract_get_string_size(element->name);\n    const struct json_extract_result_s value_result =\n        json_extract_get_value_size(element->value);\n\n    result.dom_size += string_result.dom_size;\n    result.data_size += string_result.data_size;\n\n    result.dom_size += value_result.dom_size;\n    result.data_size += value_result.data_size;\n\n    element = element->next;\n  }\n\n  return result;\n}\n\nstruct json_extract_result_s\njson_extract_get_array_size(const struct json_array_s *const array) {\n  struct json_extract_result_s result;\n  size_t i;\n  const struct json_array_element_s *element = array->start;\n\n  result.dom_size = sizeof(struct json_array_s) +\n                    (sizeof(struct json_array_element_s) * array->length);\n  result.data_size = 0;\n\n  for (i = 0; i < array->length; i++) {\n    const struct json_extract_result_s value_result =\n        json_extract_get_value_size(element->value);\n\n    result.dom_size += value_result.dom_size;\n    result.data_size += value_result.data_size;\n\n    element = element->next;\n  }\n\n  return result;\n}\n\nstruct json_extract_result_s\njson_extract_get_value_size(const struct json_value_s *const value) {\n  struct json_extract_result_s result = {0, 0};\n\n  switch (value->type) {\n  default:\n    break;\n  case json_type_object:\n    result = json_extract_get_object_size(\n        (const struct json_object_s *)value->payload);\n    break;\n  case json_type_array:\n    result = json_extract_get_array_size(\n        (const struct json_array_s *)value->payload);\n    break;\n  case json_type_number:\n    result = json_extract_get_number_size(\n        (const struct json_number_s *)value->payload);\n    break;\n  case json_type_string:\n    result = json_extract_get_string_size(\n        (const struct json_string_s *)value->payload);\n    break;\n  }\n\n  result.dom_size += sizeof(struct json_value_s);\n\n  return result;\n}\n\nstruct json_extract_state_s {\n  char *dom;\n  char *data;\n};\n\njson_weak void json_extract_copy_value(struct json_extract_state_s *const state,\n                                       const struct json_value_s *const value);\nvoid json_extract_copy_value(struct json_extract_state_s *const state,\n                             const struct json_value_s *const value) {\n  struct json_string_s *string;\n  struct json_number_s *number;\n  struct json_object_s *object;\n  struct json_array_s *array;\n  struct json_value_s *new_value;\n\n  memcpy(state->dom, value, sizeof(struct json_value_s));\n  new_value = (struct json_value_s *)state->dom;\n  state->dom += sizeof(struct json_value_s);\n  new_value->payload = state->dom;\n\n  if (json_type_string == value->type) {\n    memcpy(state->dom, value->payload, sizeof(struct json_string_s));\n    string = (struct json_string_s *)state->dom;\n    state->dom += sizeof(struct json_string_s);\n\n    memcpy(state->data, string->string, string->string_size + 1);\n    string->string = state->data;\n    state->data += string->string_size + 1;\n  } else if (json_type_number == value->type) {\n    memcpy(state->dom, value->payload, sizeof(struct json_number_s));\n    number = (struct json_number_s *)state->dom;\n    state->dom += sizeof(struct json_number_s);\n\n    memcpy(state->data, number->number, number->number_size);\n    number->number = state->data;\n    state->data += number->number_size;\n  } else if (json_type_object == value->type) {\n    struct json_object_element_s *element;\n    size_t i;\n\n    memcpy(state->dom, value->payload, sizeof(struct json_object_s));\n    object = (struct json_object_s *)state->dom;\n    state->dom += sizeof(struct json_object_s);\n\n    element = object->start;\n    object->start = (struct json_object_element_s *)state->dom;\n\n    for (i = 0; i < object->length; i++) {\n      struct json_value_s *previous_value;\n      struct json_object_element_s *previous_element;\n\n      memcpy(state->dom, element, sizeof(struct json_object_element_s));\n      element = (struct json_object_element_s *)state->dom;\n      state->dom += sizeof(struct json_object_element_s);\n\n      string = element->name;\n      memcpy(state->dom, string, sizeof(struct json_string_s));\n      string = (struct json_string_s *)state->dom;\n      state->dom += sizeof(struct json_string_s);\n      element->name = string;\n\n      memcpy(state->data, string->string, string->string_size + 1);\n      string->string = state->data;\n      state->data += string->string_size + 1;\n\n      previous_value = element->value;\n      element->value = (struct json_value_s *)state->dom;\n      json_extract_copy_value(state, previous_value);\n\n      previous_element = element;\n      element = element->next;\n\n      if (element) {\n        previous_element->next = (struct json_object_element_s *)state->dom;\n      }\n    }\n  } else if (json_type_array == value->type) {\n    struct json_array_element_s *element;\n    size_t i;\n\n    memcpy(state->dom, value->payload, sizeof(struct json_array_s));\n    array = (struct json_array_s *)state->dom;\n    state->dom += sizeof(struct json_array_s);\n\n    element = array->start;\n    array->start = (struct json_array_element_s *)state->dom;\n\n    for (i = 0; i < array->length; i++) {\n      struct json_value_s *previous_value;\n      struct json_array_element_s *previous_element;\n\n      memcpy(state->dom, element, sizeof(struct json_array_element_s));\n      element = (struct json_array_element_s *)state->dom;\n      state->dom += sizeof(struct json_array_element_s);\n\n      previous_value = element->value;\n      element->value = (struct json_value_s *)state->dom;\n      json_extract_copy_value(state, previous_value);\n\n      previous_element = element;\n      element = element->next;\n\n      if (element) {\n        previous_element->next = (struct json_array_element_s *)state->dom;\n      }\n    }\n  }\n}\n\nstruct json_value_s *json_extract_value_ex(const struct json_value_s *value,\n                                           void *(*alloc_func_ptr)(void *,\n                                                                   size_t),\n                                           void *user_data) {\n  void *allocation;\n  struct json_extract_result_s result;\n  struct json_extract_state_s state;\n  size_t total_size;\n\n  if (json_null == value) {\n    /* invalid value was null! */\n    return json_null;\n  }\n\n  result = json_extract_get_value_size(value);\n  total_size = result.dom_size + result.data_size;\n\n  if (json_null == alloc_func_ptr) {\n    allocation = malloc(total_size);\n  } else {\n    allocation = alloc_func_ptr(user_data, total_size);\n  }\n\n  state.dom = (char *)allocation;\n  state.data = state.dom + result.dom_size;\n\n  json_extract_copy_value(&state, value);\n\n  return (struct json_value_s *)allocation;\n}\n\nstruct json_string_s *json_value_as_string(struct json_value_s *const value) {\n  if (value->type != json_type_string) {\n    return json_null;\n  }\n\n  return (struct json_string_s *)value->payload;\n}\n\nstruct json_number_s *json_value_as_number(struct json_value_s *const value) {\n  if (value->type != json_type_number) {\n    return json_null;\n  }\n\n  return (struct json_number_s *)value->payload;\n}\n\nstruct json_object_s *json_value_as_object(struct json_value_s *const value) {\n  if (value->type != json_type_object) {\n    return json_null;\n  }\n\n  return (struct json_object_s *)value->payload;\n}\n\nstruct json_array_s *json_value_as_array(struct json_value_s *const value) {\n  if (value->type != json_type_array) {\n    return json_null;\n  }\n\n  return (struct json_array_s *)value->payload;\n}\n\nint json_value_is_true(const struct json_value_s *const value) {\n  return value->type == json_type_true;\n}\n\nint json_value_is_false(const struct json_value_s *const value) {\n  return value->type == json_type_false;\n}\n\nint json_value_is_null(const struct json_value_s *const value) {\n  return value->type == json_type_null;\n}\n\njson_weak int\njson_write_minified_get_value_size(const struct json_value_s *value,\n                                   size_t *size);\n\njson_weak int json_write_get_number_size(const struct json_number_s *number,\n                                         size_t *size);\nint json_write_get_number_size(const struct json_number_s *number,\n                               size_t *size) {\n  json_uintmax_t parsed_number;\n  size_t i;\n\n  if (number->number_size >= 2) {\n    switch (number->number[1]) {\n    default:\n      break;\n    case 'x':\n    case 'X':\n      /* the number is a json_parse_flags_allow_hexadecimal_numbers hexadecimal\n       * so we have to do extra work to convert it to a non-hexadecimal for JSON\n       * output. */\n      parsed_number = json_strtoumax(number->number, json_null, 0);\n\n      i = 0;\n\n      while (0 != parsed_number) {\n        parsed_number /= 10;\n        i++;\n      }\n\n      *size += i;\n      return 0;\n    }\n  }\n\n  /* check to see if the number has leading/trailing decimal point. */\n  i = 0;\n\n  /* skip any leading '+' or '-'. */\n  if ((i < number->number_size) &&\n      (('+' == number->number[i]) || ('-' == number->number[i]))) {\n    i++;\n  }\n\n  /* check if we have infinity. */\n  if ((i < number->number_size) && ('I' == number->number[i])) {\n    const char *inf = \"Infinity\";\n    size_t k;\n\n    for (k = i; k < number->number_size; k++) {\n      const char c = *inf++;\n\n      /* Check if we found the Infinity string! */\n      if ('\\0' == c) {\n        break;\n      } else if (c != number->number[k]) {\n        break;\n      }\n    }\n\n    if ('\\0' == *inf) {\n      /* Inf becomes 1.7976931348623158e308 because JSON can't support it. */\n      *size += 22;\n\n      /* if we had a leading '-' we need to record it in the JSON output. */\n      if ('-' == number->number[0]) {\n        *size += 1;\n      }\n    }\n\n    return 0;\n  }\n\n  /* check if we have nan. */\n  if ((i < number->number_size) && ('N' == number->number[i])) {\n    const char *nan = \"NaN\";\n    size_t k;\n\n    for (k = i; k < number->number_size; k++) {\n      const char c = *nan++;\n\n      /* Check if we found the NaN string! */\n      if ('\\0' == c) {\n        break;\n      } else if (c != number->number[k]) {\n        break;\n      }\n    }\n\n    if ('\\0' == *nan) {\n      /* NaN becomes 1 because JSON can't support it. */\n      *size += 1;\n\n      return 0;\n    }\n  }\n\n  /* if we had a leading decimal point. */\n  if ((i < number->number_size) && ('.' == number->number[i])) {\n    /* 1 + because we had a leading decimal point. */\n    *size += 1;\n    goto cleanup;\n  }\n\n  for (; i < number->number_size; i++) {\n    const char c = number->number[i];\n    if (!('0' <= c && c <= '9')) {\n      break;\n    }\n  }\n\n  /* if we had a trailing decimal point. */\n  if ((i + 1 == number->number_size) && ('.' == number->number[i])) {\n    /* 1 + because we had a trailing decimal point. */\n    *size += 1;\n    goto cleanup;\n  }\n\ncleanup:\n  *size += number->number_size; /* the actual string of the number. */\n\n  /* if we had a leading '+' we don't record it in the JSON output. */\n  if ('+' == number->number[0]) {\n    *size -= 1;\n  }\n\n  return 0;\n}\n\njson_weak int json_write_get_string_size(const struct json_string_s *string,\n                                         size_t *size);\nint json_write_get_string_size(const struct json_string_s *string,\n                               size_t *size) {\n  size_t i;\n  for (i = 0; i < string->string_size; i++) {\n    switch (string->string[i]) {\n    case '\"':\n    case '\\\\':\n    case '\\b':\n    case '\\f':\n    case '\\n':\n    case '\\r':\n    case '\\t':\n      *size += 2;\n      break;\n    default:\n      *size += 1;\n      break;\n    }\n  }\n\n  *size += 2; /* need to encode the surrounding '\"' characters. */\n\n  return 0;\n}\n\njson_weak int\njson_write_minified_get_array_size(const struct json_array_s *array,\n                                   size_t *size);\nint json_write_minified_get_array_size(const struct json_array_s *array,\n                                       size_t *size) {\n  struct json_array_element_s *element;\n\n  *size += 2; /* '[' and ']'. */\n\n  if (1 < array->length) {\n    *size += array->length - 1; /* ','s seperate each element. */\n  }\n\n  for (element = array->start; json_null != element; element = element->next) {\n    if (json_write_minified_get_value_size(element->value, size)) {\n      /* value was malformed! */\n      return 1;\n    }\n  }\n\n  return 0;\n}\n\njson_weak int\njson_write_minified_get_object_size(const struct json_object_s *object,\n                                    size_t *size);\nint json_write_minified_get_object_size(const struct json_object_s *object,\n                                        size_t *size) {\n  struct json_object_element_s *element;\n\n  *size += 2; /* '{' and '}'. */\n\n  *size += object->length; /* ':'s seperate each name/value pair. */\n\n  if (1 < object->length) {\n    *size += object->length - 1; /* ','s seperate each element. */\n  }\n\n  for (element = object->start; json_null != element; element = element->next) {\n    if (json_write_get_string_size(element->name, size)) {\n      /* string was malformed! */\n      return 1;\n    }\n\n    if (json_write_minified_get_value_size(element->value, size)) {\n      /* value was malformed! */\n      return 1;\n    }\n  }\n\n  return 0;\n}\n\njson_weak int\njson_write_minified_get_value_size(const struct json_value_s *value,\n                                   size_t *size);\nint json_write_minified_get_value_size(const struct json_value_s *value,\n                                       size_t *size) {\n  switch (value->type) {\n  default:\n    /* unknown value type found! */\n    return 1;\n  case json_type_number:\n    return json_write_get_number_size((struct json_number_s *)value->payload,\n                                      size);\n  case json_type_string:\n    return json_write_get_string_size((struct json_string_s *)value->payload,\n                                      size);\n  case json_type_array:\n    return json_write_minified_get_array_size(\n        (struct json_array_s *)value->payload, size);\n  case json_type_object:\n    return json_write_minified_get_object_size(\n        (struct json_object_s *)value->payload, size);\n  case json_type_true:\n    *size += 4; /* the string \"true\". */\n    return 0;\n  case json_type_false:\n    *size += 5; /* the string \"false\". */\n    return 0;\n  case json_type_null:\n    *size += 4; /* the string \"null\". */\n    return 0;\n  }\n}\n\njson_weak char *json_write_minified_value(const struct json_value_s *value,\n                                          char *data);\n\njson_weak char *json_write_number(const struct json_number_s *number,\n                                  char *data);\nchar *json_write_number(const struct json_number_s *number, char *data) {\n  json_uintmax_t parsed_number, backup;\n  size_t i;\n\n  if (number->number_size >= 2) {\n    switch (number->number[1]) {\n    default:\n      break;\n    case 'x':\n    case 'X':\n      /* The number is a json_parse_flags_allow_hexadecimal_numbers hexadecimal\n       * so we have to do extra work to convert it to a non-hexadecimal for JSON\n       * output. */\n      parsed_number = json_strtoumax(number->number, json_null, 0);\n\n      /* We need a copy of parsed number twice, so take a backup of it. */\n      backup = parsed_number;\n\n      i = 0;\n\n      while (0 != parsed_number) {\n        parsed_number /= 10;\n        i++;\n      }\n\n      /* Restore parsed_number to its original value stored in the backup. */\n      parsed_number = backup;\n\n      /* Now use backup to take a copy of i, or the length of the string. */\n      backup = i;\n\n      do {\n        *(data + i - 1) = '0' + (char)(parsed_number % 10);\n        parsed_number /= 10;\n        i--;\n      } while (0 != parsed_number);\n\n      data += backup;\n\n      return data;\n    }\n  }\n\n  /* check to see if the number has leading/trailing decimal point. */\n  i = 0;\n\n  /* skip any leading '-'. */\n  if ((i < number->number_size) &&\n      (('+' == number->number[i]) || ('-' == number->number[i]))) {\n    i++;\n  }\n\n  /* check if we have infinity. */\n  if ((i < number->number_size) && ('I' == number->number[i])) {\n    const char *inf = \"Infinity\";\n    size_t k;\n\n    for (k = i; k < number->number_size; k++) {\n      const char c = *inf++;\n\n      /* Check if we found the Infinity string! */\n      if ('\\0' == c) {\n        break;\n      } else if (c != number->number[k]) {\n        break;\n      }\n    }\n\n    if ('\\0' == *inf++) {\n      const char *dbl_max;\n\n      /* if we had a leading '-' we need to record it in the JSON output. */\n      if ('-' == number->number[0]) {\n        *data++ = '-';\n      }\n\n      /* Inf becomes 1.7976931348623158e308 because JSON can't support it. */\n      for (dbl_max = \"1.7976931348623158e308\"; '\\0' != *dbl_max; dbl_max++) {\n        *data++ = *dbl_max;\n      }\n\n      return data;\n    }\n  }\n\n  /* check if we have nan. */\n  if ((i < number->number_size) && ('N' == number->number[i])) {\n    const char *nan = \"NaN\";\n    size_t k;\n\n    for (k = i; k < number->number_size; k++) {\n      const char c = *nan++;\n\n      /* Check if we found the NaN string! */\n      if ('\\0' == c) {\n        break;\n      } else if (c != number->number[k]) {\n        break;\n      }\n    }\n\n    if ('\\0' == *nan++) {\n      /* NaN becomes 0 because JSON can't support it. */\n      *data++ = '0';\n      return data;\n    }\n  }\n\n  /* if we had a leading decimal point. */\n  if ((i < number->number_size) && ('.' == number->number[i])) {\n    i = 0;\n\n    /* skip any leading '+'. */\n    if ('+' == number->number[i]) {\n      i++;\n    }\n\n    /* output the leading '-' if we had one. */\n    if ('-' == number->number[i]) {\n      *data++ = '-';\n      i++;\n    }\n\n    /* insert a '0' to fix the leading decimal point for JSON output. */\n    *data++ = '0';\n\n    /* and output the rest of the number as normal. */\n    for (; i < number->number_size; i++) {\n      *data++ = number->number[i];\n    }\n\n    return data;\n  }\n\n  for (; i < number->number_size; i++) {\n    const char c = number->number[i];\n    if (!('0' <= c && c <= '9')) {\n      break;\n    }\n  }\n\n  /* if we had a trailing decimal point. */\n  if ((i + 1 == number->number_size) && ('.' == number->number[i])) {\n    i = 0;\n\n    /* skip any leading '+'. */\n    if ('+' == number->number[i]) {\n      i++;\n    }\n\n    /* output the leading '-' if we had one. */\n    if ('-' == number->number[i]) {\n      *data++ = '-';\n      i++;\n    }\n\n    /* and output the rest of the number as normal. */\n    for (; i < number->number_size; i++) {\n      *data++ = number->number[i];\n    }\n\n    /* insert a '0' to fix the trailing decimal point for JSON output. */\n    *data++ = '0';\n\n    return data;\n  }\n\n  i = 0;\n\n  /* skip any leading '+'. */\n  if ('+' == number->number[i]) {\n    i++;\n  }\n\n  for (; i < number->number_size; i++) {\n    *data++ = number->number[i];\n  }\n\n  return data;\n}\n\njson_weak char *json_write_string(const struct json_string_s *string,\n                                  char *data);\nchar *json_write_string(const struct json_string_s *string, char *data) {\n  size_t i;\n\n  *data++ = '\"'; /* open the string. */\n\n  for (i = 0; i < string->string_size; i++) {\n    switch (string->string[i]) {\n    case '\"':\n      *data++ = '\\\\'; /* escape the control character. */\n      *data++ = '\"';\n      break;\n    case '\\\\':\n      *data++ = '\\\\'; /* escape the control character. */\n      *data++ = '\\\\';\n      break;\n    case '\\b':\n      *data++ = '\\\\'; /* escape the control character. */\n      *data++ = 'b';\n      break;\n    case '\\f':\n      *data++ = '\\\\'; /* escape the control character. */\n      *data++ = 'f';\n      break;\n    case '\\n':\n      *data++ = '\\\\'; /* escape the control character. */\n      *data++ = 'n';\n      break;\n    case '\\r':\n      *data++ = '\\\\'; /* escape the control character. */\n      *data++ = 'r';\n      break;\n    case '\\t':\n      *data++ = '\\\\'; /* escape the control character. */\n      *data++ = 't';\n      break;\n    default:\n      *data++ = string->string[i];\n      break;\n    }\n  }\n\n  *data++ = '\"'; /* close the string. */\n\n  return data;\n}\n\njson_weak char *json_write_minified_array(const struct json_array_s *array,\n                                          char *data);\nchar *json_write_minified_array(const struct json_array_s *array, char *data) {\n  struct json_array_element_s *element = json_null;\n\n  *data++ = '['; /* open the array. */\n\n  for (element = array->start; json_null != element; element = element->next) {\n    if (element != array->start) {\n      *data++ = ','; /* ','s seperate each element. */\n    }\n\n    data = json_write_minified_value(element->value, data);\n\n    if (json_null == data) {\n      /* value was malformed! */\n      return json_null;\n    }\n  }\n\n  *data++ = ']'; /* close the array. */\n\n  return data;\n}\n\njson_weak char *json_write_minified_object(const struct json_object_s *object,\n                                           char *data);\nchar *json_write_minified_object(const struct json_object_s *object,\n                                 char *data) {\n  struct json_object_element_s *element = json_null;\n\n  *data++ = '{'; /* open the object. */\n\n  for (element = object->start; json_null != element; element = element->next) {\n    if (element != object->start) {\n      *data++ = ','; /* ','s seperate each element. */\n    }\n\n    data = json_write_string(element->name, data);\n\n    if (json_null == data) {\n      /* string was malformed! */\n      return json_null;\n    }\n\n    *data++ = ':'; /* ':'s seperate each name/value pair. */\n\n    data = json_write_minified_value(element->value, data);\n\n    if (json_null == data) {\n      /* value was malformed! */\n      return json_null;\n    }\n  }\n\n  *data++ = '}'; /* close the object. */\n\n  return data;\n}\n\njson_weak char *json_write_minified_value(const struct json_value_s *value,\n                                          char *data);\nchar *json_write_minified_value(const struct json_value_s *value, char *data) {\n  switch (value->type) {\n  default:\n    /* unknown value type found! */\n    return json_null;\n  case json_type_number:\n    return json_write_number((struct json_number_s *)value->payload, data);\n  case json_type_string:\n    return json_write_string((struct json_string_s *)value->payload, data);\n  case json_type_array:\n    return json_write_minified_array((struct json_array_s *)value->payload,\n                                     data);\n  case json_type_object:\n    return json_write_minified_object((struct json_object_s *)value->payload,\n                                      data);\n  case json_type_true:\n    data[0] = 't';\n    data[1] = 'r';\n    data[2] = 'u';\n    data[3] = 'e';\n    return data + 4;\n  case json_type_false:\n    data[0] = 'f';\n    data[1] = 'a';\n    data[2] = 'l';\n    data[3] = 's';\n    data[4] = 'e';\n    return data + 5;\n  case json_type_null:\n    data[0] = 'n';\n    data[1] = 'u';\n    data[2] = 'l';\n    data[3] = 'l';\n    return data + 4;\n  }\n}\n\nvoid *json_write_minified(const struct json_value_s *value, size_t *out_size) {\n  size_t size = 0;\n  char *data = json_null;\n  char *data_end = json_null;\n\n  if (json_null == value) {\n    return json_null;\n  }\n\n  if (json_write_minified_get_value_size(value, &size)) {\n    /* value was malformed! */\n    return json_null;\n  }\n\n  size += 1; /* for the '\\0' null terminating character. */\n\n  data = (char *)malloc(size);\n\n  if (json_null == data) {\n    /* malloc failed! */\n    return json_null;\n  }\n\n  data_end = json_write_minified_value(value, data);\n\n  if (json_null == data_end) {\n    /* bad chi occurred! */\n    free(data);\n    return json_null;\n  }\n\n  /* null terminated the string. */\n  *data_end = '\\0';\n\n  if (json_null != out_size) {\n    *out_size = size;\n  }\n\n  return data;\n}\n\njson_weak int json_write_pretty_get_value_size(const struct json_value_s *value,\n                                               size_t depth, size_t indent_size,\n                                               size_t newline_size,\n                                               size_t *size);\n\njson_weak int json_write_pretty_get_array_size(const struct json_array_s *array,\n                                               size_t depth, size_t indent_size,\n                                               size_t newline_size,\n                                               size_t *size);\nint json_write_pretty_get_array_size(const struct json_array_s *array,\n                                     size_t depth, size_t indent_size,\n                                     size_t newline_size, size_t *size) {\n  struct json_array_element_s *element;\n\n  *size += 1; /* '['. */\n\n  if (0 < array->length) {\n    /* if we have any elements we need to add a newline after our '['. */\n    *size += newline_size;\n\n    *size += array->length - 1; /* ','s seperate each element. */\n\n    for (element = array->start; json_null != element;\n         element = element->next) {\n      /* each element gets an indent. */\n      *size += (depth + 1) * indent_size;\n\n      if (json_write_pretty_get_value_size(element->value, depth + 1,\n                                           indent_size, newline_size, size)) {\n        /* value was malformed! */\n        return 1;\n      }\n\n      /* each element gets a newline too. */\n      *size += newline_size;\n    }\n\n    /* since we wrote out some elements, need to add a newline and indentation.\n     */\n    /* to the trailing ']'. */\n    *size += depth * indent_size;\n  }\n\n  *size += 1; /* ']'. */\n\n  return 0;\n}\n\njson_weak int\njson_write_pretty_get_object_size(const struct json_object_s *object,\n                                  size_t depth, size_t indent_size,\n                                  size_t newline_size, size_t *size);\nint json_write_pretty_get_object_size(const struct json_object_s *object,\n                                      size_t depth, size_t indent_size,\n                                      size_t newline_size, size_t *size) {\n  struct json_object_element_s *element;\n\n  *size += 1; /* '{'. */\n\n  if (0 < object->length) {\n    *size += newline_size; /* need a newline next. */\n\n    *size += object->length - 1; /* ','s seperate each element. */\n\n    for (element = object->start; json_null != element;\n         element = element->next) {\n      /* each element gets an indent and newline. */\n      *size += (depth + 1) * indent_size;\n      *size += newline_size;\n\n      if (json_write_get_string_size(element->name, size)) {\n        /* string was malformed! */\n        return 1;\n      }\n\n      *size += 3; /* seperate each name/value pair with \" : \". */\n\n      if (json_write_pretty_get_value_size(element->value, depth + 1,\n                                           indent_size, newline_size, size)) {\n        /* value was malformed! */\n        return 1;\n      }\n    }\n\n    *size += depth * indent_size;\n  }\n\n  *size += 1; /* '}'. */\n\n  return 0;\n}\n\njson_weak int json_write_pretty_get_value_size(const struct json_value_s *value,\n                                               size_t depth, size_t indent_size,\n                                               size_t newline_size,\n                                               size_t *size);\nint json_write_pretty_get_value_size(const struct json_value_s *value,\n                                     size_t depth, size_t indent_size,\n                                     size_t newline_size, size_t *size) {\n  switch (value->type) {\n  default:\n    /* unknown value type found! */\n    return 1;\n  case json_type_number:\n    return json_write_get_number_size((struct json_number_s *)value->payload,\n                                      size);\n  case json_type_string:\n    return json_write_get_string_size((struct json_string_s *)value->payload,\n                                      size);\n  case json_type_array:\n    return json_write_pretty_get_array_size(\n        (struct json_array_s *)value->payload, depth, indent_size, newline_size,\n        size);\n  case json_type_object:\n    return json_write_pretty_get_object_size(\n        (struct json_object_s *)value->payload, depth, indent_size,\n        newline_size, size);\n  case json_type_true:\n    *size += 4; /* the string \"true\". */\n    return 0;\n  case json_type_false:\n    *size += 5; /* the string \"false\". */\n    return 0;\n  case json_type_null:\n    *size += 4; /* the string \"null\". */\n    return 0;\n  }\n}\n\njson_weak char *json_write_pretty_value(const struct json_value_s *value,\n                                        size_t depth, const char *indent,\n                                        const char *newline, char *data);\n\njson_weak char *json_write_pretty_array(const struct json_array_s *array,\n                                        size_t depth, const char *indent,\n                                        const char *newline, char *data);\nchar *json_write_pretty_array(const struct json_array_s *array, size_t depth,\n                              const char *indent, const char *newline,\n                              char *data) {\n  size_t k, m;\n  struct json_array_element_s *element;\n\n  *data++ = '['; /* open the array. */\n\n  if (0 < array->length) {\n    for (k = 0; '\\0' != newline[k]; k++) {\n      *data++ = newline[k];\n    }\n\n    for (element = array->start; json_null != element;\n         element = element->next) {\n      if (element != array->start) {\n        *data++ = ','; /* ','s seperate each element. */\n\n        for (k = 0; '\\0' != newline[k]; k++) {\n          *data++ = newline[k];\n        }\n      }\n\n      for (k = 0; k < depth + 1; k++) {\n        for (m = 0; '\\0' != indent[m]; m++) {\n          *data++ = indent[m];\n        }\n      }\n\n      data = json_write_pretty_value(element->value, depth + 1, indent, newline,\n                                     data);\n\n      if (json_null == data) {\n        /* value was malformed! */\n        return json_null;\n      }\n    }\n\n    for (k = 0; '\\0' != newline[k]; k++) {\n      *data++ = newline[k];\n    }\n\n    for (k = 0; k < depth; k++) {\n      for (m = 0; '\\0' != indent[m]; m++) {\n        *data++ = indent[m];\n      }\n    }\n  }\n\n  *data++ = ']'; /* close the array. */\n\n  return data;\n}\n\njson_weak char *json_write_pretty_object(const struct json_object_s *object,\n                                         size_t depth, const char *indent,\n                                         const char *newline, char *data);\nchar *json_write_pretty_object(const struct json_object_s *object, size_t depth,\n                               const char *indent, const char *newline,\n                               char *data) {\n  size_t k, m;\n  struct json_object_element_s *element;\n\n  *data++ = '{'; /* open the object. */\n\n  if (0 < object->length) {\n    for (k = 0; '\\0' != newline[k]; k++) {\n      *data++ = newline[k];\n    }\n\n    for (element = object->start; json_null != element;\n         element = element->next) {\n      if (element != object->start) {\n        *data++ = ','; /* ','s seperate each element. */\n\n        for (k = 0; '\\0' != newline[k]; k++) {\n          *data++ = newline[k];\n        }\n      }\n\n      for (k = 0; k < depth + 1; k++) {\n        for (m = 0; '\\0' != indent[m]; m++) {\n          *data++ = indent[m];\n        }\n      }\n\n      data = json_write_string(element->name, data);\n\n      if (json_null == data) {\n        /* string was malformed! */\n        return json_null;\n      }\n\n      /* \" : \"s seperate each name/value pair. */\n      *data++ = ' ';\n      *data++ = ':';\n      *data++ = ' ';\n\n      data = json_write_pretty_value(element->value, depth + 1, indent, newline,\n                                     data);\n\n      if (json_null == data) {\n        /* value was malformed! */\n        return json_null;\n      }\n    }\n\n    for (k = 0; '\\0' != newline[k]; k++) {\n      *data++ = newline[k];\n    }\n\n    for (k = 0; k < depth; k++) {\n      for (m = 0; '\\0' != indent[m]; m++) {\n        *data++ = indent[m];\n      }\n    }\n  }\n\n  *data++ = '}'; /* close the object. */\n\n  return data;\n}\n\njson_weak char *json_write_pretty_value(const struct json_value_s *value,\n                                        size_t depth, const char *indent,\n                                        const char *newline, char *data);\nchar *json_write_pretty_value(const struct json_value_s *value, size_t depth,\n                              const char *indent, const char *newline,\n                              char *data) {\n  switch (value->type) {\n  default:\n    /* unknown value type found! */\n    return json_null;\n  case json_type_number:\n    return json_write_number((struct json_number_s *)value->payload, data);\n  case json_type_string:\n    return json_write_string((struct json_string_s *)value->payload, data);\n  case json_type_array:\n    return json_write_pretty_array((struct json_array_s *)value->payload, depth,\n                                   indent, newline, data);\n  case json_type_object:\n    return json_write_pretty_object((struct json_object_s *)value->payload,\n                                    depth, indent, newline, data);\n  case json_type_true:\n    data[0] = 't';\n    data[1] = 'r';\n    data[2] = 'u';\n    data[3] = 'e';\n    return data + 4;\n  case json_type_false:\n    data[0] = 'f';\n    data[1] = 'a';\n    data[2] = 'l';\n    data[3] = 's';\n    data[4] = 'e';\n    return data + 5;\n  case json_type_null:\n    data[0] = 'n';\n    data[1] = 'u';\n    data[2] = 'l';\n    data[3] = 'l';\n    return data + 4;\n  }\n}\n\nvoid *json_write_pretty(const struct json_value_s *value, const char *indent,\n                        const char *newline, size_t *out_size) {\n  size_t size = 0;\n  size_t indent_size = 0;\n  size_t newline_size = 0;\n  char *data = json_null;\n  char *data_end = json_null;\n\n  if (json_null == value) {\n    return json_null;\n  }\n\n  if (json_null == indent) {\n    indent = \"  \"; /* default to two spaces. */\n  }\n\n  if (json_null == newline) {\n    newline = \"\\n\"; /* default to linux newlines. */\n  }\n\n  while ('\\0' != indent[indent_size]) {\n    ++indent_size; /* skip non-null terminating characters. */\n  }\n\n  while ('\\0' != newline[newline_size]) {\n    ++newline_size; /* skip non-null terminating characters. */\n  }\n\n  if (json_write_pretty_get_value_size(value, 0, indent_size, newline_size,\n                                       &size)) {\n    /* value was malformed! */\n    return json_null;\n  }\n\n  size += 1; /* for the '\\0' null terminating character. */\n\n  data = (char *)malloc(size);\n\n  if (json_null == data) {\n    /* malloc failed! */\n    return json_null;\n  }\n\n  data_end = json_write_pretty_value(value, 0, indent, newline, data);\n\n  if (json_null == data_end) {\n    /* bad chi occurred! */\n    free(data);\n    return json_null;\n  }\n\n  /* null terminated the string. */\n  *data_end = '\\0';\n\n  if (json_null != out_size) {\n    *out_size = size;\n  }\n\n  return data;\n}\n\n#if defined(__clang__)\n#pragma clang diagnostic pop\n#elif defined(_MSC_VER)\n#pragma warning(pop)\n#endif\n\n#endif /* SHEREDOM_JSON_H_INCLUDED. */\n"
  },
  {
    "path": "patch/macro.h",
    "content": "﻿/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n\n//#define PATCH_INTERNAL\n\n#define PATCH_VERSION_NAME \"patch.aul \" PATCH_VERSION_STR\n\n#ifdef PATCH_INTERNAL\n#define PATCH_VERSION_STR \"internal build:\" __DATE__ \" \" __TIME__ \"\"\n\n#define PATCH_SWITCH_EXCEPTION_LOG\n#define PATCH_SWITCH_SYSINFO_MODIFY\n#define PATCH_SWITCH_TRANSRATE\n#define PATCH_SWITCH_SETTING_GUI\n\n\n#define PATCH_SWITCH_ACCESS_KEY access_key\n#define PATCH_SWITCH_FILEINFO file_info\n#define PATCH_SWITCH_SUSIE_LOAD susie_load\n#define PATCH_SWITCH_SPLASH splash\n#define PATCH_SWITCH_TRA_AVIUTL_FILTER tra_aviutl_filter\n#define PATCH_SWITCH_EXO_AVIUTL_FILTER exo_aviutl_filter\n#define PATCH_SWITCH_EXO_TRACK_MINUSVAL exo_track_minusval\n#define PATCH_SWITCH_EXO_SCENEIDX exo_sceneidx\n#define PATCH_SWITCH_EXO_TRACKPARAM exo_trackparam\n#define PATCH_SWITCH_EXO_SPECIALCOLORCONV exo_specialcolorconv\n#define PATCH_SWITCH_TEXT_OP_SIZE text_op_size\n#define PATCH_SWITCH_IGNORE_MEDIA_PARAM_RESET ignore_media_param_reset\n#define PATCH_SWITCH_FONT_DIALOG font_dialog\n#define PATCH_SWITCH_SCROLL_OBJDLG scroll_objdlg\n#define PATCH_SWITCH_ALPHA_BG alpha_bg\n#define PATCH_SWITCH_HELPFUL_MSGBOX helpful_msgbox\n#define PATCH_SWITCH_THEME_CC theme_cc\n#define PATCH_SWITCH_EXEDITWINDOW_SIZING exeditwindow_sizing\n#define PATCH_SWITCH_SETTINGDIALOG_MOVE settingdialog_move\n#define PATCH_SWITCH_SETTINGDIALOG_EXCOLORCONFIG settingdialog_excolorconfig\n\n#define PATCH_SWITCH_UNDO undo\n#ifdef PATCH_SWITCH_UNDO\n\t#define PATCH_SWITCH_UNDO_REDO undo_redo\n#endif\n\n#define PATCH_SWITCH_CONSOLE console\n#ifdef PATCH_SWITCH_CONSOLE\n\n#define PATCH_SWITCH_DEBUGSTRING console_debug_string\n\n#endif // ifdef PATCH_SWITCH_CONSOLE\n\n\n#define PATCH_SWITCH_LUA lua\n#ifdef PATCH_SWITCH_LUA\n\n\t#define PATCH_SWITCH_LUA_ENV lua_env\n\t#define PATCH_SWITCH_LUA_GETVALUE lua_getvalueex\n\t#define PATCH_SWITCH_LUA_RAND lua_rand\n\t#define PATCH_SWITCH_LUA_RANDEX lua_randex\n\t#define PATCH_SWITCH_LUA_PATH lua_path\n\n\t//#define PATCH_SWITCH_LUA_COPYBUFFER_SMEM lua_copybuffer_smem\n\n\n#endif // ifdef PATCH_SWITCH_LUA\n\n\n#define PATCH_SWITCH_FAST fast\n#ifdef PATCH_SWITCH_FAST\n\t\n\t#define PATCH_SWITCH_FAST_GETPUTPIXELDATA fast_getputpixeldata\n\t#define PATCH_SWITCH_FAST_SETTINGDIALOG fast_settingdialog\n\t#define PATCH_SWITCH_FAST_EXEDITWINDOW fast_exeditwindow\n\n\t#define PATCH_SWITCH_CL cl\n\t#ifdef PATCH_SWITCH_CL\n\t\t#define PATCH_SWITCH_FAST_POLORTRANSFORM fast_polortransform\n\t\t#define PATCH_SWITCH_FAST_RADIATIONALBLUR fast_radiationalblur\n\t\t#define PATCH_SWITCH_FAST_FLASH fast_flash\n\n\t#endif // define PATCH_SWITCH_CL\n\n#endif //define PATCH_SWITCH_FAST\n\n#else // ifdef PATCH_INTERNAL\n#define PATCH_VERSION_STR \"r43 beta1\"\n\n#define PATCH_SWITCH_EXCEPTION_LOG\n#define PATCH_SWITCH_SYSINFO_MODIFY\n\n#define PATCH_SWITCH_ACCESS_KEY access_key\n#define PATCH_SWITCH_COLORPALETTE_CACHE colorpalette_cache\n#define PATCH_SWITCH_TRA_AVIUTL_FILTER tra_aviutl_filter\n#define PATCH_SWITCH_TRA_CHANGE_DRAWFILTER tra_change_drawfilter\n#define PATCH_SWITCH_TRA_SPECIFIED_SPEED tra_specified_speed\n#define PATCH_SWITCH_AUP_SCENE_SETTING aup_scene_setting\n#define PATCH_SWITCH_AUP_LAYER_SETTING aup_layer_setting\n#define PATCH_SWITCH_EXO_AVIUTL_FILTER exo_aviutl_filter\n#define PATCH_SWITCH_EXO_TRACK_MINUSVAL exo_track_minusval\n#define PATCH_SWITCH_EXO_SCENEIDX exo_sceneidx\n#define PATCH_SWITCH_EXO_TRACKPARAM exo_trackparam\n#define PATCH_SWITCH_EXO_MIDPT_AND_TRA exo_midpt_tra\n#define PATCH_SWITCH_EXO_SPECIALCOLORCONV exo_specialcolorconv\n#define PATCH_SWITCH_EXO_FOLD_GUI exo_fold_gui\n#define PATCH_SWITCH_TEXT_OP_SIZE text_op_size\n#define PATCH_SWITCH_IGNORE_MEDIA_PARAM_RESET ignore_media_param_reset\n#define PATCH_SWITCH_THEME_CC theme_cc\n#define PATCH_SWITCH_EXEDITWINDOW_SIZING exeditwindow_sizing\n#define PATCH_SWITCH_SETTINGDIALOG_MOVE settingdialog_move\n#define PATCH_SWITCH_SETTINGDIALOG_EXCOLORCONFIG settingdialog_excolorconfig\n#define PATCH_SWITCH_CANCEL_BOOST_CONFLICT\n#define PATCH_SWITCH_WARNING_OLD_LSW\n#define PATCH_SWITCH_FAILED_SJIS_MSGBOX failed_sjis\n#define PATCH_SWITCH_FAILED_LONGER_PATH failed_longpath\n#define PATCH_SWITCH_FAILED_FILE_DROP failed_filedrop\n#define PATCH_SWITCH_OBJ_COLORCORRECTION obj_colorcorrection\n#define PATCH_SWITCH_OBJ_GLOW obj_glow\n#define PATCH_SWITCH_OBJ_LENSBLUR obj_lensblur\n#define PATCH_SWITCH_OBJ_NOISE obj_noise\n#define PATCH_SWITCH_OBJ_SPECIALCOLORCONV obj_specialcolorconv\n#define PATCH_SWITCH_RCLICKMENU_SPLIT rclickmenu_split\n#define PATCH_SWITCH_RCLICKMENU_DELETE rclickmenu_delete\n#define PATCH_SWITCH_BLEND blend\n#define PATCH_SWITCH_ADD_EXTENSION add_extension\n#define PATCH_SWITCH_DIALOG_NEW_FILE dlg_newfile\n#define PATCH_SWITCH_PLAYBACK_SPEED pb_speed\n#define PATCH_SWITCH_SETTING_NEW_PROJECT setting_newproject\n\n#define PATCH_SWITCH_UNDO undo\n#ifdef PATCH_SWITCH_UNDO\n\t#define PATCH_SWITCH_UNDO_REDO undo_redo\n\t#ifdef PATCH_SWITCH_UNDO_REDO\n\t\t#define PATCH_SWITCH_UNDO_REDO_SHIFT undo_redo_shift\n\t#endif\n#endif\n\n#define PATCH_SWITCH_CONSOLE console\n#ifdef PATCH_SWITCH_CONSOLE\n\t#define PATCH_SWITCH_DEBUGSTRING console_debug_string\n#endif // ifdef PATCH_SWITCH_CONSOLE\n\n#define PATCH_SWITCH_LUA lua\n#ifdef PATCH_SWITCH_LUA\n\t#define PATCH_SWITCH_LUA_ENV lua_env\n\t#define PATCH_SWITCH_LUA_GETVALUE lua_getvalue\n\t#define PATCH_SWITCH_LUA_RAND lua_rand\n\t#define PATCH_SWITCH_LUA_RANDEX lua_randex\n\t#define PATCH_SWITCH_LUA_PATH lua_path\n\n\t//#define PATCH_SWITCH_LUA_COPYBUFFER_SMEM lua_copybuffer_smem\n\n#endif // ifdef PATCH_SWITCH_LUA\n\n#define PATCH_SWITCH_FAST fast\n#ifdef PATCH_SWITCH_FAST\n\t\n\t#define PATCH_SWITCH_FAST_SETTINGDIALOG fast_settingdialog\n\t#define PATCH_SWITCH_FAST_EXEDITWINDOW fast_exeditwindow\n\t#define PATCH_SWITCH_FAST_TEXT fast_text\n\t#define PATCH_SWITCH_FAST_CREATE_FIGURE fast_create_figure\n\t#define PATCH_SWITCH_FAST_BORDER fast_border\n\t#define PATCH_SWITCH_FAST_GLOW fast_glow\n\n\t#define PATCH_SWITCH_CL cl\n\t#ifdef PATCH_SWITCH_CL\n\t\t#define PATCH_SWITCH_FAST_POLORTRANSFORM fast_polortransform\n\t\t#define PATCH_SWITCH_FAST_DISPLACEMENTMAP fast_displacementmap\n\t\t#define PATCH_SWITCH_FAST_RADIATIONALBLUR fast_radiationalblur\n\t\t#define PATCH_SWITCH_FAST_FLASH fast_flash\n\t\t#define PATCH_SWITCH_FAST_DIRECTIONALBLUR fast_directionalblur\n\t\t#define PATCH_SWITCH_FAST_LENSBLUR fast_lensblur\n\n\t#endif // define PATCH_SWITCH_CL\n\n#endif //define PATCH_SWITCH_FAST\n\n#endif // ifdef PATCH_INTERNAL\n\n#define PATCH_SWITCHER_DEFINE_STRING(s) #s\n#define PATCH_SWITCHER_DEFINE_STRINGX(s) PATCH_SWITCHER_DEFINE_STRING(s)\n#define PATCH_SWITCHER_DEFINE_VALUE(s) s\n#define PATCH_SWITCHER_KEY_JOINNER(a, b) a ## b\n#define PATCH_SWITCHER_KEY_JOINNERX(a, b) PATCH_SWITCHER_KEY_JOINNER(a, b)\n#define PATCH_SWITCHER_DEFINE(name, def) bool name = def; inline static constexpr const char PATCH_SWITCHER_KEY_JOINNER(key_, name)[] = PATCH_SWITCHER_DEFINE_STRING(name);\n#define PATCH_SWITCHER_DEFINE_EX(name, def, key) bool name = def; inline static constexpr const char PATCH_SWITCHER_KEY_JOINNER(key_, name)[] = PATCH_SWITCHER_DEFINE_STRING(key);\n#define PATCH_SWITCHER_IF(name) if (load_variable(elm, PATCH_SWITCHER_KEY_JOINNER(key_, name), name)) continue;\n#define PATCH_SWITCHER_STORE(name) tj(PATCH_SWITCHER_KEY_JOINNER(key_, name), name);\n#define PATCH_SWITCHER_MEMBER(name) GLOBAL::config.switcher.name\n"
  },
  {
    "path": "patch/moduledata.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include <cstdint>\n#include <utility>\n#include <vector>\n#include <string>\n#include <unordered_map>\n#include <map>\n#include <set>\n#include <optional>\n#include <mutex>\n#include <compare>\n\n#include <Windows.h>\n\n#include \"hash.hpp\"\n\nstruct ModulesDataEntry {\n\tuintptr_t begin;\n\tuintptr_t end;\n\tstd::string name;\n\tstd::optional<SHA256> hash;\n};\n\ninline static std::pair<std::vector<ModulesDataEntry>, std::string_view> getModulesData() {\n\tstd::vector<ModulesDataEntry> ret;\n\tauto snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, NULL);\n\tif (snapshot != INVALID_HANDLE_VALUE) {\n\t\tMODULEENTRY32 entry{ .dwSize = sizeof(MODULEENTRY32) };\n\t\tif (Module32First(snapshot, &entry)) {\n\t\t\tdo {\n\t\t\t\tret.emplace_back(\n\t\t\t\t\treinterpret_cast<uintptr_t>(entry.modBaseAddr),\n\t\t\t\t\treinterpret_cast<uintptr_t>(entry.modBaseAddr) + static_cast<uintptr_t>(entry.modBaseSize),\n\t\t\t\t\tentry.szModule,\n\t\t\t\t\tSHA256::make_opt(entry.szExePath)\n\t\t\t\t);\n\t\t\t} while (Module32Next(snapshot, &entry));\n\t\t\tCloseHandle(snapshot);\n\t\t}\n\t\telse {\n\t\t\tauto err = GetLastError();\n\t\t\tCloseHandle(snapshot);\n\t\t\treturn { ret,\"LastError:{}\"_fmt(err) };\n\t\t}\n\t}\n\telse {\n\t\tauto err = GetLastError();\n\t\tCloseHandle(snapshot);\n\t\treturn { ret,\"LastError:{}\"_fmt(err) };\n\t}\n\tstd::sort(ret.begin(), ret.end(), [](auto a, auto b) { return a.begin < b.begin; });\n\treturn { ret, \"\" };\n}\n\ninline std::weak_ordering operator<=>(const ModulesDataEntry& a, const ModulesDataEntry& b) {\n\treturn a.begin <=> b.begin;\n}\n\nclass ModulesData {\n\tinline static std::vector<ModulesDataEntry> modules_data_cache;\n\tinline static std::set<std::string> modules_data_cache_name;\n\npublic:\n\tinline static std::mutex mtx;\n\n\tstatic void update() {\n\t\tauto snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, NULL);\n\t\tif (snapshot != INVALID_HANDLE_VALUE) {\n\t\t\tMODULEENTRY32 entry{ .dwSize = sizeof(MODULEENTRY32) };\n\t\t\tif (Module32First(snapshot, &entry)) {\n\t\t\t\tdo {\n\t\t\t\t\tif (!modules_data_cache_name.contains(entry.szModule)) {\n\t\t\t\t\t\tmodules_data_cache_name.insert(entry.szModule);\n\t\t\t\t\t\tmodules_data_cache.emplace_back(\n\t\t\t\t\t\t\treinterpret_cast<uintptr_t>(entry.modBaseAddr),\n\t\t\t\t\t\t\treinterpret_cast<uintptr_t>(entry.modBaseAddr) + static_cast<uintptr_t>(entry.modBaseSize),\n\t\t\t\t\t\t\tentry.szModule,\n\t\t\t\t\t\t\tSHA256::make_opt(entry.szExePath)\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} while (Module32Next(snapshot, &entry));\n\t\t\t\tCloseHandle(snapshot);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tauto err = GetLastError();\n\t\t\t\tCloseHandle(snapshot);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tauto err = GetLastError();\n\t\t\tCloseHandle(snapshot);\n\t\t}\n\t}\n\n\tstatic const auto& get() {\n\t\tif (!std::is_sorted(modules_data_cache.cbegin(), modules_data_cache.cend(), [](auto a, auto b) { return a.begin < b.begin; })) {\n\t\t\tstd::sort(modules_data_cache.begin(), modules_data_cache.end(), [](auto a, auto b) { return a.begin < b.begin; });\n\t\t}\n\t\treturn modules_data_cache;\n\t}\n};\n"
  },
  {
    "path": "patch/multi_threading.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include <thread>\n#include <type_traits>\n#include <vector>\n#include <mutex>\n#include <Windows.h>\n\ninline class {\n\tinline static std::once_flag init_flag;\n\tinline static size_t thread_num;\n\tstatic void init() {\n\t\tSYSTEM_INFO info;\n\t\tGetSystemInfo(&info);\n\t\tthread_num = info.dwNumberOfProcessors;\n\t}\npublic:\n\ttemplate<class T, std::enable_if_t<std::is_invocable_v<T, size_t, size_t>, std::nullptr_t> = nullptr>\n\tinline void operator()(T func) const {\n\t\tstd::call_once(init_flag, init);\n\t\tstd::vector<std::thread> threads;\n\t\tfor (size_t i = 0; i < thread_num; i++) threads.emplace_back(func, i, thread_num);\n\t\tfor (auto&& t : threads) t.join();\n\t}\n\tauto get_thread_num() const {\n\t\tstd::call_once(init_flag, init);\n\t\treturn thread_num;\n\t}\n} multi_threading;\n"
  },
  {
    "path": "patch/mylua.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"global.hpp\"\n\n/*\n    patch内でluaを使うとき用のコード群\n*/\n\nusing lua_State = struct lua_State;\nusing lua_Number = double;\nusing lua_Integer = ptrdiff_t;\nusing lua_CFunction = int(__cdecl*)(lua_State* L);\nusing lua_Reader = const char* (__cdecl*)(lua_State* L, void* data, size_t* size);\nusing lua_Writer = int(__cdecl*)(lua_State* L, const void* data, size_t sz, void* ud);\n\nconstexpr const int LUA_REGISTRYINDEX = -10000;\nconstexpr const int LUA_ENVIRONINDEX = -10001;\nconstexpr const int LUA_GLOBALSINDEX = -10002;\nconstexpr auto lua_upvalueindex(int i) { return LUA_GLOBALSINDEX - i; }\n\nenum {\n    LUA_TNONE = -1,\n    LUA_TNIL = 0,\n    LUA_TBOOLEAN = 1,\n    LUA_TLIGHTUSERDATA = 2,\n    LUA_TNUMBER = 3,\n    LUA_TSTRING = 4,\n    LUA_TTABLE = 5,\n    LUA_TFUNCTION = 6,\n    LUA_TUISERDATA = 7,\n    LUA_TTHREAD = 8,\n};\n\nenum {\n    LUA_YIELD = 1,\n    LUA_ERRRUN = 2,\n    LUA_ERRSYNTAX = 3,\n    LUA_ERRMEM = 4,\n    LUA_ERRERR = 5,\n};\n\nstruct luaL_Reg {\n    const char* name;\n    lua_CFunction* func;\n};\n\n#define defluafunc(offset, ret, ...) (*reinterpret_cast<ret (__cdecl**)(__VA_ARGS__)>(GLOBAL::exedit_base + offset))\n#define lua_close\t\t\t    defluafunc(0x1b24ac, void, lua_State*)\n#define lua_createtable\t\t    defluafunc(0x1b2b30, void, lua_State*, int, int)\n#define lua_getfield\t\t    defluafunc(0x1bacc8, void, lua_State*, int, const char*)\n#define lua_gettable            defluafunc(0x1bab68, void, lua_State*, int)\n#define lua_gettop\t\t\t    defluafunc(0x1b23ac, int, lua_State*)\n#define lua_isnumber\t\t    defluafunc(0x1b2b38, int, lua_State*, int)\n#define lua_isuserdata\t\t    defluafunc(0x1b24a4, int, lua_State*, int)\n#define lua_newuserdata         defluafunc(0x1b248c, void*, lua_State*, size_t)\n#define lua_pcall\t\t\t    defluafunc(0x1bac8c, int, lua_State*, int, int, int)\n#define lua_pushboolean\t\t    defluafunc(0x1b2b44, void*, lua_State*, int)\n#define lua_pushinteger\t\t    defluafunc(0x1bab78, void*, lua_State*, int)\n#define lua_pushlightuserdata   defluafunc(0x1b2b00, void, lua_State*, void*)\n#define lua_pushnil             defluafunc(0x1b23c0, void, lua_State*)\n#define lua_pushnumber\t\t    defluafunc(0x1b28d8, void, lua_State*, lua_Number)\n#define lua_pushstring          defluafunc(0x1b28e0, void, lua_State*, const char*)\n#define lua_setfield            defluafunc(0x1bab5c, void, lua_State*, int, const char*)\n#define lua_sethook             defluafunc(0x1b23b4, int, lua_State*, lua_Hook, int, int)\n#define lua_settable            defluafunc(0x1b2320, void, lua_State*, int)\n#define lua_settop\t\t\t    defluafunc(0x1b23c4, void, lua_State*, int)\n#define lua_toboolean           defluafunc(0x1b2b14, int, lua_State*, int)\n#define lua_tointeger           defluafunc(0x1b29f0, lua_Integer, lua_State*, int)\n#define lua_tolstring\t\t    defluafunc(0x1b21ec, const char*, lua_State*, int, size_t*)\n#define lua_tonumber\t\t    defluafunc(0x1b21e8, lua_Number, lua_State*, int)\n#define lua_touserdata\t\t    defluafunc(0x1b2490, void*, lua_State*, int)\n#define lua_type\t\t\t    defluafunc(0x1bab70, int, lua_State*, int)\n\n#define luaL_checkinteger\t    defluafunc(0x1b2b48, lua_Integer, lua_State*, int)\n#define luaL_checklstring\t    defluafunc(0x1bacb4, const char*, lua_State*, int, size_t*)\n#define luaL_checknumber\t    defluafunc(0x1b220c, lua_Number, lua_State*, int)\n#define luaL_error              defluafunc(0x1b2488, int, lua_State*, const char*, ...)\n#define luaL_loadstring         defluafunc(0x1b2b1c, int, lua_State*, const char*)\n#define luaL_newstate\t\t    defluafunc(0x1b2208, lua_State*, void)\n#define luaL_openlibs\t\t    defluafunc(0x1b28e4, void, lua_State*)\n#define luaL_register\t\t    defluafunc(0x1b2b24, void, lua_State*, const char*, luaL_Reg*)\n\ninline int(__cdecl* lua_isstring)(lua_State* L, int idx);\ninline void(__cdecl* lua_pushcclosure)(lua_State* L, lua_CFunction fn, int n);\ninline void(__cdecl* lua_remove)(lua_State* L, int index);\ninline void(__cdecl* lua_setmetatable)(lua_State* L, int index);\ninline int(__cdecl* luaL_newmetatable)(lua_State* L, const char* tname);\ninline void(__cdecl* lua_pushvalue)(lua_State* L, int index);\n\ninline bool lua_isfunction(lua_State* L, int index) { return lua_type(L, index) == LUA_TFUNCTION; }\ninline bool lua_istable(lua_State* L, int index) { return lua_type(L, index) == LUA_TTABLE; }\ninline bool lua_islightuserdata(lua_State* L, int index) { return lua_type(L, index) == LUA_TLIGHTUSERDATA; }\ninline bool lua_isnil(lua_State* L, int index) { return lua_type(L, index) == LUA_TNIL; }\ninline bool lua_isboolean(lua_State* L, int index) { return lua_type(L, index) == LUA_TBOOLEAN; }\ninline bool lua_isthread(lua_State* L, int index) { return lua_type(L, index) == LUA_TTHREAD; }\ninline bool lua_isnone(lua_State* L, int index) { return lua_type(L, index) == LUA_TNONE; }\ninline bool lua_isnoneornil(lua_State* L, int index) { return lua_type(L, index) <= 0; }\n\n//template<size_t N> inline auto lua_pushliteral(lua_State* L, const char(&s)[N]) { return lua_pushlstring(L, s, N); }\ninline auto lua_tostring(lua_State* L, int i) { return lua_tolstring(L, i, nullptr); }\ninline auto luaL_checkstring(lua_State* L, int i) { return luaL_checklstring(L, i, nullptr); }\ninline auto lua_pushcfunction(lua_State* L, lua_CFunction f) { return lua_pushcclosure(L, f, 0); }\ninline auto lua_pop(lua_State* L, int n) { return lua_settop(L, -n - 1); }\ninline auto lua_setglobal(lua_State* L, const char* s) { return lua_setfield(L, LUA_GLOBALSINDEX, s); }\ninline auto lua_getglobal(lua_State* L, const char* s) { return lua_getfield(L, LUA_GLOBALSINDEX, s); }\ninline auto lua_newtable(lua_State* L) { return lua_createtable(L, 0, 0); }\n\ninline auto luaL_getmetatable(lua_State* L, const char* tname) { return lua_getfield(L, LUA_REGISTRYINDEX, tname); }\n"
  },
  {
    "path": "patch/mywindow.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include <exedit.hpp>\n\n#include \"global.hpp\"\n#include \"offset_address.hpp\"\n#include \"util.hpp\"\n#include \"util_resource.hpp\"\n\n#include \"patch_exo_trackminusval.hpp\"\n\n// playground\ninline class mywindow_t {\n\tHMENU hmenu;\n\tHWND hwnd;\n\n\tinline static LRESULT CALLBACK wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {\n\t\tif (message != WM_COMMAND) return DefWindowProc(hwnd, message, wparam, lparam);\n\t\tswitch (LOWORD(wparam)) {\n\t\tcase 10000: {\n\t\t\tpatch::exo_trackminusval.switching(false);\n\t\t\treturn FALSE;\n\t\t}\n\t\tcase 10001: {\n\t\t\tpatch::exo_trackminusval.switching(true);\n\t\t\treturn FALSE;\n\t\t}\n\t\t}\n\t\treturn DefWindowProc(hwnd, message, wparam, lparam);\n\t}\n\npublic:\n#if _DEBUG\n\t~mywindow_t() {\n\t\tDestroyWindow(hwnd);\n\t\tDestroyMenu(hmenu);\n\t}\n\n\tvoid init() {\n\t\thmenu = CreateMenu();\n\t\tInsertMenuA(hmenu, -1, MF_BYPOSITION | MF_STRING, 10000, \"switch\");\n\t\tInsertMenuA(hmenu, -1, MF_BYPOSITION | MF_STRING, 10001, \"switch2\");\n\n\t\thwnd = CreateWindowA(\"STATIC\", \"patchhhhhhhh\", 0, 0, 0, 1000, 500, NULL, hmenu, GLOBAL::patchaul_hinst, NULL);\n\n\t\tSetWindowLongA(hwnd, GWL_WNDPROC, (LONG)&wndproc);\n\n\t\tShowWindow(hwnd, SW_SHOWNORMAL);\n\t}\n#else\n\tvoid init() {}\n#endif\n}mywindow;\n"
  },
  {
    "path": "patch/offset_address.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"util_int.hpp\"\n\nnamespace OFS {\n\tnamespace AviUtl {\n\t\tconstexpr i32 InitAuf = 0x02c930;\n\t\tconstexpr i32 VersionString = 0x07425c;\n\t\tconstexpr i32 default_resource_hmod = 0x2c525c;\n\t\tconstexpr i32 getsys_versionstr_arg = 0x022187;\n\t\tconstexpr i32 current_resource_hmod = 0x2d910c;\n\t\tconstexpr i32 edit_handle_ptr = 0x08717c;\n\t\tconstexpr i32 saveProjectFile = 0x024160;\n\t\t\n\t\tconstexpr i32 str_dot_avi = 0x0745fc; // \".avi\"\n\t\t\n\t\tconstexpr i32 filter_clipping_and_resize_ptr = 0x07ad58;\n\t}\n\n\tnamespace ExEdit {\n\t\tconstexpr i32 exedit_fp = 0x14d4b4;\n\t\t\n\t\tconstexpr i32 aviutl_hwnd = 0x135c6c;\n\t\tconstexpr i32 exedit_hwnd = 0x177a44;\n\t\tconstexpr i32 settingdialog_hwnd = 0x1539c8;\n\t\t\n\t\tconstexpr i32 blend_yca_normal_func = 0x007df0;\n\t\tconstexpr i32 blend_yc_normal_func = 0x007f20;\n\t\t\n\t\tconstexpr i32 ConvertFilter2Exo_TrackScaleJudge_RangeBegin = 0x028a8d;\n\t\tconstexpr i32 ConvertFilter2Exo_TrackScaleJudge_Overwrite1 = 0x028a84;\n\t\tconstexpr i32 ConvertFilter2Exo_TrackScaleJudge_Overwrite2 = 0x0289cb;\n\t\tconstexpr i32 ConvertFilter2Exo_TrackScaleJudge_Overwrite3 = 0x028a00;\n\n\t\tconstexpr i32 efSceneAudio_exdatause_idx_type = 0x0aeb5c;\n\t\tconstexpr i32 efSceneAudio_exdatause_idx_name = 0x0aeb60;\n\t\tconstexpr i32 efScene_exdatause_idx_name = 0x0ae9b0;\n\n\t\tconstexpr i32 exo_readtrack = 0x029090;\n\t\tconstexpr i32 str2int2 = 0x0918ab;\n\n\t\tconstexpr i32 exo_trackparam_overwrite = 0x0299d1;\n\n\t\tconstexpr i32 efpip_g = 0x1b2b20;\n\n\t\tconstexpr i32 getpixeldata = 0x09a65c;\n\t\tconstexpr i32 rgb2yc = 0x06fed0;\n\n\t\tconstexpr i32 exedit_max_h_add8 = 0x135c64;\n\t\tconstexpr i32 exedit_buffer_line = 0x135c68;\n\n\t\tconstexpr i32 exedit_YC_vram_w = 0x149840;\n\t\tconstexpr i32 exedit_YC_vram_h = 0x14ca4c;\n\n\t\tconstexpr i32 exedit_max_w = 0x196748;\n\t\tconstexpr i32 exedit_max_h = 0x1920e0;\n\n\t\tconstexpr i32 memory_ptr = 0x01a5328;\n\n\t\tconstexpr i32 CreateFigure_var_ptr = 0x1e4798;\n\t\tconstexpr i32 CreateFigure_circle_func_call = 0x073882;\n\t\tconstexpr i32 CreateFigure_circle_func_mt_call = 0x0738ac;\n\t\tconstexpr i32 CreateFigure_polygons_func_call = 0x073949;\n\t\tconstexpr i32 CreateFigure_polygons_func_mt_call = 0x07395b;\n\n\t\tconstexpr i32 efBorder_func_proc_var_ptr = 0x0a5d28;\n\t\tconstexpr i32 efBorder_func_proc_ptr = 0x0515d0;\n\t\tconstexpr i32 efBorder_var_ptr = 0x1b1e30;\n\t\tconstexpr i32 efGlow_var_ptr = 0x1b2010;\n\t\tconstexpr i32 efPolorTransform_func_proc = 0x0748a0;\n\t\tconstexpr i32 efPolorTransform_func_proc_ptr = 0x0add30;\n\t\tconstexpr i32 efPolorTransform_mt_func_call = 0x074a62;\n\t\tconstexpr i32 efPolorTransform_var_ptr = 0x1e48c0;\n\t\tconstexpr i32 efDisplacementMap_mt_func_call = 0x01f154;\n\t\tconstexpr i32 efDisplacementMap_var_ptr = 0x11effc;\n\t\tconstexpr i32 efRadiationalBlur_func_proc = 0x00b310;\n\t\tconstexpr i32 efRadiationalBlur_func_proc_ptr = 0x09fdb0;\n\t\tconstexpr i32 efRadiationalBlur_var_ptr = 0x0d75a8;\n\t\tconstexpr i32 efFlash_func_proc = 0x04e560;\n\t\tconstexpr i32 efFlash_var_ptr = 0x1a6b7c;\n\t\tconstexpr i32 efFlash_func_proc_ptr = 0x0a5a28;\n\t\tconstexpr i32 efDirectionalBlur_func_proc_ptr = 0x0a00a0;\n\t\tconstexpr i32 efDirectionalBlur_var_ptr = 0x0d75cc;\n\t\tconstexpr i32 efDirectionalBlur_Filter_mt_func_call = 0x00cae6;\n\t\tconstexpr i32 efLensBlur_Media_mt_func_call = 0x012761;\n\t\tconstexpr i32 efLensBlur_Filter_mt_func_call = 0x012786;\n\t\tconstexpr i32 efLensBlur_var_ptr = 0x11ec5c;\n\n\t\tconstexpr i32 ScriptProcessingFilter = 0x1b2b10;\n\n\t\tconstexpr i32 ini_extension_buf = 0x14cb58;\n\t\tconstexpr i32 str_DOUGAFILE = 0x09df6c; // \"動画ファイル\"\n\t\tconstexpr i32 str_ONSEIFILE = 0x0ba698; // \"音声ファイル\"\n\n\t\t\n\t\tconstexpr i32 exedit_edit_open = 0x03ac30;\n\n\t\tconstexpr i32 exfunc_10 = 0x04abe0;\n\t\tconstexpr i32 exfunc_08 = 0x04ab40;\n\t\tconstexpr i32 func_0x047ad0 = 0x047ad0;\n\t\tconstexpr i32 exfunc_64 = 0x04d040;\n\t\tconstexpr i32 scenechange_progress_times4096 = 0x230c60;\n\t\tconstexpr i32 exfunc_1c = 0x04ade0;\n\t\tconstexpr i32 GetCurrentProcessing = 0x047ba0;\n\t\tconstexpr i32 LoadedFilterTable = 0x187c98;\n\t\tconstexpr i32 splitted_object_new_group_belong = 0x034f90;\n\t\tconstexpr i32 DrawTimelineMask = 0x0392f0;\n\t\tconstexpr i32 disp_settingdialog = 0x039550;\n\t\tconstexpr i32 filter_sendmessage = 0x04a1a0;\n\t\tconstexpr i32 get_near_object_idx = 0x0445a0;\n\t\tconstexpr i32 TraScript_ProcessingObjectIndex = 0x1b2b04;\n\t\tconstexpr i32 TraScript_ProcessingTrackBarIndex = 0x1b21f4;\n\t\tconstexpr i32 TraScript_Time = 0x1b28c8;\n\n\t\tconstexpr i32 LoadLua = 0x0646e0;\n\t\tconstexpr i32 hmodule_lua = 0x1bac9c;\n\t\tconstexpr i32 luaL_Reg_global_table = 0x09a680;\n\t\tconstexpr i32 luaL_Reg_obj_table = 0x09a5c0;\n\t\tconstexpr i32 exeditdir = 0x1b2b18;\n\t\tconstexpr i32 sScriptFolderName = 0x1b2b4c;\n\n\t\tconstexpr i32 l_effect = 0x05d0a0;\n\t\tconstexpr i32 l_load = 0x05ef50;\n\t\tconstexpr i32 l_draw = 0x05e250;\n\t\tconstexpr i32 l_drawpoly = 0x05e680;\n\t\tconstexpr i32 l_setanchor = 0x0625e0;\n\n\t\tconstexpr i32 GetOrCreateLuaState = 0x064660;\n\t\tconstexpr i32 LuaUnload = 0x064e90;\n\t\tconstexpr i32 SetLuaPathAndCpath = 0x064550;\n\t\tconstexpr i32 DoScriptInit = 0x0641a0;\n\t\tconstexpr i32 DoScriptExit = 0x064250;\n\t\tconstexpr i32 luastateidx = 0x1baccc;\n\n\t\tconstexpr i32 lua_pop_nop = 0x064d15;\n\t\tconstexpr i32 lua_set_nop = 0x06442a;\n\t\tconstexpr i32 lua_tonumber_arg = 0x064d64;\n\t\tconstexpr i32 lua_tostring_calling1 = 0x064d44;\n\t\tconstexpr i32 lua_tostring_calling2 = 0x06448b;\n\t\tconstexpr i32 lua_tostring_calling3 = 0x064449;\n\n\t\tconstexpr i32 OutputDebugString_calling_err1 = 0x064453;\n\t\tconstexpr i32 OutputDebugString_calling_err2 = 0x064495;\n\t\tconstexpr i32 OutputDebugString_calling_err3 = 0x064d4e;\n\t\tconstexpr i32 OutputDebugString_calling_dbg = 0x05d099;\n\n\t\tconstexpr i32 ignore_media_param_reset_mov = 0x00674d;\n\t\tconstexpr i32 ignore_media_param_reset_aud = 0x090116;\n\n\t\tconstexpr i32 ExtendedFilter_wndcls = 0x02e872;\n\n\t\tconstexpr i32 loaded_spi_array = 0x2321f0;\n\n\t\tconstexpr i32 MyFindFirstFile = 0x04e220;\n\t\tconstexpr i32 MyFindNextFile = 0x04e270;\n\t\tconstexpr i32 LoadSpi = 0x08a210;\n\n\t\tconstexpr i32 text_op_logfont_size = 0x050716;\n\t\tconstexpr i32 specialcolorconv_status2 = 0x0a14f4;\n\n\t\tconstexpr i32 ObjectArrayPointer = 0x1e0fa4;\n\t\tconstexpr i32 NextObjectIdxArray = 0x1592d8;\n\n\t\tconstexpr i32 ScaleColorBackGround = 0x0a4048;\n\t\tconstexpr i32 ScaleColorForeGround = 0x0a404c;\n\t\tconstexpr i32 LayerNameRectWidth = 0x037d1a;\n\t\tconstexpr i32 layer_height_array = 0x0a3e08;\n\t\t\n\t\t//constexpr i32 LayerLockBorder = 0x037d78; // push char されているので安直には無理\n\t\tconstexpr i32 LayerLockBorder_mod = 0x037d71;\n\t\tconstexpr i32 LayerLockCenter = 0x037d81;\n\t\tconstexpr i32 LayerClippingBorder = 0x037e96;\n\t\tconstexpr i32 LayerClippingCenter = 0x037ea2;\n\t\tconstexpr i32 LayerLinkBorder = 0x037dfd;\n\t\tconstexpr i32 LayerLinkCenter = 0x037e09;\n\t\tconstexpr i32 LayerHideAlpha = 0x09a570;\n\n\t\tconstexpr i32 ObjectColorMedia = 0x0a40e0;\n\t\tconstexpr i32 ObjectColorMFilter = 0x0a4104;\n\t\tconstexpr i32 ObjectColorSound = 0x0a4128;\n\t\tconstexpr i32 ObjectColorSFilter = 0x0a414c;\n\t\tconstexpr i32 ObjectColorControl = 0x0a4170;\n\t\tconstexpr i32 ObjectColorUnknown = 0x0a4194;\n\t\tconstexpr i32 ObjectColorInactive = 0x0a41b8;\n\n\t\tconstexpr i32 ObjectNameColor = 0x0a4040;\n\t\tconstexpr i32 ObjectNameColorShow = 0x0a4040;\n\t\tconstexpr i32 ObjectNameColorHide = 0x0a4044;\n\t\tconstexpr i32 MidPointSize = 0x0a3e14;\n\t\tconstexpr i32 ObjectClippingColorB = 0x0375d7;\n\t\tconstexpr i32 ObjectClippingColorG = 0x0375d9;\n\t\tconstexpr i32 ObjectClippingColorR = 0x0375db;\n\t\tconstexpr i32 ObjectClippingHeight = 0x0375e2;\n\n\t\tconstexpr i32 BPMGridColorBeat = 0x0a4050;\n\t\tconstexpr i32 BPMGridColorMeasure = 0x0a4054;\n\n\t}\n}\n"
  },
  {
    "path": "patch/overwrite_resource.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"overwrite_resource.hpp\"\n#include \"patch_access_key.hpp\"\n\n\n//template <class Func, class... Args>inline std::invoke_result<Func, Args...> resource_func_wrap_helper(Func func) {}\n\nHRSRC WINAPI overwrite_resource_t::FindResourceA_Wrap(HMODULE hModule, LPCSTR lpName, LPCSTR lpType) {\n\tif (hModule != GLOBAL::patchaul_hinst) return (*FindResourceA_org)(hModule, lpName, lpType);\n\tauto ret = (*FindResourceA_org)(hModule, lpName, lpType);\n\tif (ret) return ret;\n\treturn (*FindResourceA_org)(default_default_resource_hmod, lpName, lpType);\n}\n\nHCURSOR WINAPI overwrite_resource_t::LoadCursorA_Wrap(HINSTANCE hInstance, LPCSTR lpCursorName) {\n\tif (hInstance != GLOBAL::patchaul_hinst) return (*LoadCursorA_org)(hInstance, lpCursorName);\n\tif ((*FindResourceA_org)(hInstance, lpCursorName, RT_CURSOR)) {\n\t\treturn (*LoadCursorA_org)(hInstance, lpCursorName);\n\t}\n\treturn (*LoadCursorA_org)(default_default_resource_hmod, lpCursorName);\n}\nHICON WINAPI overwrite_resource_t::LoadIconA_Wrap(HINSTANCE hInstance, LPCSTR lpIconName) {\n\tif (hInstance != GLOBAL::patchaul_hinst) return (*LoadIconA_org)(hInstance, lpIconName);\n\tif ((*FindResourceA_org)(hInstance, lpIconName, RT_ICON)) {\n\t\treturn (*LoadIconA_org)(hInstance, lpIconName);\n\t}\n\treturn (*LoadIconA_org)(default_default_resource_hmod, lpIconName);\n}\nHANDLE WINAPI overwrite_resource_t::LoadImageA_Wrap(HINSTANCE hInst, LPCSTR name, UINT type, int cx, int cy, UINT fuLoad) {\n\tif (hInst != GLOBAL::patchaul_hinst) return (*LoadImageA_org)(hInst, name, type, cx, cy, fuLoad);\n\tauto ret = (*LoadImageA_org)(hInst, name, type, cx, cy, fuLoad);\n\tif (ret) return ret;\n\treturn (*LoadImageA_org)(default_default_resource_hmod, name, type, cx, cy, fuLoad);\n}\nHMENU WINAPI overwrite_resource_t::LoadMenuA_Wrap(HINSTANCE hInstance, LPCSTR lpMenuName) {\n\tHMENU ret;\n\tdo {\n\t\tif (hInstance != GLOBAL::patchaul_hinst) {\n\t\t\tret = (*LoadMenuA_org)(hInstance, lpMenuName);\n\t\t\tbreak;\n\t\t}\n\t\tif ((*FindResourceA_org)(hInstance, lpMenuName, RT_MENU)) {\n\t\t\tret = (*LoadMenuA_org)(hInstance, lpMenuName);\n\t\t\tbreak;\n\t\t}\n\t\tret = (*LoadMenuA_org)(default_default_resource_hmod, lpMenuName);\n\t\tbreak;\n\t} while (0);\n\t#ifdef PATCH_SWITCH_ACCESS_KEY\n\t\treturn patch::access_key.modify(lpMenuName, ret);\n\t#else\n\t\treturn ret;\n\t#endif\n}\nint WINAPI overwrite_resource_t::LoadStringA_Wrap(HINSTANCE hInstance, UINT uID, LPSTR lpBuffer, int cchBufferMax) {\n\tif (hInstance != GLOBAL::patchaul_hinst) return (*LoadStringA_org)(hInstance, uID, lpBuffer, cchBufferMax);\n\tauto ret = (*LoadStringA_org)(hInstance, uID, lpBuffer, cchBufferMax);\n\tif (ret) return ret;\n\treturn (*LoadStringA_org)(default_default_resource_hmod, uID, lpBuffer, cchBufferMax);\n}\n\nINT_PTR WINAPI overwrite_resource_t::DialogBoxParamA_Wrap(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) {\n\tif (hInstance != GLOBAL::patchaul_hinst) return (*DialogBoxParamA_org)(hInstance, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam);\n\tif ((*FindResourceA_org)(hInstance, lpTemplateName, RT_DIALOG)) {\n\t\treturn (*DialogBoxParamA_org)(hInstance, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam);\n\t}\n\treturn (*DialogBoxParamA_org)(default_default_resource_hmod, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam);\n}\n\nHWND WINAPI overwrite_resource_t::CreateDialogParamA_Wrap(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) {\n\tif (hInstance != GLOBAL::patchaul_hinst) return (*CreateDialogParamA_org)(hInstance, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam);\n\tif ((*FindResourceA_org)(hInstance, lpTemplateName, RT_DIALOG)) {\n\t\treturn (*CreateDialogParamA_org)(hInstance, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam);;\n\t}\n\treturn (*CreateDialogParamA_org)(default_default_resource_hmod, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam);\n}\n\nBOOL APIENTRY overwrite_resource_t::GetSaveFileNameA_Wrap(LPOPENFILENAMEA ofnap) {\n\tif (ofnap->hInstance != GLOBAL::patchaul_hinst || ofnap->lpTemplateName == NULL) return (*GetSaveFileNameA_org)(ofnap);\n\tauto fr_ret = (*FindResourceA_org)(GLOBAL::patchaul_hinst, ofnap->lpTemplateName, RT_DIALOG);\n\tif (fr_ret) return (*GetSaveFileNameA_org)(ofnap);\n\tofnap->hInstance = default_default_resource_hmod;\n\tauto ret = (*GetSaveFileNameA_org)(ofnap);\n\tofnap->hInstance = GLOBAL::patchaul_hinst;\n\treturn ret;\n}\n\nBOOL APIENTRY overwrite_resource_t::GetOpenFileNameA_Wrap(LPOPENFILENAMEA ofnap) {\n\tif (ofnap->hInstance != GLOBAL::patchaul_hinst || ofnap->lpTemplateName == NULL) return (*GetOpenFileNameA_org)(ofnap);\n\tauto fr_ret = (*FindResourceA_org)(GLOBAL::patchaul_hinst, ofnap->lpTemplateName, RT_DIALOG);\n\tif (fr_ret) return (*GetOpenFileNameA_org)(ofnap);\n\tofnap->hInstance = default_default_resource_hmod;\n\tauto ret = (*GetOpenFileNameA_org)(ofnap);\n\tofnap->hInstance = GLOBAL::patchaul_hinst;\n\treturn ret;\n}\n"
  },
  {
    "path": "patch/overwrite_resource.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"util.hpp\"\n#include \"util_pe.hpp\"\n#include \"util_resource.hpp\"\n#include \"offset_address.hpp\"\n\n#define overwrite_resource_t_func_org_def(name) inline static std::add_pointer_t<decltype(&name)> name##_org\n#define overwrite_resource_t_func_ptr_def(name) inline const static auto name##_ptr = &name\n\ninline class overwrite_resource_t {\npublic:\n\tstatic HRSRC WINAPI FindResourceA_Wrap(HMODULE hModule, LPCSTR lpName, LPCSTR lpType);\n\tstatic BOOL APIENTRY GetSaveFileNameA_Wrap(LPOPENFILENAMEA ofnap);\n\tstatic BOOL APIENTRY GetOpenFileNameA_Wrap(LPOPENFILENAMEA ofnap);\n\n\tstatic HCURSOR WINAPI LoadCursorA_Wrap(HINSTANCE hInstance, LPCSTR lpCursorName);\n\tstatic HICON WINAPI LoadIconA_Wrap(HINSTANCE hInstance, LPCSTR lpIconName);\n\tstatic HANDLE WINAPI LoadImageA_Wrap(HINSTANCE hInst, LPCSTR name, UINT type, int cx, int cy, UINT fuLoad);\n\tstatic HMENU WINAPI LoadMenuA_Wrap(HINSTANCE hInstance, LPCSTR lpMenuName);\n\tstatic int WINAPI LoadStringA_Wrap(HINSTANCE hInstance, UINT uID, LPSTR lpBuffer, int cchBufferMax);\n\t\n\tstatic INT_PTR WINAPI DialogBoxParamA_Wrap(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam);\n\tstatic HWND WINAPI CreateDialogParamA_Wrap(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam);\n\t\nprivate:\n\n\tinline static HMODULE default_default_resource_hmod;\n\n\toverwrite_resource_t_func_ptr_def(FindResourceA_Wrap);\n\toverwrite_resource_t_func_ptr_def(GetSaveFileNameA_Wrap);\n\toverwrite_resource_t_func_ptr_def(GetOpenFileNameA_Wrap);\n\toverwrite_resource_t_func_ptr_def(LoadCursorA_Wrap);\n\toverwrite_resource_t_func_ptr_def(LoadIconA_Wrap);\n\toverwrite_resource_t_func_ptr_def(LoadImageA_Wrap);\n\toverwrite_resource_t_func_ptr_def(LoadMenuA_Wrap);\n\toverwrite_resource_t_func_ptr_def(LoadStringA_Wrap);\n\toverwrite_resource_t_func_ptr_def(DialogBoxParamA_Wrap);\n\toverwrite_resource_t_func_ptr_def(CreateDialogParamA_Wrap);\n\n\toverwrite_resource_t_func_org_def(FindResourceA);\n\toverwrite_resource_t_func_org_def(GetSaveFileNameA);\n\toverwrite_resource_t_func_org_def(GetOpenFileNameA);\n\toverwrite_resource_t_func_org_def(LoadCursorA);\n\toverwrite_resource_t_func_org_def(LoadIconA);\n\toverwrite_resource_t_func_org_def(LoadImageA);\n\toverwrite_resource_t_func_org_def(LoadMenuA);\n\toverwrite_resource_t_func_org_def(LoadStringA);\n\toverwrite_resource_t_func_org_def(DialogBoxParamA);\n\toverwrite_resource_t_func_org_def(CreateDialogParamA);\n\n\tstatic void InitAtResourceLoaded() {\n\t\tfor (auto& s : patch_resource_message_stack) {\n\t\t\ts->fire();\n\t\t}\n\t\tpatch_resource_message_stack.clear();\n\t}\n\tinline static auto InitAtResourceLoaded_ptr = &InitAtResourceLoaded;\n\npublic:\n\tvoid operator()() {\n\t\t/*\n\t\t\t・LoadLibrary直後のEnumResourceLanguagesAを消し飛ばす\n\t\t\t　・patch.aulのリソースを別に登録させない\n\t\t\t　・patch.aulは正しい言語拡張リソースではなかったということにする\n\t\t\t　　・これで必ず毎回読まれるようになる\n\n\t\t\t・AviUtlのデフォルトのリソースのHMODULEをこれにする\n\t\t\t　・メニューを読んであとから編集～はしない\n\n\t\t\t ・SaveDialogとOpenDIalogのTEMPLETEどうしよう...\n\t\t\t 　・これも乗っ取っちまえ\n\t\t*/\n\t\n\t\t// reinterpret_cast<i32>(search_import((HMODULE)GLOBAL::aviutl_base, \"COMDLG32.DLL\", \"GetOpenFileNameA\")),\n\t\tauto reloc_list = search_reloc((HMODULE)GLOBAL::aviutl_base, {\n\t\t\t0x06f07c, // GetOpenFileNameA \n\t\t\t0x06f074, // GetSaveFileNameA\n\t\t\t0x06f0dc, // FindResourceA\n\t\t\t0x06f400, // LoadCursorA\n\t\t\t0x06f394, // LoadIconA\n\t\t\t0x06f3a0, // LoadImageA\n\t\t\t0x06f3b8, // LoadMenuA\n\t\t\t0x06f3b4, // LoadStringA\n\t\t\t0x06f3b0, // DialogBoxParamA\n\t\t\t0x06f3ac, // CreateDialogParamA\n\t\t});\n\n\t\tfor (auto v : reloc_list[0x06f07c])\n\t\t\tOverWriteOnProtectHelper(reinterpret_cast<i32>(v), 4).store_i32(0, &GetOpenFileNameA_Wrap_ptr);\n\n\t\tfor (auto v : reloc_list[0x06f074])\n\t\t\tOverWriteOnProtectHelper(reinterpret_cast<i32>(v), 4).store_i32(0, &GetSaveFileNameA_Wrap_ptr);\n\n\t\tfor (auto v : reloc_list[0x06f0dc])\n\t\t\tOverWriteOnProtectHelper(reinterpret_cast<i32>(v), 4).store_i32(0, &FindResourceA_Wrap_ptr);\n\n\t\tfor (auto v : reloc_list[0x06f400])\n\t\t\tOverWriteOnProtectHelper(reinterpret_cast<i32>(v), 4).store_i32(0, &LoadCursorA_Wrap_ptr);\n\n\t\tfor (auto v : reloc_list[0x06f394])\n\t\t\tOverWriteOnProtectHelper(reinterpret_cast<i32>(v), 4).store_i32(0, &LoadIconA_Wrap_ptr);\n\n\t\tfor (auto v : reloc_list[0x06f3a0])\n\t\t\tOverWriteOnProtectHelper(reinterpret_cast<i32>(v), 4).store_i32(0, &LoadImageA_Wrap_ptr);\n\n\t\tfor (auto v : reloc_list[0x06f3b8])\n\t\t\tOverWriteOnProtectHelper(reinterpret_cast<i32>(v), 4).store_i32(0, &LoadMenuA_Wrap_ptr);\n\n\t\tfor (auto v : reloc_list[0x06f3b4])\n\t\t\tOverWriteOnProtectHelper(reinterpret_cast<i32>(v), 4).store_i32(0, &LoadStringA_Wrap_ptr);\n\n\t\tfor (auto v : reloc_list[0x06f3b0])\n\t\t\tOverWriteOnProtectHelper(reinterpret_cast<i32>(v), 4).store_i32(0, &DialogBoxParamA_Wrap_ptr);\n\n\t\tfor (auto v : reloc_list[0x06f3ac])\n\t\t\tOverWriteOnProtectHelper(reinterpret_cast<i32>(v), 4).store_i32(0, &CreateDialogParamA_Wrap_ptr);\n\n#define def(name, ofs) name = reinterpret_cast<decltype(name)>(GLOBAL::aviutl_base + ofs)\n\t\tdef(GetOpenFileNameA_org  , 0x06f07c);\n\t\tdef(GetSaveFileNameA_org  , 0x06f074);\n\t\tdef(FindResourceA_org     , 0x06f0dc);\n\t\tdef(LoadCursorA_org       , 0x06f400);\n\t\tdef(LoadIconA_org         , 0x06f394);\n\t\tdef(LoadImageA_org        , 0x06f3a0);\n\t\tdef(LoadMenuA_org         , 0x06f3b8);\n\t\tdef(LoadStringA_org       , 0x06f3b4);\n\t\tdef(DialogBoxParamA_org   , 0x06f3b0);\n\t\tdef(CreateDialogParamA_org, 0x06f3ac);\n#undef def\n\n\t\t/*\n\t\tOverWriteOnProtectHelper(GLOBAL::aviutl_base + 0x06f07c, 4).store_i32(0, GetOpenFileNameA_Wrap);\n\t\tOverWriteOnProtectHelper(GLOBAL::aviutl_base + 0x06f074, 4).store_i32(0, GetSaveFileNameA_Wrap);\n\t\tOverWriteOnProtectHelper(GLOBAL::aviutl_base + 0x06f0dc, 4).store_i32(0, FindResourceA_Wrap);\n\n\t\tOverWriteOnProtectHelper(GLOBAL::aviutl_base + 0x06f400, 4).store_i32(0, LoadCursorA_Wrap);\n\t\tOverWriteOnProtectHelper(GLOBAL::aviutl_base + 0x06f394, 4).store_i32(0, LoadIconA_Wrap);\n\t\tOverWriteOnProtectHelper(GLOBAL::aviutl_base + 0x06f3a0, 4).store_i32(0, LoadImageA_Wrap);\n\t\tOverWriteOnProtectHelper(GLOBAL::aviutl_base + 0x06f3b8, 4).store_i32(0, LoadMenuA_Wrap);\n\t\tOverWriteOnProtectHelper(GLOBAL::aviutl_base + 0x06f3b4, 4).store_i32(0, LoadStringA_Wrap);\n\n\t\tOverWriteOnProtectHelper(GLOBAL::aviutl_base + 0x06f3b0, 4).store_i32(0, DialogBoxParamA_Wrap);\n\t\tOverWriteOnProtectHelper(GLOBAL::aviutl_base + 0x06f3ac, 4).store_i32(0, CreateDialogParamA_Wrap);\n\t\t*/\n\n\t\t// default_resource_hmod\n\t\tauto default_resource_hmod_ptr = (HMODULE*)(GLOBAL::aviutl_base + OFS::AviUtl::default_resource_hmod);\n\t\tdefault_default_resource_hmod = std::exchange(*default_resource_hmod_ptr, GLOBAL::patchaul_hinst);\n\n\t\tconst char code[] =\n\t\t\t\"\\x50\" // push eax\n\t\t\t\"\\xff\\x15xxxx\" // call [i32]\n\t\t\t\"\\x58\" // pop eax\n\t\t\t\"\\xc3\"; // ret\n\n\t\tOverWriteOnProtectHelper h(GLOBAL::aviutl_base + 0x0548e0, sizeof(code) - 1);\n\t\tmemcpy((void*)(GLOBAL::aviutl_base + 0x0548e0), code, sizeof(code) - 1);\n\t\th.store_i32(3, &InitAtResourceLoaded_ptr);\n\n\t}\n\n} overwrite_resource;\n\n"
  },
  {
    "path": "patch/packages.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<packages>\n  <package id=\"boost\" version=\"1.79.0\" targetFramework=\"native\" />\n  <package id=\"boost_system-vc143\" version=\"1.79.0\" targetFramework=\"native\" />\n</packages>"
  },
  {
    "path": "patch/patch.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"macro.h\"\n\n#include \"init.hpp\"\n\n\n#include \"add_dll_ref.hpp\"\n#include \"config.hpp\"\n\nBOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) {\n\tstatic bool loading_self = false;\n\tswitch (fdwReason) {\n\tcase DLL_PROCESS_ATTACH:\n\t\tDisableThreadLibraryCalls(hinstDLL);\n\n\t\tif (add_dll_ref.dllmain_if_break())break;\n\n\t\tGLOBAL::init_minimum(hinstDLL);\n\n\t\tinit.InitAtDllMain();\n\n\t\tbreak;\n\tcase DLL_PROCESS_DETACH:\n\t\t//GLOBAL::config.store(GLOBAL::patchaul_config_path);\n\t\tconfig2.store(GLOBAL::patchaul_config_path);\n\t\t#ifdef PATCH_SWITCH_CONSOLE\n\t\t\tpatch::console.exit();\n\t\t#endif\n\t\tbreak;\n\t}\n\treturn TRUE;\n}\n"
  },
  {
    "path": "patch/patch.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n\n#include \"patch_access_key.hpp\"\n#include \"patch_exo_sceneidx.hpp\"\n#include \"patch_exo_trackparam.hpp\"\n#include \"patch_exo_trackminusval.hpp\"\n#include \"patch_tra_aviutlfilter.hpp\"\n#include \"patch_exo_aviutlfilter.hpp\"\n#include \"patch_exo_specialcolorconv.hpp\"\n#include \"patch_lua.hpp\"\n#include \"patch_console.hpp\"\n#include \"patch_exception_log.hpp\"\n#include \"patch_aviutl_wndproc_override.hpp\"\n#include \"patch_sysinfo_write.hpp\"\n#include \"patch_splash.hpp\"\n#include \"patch_scroll_objdlg.hpp\"\n#include \"patch_text_op_size.hpp\"\n#include \"patch_ignore_media_param_reset.hpp\"\n#include \"patch_susie_load.hpp\"\n#include \"patch_alpha_bg.hpp\"\n#include \"patch_theme_cc.hpp\"\n#include \"patch_helpful_msgbox.hpp\"\n#include \"patch_fast_setting_dialog.hpp\"\n#include \"patch_fast_exeditwindow.hpp\"\n#include \"patch_exeditwindow_sizing.hpp\"\n#include \"patch_setting_dialog_wndproc_override.hpp\"\n#include \"patch_undo.hpp\"\n#include \"patch_fast_getputpixeldata.hpp\"\n#include \"patch_fast_polortransform.hpp\"\n#include \"patch_fast_displacementmap.hpp\"\n#include \"patch_fast_radiationalblur.hpp\"\n#include \"patch_fast_flash.hpp\"\n#include \"patch_fast_lensblur.hpp\"\n#include \"patch_font_dialog.hpp\"\n#include \"patch_setting_dialog_move.hpp\"\n#include \"patch_redo.hpp\"\n#include \"patch_fast.hpp\"\n#include \"patch_fast_cl.hpp\"\n#include \"patch_lua_getvalueex.hpp\"\n#include \"patch_lua_rand.hpp\"\n#include \"patch_lua_randex.hpp\"\n#include \"patch_fast_text.hpp\"\n#include \"patch_fast_create_figure.hpp\"\n#include \"patch_obj_lensblur.hpp\"\n#include \"patch_obj_noise.hpp\"\n#include \"patch_setting_dialog_excolorconfig.hpp\"\n#include \"patch_fast_border.hpp\"\n#include \"patch_fast_directionalblur.hpp\"\n#include \"patch_rclickmenu_split.hpp\"\n#include \"patch_rclickmenu_delete.hpp\"\n#include \"patch_tra_change_drawfilter.hpp\"\n#include \"patch_tra_specified_speed.hpp\"\n#include \"patch_blend.hpp\"\n#include \"patch_failed_sjis_msgbox.hpp\"\n#include \"patch_obj_colorcorrection.hpp\"\n#include \"patch_aup_scene_setting.hpp\"\n#include \"patch_exo_fold_gui.hpp\"\n#include \"patch_colorpalette_cache.hpp\"\n#include \"patch_add_extension.hpp\"\n#include \"patch_obj_specialcolorconv.hpp\"\n#include \"patch_dialog_new_file.hpp\"\n#include \"patch_exo_midpt_and_tra.hpp\"\n#include \"patch_fileinfo.hpp\"\n#include \"patch_playback_speed.hpp\"\n#include \"patch_fast_glow.hpp\"\n#include \"patch_obj_glow.hpp\"\n#include \"patch_setting_new_project.hpp\"\n#include \"patch_aup_layer_setting.hpp\"\n#include \"patch_failed_file_drop.hpp\"\n#include \"patch_failed_longer_path.hpp\"\n"
  },
  {
    "path": "patch/patch.rc",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include <winres.h>\n#include \"resource.h\"\n#include \"macro.h\"\n\nSTRINGTABLE\nLANGUAGE LANG_JAPANESE,SUBLANG_DEFAULT\n{\n\t0,\t\t\"日本語 (patched)\"\n\t1,\t\t\"patch.aul by ePi\"\n\n\t10,\t\t\"デフォルト\"\n\t11,\t\t\"自動\"\n\t12,\t\t\"なし\"\n\t13,\t\t\"秒\"\n\t14,\t\t\"分\"\n\t15,\t\t\"時間\"\n\t16,\t\t\"インターレース解除\"\n\t17,\t\t\"奇数\"\n\t18,\t\t\"偶数\"\n\t19,\t\t\"二重化\"\n\t21,\t\t\"自動\"\n\t22,\t\t\"自動24fps\"\n\t23,\t\t\"標準\"\n\t24,\t\t\"反転\"\n\t25,\t\t\"周期\"\n\t26,\t\t\"不明\"\n\t27,\t\t\"出力中\"\n\t28,\t\t\"計測中\"\n\t29,\t\t\"検索中\"\n\t30,\t\t\"残り時間\"\n\t31,\t\t\"再圧縮不可\"\n\t32,\t\t\"未圧縮\"\n\t33,\t\t\"fps変換無し\"\n\t34,\t\t\"画像サイズ\"\n\t35,\t\t\"記録時間\"\n\t36,\t\t\"フレームレート\"\n\t37,\t\t\"フレーム数\"\n\t38,\t\t\"ビデオ圧縮\"\n\t39,\t\t\"サンプリングレート\"\n\t40,\t\t\"チャンネル数\"\n\t41,\t\t\"オーディオ形式\"\n\t42,\t\t\"強さ\"\n\t43,\t\t\"範囲\"\n\t44,\t\t\"しきい値\"\n\t45,\t\t\"下限値\"\n\t46,\t\t\"上限値\"\n\t49,\t\t\"上\"\n\t50,\t\t\"下\"\n\t51,\t\t\"左\"\n\t52,\t\t\"右\"\n\t53,\t\t\"明るさ\"\n\t54,\t\t\"コントラスト\"\n\t55,\t\t\"輝度\"\n\t56,\t\t\"ガンマ\"\n\t57,\t\t\"色の濃さ\"\n\t58,\t\t\"色合い\"\n\t59,\t\t\"レベル\"\n\t60,\t\t\"音量の最大化\"\n\t61,\t\t\"ぼかしフィルタ\"\n\t62,\t\t\"クリッピング＆リサイズ\"\n\t63,\t\t\"元の縦横比に合わせる\"\n\t64,\t\t\"元のサイズに拡大\"\n\t66,\t\t\"色調補正\"\n\t67,\t\t\"拡張色調補正\"\n\t68,\t\t\"TV -> PC スケール補正\"\n\t69,\t\t\"RGBの同期\"\n\t73,\t\t\"ヒストグラム\"\n\t74,\t\t\"インターレースの解除\"\n\t75,\t\t\"自動24fps解除\"\n\t76,\t\t\"ドット単位解除\"\n\t77,\t\t\"イメージ表示\"\n\t78,\t\t\"自動解除\"\n\t79,\t\t\"動き重視\"\n\t80,\t\t\"横縞部分を二重化\"\n\t81,\t\t\"奇数偶数解除\"\n\t82,\t\t\"位置補間\"\n\t83,\t\t\"適合補間\"\n\t84,\t\t\"インターリーブ\"\n\t85,\t\t\"0.5秒\"\n\t86,\t\t\"1秒\"\n\t87,\t\t\"2秒\"\n\t88,\t\t\"1フレーム\"\n\t89,\t\t\"2フレーム\"\n\t90,\t\t\"5フレーム\"\n\t91,\t\t\"10フレーム\"\n\t92,\t\t\"指定フレーム数\"\n\t93,\t\t\"ナビゲートウィンドウ\"\n\t94,\t\t\"ノイズ除去フィルタ\"\n\t95,\t\t\"ノイズ除去(時間軸)フィルタ\"\n\t96,\t\t\"再生ウィンドウ\"\n\t97,\t\t\"フレームレートの変更\"\n\t98,\t\t\"フレームレートの設定\"\n\t99,\t\t\"24fps<-30fpsの間引きには自動24fpsの処理を使う\"\n\t100,\t\"サイズの変更\"\n\t101,\t\"指定サイズ\"\n\t102,\t\"シャープフィルタ\"\n\t105,\t\"連番BmpFile (*.bmp)|*.bmp\"\n\t106,\t\"ツールウィンドウ\"\n\t107,\t\"の設定\"\n\t108,\t\"の表示\"\n\t109\t\t\"フィールドオーダー\"\n\t110\t\t\"ボトムフィールド -> トップフィールド\"\n\t111\t\t\"トップフィールド -> ボトムフィールド\"\n\t112\t\t\"ファイル制御\"\n\t113\t\t\"ビデオ展開形式\"\n\t114\t\t\"音量の調整\"\n\t115\t\t\"音声の位置調整\"\n\t116\t\t\"位置\"\n\t122\t\t\"縁塗りつぶし\"\n\t123\t\t\"黒で塗る\"\n\t124\t\t\"縁の色で塗る\"\n\t125\t\t\"PC -> TV スケール補正\"\n\t128\t\t\"中央に配置\"\n\t129\t\t\"何もしない\"\n\t130\t\t\"ウィンドウズをシャットダウン\"\n\t131\t\t\"ウィンドウズを休止\"\n\t132\t\t\"ウィンドウズをサスペンド\"\n\t133\t\t\"AviUtlを終了\"\n\t134\t\t\"バッチ出力リスト\"\n\t135\t\t\"[出力ファイル名が指定されていません]\"\n\t136\t\t\"色変換の設定\"\n\t137\t\t\"[ 入力 ]\"\n\t138\t\t\"[ 出力 ]\"\n\t139\t\t\"追加読み込み\"\n\t140\t\t\"音声読み込み\"\n\t141\t\t\"プロジェクトを開く\"\n\t142\t\t\"プロジェクトを保存\"\n\t143\t\t\"AVI出力\"\n\t144\t\t\"WAV出力\"\n\t145\t\t\"AviUtlを終了＆ウィンドウズを休止\"\n\t146\t\t\"AviUtlを終了＆ウィンドウズをサスペンド\"\n\t1000,\t\"ファイルの読み込みに失敗しました。\"\n\t1001,\t\"ファイルの書き込みに失敗しました。\\n\\nディスクの空き容量が足りないか\\n作成できるファイルサイズの上限を超えた可能性があります。\"\n\t1002,\t\"ファイルの作成に失敗しました。\"\n\t1003,\t\"このファイルには対応していません。\"\n\t1004,\t\"使用されていたファイルが見つからないか変更されています。\\n別のファイルを指定しますか？\"\n\t1005,\t\"同時に読み込めるファイルは%d個までです。\"\n\t1006,\t\"%dx%dを超える画像サイズのファイルは編集できません。\\n\\n最大画像サイズはシステムの設定で変更出来ます。\"\n\t1007,\t\"%dx%dより小さい画像サイズのファイルは編集できません。\"\n\t1008,\t\"編集できる最大フレーム数は%dフレームまでです。\\n\\n最大フレーム数はシステムの設定で変更出来ます。\"\n\t1009,\t\"再圧縮するフレームがありますがよろしいですか？\\n\\n※フレーム%d%s。\"\n\t1010,\t\"バッチ登録は最大%d個までです。\"\n\t1011,\t\"の画像フォーマットが違う\"\n\t1012,\t\"の画像サイズが違う\"\n\t1013,\t\"がキーフレームから続いていない\"\n\t1014,\t\"が60fps化モードで読み込まれている\"\n\t1015,\t\"編集しているファイルへの上書きは出来ません。\"\n\t1016,\t\"ビデオ圧縮の初期化に失敗しました。\\n\\n画像サイズを特定の倍数にしないと\\n使用出来ないコーデックの可能性があります。\"\n\t1017,\t\"オーディオ圧縮の初期化に失敗しました。\\n\\n使用出来ないコーデックの可能性があります。\"\n\t1018,\t\"出力を中断しますか？\"\n\t1019,\t\"検索を中断しますか？\"\n\t1020,\t\"ありません。\"\n\t1021,\t\"使用されていません。\"\n\t1022,\t\"プロファイル名に以下の文字は使えません。\\n\\n%s\"\n\t1023,\t\"入力ファイルへの上書きは出来ません。\"\n\t1024,\t\"連結できるファイルは最大%d個までです。\"\n\t1025,\t\"再圧縮しないと正常なファイルが作成されない可能性がありますがよろしいですか？\"\n\t1026,\t\"出力プラグインが見つかりません。\"\n\t1028,\t\"ファイルの情報\"\n\t1029,\t\"プラグインフィルタ情報\"\n\t1030,\t\"入力プラグイン情報\"\n\t1031,\t\"出力プラグイン情報\"\n\t1032,\t\"オーバーレイ情報\"\n\t1033,\t\"バージョン情報\"\n\t1034,\t\"言語拡張リソース情報\"\n\t1035,\t\"メモリの確保に失敗しました。\\n\\nキャッシュサイズを調整して再試行しますか？\"\n\t1036,\t\"バッチ出力に失敗したファイルがあります。\"\n\t1037,\t\"すべて削除しますがよろしいですか？\"\n\t1038,\t\"ファイルの読み込みに失敗しました。\\n\\nこのファイル形式には対応していないか\\n対応するコーデックやプラグインが\\n登録されていない可能性があります。\"\n\t1039,\t\"ファイルの出力に失敗しました。\"\n\t1040,\t\"[開始]ボタンを押すとバッチ出力を開始します\"\n\t1041,\t\"すべて正常に終了しました\"\n\t1042,\t\"\\x22%s\\x22を出力中です\"\n\t1043,\t\"他のプロセスでの出力終了を待っています\"\n\t1044,\t\"色変換プラグイン情報\"\n\t1045,\t\"複数の操作が同じショートカットキーに割り当てられています\\n\\n%s\\n%s\\n\"\n\t1046,\t\"現在の編集データは破棄されますがよろしいですか？\"\n\t1047,\t\"メモリをアドレスに割り当てることができません。\"\n\n\tPATCH_RS_PATCH_FAILED_TO_SAVE_SETTING, \t\t\t\t\"設定ファイルの保存に失敗\"\n\tPATCH_RS_PATCH_FAILED_TO_LOAD_SETTING,\t\t\t\t\"設定ファイルの読込に失敗\"\n\tPATCH_RS_PATCH_FAILED_TO_INIT_CONSOLE,\t\t\t\t\"コンソールの初期化に失敗\"\n\tPATCH_RS_PATCH_CONSOLE_IS_DIABLED,\t\t\t\t\t\"コンソール機能は無効になっています。\\n有効にするには、switch.console を true にしてください。\"\n\tPATCH_RS_PATCH_INVALID_SETTING_JSON,\t\t\t\t\"設定ファイルは不正なjsonです。文法を確認してください。\\n設定は読込/保存されません。\"\n\tPATCH_RS_PATCH_CONFLICT_PLUGIN,\t\t\t\t\t\t\"以下プラグインの機能はpatch.aulが既に持っているため、除去してください。\\nプラグインファイルを削除しますか？\\n\\n{}\"\n\tPATCH_RS_PATCH_OLD_LSW,\t\t\t\t\t\t\t\t\"古いバージョンのL-SMASH Worksを使用しようとしています。このバージョンの使用は推奨されません。\\n新しいバージョンへとアクセスしますか？\"\n\tPATCH_RS_PATCH_FAILED_TO_CREATE_EXCEPTION_DIALOG,\t\"patch.aulは例外ダイアログの生成に失敗しました。({})\\n例外の詳細情報は log/{} に保存されています。\\n情報\\n{}\"\n\tPATCH_RS_PATCH_WEB_CONFIRM,\t\t\t\t\t\t\t\"次の外部Webサイトを開きますか？\"\n\tPATCH_RS_PATCH_WEB_CONFIRM_BUTTON_OPEN, \t\t\t\"開く\"\n\tPATCH_RS_PATCH_WEB_CONFIRM_BUTTON_COPY, \t\t\t\"URLをコピー\"\n\tPATCH_RS_PATCH_WEB_CONFIRM_BUTTON_CANCEL, \t\t\t\"キャンセル\"\n\n#ifdef PATCH_SWITCH_CL\n\tPATCH_RS_PATCH_CANT_USE_CL,\t\t\t\t\t\t\t\"OpenCL Effectは使用できません\"\n#endif\n\n#ifdef PATCH_SWITCH_TRANSRATE\n#endif\n}\n\nAVIUTL MENU\n{\n\tPOPUP \"ファイル\"\n\t{\n\t\tMENUITEM \"開く\", 5097\n\t\tMENUITEM \"閉じる\", 5157\n\t\tMENUITEM \"追加読み込み\", 5100\n\t\tMENUITEM \"音声読み込み\", 5168\n\t\tMENUITEM SEPARATOR\n\t\tMENUITEM \"編集プロジェクトを開く\", 5118\n\t\tMENUITEM \"編集プロジェクトの保存\", 1023\n\t\tMENUITEM \"編集プロジェクトの上書き\", 1024\n\t\tMENUITEM SEPARATOR\n\t\tMENUITEM \"AVI出力\", 1003\n\t\tMENUITEM \"WAV出力\", 1062\n\t\tPOPUP \"プラグイン出力\"\n\t\t{\n\t\t\tMENUITEM \"\", 5395\n\t\t}\n\t\tMENUITEM \"バッチ出力\", 1025\n\t\tMENUITEM \"出力の中断\", 1009\n\t\tMENUITEM SEPARATOR\n\t\tPOPUP \"インポート\"\n\t\t{\n\t\t\tMENUITEM \"キーフレームリスト\", 5167\n\t\t\tMENUITEM \"\", 14000\n\t\t}\n\t\tPOPUP \"エクスポート\"\n\t\t{\n\t\t\tMENUITEM \"キーフレームリスト\", 1054\n\t\t\tMENUITEM \"\", 15000\n\t\t}\n\t\tPOPUP \"AVIファイル操作\"\n\t\t{\n\t\t\tMENUITEM \"AVIファイルの連結\", 1057\n\t\t\tMENUITEM \"AVIファイルの合成\", 1058\n\t\t}\n\t\tPOPUP \"最近使ったファイル\"\n\t\t{\n\t\t\tMENUITEM \"なし\", 5596\n\t\t\tMENUITEM SEPARATOR\n\t\t\tMENUITEM \"最近使ったファイルの履歴を消去\", 1073\n\t\t}\n\t\tMENUITEM SEPARATOR\n\t\tPOPUP \"環境設定\"\n\t\t{\n\t\t\tPOPUP \"優先度\"\n\t\t\t{\n\t\t\t\tMENUITEM \"Highest\", 1041\n\t\t\t\tMENUITEM \"High\", 1040\n\t\t\t\tMENUITEM \"Normal\", 1039\n\t\t\t\tMENUITEM \"Low\", 1038\n\t\t\t\tMENUITEM \"Lowest\", 1037\n\t\t\t\tMENUITEM SEPARATOR\n\t\t\t\tMENUITEM \"Realtime\", 1042\n\t\t\t}\n\t\t\tMENUITEM SEPARATOR\n\t\t\tMENUITEM \"システムの設定\", 108\n\t\t\tMENUITEM \"コーデックの設定\", 109\n\t\t\tPOPUP \"入力プラグインの設定\"\n\t\t\t{\n\t\t\t\tMENUITEM \"\", 5595\n\t\t\t}\n\t\t\tMENUITEM \"入力プラグイン優先度の設定\", 1086\n\t\t\tMENUITEM \"ショートカットキーの設定\", 102\n\t\t\tMENUITEM \"言語の設定 (Language)\", 106\n\t\t\tMENUITEM SEPARATOR\n\t\t\tMENUITEM \"ウィンドウの位置を初期化\", 111\n\t\t}\n\t\tMENUITEM SEPARATOR\n\t\tMENUITEM \"終了\", 1002\n\t}\n\tPOPUP \"フィルタ\"\n\t{\n\t\tMENUITEM \"\", 10000\n\t\tMENUITEM SEPARATOR\n\t\tMENUITEM \"\", 10999\n\t\tMENUITEM SEPARATOR\n\t\tMENUITEM \"すべてのフィルタをOFFにする\", 5183\n\t}\n\tPOPUP \"設定\"\n\t{\n\t\tMENUITEM \"\", 11000\n\t\tMENUITEM SEPARATOR\n\t\tMENUITEM \"\", 11999\n\t\tMENUITEM SEPARATOR\n\t\tMENUITEM \"\", 11998\n\t\tMENUITEM SEPARATOR\n\t\tPOPUP \"圧縮の設定\"\n\t\t{\n\t\t\tMENUITEM \"ビデオ圧縮の設定\", 5127\n\t\t\tMENUITEM \"オーディオ圧縮の設定\", 5128\n\t\t\tMENUITEM SEPARATOR\n\t\t\tMENUITEM \"プラグイン出力の設定\", 5399\n\t\t}\n\t\tPOPUP \"フィルタ順序の設定\"\n\t\t{\n\t\t\tMENUITEM \"ビデオフィルタ順序の設定\", 5139\n\t\t\tMENUITEM \"オーディオフィルタ順序の設定\", 5181\n\t\t}\n\t}\n\tPOPUP \"編集\"\n\t{\n\t\tMENUITEM \"現在のフレームの画像をコピー\", 1020\n\t\tMENUITEM \"現在のフレームに画像を貼り付け\", 5117\n\t\tMENUITEM \"現在のフレームをクリップボードにコピー\", 1026\n\t\tMENUITEM \"現在のフレームにクリップボードから貼り付け\", 5123\n\t\tMENUITEM \"現在のフレームの出力イメージをクリップボードにコピー\", 1070\n\t\tMENUITEM \"指定のフレームに移動\", 5131\n\t\tMENUITEM \"選択範囲の指定\", 5115\n\t\tMENUITEM \"選択範囲のフレームに画像を貼り付け\", 5184\n\t\tMENUITEM \"選択範囲のフレーム切り出し\", 5143\n\t\tMENUITEM \"選択範囲のフレーム削除\", 5101\n\t\tMENUITEM SEPARATOR\n\t\tMENUITEM \"元に戻す\", 5147\n\t\tMENUITEM \"すべてのフレームを選択\", 5112\n\t\tMENUITEM SEPARATOR\n\t\tMENUITEM \"選択範囲を新しいプロファイルにする\", 5109\n\t\tMENUITEM \"選択範囲を新しい圧縮の設定にする\", 5126\n\t\tMENUITEM \"選択範囲のインターレース解除を指定\", 5125\n\t\tPOPUP \"現在のフレームのインターレース解除\"\n\t\t{\n\t\t\tMENUITEM \"標準\", 5196\n\t\t\tMENUITEM \"反転\", 5197\n\t\t\tMENUITEM \"奇数\", 5198\n\t\t\tMENUITEM \"偶数\", 5199\n\t\t\tMENUITEM \"二重化\", 5200\n\t\t\tMENUITEM \"自動\", 5201\n\t\t}\n\t\tPOPUP \"現在のフレームのプロファイル\"\n\t\t{\n\t\t\tMENUITEM \"標準プロファイル\", 5206\n\t\t\tMENUITEM \"プロファイル[1]\", 5207\n\t\t\tMENUITEM \"プロファイル[2]\", 5208\n\t\t\tMENUITEM \"プロファイル[3]\", 5209\n\t\t\tMENUITEM \"プロファイル[4]\", 5210\n\t\t\tMENUITEM \"プロファイル[5]\", 5211\n\t\t\tMENUITEM \"プロファイル[6]\", 5212\n\t\t\tMENUITEM \"プロファイル[7]\", 5213\n\t\t\tMENUITEM \"プロファイル[8]\", 5214\n\t\t\tMENUITEM \"プロファイル[9]\", 5215\n\t\t}\n\t\tMENUITEM SEPARATOR\n\t\tMENUITEM \"現在のフレームをキーフレームにする\", 5129\n\t\tMENUITEM \"現在のフレームを優先間引きフレームにする\", 5132\n\t\tMENUITEM \"現在のフレームをマークする\", 5130\n\t\tMENUITEM \"現在のフレームをコピーフレームにする\", 5156\n\t\tMENUITEM SEPARATOR\n\t\tMENUITEM \"再生速度の情報を変更\", 5398\n\t\tMENUITEM SEPARATOR\n\t\tPOPUP \"基本機能\"\n\t\t{\n\t\t\tMENUITEM \"次のフレームに移動 (→)\", 9002\n\t\t\tMENUITEM \"前のフレームに移動 (←)\", 9001\n\t\t\tMENUITEM \"削除フレームを飛ばして次のフレームに移動 (↓)\", 5142\n\t\t\tMENUITEM \"削除フレームを飛ばして前のフレームに移動 (↑)\", 5141\n\t\t\tMENUITEM \"先頭のフレームに移動(Home)\", 5396\n\t\t\tMENUITEM \"最後のフレームに移動(End)\", 5397\n\t\t\tMENUITEM \"現在のフレームを選択開始フレームにする ([)\", 5110\n\t\t\tMENUITEM \"現在のフレームを選択終了フレームにする (])\", 5111\n\t\t\tMENUITEM \"選択開始フレームに移動\", 5103\n\t\t\tMENUITEM \"選択終了フレームに移動\", 5104\n\t\t\tMENUITEM \"次のキーフレームに移動\", 5174\n\t\t\tMENUITEM \"前のキーフレームに移動\", 5175\n\t\t\tMENUITEM \"次のマークフレームに移動\", 5178\n\t\t\tMENUITEM \"前のマークフレームに移動\", 5179\n\t\t\tMENUITEM \"次のプロファイルの変更フレームに移動\", 5176\n\t\t\tMENUITEM \"前のプロファイルの変更フレームに移動\", 5177\n\t\t\tMENUITEM \"次のフレーム不連続点に移動\", 5170\n\t\t\tMENUITEM \"前のフレーム不連続点に移動\", 5171\n\t\t\tMENUITEM \"任意フレーム数次移動A (PageDown)\", 5187\n\t\t\tMENUITEM \"任意フレーム数前移動A (PageUp)\", 5188\n\t\t\tMENUITEM \"任意フレーム数次移動B\", 5189\n\t\t\tMENUITEM \"任意フレーム数前移動B\", 5190\n\t\t\tMENUITEM \"任意フレーム数次移動C\", 5191\n\t\t\tMENUITEM \"任意フレーム数前移動C\", 5192\n\t\t\tMENUITEM \"任意フレーム数次移動D\", 5193\n\t\t\tMENUITEM \"任意フレーム数前移動D\", 5194\n\t\t\tMENUITEM \"現在のフレームから再生ウィンドウで再生/停止\", 1099\n\t\t\tMENUITEM \"現在のフレーム番号をクリップボードにコピー\", 1090\n\t\t}\n\t}\n\tPOPUP \"プロファイル\"\n\t{\n\t\tMENUITEM \"\", 8005\n\t\tMENUITEM SEPARATOR\n\t\tPOPUP \"プロファイルの編集\"\n\t\t{\n\t\t\tMENUITEM \"新しいプロファイルを作る\", 8001\n\t\t\tMENUITEM \"現在のプロファイルを削除する\", 8002\n\t\t\tMENUITEM \"現在のプロファイルを初期値に戻す\", 8000\n\t\t}\n\t}\n\tPOPUP \"表示\"\n\t{\n\t\tPOPUP \"拡大表示\"\n\t\t{\n\t\t\tMENUITEM \"25%\", 9200\n\t\t\tMENUITEM \"50%\", 9201\n\t\t\tMENUITEM \"100%\", 9202\n\t\t\tMENUITEM \"200%\", 9203\n\t\t\tMENUITEM \"300%\", 9204\n\t\t\tMENUITEM \"400%\", 9205\n\t\t\tMENUITEM \"WindowSize\", 9206\n\t\t\tMENUITEM SEPARATOR\n\t\t\tMENUITEM \"ズームイン\", 9107\n\t\t\tMENUITEM \"ズームアウト\", 9108\n\t\t\tMENUITEM SEPARATOR\n\t\t\tMENUITEM \"ウィンドウサイズを自動変更\", 9116\n\t\t}\n\t\tMENUITEM \"オーディオ波形の表示\", 9104\n\t\tMENUITEM \"時間の表示\", 9114\n\t\tMENUITEM \"セーブ中もプレビュー表示\", 9105\n\t\tMENUITEM \"セーブ中にデータレートを表示\", 9115\n\t\tMENUITEM \"間引き予定フレームの表示\", 9106\n\t\tMENUITEM \"再圧縮が必要なフレームの表示\", 9110\n\t\tMENUITEM \"ソースファイルのキーフレーム表示\", 9109\n\t\tMENUITEM SEPARATOR\n\t\tMENUITEM \"\", 10998\n\t\tMENUITEM SEPARATOR\n#ifdef PATCH_SWITCH_CONSOLE\n\t\tMENUITEM \"コンソールの表示\", PATCH_MENU_CONSOLE\n\t\tMENUITEM SEPARATOR\n#endif\n\t\tMENUITEM \"常に手前に表示\", 9113\n\t\tMENUITEM \"オーバーレイ表示\", 9111\n\t\tMENUITEM \"セーブ中のみフィルタリングして表示\", 5144\n\t}\n\tPOPUP \"その他\"\n\t{\n\t\tMENUITEM \"ファイルの情報\", 1006\n\t\tMENUITEM \"オーバーレイ情報\", 104\n\t\tMENUITEM \"プラグインフィルタ情報\", 101\n\t\tMENUITEM \"入力プラグイン情報\", 103\n\t\tMENUITEM \"出力プラグイン情報\", 105\n\t\tMENUITEM \"色変換プラグイン情報\", 110\n\t\tMENUITEM \"言語拡張リソース情報\", 107\n\t\tMENUITEM SEPARATOR\n\t\tMENUITEM \"バージョン情報\", 100\n\t\tMENUITEM \"patch.aul\", PATCH_MENU_INFO\n\t}\n}\n\nPATCH_DIALOG_EXCEPTION DIALOGEX 0, 0, 286, 166\nSTYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_NOFAILCREATE\nCAPTION \"AviUtl : Application Exception\"\nFONT 8, \"MS Shell Dlg\", 400, 0, 0x1\n{\n    DEFPUSHBUTTON   \"OK\", PATCH_ID_EXCEPTION_OK, 18, 108, 120, 14\n    PUSHBUTTON      \"詳細\",PATCH_ID_EXCEPTION_DETAIL_BUTTON, 150, 108, 120, 14\n\tPUSHBUTTON      \"編集プロジェクトの保存\",PATCH_ID_EXCEPTION_SAVE_PROJECT, 18, 148, 252, 14\n    LTEXT           \"例外が発生しました。\\n詳細情報は以下のファイルに出力されました。\", PATCH_ID_EXCEPTION_LABEL1, 10, 6, 264, 18\n\tLTEXT           \"この画面から、現在の編集プロジェクトの保存が出来ます\\n(元のファイルと同じ名前は使用しないでください)。\", PATCH_ID_EXCEPTION_LABEL2, 10, 128, 264, 18\n    CONTROL         \"dummy syslink\", PATCH_ID_EXCEPTION_LINK, \"SysLink\", WS_GROUP | WS_TABSTOP, 10, 25, 264, 12\n    EDITTEXT        PATCH_ID_EXCEPTION_DETAIL_TEXT, 10, 38, 266, 54, ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_READONLY | ES_MULTILINE\n\tCONTROL         \"しばらく同種のメッセージの表示を停止する\", PATCH_ID_EXCEPTION_STOPMES, \"Button\", BS_AUTOCHECKBOX | WS_TABSTOP, 11, 94, 258, 12\n/*\n\tCOMBOBOX\t\tPATCH_ID_EXCEPTION_THREADID_COMBO, 227, 7, 51, 12,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP\n\tLTEXT\t\t\t\"thread id\", PATCH_ID_EXCEPTION_LABEL3, 184, 9, 42, 8\n*/\n}\n\n#ifdef PATCH_SWITCH_SPLASH\n\nSPLASH RCDATA \"splash.png\"\n\n#endif\n"
  },
  {
    "path": "patch/patch.vcxproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|Win32\">\n      <Configuration>Debug</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release_PDB|Win32\">\n      <Configuration>Release_PDB</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|Win32\">\n      <Configuration>Release</Configuration>\n      <Platform>Win32</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"add_dll_ref.hpp\" />\n    <ClInclude Include=\"config.hpp\" />\n    <ClInclude Include=\"config_rw.hpp\" />\n    <ClInclude Include=\"cryptostring.hpp\" />\n    <ClInclude Include=\"debug_log.hpp\" />\n    <ClInclude Include=\"gate.hpp\" />\n    <ClInclude Include=\"global.hpp\" />\n    <ClInclude Include=\"global_minimum.hpp\" />\n    <ClInclude Include=\"hash.hpp\" />\n    <ClInclude Include=\"init.hpp\" />\n    <ClInclude Include=\"json.h\" />\n    <ClInclude Include=\"macro.h\" />\n    <ClInclude Include=\"moduledata.hpp\" />\n    <ClInclude Include=\"multi_threading.hpp\" />\n    <ClInclude Include=\"mylua.hpp\" />\n    <ClInclude Include=\"mywindow.hpp\" />\n    <ClInclude Include=\"offset_address.hpp\" />\n    <ClInclude Include=\"overwrite_resource.hpp\" />\n    <ClInclude Include=\"patch.hpp\" />\n    <ClInclude Include=\"patch_access_key.hpp\" />\n    <ClInclude Include=\"patch_add_extension.hpp\" />\n    <ClInclude Include=\"patch_alpha_bg.hpp\" />\n    <ClInclude Include=\"patch_aup_layer_setting.hpp\" />\n    <ClInclude Include=\"patch_aup_scene_setting.hpp\" />\n    <ClInclude Include=\"patch_aviutl_wndproc_override.hpp\" />\n    <ClInclude Include=\"patch_base.hpp\" />\n    <ClInclude Include=\"patch_blend.hpp\" />\n    <ClInclude Include=\"patch_colorpalette_cache.hpp\" />\n    <ClInclude Include=\"patch_console.hpp\" />\n    <ClInclude Include=\"patch_copybuffer_smem.hpp\" />\n    <ClInclude Include=\"patch_dialog_new_file.hpp\" />\n    <ClInclude Include=\"patch_exception_history.hpp\" />\n    <ClInclude Include=\"patch_exception_log.hpp\" />\n    <ClInclude Include=\"patch_exception_log_dialog.hpp\" />\n    <ClInclude Include=\"patch_exeditwindow_sizing.hpp\" />\n    <ClInclude Include=\"patch_exo_aviutlfilter.hpp\" />\n    <ClInclude Include=\"patch_exo_fold_gui.hpp\" />\n    <ClInclude Include=\"patch_exo_midpt_and_tra.hpp\" />\n    <ClInclude Include=\"patch_exo_sceneidx.hpp\" />\n    <ClInclude Include=\"patch_exo_specialcolorconv.hpp\" />\n    <ClInclude Include=\"patch_exo_trackminusval.hpp\" />\n    <ClInclude Include=\"patch_exo_trackparam.hpp\" />\n    <ClInclude Include=\"patch_failed_file_drop.hpp\" />\n    <ClInclude Include=\"patch_failed_longer_path.hpp\" />\n    <ClInclude Include=\"patch_failed_sjis_msgbox.hpp\" />\n    <ClInclude Include=\"patch_fast.hpp\" />\n    <ClInclude Include=\"patch_fast_border.hpp\" />\n    <ClInclude Include=\"patch_fast_cl.hpp\" />\n    <ClInclude Include=\"patch_fast_create_figure.hpp\" />\n    <ClInclude Include=\"patch_fast_directionalblur.hpp\" />\n    <ClInclude Include=\"patch_fast_displacementmap.hpp\" />\n    <ClInclude Include=\"patch_fast_exeditwindow.hpp\" />\n    <ClInclude Include=\"patch_fast_flash.hpp\" />\n    <ClInclude Include=\"patch_fast_getputpixeldata.hpp\" />\n    <ClInclude Include=\"patch_fast_glow.hpp\" />\n    <ClInclude Include=\"patch_fast_lensblur.hpp\" />\n    <ClInclude Include=\"patch_fast_polortransform.hpp\" />\n    <ClInclude Include=\"patch_fast_radiationalblur.hpp\" />\n    <ClInclude Include=\"patch_fast_setting_dialog.hpp\" />\n    <ClInclude Include=\"patch_fast_text.hpp\" />\n    <ClInclude Include=\"patch_fileinfo.hpp\" />\n    <ClInclude Include=\"patch_font_dialog.hpp\" />\n    <ClInclude Include=\"patch_helpful_msgbox.hpp\" />\n    <ClInclude Include=\"patch_ignore_media_param_reset.hpp\" />\n    <ClInclude Include=\"patch_lua.hpp\" />\n    <ClInclude Include=\"patch_lua_getvalueex.hpp\" />\n    <ClInclude Include=\"patch_lua_rand.hpp\" />\n    <ClInclude Include=\"patch_lua_randex.hpp\" />\n    <ClInclude Include=\"patch_obj_colorcorrection.hpp\" />\n    <ClInclude Include=\"patch_obj_glow.hpp\" />\n    <ClInclude Include=\"patch_obj_lensblur.hpp\" />\n    <ClInclude Include=\"patch_obj_noise.hpp\" />\n    <ClInclude Include=\"patch_obj_specialcolorconv.hpp\" />\n    <ClInclude Include=\"patch_playback_speed.hpp\" />\n    <ClInclude Include=\"patch_rclickmenu_delete.hpp\" />\n    <ClInclude Include=\"patch_rclickmenu_split.hpp\" />\n    <ClInclude Include=\"patch_redo.hpp\" />\n    <ClInclude Include=\"patch_scroll_objdlg.hpp\" />\n    <ClInclude Include=\"patch_setting_dialog_excolorconfig.hpp\" />\n    <ClInclude Include=\"patch_setting_dialog_wndproc_override.hpp\" />\n    <ClInclude Include=\"patch_setting_gui.hpp\" />\n    <ClInclude Include=\"patch_setting_new_project.hpp\" />\n    <ClInclude Include=\"patch_splash.hpp\" />\n    <ClInclude Include=\"patch_susie_load.hpp\" />\n    <ClInclude Include=\"patch_sysinfo_write.hpp\" />\n    <ClInclude Include=\"patch_text_op_size.hpp\" />\n    <ClInclude Include=\"patch_theme_cc.hpp\" />\n    <ClInclude Include=\"patch_tra_aviutlfilter.hpp\" />\n    <ClInclude Include=\"patch_tra_change_drawfilter.hpp\" />\n    <ClInclude Include=\"patch_tra_specified_speed.hpp\" />\n    <ClInclude Include=\"patch_undo.hpp\" />\n    <ClInclude Include=\"restorable_patch.hpp\" />\n    <ClInclude Include=\"resource.h\" />\n    <ClInclude Include=\"stopwatch.hpp\" />\n    <ClInclude Include=\"timer.hpp\" />\n    <ClInclude Include=\"util.hpp\" />\n    <ClInclude Include=\"util_int.hpp\" />\n    <ClInclude Include=\"util_magic.hpp\" />\n    <ClInclude Include=\"util_others.hpp\" />\n    <ClInclude Include=\"util_pe.hpp\" />\n    <ClInclude Include=\"util_resource.hpp\" />\n    <ClInclude Include=\"version.hpp\" />\n    <ClInclude Include=\"patch_setting_dialog_move.hpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"init.cpp\" />\n    <ClCompile Include=\"overwrite_resource.cpp\" />\n    <ClCompile Include=\"patch.cpp\" />\n    <ClCompile Include=\"patch_add_extension.cpp\" />\n    <ClCompile Include=\"patch_aviutl_wndproc_override.cpp\" />\n    <ClCompile Include=\"patch_blend.cpp\" />\n    <ClCompile Include=\"patch_exception_log.cpp\" />\n    <ClCompile Include=\"patch_exception_log_dialog.cpp\" />\n    <ClCompile Include=\"patch_exo_trackminusval.cpp\" />\n    <ClCompile Include=\"patch_failed_longer_path.cpp\" />\n    <ClCompile Include=\"patch_failed_sjis_msgbox.cpp\" />\n    <ClCompile Include=\"patch_fast_border.cpp\" />\n    <ClCompile Include=\"patch_fast_create_figure.cpp\" />\n    <ClCompile Include=\"patch_fast_directionalblur.cpp\" />\n    <ClCompile Include=\"patch_fast_displacementmap.cpp\" />\n    <ClCompile Include=\"patch_fast_exeditwindow.cpp\" />\n    <ClCompile Include=\"patch_fast_flash.cpp\" />\n    <ClCompile Include=\"patch_fast_getputpixeldata.cpp\" />\n    <ClCompile Include=\"patch_fast_glow.cpp\" />\n    <ClCompile Include=\"patch_fast_lensblur.cpp\" />\n    <ClCompile Include=\"patch_fast_polortransform.cpp\" />\n    <ClCompile Include=\"patch_fast_radiationalblur.cpp\" />\n    <ClCompile Include=\"patch_fast_setting_dialog.cpp\" />\n    <ClCompile Include=\"patch_fast_text.cpp\" />\n    <ClCompile Include=\"patch_helpful_msgbox.cpp\" />\n    <ClCompile Include=\"patch_lua.cpp\" />\n    <ClCompile Include=\"patch_lua_getvalueex.cpp\" />\n    <ClCompile Include=\"patch_lua_rand.cpp\" />\n    <ClCompile Include=\"patch_lua_randex.cpp\" />\n    <ClCompile Include=\"patch_console.cpp\" />\n    <ClCompile Include=\"patch_obj_colorcorrection.cpp\" />\n    <ClCompile Include=\"patch_obj_lensblur.cpp\" />\n    <ClCompile Include=\"patch_rclickmenu_delete.cpp\" />\n    <ClCompile Include=\"patch_rclickmenu_split.cpp\" />\n    <ClCompile Include=\"patch_redo.cpp\" />\n    <ClCompile Include=\"patch_setting_dialog_excolorconfig.cpp\" />\n    <ClCompile Include=\"patch_setting_dialog_wndproc_override.cpp\" />\n    <ClCompile Include=\"patch_setting_new_project.cpp\" />\n    <ClCompile Include=\"patch_splash.cpp\" />\n    <ClCompile Include=\"patch_susie_load.cpp\" />\n    <ClCompile Include=\"patch_tra_change_drawfilter.cpp\" />\n    <ClCompile Include=\"patch_undo.cpp\" />\n    <ClCompile Include=\"util_others.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"patch.rc\" />\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\".editorconfig\" />\n    <None Include=\"clprogram.cl\" />\n    <None Include=\"packages.config\" />\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <VCProjectVersion>16.0</VCProjectVersion>\n    <Keyword>Win32Proj</Keyword>\n    <ProjectGuid>{20c4ed31-b17f-445a-90fe-77f8119f831b}</ProjectGuid>\n    <RootNamespace>patch</RootNamespace>\n    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>true</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release_PDB|Win32'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n    <UseDebugLibraries>false</UseDebugLibraries>\n    <PlatformToolset>v143</PlatformToolset>\n    <WholeProgramOptimization>true</WholeProgramOptimization>\n    <CharacterSet>MultiByte</CharacterSet>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"Shared\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Condition=\"'$(Configuration)|$(Platform)'=='Release_PDB|Win32'\" Label=\"PropertySheets\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <LinkIncremental>true</LinkIncremental>\n    <TargetExt>.aul</TargetExt>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n    <TargetExt>.aul</TargetExt>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release_PDB|Win32'\">\n    <LinkIncremental>false</LinkIncremental>\n    <TargetExt>.aul</TargetExt>\n  </PropertyGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <LanguageStandard>stdcpplatest</LanguageStandard>\n      <AdditionalIncludeDirectories>aviutl_exedit_sdk;winwrap;%CUDA_PATH%\\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <AdditionalOptions>/source-charset:utf-8 /execution-charset:shift_jis %(AdditionalOptions)</AdditionalOptions>\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <DelayLoadDLLs>OpenCL.DLL</DelayLoadDLLs>\n      <AdditionalLibraryDirectories>%CUDA_PATH%\\lib\\Win32</AdditionalLibraryDirectories>\n    </Link>\n    <PostBuildEvent>\n      <Command>xcopy /Y \"$(TargetPath)\" \"$(SolutionDir)test\\\"\nxcopy /Y \"$(TargetPath)\" \"$(SolutionDir)pack\\\"\nxcopy /Y \"$(SolutionDir)patch.aul.txt\" \"$(SolutionDir)pack\\\"\nxcopy /Y \"$(SolutionDir)credits.md\" \"$(SolutionDir)pack\\\"\nxcopy /Y \"$(SolutionDir)LICENSE\" \"$(SolutionDir)pack\\\"\nxcopy /Y \"$(SolutionDir)COPYING\" \"$(SolutionDir)pack\\\"\nxcopy /Y \"$(SolutionDir)COPYING.LESSER\" \"$(SolutionDir)pack\\\"</Command>\n    </PostBuildEvent>\n    <ResourceCompile>\n      <AdditionalOptions>/c 65001 %(AdditionalOptions)</AdditionalOptions>\n    </ResourceCompile>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <LanguageStandard>stdcpplatest</LanguageStandard>\n      <AdditionalIncludeDirectories>aviutl_exedit_sdk;winwrap;%CUDA_PATH%\\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <AdditionalOptions>/source-charset:utf-8 /execution-charset:shift_jis %(AdditionalOptions)</AdditionalOptions>\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>false</GenerateDebugInformation>\n      <DelayLoadDLLs>OpenCL.DLL</DelayLoadDLLs>\n      <AdditionalLibraryDirectories>%CUDA_PATH%\\lib\\Win32</AdditionalLibraryDirectories>\n    </Link>\n    <PostBuildEvent>\n      <Command>copy /Y \"$(TargetPath)\" \"$(SolutionDir)test\\$(TargetFileName)\"\ncopy /Y \"$(TargetPath)\" \"$(SolutionDir)pack\\$(TargetFileName)\"\ncopy /Y \"$(SolutionDir)patch.aul.txt\" \"$(SolutionDir)pack\\patch.aul.txt\"\ncopy /Y \"$(SolutionDir)credits.md\" \"$(SolutionDir)pack\\credits.md\"\ncopy /Y \"$(SolutionDir)LICENSE\" \"$(SolutionDir)pack\\LICENSE\"\ncopy /Y \"$(SolutionDir)COPYING\" \"$(SolutionDir)pack\\COPYING\"\ncopy /Y \"$(SolutionDir)COPYING.LESSER\" \"$(SolutionDir)pack\\COPYING.LESSER\"</Command>\n    </PostBuildEvent>\n    <ResourceCompile>\n      <AdditionalOptions>/c 65001 %(AdditionalOptions)</AdditionalOptions>\n    </ResourceCompile>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release_PDB|Win32'\">\n    <ClCompile>\n      <WarningLevel>Level3</WarningLevel>\n      <FunctionLevelLinking>true</FunctionLevelLinking>\n      <IntrinsicFunctions>true</IntrinsicFunctions>\n      <SDLCheck>true</SDLCheck>\n      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <ConformanceMode>true</ConformanceMode>\n      <LanguageStandard>stdcpplatest</LanguageStandard>\n      <AdditionalIncludeDirectories>aviutl_exedit_sdk;winwrap;%CUDA_PATH%\\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <AdditionalOptions>/source-charset:utf-8 %(AdditionalOptions)</AdditionalOptions>\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\n    </ClCompile>\n    <Link>\n      <SubSystem>Console</SubSystem>\n      <EnableCOMDATFolding>true</EnableCOMDATFolding>\n      <OptimizeReferences>true</OptimizeReferences>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <DelayLoadDLLs>OpenCL.DLL</DelayLoadDLLs>\n      <AdditionalLibraryDirectories>%CUDA_PATH%\\lib\\Win32</AdditionalLibraryDirectories>\n    </Link>\n    <PostBuildEvent>\n      <Command>copy /Y \"$(TargetPath)\" \"$(SolutionDir)test\\$(TargetFileName)\"\ncopy /Y \"$(TargetPath)\" \"$(SolutionDir)pack\\$(TargetFileName)\"\ncopy /Y \"$(SolutionDir)patch.aul.txt\" \"$(SolutionDir)pack\\patch.aul.txt\"\ncopy /Y \"$(SolutionDir)credits.md\" \"$(SolutionDir)pack\\credits.md\"\ncopy /Y \"$(SolutionDir)LICENSE\" \"$(SolutionDir)pack\\LICENSE\"\ncopy /Y \"$(SolutionDir)COPYING\" \"$(SolutionDir)pack\\COPYING\"\ncopy /Y \"$(SolutionDir)COPYING.LESSER\" \"$(SolutionDir)pack\\COPYING.LESSER\"</Command>\n    </PostBuildEvent>\n    <ResourceCompile>\n      <AdditionalOptions>/c 65001 %(AdditionalOptions)</AdditionalOptions>\n    </ResourceCompile>\n  </ItemDefinitionGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n    <Import Project=\"..\\packages\\boost.1.79.0\\build\\boost.targets\" Condition=\"Exists('..\\packages\\boost.1.79.0\\build\\boost.targets')\" />\n    <Import Project=\"..\\packages\\boost_system-vc143.1.79.0\\build\\boost_system-vc143.targets\" Condition=\"Exists('..\\packages\\boost_system-vc143.1.79.0\\build\\boost_system-vc143.targets')\" />\n  </ImportGroup>\n  <Target Name=\"EnsureNuGetPackageBuildImports\" BeforeTargets=\"PrepareForBuild\">\n    <PropertyGroup>\n      <ErrorText>このプロジェクトは、このコンピューター上にない NuGet パッケージを参照しています。それらのパッケージをダウンロードするには、[NuGet パッケージの復元] を使用します。詳細については、http://go.microsoft.com/fwlink/?LinkID=322105 を参照してください。見つからないファイルは {0} です。</ErrorText>\n    </PropertyGroup>\n    <Error Condition=\"!Exists('..\\packages\\boost.1.79.0\\build\\boost.targets')\" Text=\"$([System.String]::Format('$(ErrorText)', '..\\packages\\boost.1.79.0\\build\\boost.targets'))\" />\n    <Error Condition=\"!Exists('..\\packages\\boost_system-vc143.1.79.0\\build\\boost_system-vc143.targets')\" Text=\"$([System.String]::Format('$(ErrorText)', '..\\packages\\boost_system-vc143.1.79.0\\build\\boost_system-vc143.targets'))\" />\n  </Target>\n</Project>"
  },
  {
    "path": "patch/patch.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"feature\">\n      <UniqueIdentifier>{f2c356a4-9aa7-4917-b27b-4b37a59cc03e}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"feature\\fast\">\n      <UniqueIdentifier>{0921e89c-9ee4-4242-9edf-9f1278a8fd04}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"util\">\n      <UniqueIdentifier>{42fd95df-c430-425e-839f-50891f36ebff}</UniqueIdentifier>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"cryptostring.hpp\" />\n    <ClInclude Include=\"debug_log.hpp\" />\n    <ClInclude Include=\"gate.hpp\" />\n    <ClInclude Include=\"global.hpp\" />\n    <ClInclude Include=\"global_minimum.hpp\" />\n    <ClInclude Include=\"hash.hpp\" />\n    <ClInclude Include=\"init.hpp\" />\n    <ClInclude Include=\"json.h\" />\n    <ClInclude Include=\"macro.h\" />\n    <ClInclude Include=\"moduledata.hpp\" />\n    <ClInclude Include=\"multi_threading.hpp\" />\n    <ClInclude Include=\"mylua.hpp\" />\n    <ClInclude Include=\"mywindow.hpp\" />\n    <ClInclude Include=\"offset_address.hpp\" />\n    <ClInclude Include=\"overwrite_resource.hpp\" />\n    <ClInclude Include=\"patch.hpp\" />\n    <ClInclude Include=\"resource.h\" />\n    <ClInclude Include=\"stopwatch.hpp\" />\n    <ClInclude Include=\"version.hpp\" />\n    <ClInclude Include=\"add_dll_ref.hpp\" />\n    <ClInclude Include=\"patch_access_key.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_alpha_bg.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_aviutl_wndproc_override.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_console.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_copybuffer_smem.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_exception_history.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_exception_log.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_exception_log_dialog.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_exeditwindow_sizing.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_exo_aviutlfilter.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_exo_sceneidx.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_exo_specialcolorconv.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_exo_trackminusval.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_exo_trackparam.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_font_dialog.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_helpful_msgbox.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_ignore_media_param_reset.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_lua.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_lua_getvalueex.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_lua_rand.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_lua_randex.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_scroll_objdlg.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_setting_gui.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_splash.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_susie_load.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_sysinfo_write.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_text_op_size.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_theme_cc.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_fast_setting_dialog.hpp\">\n      <Filter>feature\\fast</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_fast_exeditwindow.hpp\">\n      <Filter>feature\\fast</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_fast_getputpixeldata.hpp\">\n      <Filter>feature\\fast</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_fast_polortransform.hpp\">\n      <Filter>feature\\fast</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_fast_radiationalblur.hpp\">\n      <Filter>feature\\fast</Filter>\n    </ClInclude>\n    <ClInclude Include=\"util_resource.hpp\">\n      <Filter>util</Filter>\n    </ClInclude>\n    <ClInclude Include=\"util.hpp\">\n      <Filter>util</Filter>\n    </ClInclude>\n    <ClInclude Include=\"util_int.hpp\">\n      <Filter>util</Filter>\n    </ClInclude>\n    <ClInclude Include=\"util_magic.hpp\">\n      <Filter>util</Filter>\n    </ClInclude>\n    <ClInclude Include=\"util_others.hpp\">\n      <Filter>util</Filter>\n    </ClInclude>\n    <ClInclude Include=\"util_pe.hpp\">\n      <Filter>util</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_setting_dialog_wndproc_override.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_setting_dialog_move.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_undo.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"config.hpp\" />\n    <ClInclude Include=\"patch_base.hpp\" />\n    <ClInclude Include=\"restorable_patch.hpp\" />\n    <ClInclude Include=\"config_rw.hpp\" />\n    <ClInclude Include=\"patch_redo.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_fast.hpp\">\n      <Filter>feature\\fast</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_fast_cl.hpp\">\n      <Filter>feature\\fast</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_fast_flash.hpp\">\n      <Filter>feature\\fast</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_tra_aviutlfilter.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_fast_text.hpp\">\n      <Filter>feature\\fast</Filter>\n    </ClInclude>\n    <ClInclude Include=\"timer.hpp\" />\n    <ClInclude Include=\"patch_setting_dialog_excolorconfig.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_fast_border.hpp\">\n      <Filter>feature\\fast</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_fast_directionalblur.hpp\">\n      <Filter>feature\\fast</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_fast_lensblur.hpp\">\n      <Filter>feature\\fast</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_obj_lensblur.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_obj_noise.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_blend.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_rclickmenu_delete.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_rclickmenu_split.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_tra_change_drawfilter.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_tra_specified_speed.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_failed_sjis_msgbox.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_fast_displacementmap.hpp\">\n      <Filter>feature\\fast</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_fast_create_figure.hpp\">\n      <Filter>feature\\fast</Filter>\n    </ClInclude>\n    <ClInclude Include=\"patch_obj_colorcorrection.hpp\">\n      <Filter>feature</Filter>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"init.cpp\" />\n    <ClCompile Include=\"overwrite_resource.cpp\" />\n    <ClCompile Include=\"patch.cpp\" />\n    <ClCompile Include=\"patch_aviutl_wndproc_override.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_exception_log.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_exception_log_dialog.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_exo_trackminusval.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_helpful_msgbox.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_lua.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_lua_getvalueex.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_lua_rand.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_lua_randex.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_console.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_splash.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_susie_load.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_fast_getputpixeldata.cpp\">\n      <Filter>feature\\fast</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_fast_polortransform.cpp\">\n      <Filter>feature\\fast</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_fast_radiationalblur.cpp\">\n      <Filter>feature\\fast</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_fast_setting_dialog.cpp\">\n      <Filter>feature\\fast</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_fast_exeditwindow.cpp\">\n      <Filter>feature\\fast</Filter>\n    </ClCompile>\n    <ClCompile Include=\"util_others.cpp\">\n      <Filter>util</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_undo.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_setting_dialog_wndproc_override.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_redo.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_fast_flash.cpp\">\n      <Filter>feature\\fast</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_fast_text.cpp\">\n      <Filter>feature\\fast</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_setting_dialog_excolorconfig.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_fast_border.cpp\">\n      <Filter>feature\\fast</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_fast_directionalblur.cpp\">\n      <Filter>feature\\fast</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_fast_lensblur.cpp\">\n      <Filter>feature\\fast</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_obj_lensblur.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_blend.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_rclickmenu_delete.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_rclickmenu_split.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_tra_change_drawfilter.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_failed_sjis_msgbox.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_fast_displacementmap.cpp\">\n      <Filter>feature\\fast</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_fast_create_figure.cpp\">\n      <Filter>feature\\fast</Filter>\n    </ClCompile>\n    <ClCompile Include=\"patch_obj_colorcorrection.cpp\">\n      <Filter>feature</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <ResourceCompile Include=\"patch.rc\" />\n  </ItemGroup>\n  <ItemGroup>\n    <None Include=\".editorconfig\" />\n    <None Include=\"clprogram.cl\" />\n    <None Include=\"packages.config\" />\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "patch/patch_access_key.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_ACCESS_KEY\n\n#include \"global.hpp\"\n#include \"config_rw.hpp\"\n\nnamespace patch {\n\n\t// LoadMenuA 時にmodifyを噛ませる\n\t// メニューにアクセスキーの追加をする\n\tinline class access_key_t {\n\n\t\tstruct Menu {\n\t\t\tenum {\n\t\t\t\tFile,\n\t\t\t\tFilter,\n\t\t\t\tSetting,\n\t\t\t\tEdit,\n\t\t\t\tProfile,\n\t\t\t\tView,\n\t\t\t\tOther,\n\t\t\t\tCount\n\t\t\t};\n\t\t};\n\n\t\tchar map_key[Menu::Count] = {\n\t\t\t'F',\n\t\t\t'L',\n\t\t\t'S',\n\t\t\t'E',\n\t\t\t'P',\n\t\t\t'V',\n\t\t\t'O',\n\t\t};\n\n\t\t// どのメニューがあるかでどのフォルダかを調べる\n\t\tUINT mark_map[Menu::Count] = {\n\t\t\t5097,\n\t\t\t5183,\n\t\t\t5127,\n\t\t\t1020,\n\t\t\t8001,\n\t\t\t9200,\n\t\t\t1006\n\t\t};\n\n\t\tinline static bool find_menu(HMENU hMenu, UINT id) {\n\t\t\tauto menu_n = GetMenuItemCount(hMenu);\n\t\t\tfor (int i = 0; i < menu_n; i++) {\n\t\t\t\tMENUITEMINFOW mii{\n\t\t\t\t\t.cbSize = sizeof(mii),\n\t\t\t\t\t.fMask = MIIM_ID | MIIM_SUBMENU,\n\t\t\t\t};\n\t\t\t\tGetMenuItemInfoW(hMenu, i, TRUE, &mii);\n\t\t\t\tif (mii.hSubMenu != NULL) {\n\t\t\t\t\tauto ret = find_menu(mii.hSubMenu, id);\n\t\t\t\t\tif (ret)return true;\n\t\t\t\t}\n\t\t\t\tif (mii.wID == id) return true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t}\n\n\t\tbool enabled = false;\n\t\tbool enabled_i;\n\n\t\tinline static const char key[] = \"access_key\";\n\n\tpublic:\n\t\tvoid switching(bool flag) {\n\t\t\tenabled = flag;\n\t\t}\n\n\t\tbool is_enabled() { return enabled; }\n\t\tbool is_enabled_i() { return enabled_i; }\n\t\t\n\t\tvoid init() {\n\t\t\tenabled_i = enabled;\n\t\t}\n\n\t\tvoid switch_load(ConfigReader& cr) {\n\t\t\tcr.regist(key, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, enabled);\n\t\t\t});\n\t\t}\n\n\t\tvoid switch_store(ConfigWriter& cw) {\n\t\t\tcw.append(key, enabled);\n\t\t}\n\n\n\t\tHMENU modify(LPCSTR key, HMENU hMenu) {\n\t\t\tif (!enabled_i) return hMenu;\n\n\t\t\tif (lstrcmpiA(key, \"AVIUTL\") != 0)return hMenu;\n\n\t\t\tauto find_submenu = [](HMENU hMenu, int idx, UINT id) {\n\t\t\t\tauto sub = GetSubMenu(hMenu, idx);\n\n\t\t\t\tauto menu_n = GetMenuItemCount(sub);\n\t\t\t\tfor (int i = 0; i < menu_n; i++) {\n\t\t\t\t\tMENUITEMINFOW mii{\n\t\t\t\t\t\t.cbSize = sizeof(mii),\n\t\t\t\t\t\t.fMask = MIIM_ID,\n\t\t\t\t\t};\n\t\t\t\t\tGetMenuItemInfoW(sub, i, TRUE, &mii);\n\t\t\t\t\tif (mii.wID == id) return true;\n\t\t\t\t}\n\n\t\t\t\treturn false;\n\t\t\t};\n\n\t\t\tfor (int i = 0; i < Menu::Count; i++) {\n\t\t\t\tauto menu_n = GetMenuItemCount(hMenu);\n\t\t\t\tfor (int j = 0; j < menu_n; j++) {\n\t\t\t\t\tMENUITEMINFOW mii{\n\t\t\t\t\t\t.cbSize = sizeof(mii),\n\t\t\t\t\t\t.fMask = MIIM_STRING | MIIM_ID,\n\t\t\t\t\t\t.dwTypeData = NULL\n\t\t\t\t\t};\n\t\t\t\t\tGetMenuItemInfoW(hMenu, j, TRUE, &mii);\n\n\t\t\t\t\tif (find_menu(GetSubMenu(hMenu, j), mark_map[i])) {\n\t\t\t\t\t\tstd::wstring buf;\n\t\t\t\t\t\tbuf.resize(mii.cch);\n\t\t\t\t\t\tmii.fMask = MIIM_STRING;\n\t\t\t\t\t\tmii.dwTypeData = buf.data();\n\t\t\t\t\t\tmii.cch = buf.size() + 1;\n\t\t\t\t\t\tGetMenuItemInfoW(hMenu, j, TRUE, &mii);\n\t\t\t\t\t\n\t\t\t\t\t\tbuf.append(L\"(&\");\n\t\t\t\t\t\tbuf.push_back(map_key[i]);\n\t\t\t\t\t\tbuf.push_back(L')');\n\t\t\t\t\t\t\n\t\t\t\t\t\tmii.fMask = MIIM_STRING;\n\t\t\t\t\t\tmii.dwTypeData = buf.data();\n\t\t\t\t\t\tmii.cch = buf.size() + 1;\n\t\t\t\t\t\tSetMenuItemInfoW(hMenu, j, TRUE, &mii);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn hMenu;\n\t\t}\n\n\n\t} access_key;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_ACCESS_KEY\n"
  },
  {
    "path": "patch/patch_add_extension.cpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"patch_add_extension.hpp\"\r\n\r\n#ifdef PATCH_SWITCH_ADD_EXTENSION\r\nnamespace patch {\r\n\r\n\tint __cdecl add_extension_t::wsprintfA_wrap2701a(void* ebp, LPSTR dst, LPCSTR src) {\r\n\r\n\t\tint* flag = (int*)((int)ebp - 1308); // 1:VideoFile 2:AudioFile\r\n\t\tint* new_ext_num = (int*)((int)ebp - 1288); // new_ext_bufに追加された拡張子の数（最初の時点では0）\r\n\t\tchar* new_ext_buf = (char*)((int)ebp - 1284); // \".mp4\\0.acb\\0.xyz\\0\"のように'\\0'区切りで書いていく .aviのみ別枠として確定で追加されるのでここには追加しないこと\r\n\r\n\t\t*new_ext_num = 0;\r\n\r\n\t\tchar* str_movie_audio_file;\r\n\t\tif (*flag == 1) {\r\n\t\t\tstr_movie_audio_file = (char*)(GLOBAL::exedit_base + OFS::ExEdit::str_DOUGAFILE); // \"動画ファイル\"\r\n\t\t} else { // *flag == 2\r\n\t\t\tstr_movie_audio_file = (char*)(GLOBAL::exedit_base + OFS::ExEdit::str_ONSEIFILE); // \"音声ファイル\"\r\n\t\t}\r\n\t\tchar* ptr = (char*)(GLOBAL::exedit_base + OFS::ExEdit::ini_extension_buf);\r\n\t\tunsigned int endptr = (unsigned int)ptr + 2047; // 読み込み時に字数カウントしていればその条件にする\r\n\t\twhile ((unsigned int)ptr < endptr) {\r\n\t\t\tif (*ptr == '.') {\r\n\t\t\t\tint cnt = 1;\r\n\t\t\t\twhile (ptr[cnt] != '\\0') { // 次の区切り文字までの字数カウントついでに拡張子の大文字は小文字にしてしまう\r\n\t\t\t\t\tif ((unsigned int)ptr + cnt >= endptr) {\r\n\t\t\t\t\t\treturn wsprintfA(dst, src);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif ('A' <= ptr[cnt] && ptr[cnt] <= 'Z') {\r\n\t\t\t\t\t\tptr[cnt] += 'a' - 'A';\r\n\t\t\t\t\t}\r\n\t\t\t\t\tcnt++;\r\n\t\t\t\t}\r\n\t\t\t\tcnt++;\r\n\r\n\t\t\t\tif (lstrcmpiA(&ptr[cnt], str_movie_audio_file) == 0) {\r\n\t\t\t\t\tif (lstrcmpiA(ptr, (LPCSTR)(GLOBAL::aviutl_base + OFS::AviUtl::str_dot_avi)) != 0) { // \".avi\"\r\n\t\t\t\t\t\tlstrcpyA(new_ext_buf, ptr);\r\n\t\t\t\t\t\tnew_ext_buf += cnt;\r\n\t\t\t\t\t\t(*new_ext_num)++;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tptr += cnt;\r\n\t\t\t}\r\n\t\t\twhile (*ptr != '\\0') {\r\n\t\t\t\tptr++;\r\n\t\t\t}\r\n\t\t\tptr++;\r\n\t\t}\r\n\t\treturn wsprintfA(dst, src);\r\n\t}\r\n\r\n\r\n\r\n} // namespace patch\r\n#endif // ifdef PATCH_ADD_EXTENSION"
  },
  {
    "path": "patch/patch_add_extension.hpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_ADD_EXTENSION\r\n\r\n#include <memory>\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util.hpp\"\r\n#include \"restorable_patch.hpp\"\r\n\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch {\r\n    // init at exedit load\r\n    // 動画、音声ファイル参照の時の拡張子にexedit.iniにあるものを追加する機能\r\n    inline class add_extension_t {\r\n\r\n        static int __cdecl wsprintfA_wrap2701a(void* ebp, LPSTR dst, LPCSTR src);\r\n\r\n        bool enabled = true;\r\n        bool enabled_i;\r\n\r\n        inline static const char key[] = \"add_extension\";\r\n\r\n\r\n    public:\r\n\r\n\r\n        void init() {\r\n            enabled_i = enabled;\r\n\r\n            if (!enabled_i)return;\r\n\r\n            {\r\n                /*\r\n                    0042701a ff1584f34600            call    dword ptr [USER32.wsprintfA]\r\n                    00427020 83c408                  add     esp,+08\r\n\r\n                    ↓\r\n\r\n                    0042701a 55                      push    ebp\r\n                    0042701b e8XxXxXxXx              call    wsprintfA_wrap2701a(void* ebp, LPSTR dst, LPCSTR src)\r\n                    00427020 83c40c                  add     esp,+0c\r\n\r\n\r\n\r\n                    00427034 899df8faffff            mov     dword ptr [ebp+fffffaf8],ebx\r\n                    ↓\r\n                    00427034 eb04                    jmp     skip,+04\r\n\r\n                */\r\n\r\n                OverWriteOnProtectHelper h(GLOBAL::aviutl_base + 0x02701a, 28);\r\n                h.store_i16(0, '\\x55\\xe8');\r\n                h.replaceNearJmp(2, &wsprintfA_wrap2701a);\r\n                h.store_i8(8, '\\x0c');\r\n                h.store_i16(26, '\\xeb\\x04');\r\n\r\n            }\r\n\r\n\r\n        }\r\n        void switching(bool flag) {\r\n            enabled = flag;\r\n        }\r\n\r\n        bool is_enabled() { return enabled; }\r\n        bool is_enabled_i() { return enabled_i; }\r\n\r\n        void switch_load(ConfigReader& cr) {\r\n            cr.regist(key, [this](json_value_s* value) {\r\n                ConfigReader::load_variable(value, enabled);\r\n                });\r\n        }\r\n\r\n        void switch_store(ConfigWriter& cw) {\r\n            cw.append(key, enabled);\r\n        }\r\n\r\n    } add_extension;\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_ADD_EXTENSION\r\n"
  },
  {
    "path": "patch/patch_alpha_bg.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_ALPHA_BG\n\n#include <Windows.h>\n#include <aviutl.hpp>\n\nnamespace patch {\n\n\t// アルファチャンネル部分に背景を表示する\n\t// 凍結: 普段からアルファチャンネル付きでのレンダリングをしなきゃならない 容易に操作できるスイッチを用意しなければならない\n\tinline class alpha_bg_t {\n\n\t\tbool enabled = true;\n\t\tbool enabled_i;\n\t\tinline static const char key[] = \"alpha_bg\";\n\n\tpublic:\n\t\tstatic BOOL func_proc(AviUtl::FilterPlugin* fp, AviUtl::FilterProcInfo* fpip) {\n\t\t\tconst auto rect_size = 16;\n\n\t\t\tconst auto pattern_size = rect_size * 2;\n\t\t\tif (!fp->exfunc->is_saving(fpip->editp)) {\n\t\t\t\tconst auto w = fpip->w;\n\t\t\t\tconst auto h = fpip->h;\n\n\t\t\t\tconst auto ox = pattern_size - (w / 2) % pattern_size;\n\t\t\t\tconst auto oy = pattern_size - (h / 2) % pattern_size;\n\n\t\t\t\tfor (int y = 0; y < h; y++) {\n\t\t\t\t\tfor (int x = 0; x < w; x++) {\n\t\t\t\t\t\tauto& p = *reinterpret_cast<AviUtl::PixelYC*>(reinterpret_cast<uintptr_t>(fpip->ycp_edit) + x * fpip->yc_size + y * fpip->line_size);\n\t\t\t\t\t\tif ((\n\t\t\t\t\t\t\t((x + ox) % pattern_size < rect_size) ^\n\t\t\t\t\t\t\t((y + oy) % pattern_size < rect_size)\n\t\t\t\t\t\t\t) == 1) {\n\t\t\t\t\t\t\tp = { 3584,0,0 };\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tp = { 4096,0,0 };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn TRUE;\n\t\t}\n\n\t\t\n\t\tbool is_enabled() { return enabled; }\n\t\tbool is_enabled_i() { return enabled_i; }\n\t\t\n\t\tbool init() {\n\t\t\tenabled_i = enabled;\n\t\t}\n\n\t\tvoid switch_load(ConfigReader& cr) {\n\t\t\tcr.regist(key, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, enabled);\n\t\t\t});\n\t\t}\n\n\t\tvoid switch_store(ConfigWriter& cw) {\n\t\t\tcw.append(key, enabled);\n\t\t}\n\n\t} alpha_bg;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_ALPHA_BG\n"
  },
  {
    "path": "patch/patch_aup_layer_setting.hpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_AUP_LAYER_SETTING\r\n\r\n#include \"global.hpp\"\r\n#include \"util.hpp\"\r\n#include \"restorable_patch.hpp\"\r\n\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch {\r\n    // init at exedit load\r\n    // プロジェクトの保存時、レイヤー情報を保存する基準を変える\r\n    // 従来：オブジェクトが存在するレイヤーのみ保存する（レイヤー情報が初期値であってもわざわざ保存する）\r\n    // 変更：レイヤー情報が初期値以外のみ保存する\r\n\r\n    // 保存時のみのパッチで互換性あり\r\n    // パッチ有りで保存→パッチなしで読み込み：全てのレイヤー情報が読み込める\r\n\r\n    inline class aup_layer_setting_t {\r\n\r\n        bool enabled = true;\r\n        bool enabled_i;\r\n\r\n        inline static const char key[] = \"aup_layer_setting\";\r\n\r\n    public:\r\n\r\n        void init() {\r\n            enabled_i = enabled;\r\n\r\n            if (!enabled_i)return;\r\n\r\n            /*\r\n                100326b8 3bcb               cmp     ecx,ebx ; ecx=ObjectCount, ebx=i(0～ObjectCount)\r\n                100326ba 895c2410           mov     dword ptr [esp+10],ebx ; 0\r\n                100326be 895c2414           mov     dword ptr [esp+14],ebx ; 0\r\n                100326c2 7e3c               jng     10032700\r\n                100326c4 8b0c85a88f1610     mov     ecx,dword ptr [eax*4+10168fa8] ; ecx=SortedObjectTable[idx]\r\n                100326cb 40                 inc     eax ; idx++\r\n                100326cc 8b91c4050000       mov     edx,dword ptr [ecx+000005c4]\r\n                100326d2 c6041601           mov     byte ptr [esi+edx],01\r\n                100326d6 8b0c85a48f1610     mov     ecx,dword ptr [eax*4+10168fa4]\r\n                100326dd 8b91c4050000       mov     edx,dword ptr [ecx+000005c4]\r\n                100326e3 8b89c0050000       mov     ecx,dword ptr [ecx+000005c0]\r\n                100326e9 8d1492             lea     edx,dword ptr [edx+edx*4]\r\n                100326ec 8d1492             lea     edx,dword ptr [edx+edx*4]\r\n                100326ef 8d1491             lea     edx,dword ptr [ecx+edx*4]\r\n                100326f2 c6042a01           mov     byte ptr [edx+ebp],01\r\n                100326f6 8b0d50621410       mov     ecx,dword ptr [10146250]\r\n                100326fc 3bc1               cmp     eax,ecx\r\n                100326fe 7cc4               jl      100326c4\r\n\r\n                for(int i=0;i<ObjectCount;i++){\r\n                    obj = SortedObjectTable + i;\r\n                    scene_save_flag[obj->scene_set] = 1;\r\n                    layer_save_flag[obj->scene_set * 100 + obj->layer_set] = 1;\r\n                }\r\n\r\n                ↓\r\n\r\n\r\n                100326b8 3bcb               cmp     ecx,ebx\r\n                100326ba 895c2410           mov     dword ptr [esp+10],ebx\r\n                100326be 895c2414           mov     dword ptr [esp+14],ebx\r\n                100326c2 7e1c               jng     100326e0\r\n                100326c4 8b0c85a88f1610     mov     ecx,dword ptr [eax*4+10168fa8]\r\n                100326cb 40                 inc     eax\r\n                100326cc 8b91c4050000       mov     edx,dword ptr [ecx+000005c4]\r\n                100326d2 c6041601           mov     byte ptr [esi+edx],01\r\n\r\n                100326d6 8b0d506214Xx       mov     ecx,dword ptr [10146250]\r\n                100326dc 3bc1               cmp     eax,ecx\r\n                100326de 7ce4               jl      100326c4\r\n\r\n\r\n                100326e0 b810270000         mov     eax,0x2710 ; 10000\r\n                100326e5 48                 dec     eax\r\n                100326e6 8b0c85988418Xx     mov     ecx,dword ptr [eax*4 + exedit+188498] ; scene_setting\r\n                100326ed 85c9               test    ecx,ecx\r\n                100326ef 7409               jz      skip,9 ; 100326fa\r\n\r\n                100326f1 8bd0               mov     edx,eax\r\n                100326f3 c1ea01             shr     edx,1\r\n                100326f6 c6042a01           mov     byte ptr [edx+ebp],01\r\n\r\n                100326fa 85c0               test    eax,eax\r\n                100326fc 75e7               jnz     back,19 ; 100326e5\r\n\r\n                100326fe 90                 nop\r\n                100326ff 90                 nop\r\n\r\n                for(int i=0;i<ObjectCount;i++){\r\n                    obj = SortedObjectTable + i;\r\n                    scene_save_flag[obj->scene_set] = 1;\r\n                }\r\n                for (int i = 0; i < 5000; i++) {\r\n                    if (layersetting[i].flag != 0 || layersetting[i].name != 0) {\r\n                        layer_save_flag[i] = 1;\r\n                    }\r\n                }\r\n            */\r\n\r\n            {\r\n            }\r\n            {\r\n                /*\r\n                    for (int i = 0; i < 5000; i++) {\r\n                        if (layersetting[i].flag != 0 || layersetting[i].name != 0) {\r\n                            layer_save[i] = 1;\r\n                        }\r\n                    }\r\n                */\r\n                char code_put[] = {\r\n            /*\\x8b*/\"\\x0d\\x50\\x62\\x14\\x00\"        // mov     ecx,dword ptr [exedit+146250]\r\n                    \"\\x3b\\xc1\"                    // cmp     eax,ecx\r\n                    \"\\x7c\\xe4\"                    // jl      100326c4\r\n                    \"\\xb8\\x10\\x27\\x00\\x00\"        // mov     eax,0x2710 ; 10000\r\n                    \"\\x48\"                        // dec     eax\r\n                    \"\\x8b\\x0c\\x85\\x98\\x84\\x18\\x00\"// mov     ecx,dword ptr [eax*4+ exedit+188498]\r\n                    \"\\x85\\xc9\"                    // test    ecx,ecx\r\n                    \"\\x74\\x09\"                    // jz      skip,9 ; 100326fa\r\n                    \"\\x8b\\xd0\"                    // mov     edx,eax\r\n                    \"\\xc1\\xea\\x01\"                // shr     edx,1\r\n                    \"\\xc6\\x04\\x2a\\x01\"            // mov     byte ptr [edx+ebp],01\r\n                    \"\\x85\\xc0\"                    // test    eax,eax\r\n                    \"\\x75\\xe7\"                    // jnz     back,19 ; 100326e5\r\n                    \"\\x90\"                        // nop\r\n                    \"\\x90\"                        // nop\r\n                };\r\n\r\n                *(int*)(&code_put[1]) = GLOBAL::exedit_base + 0x146250;\r\n                *(int*)(&code_put[18]) = GLOBAL::exedit_base + 0x188498;\r\n\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x0326c3, 61);\r\n                h.store_i8(0, 0x1c);\r\n\r\n                memcpy(reinterpret_cast<void*>(h.address()+20), code_put, sizeof(code_put) - 1);\r\n            }\r\n\r\n\r\n        }\r\n        void switching(bool flag) {\r\n            enabled = flag;\r\n        }\r\n\r\n        bool is_enabled() { return enabled; }\r\n        bool is_enabled_i() { return enabled_i; }\r\n\r\n        void switch_load(ConfigReader& cr) {\r\n            cr.regist(key, [this](json_value_s* value) {\r\n                ConfigReader::load_variable(value, enabled);\r\n                });\r\n        }\r\n\r\n        void switch_store(ConfigWriter& cw) {\r\n            cw.append(key, enabled);\r\n        }\r\n\r\n    } aup_layer_setting;\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_AUP_LAYER_SETTING\r\n"
  },
  {
    "path": "patch/patch_aup_scene_setting.hpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_AUP_SCENE_SETTING\r\n\r\n#include \"global.hpp\"\r\n#include \"util.hpp\"\r\n#include \"restorable_patch.hpp\"\r\n\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch {\r\n    // init at exedit load\r\n    // プロジェクトの保存/読み込み時にシーン設定の一部情報（グリッド設定など）が欠けるのを修正\r\n    inline class aup_scene_setting_t {\r\n\r\n        bool enabled = true;\r\n        bool enabled_i;\r\n\r\n        inline static const char key[] = \"aup_scene_setting\";\r\n\r\n\r\n    public:\r\n\r\n        void init() {\r\n            enabled_i = enabled;\r\n\r\n            if (!enabled_i)return;\r\n\r\n            {\r\n                char save_scene_setting_all[] = {\r\n                    \"\\x8d\\x7e\\x48\"             // lea     edi,dword ptr [esi+48] ; dst\r\n                    \"\\x56\"                     // push    esi\r\n                    \"\\x8d\\x75\\x04\"             // lea     esi,dword ptr [ebp+04] ; src\r\n                    \"\\xb9\\x16\\x00\\x00\\x00\"     // mov     ecx,00000016 ; scenesetting.widthから22項目\r\n                    \"\\xf3\\xa5\"                 // rep     movsd\r\n                    \"\\x5e\"                     // pop     esi\r\n                    \"\\xeb\\x2e\"                 // jmp     skip,2e (10032781)\r\n                };\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x032742, sizeof(save_scene_setting_all) - 1);\r\n                memcpy(reinterpret_cast<void*>(h.address()), save_scene_setting_all, sizeof(save_scene_setting_all) - 1);\r\n            }\r\n            {\r\n                /*\r\n                    10031b48 8b4648             mov     eax,dword ptr [esi+48]\r\n                    10031b4b c1e205             shl     edx,05\r\n                    10031b4e 8982587a1710       mov     dword ptr [edx+10177a58],eax\r\n                    10031b54 ...\r\n                    ↓\r\n                    10031b48 8bc7               mov     eax,edi\r\n                    10031b4a 90                 nop\r\n                    10031b4b c1e205             shl     edx,05\r\n                    10031b4e 8dbaXxXxXxXx       lea     edi,dword ptr [edx+exedit+177a58] ; Xの部分は書きかえなければ良い\r\n                    10031b54 ...       load_scene_setting_all\r\n                */\r\n                char load_scene_setting_all[] = {\r\n                    \"\\x83\\xc6\\x48\"             // add     esi,+48\r\n                    \"\\xb9\\x15\\x00\\x00\\x00\"     // mov     ecx,00000015 ; こっちは21(22項目目はこの後に別の判定がある)\r\n                    \"\\xf3\\xa5\"                 // rep     movsd\r\n                    \"\\x8b\\xf8\"                 // mov     edi,eax\r\n                    \"\\x81\\xee\\x9c\\x00\\x00\\x00\" // sub     esi,0000009c ; 21*4 + 0x48\r\n                    \"\\x81\\xfb\\x2b\\x23\\x00\\x00\" // cmp     ebx,0000232b\r\n                    \"\\xeb\\x74\"                 // jmp     skip,74 (10031be2)\r\n                };\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x031b49, 25);\r\n                h.store_i16(0, '\\xc7\\x90');\r\n                h.store_i16(5, '\\x8d\\xba');\r\n                memcpy(reinterpret_cast<void*>(h.address() + 11), load_scene_setting_all, sizeof(load_scene_setting_all) - 1);\r\n            }\r\n\r\n        }\r\n        void switching(bool flag) {\r\n            enabled = flag;\r\n        }\r\n\r\n        bool is_enabled() { return enabled; }\r\n        bool is_enabled_i() { return enabled_i; }\r\n\r\n        void switch_load(ConfigReader& cr) {\r\n            cr.regist(key, [this](json_value_s* value) {\r\n                ConfigReader::load_variable(value, enabled);\r\n                });\r\n        }\r\n\r\n        void switch_store(ConfigWriter& cw) {\r\n            cw.append(key, enabled);\r\n        }\r\n\r\n    } aup_scene_setting;\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_AUP_SCENE_SETTING\r\n"
  },
  {
    "path": "patch/patch_aviutl_wndproc_override.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_aviutl_wndproc_override.hpp\"\n\nnamespace patch {\n    LRESULT CALLBACK aviutl_wndproc_override_t::wrap(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {\n        auto org = [=]() { return aviutl_wndproc_orig(hwnd, message, wparam, lparam); };\n\n        switch (message) {\n        case WM_MENUSELECT:\n            #ifdef PATCH_SWITCH_CONSOLE\n            if ((HMENU)lparam == aviutl_hmenu && HIWORD(wparam) & MF_POPUP) {\n                console.update_visible_state(aviutl_hmwnu_disp);\n            }\n            #endif\n            return org();\n        case WM_ACTIVATE: {\n            static bool first_activate_gate = false;\n            auto ret = org();\n            if (!first_activate_gate) {\n                #ifdef PATCH_SWITCH_CONSOLE\n                console.update_showwindow();\n                #endif\n                first_activate_gate = true;\n            }\n            return ret;\n        }\n        case WM_COMMAND: {\n            auto menuid = LOWORD(wparam);\n            if (20000 <= menuid && menuid < 30000) {\n                switch (menuid) {\n                    case PATCH_MENU_INFO: {\n                        MessageBoxA(hwnd, patchaul_info.get(), \"patch.aul info\", 0);\n                        return 0;\n                    }\n                    #ifdef PATCH_SWITCH_CONSOLE\n                    case PATCH_MENU_CONSOLE: {\n                        console.menu_console(aviutl_hmwnu_disp);\n                        return 0;\n                    }\n                    #endif\n                }\n            }\n            break;\n        }\n        case WM_SYSCOMMAND:\n            #ifdef PATCH_SWITCH_CONSOLE\n            switch (wparam) {\n                case SC_RESTORE: {\n                    auto ret = org();\n                    if (console.visible) {\n                        console.showWindow(SW_RESTORE);\n                    }\n                    return ret;\n                }\n                case SC_MINIMIZE: {\n                    auto ret = org();\n                    if (console.visible) {\n                        console.showWindow(SW_MINIMIZE);\n                    }\n                    return ret;\n                }\n            }\n            #endif\n            break;\n        }\n        return org();\n    }\n} // namespace patch\n"
  },
  {
    "path": "patch/patch_aviutl_wndproc_override.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n\n#include <aviutl.hpp>\n\n#include \"macro.h\"\n\n#include \"cryptostring.hpp\"\n\n#include \"global.hpp\"\n#include \"offset_address.hpp\"\n\n#include \"version.hpp\"\n#include \"util.hpp\"\n\n#include \"patch_console.hpp\"\n\nnamespace patch {\n\t// init before filter plugin load\n    // AviUtl のメインウィンドウのWndProcのフック\n\tinline class aviutl_wndproc_override_t {\n\t\tinline static HMENU aviutl_hmenu; // menu parent\n\t\tinline static HMENU aviutl_hmwnu_disp; // menu 表示\n\n\t\tinline static WNDPROC aviutl_wndproc_orig;\n\n\t\tfriend class console_t;\n\n\t\tstatic LRESULT CALLBACK wrap(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);\n\tpublic:\n\t\tinline void go() {\n\t\t\t\n\t\t\tauto hwnd = load_i32<AviUtl::EditHandle*>(GLOBAL::aviutl_base + OFS::AviUtl::edit_handle_ptr)->aviutl_window_info.main_window;\n\n\t\t\taviutl_wndproc_orig = reinterpret_cast<WNDPROC>(SetWindowLongA(hwnd, GWL_WNDPROC, reinterpret_cast<LONG>(wrap)));\n\n#ifdef PATCH_SWITCH_CONSOLE\n\t\t\tif (!patch::console.visible) console.showWindow(SW_MINIMIZE);\n#endif\n\n\t\t\taviutl_hmenu = GetMenu(hwnd);\n\t\t\taviutl_hmwnu_disp = GetSubMenu(aviutl_hmenu, 5);\n\n\t\t}\n\n\t} aviutl_wndproc_override;\n} // namespace patch\n"
  },
  {
    "path": "patch/patch_base.hpp",
    "content": "/*\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n\nnamespace patch {\n    class patch_base1 {\n\n    protected:\n        bool enabled;\n\n    public:\n        void switch_true_to_false() {}\n\n        void switch_false_to_true() {}\n\n        void switch_enabled(bool flag) {\n            if (flag) {\n                if (!enabled) switch_false_to_true();\n            }\n            else {\n                if (enabled) switch_true_to_false();\n            }\n        }\n\n    };\n\n    class patch_base2 : public patch_base1 {\n\n    protected:\n        bool enabled_i;\n\n    public:\n        void switch_enabled(bool flag) {\n            enabled = flag;\n        }\n\n        void init(bool flag) {\n            enabled = enabled_i = flag;\n        }\n    };\n\n\n}\n"
  },
  {
    "path": "patch/patch_blend.cpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"patch_blend.hpp\"\r\n\r\n#ifdef PATCH_SWITCH_BLEND\r\nnamespace patch {\r\n\r\n    void __cdecl blend_t::blend_yca_add(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a) {\r\n        src_y  += (dst->y  * dst->a) >> 12;\r\n        src_cb += (dst->cb * dst->a) >> 12;\r\n        src_cr += (dst->cr * dst->a) >> 12;\r\n        if (0x2000 < src_y) {\r\n            if (src_y < 0x3000) {\r\n                src_cb = ((0x3000 - src_y) * src_cb) >> 12;\r\n                src_cr = ((0x3000 - src_y) * src_cr) >> 12;\r\n            } else {\r\n                src_cb = src_cr = 0;\r\n            }\r\n            src_y = 0x2000;\r\n        }\r\n        blend_yca_normal(dst, src_y, src_cb, src_cr, src_a);\r\n    }\r\n\r\n\r\n    void __cdecl blend_t::blend_yca_sub(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a) {\r\n        src_y  = ((dst->y  * dst->a) >> 12) - src_y;\r\n        src_cb = ((dst->cb * dst->a) >> 12) - src_cb;\r\n        src_cr = ((dst->cr * dst->a) >> 12) - src_cr;\r\n        if (src_y < 0) {\r\n            if (src_y <= -0x400) {\r\n                src_cb = src_cr = 0;\r\n            } else {\r\n                src_cb = ((src_y + 0x400) * src_cb) >> 10;\r\n                src_cr = ((src_y + 0x400) * src_cr) >> 10;\r\n            }\r\n            src_y = 0;\r\n        }\r\n        blend_yca_normal(dst, src_y, src_cb, src_cr, src_a);\r\n    }\r\n\r\n    void __cdecl blend_t::blend_yca_mul(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a) {\r\n        int fix_y  = (dst->y  * dst->a) >> 12;\r\n        int fix_cb = (dst->cb * dst->a) >> 12;\r\n        int fix_cr = (dst->cr * dst->a) >> 12;\r\n        int src_t = (std::max)(0, ((src_cr * 0x59ba) >> 14) + src_y);\r\n        int dst_t = (std::max)(0, ((fix_cr * 0x59ba) >> 14) + fix_y);\r\n        int r = (std::min)((src_t * dst_t) >> 12, 0x2000);\r\n\r\n        src_t = (std::max)(0, ((src_cb * -0x1604 + src_cr * -0x2db2) >> 14) + src_y);\r\n        dst_t = (std::max)(0, ((fix_cb * -0x1604 + fix_cr * -0x2db2) >> 14) + fix_y);\r\n        int g = (std::min)((src_t * dst_t) >> 12, 0x2000);\r\n\r\n        src_t = (std::max)(0, ((src_cb * 0x7168) >> 14) + src_y);\r\n        dst_t = (std::max)(0, ((fix_cb * 0x7168) >> 14) + fix_y);\r\n        int b = (std::min)((src_t * dst_t) >> 12, 0x2000);\r\n\r\n        src_y  = (r * 0x1322 + g *  0x2591 + b * 0x74b ) >> 14;\r\n        src_cb = (r * -0xad0 + g * -0x152f + b * 0x2000) >> 14;\r\n        src_cr = (r * 0x2000 + g * -0x1ad0 + b * -0x52f) >> 14;\r\n\r\n        blend_yca_normal(dst, src_y, src_cb, src_cr, src_a);\r\n    }\r\n\r\n    void __cdecl blend_t::blend_yca_screen(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a) {\r\n        int fix_y  = (dst->y  * dst->a) >> 12;\r\n        int fix_cb = (dst->cb * dst->a) >> 12;\r\n        int fix_cr = (dst->cr * dst->a) >> 12;\r\n        int src_t = (std::max)(0, ((src_cr * 0x59ba) >> 14) + src_y);\r\n        int dst_t = (std::max)(0, ((fix_cr * 0x59ba) >> 14) + fix_y);\r\n        int r = dst_t - ((dst_t * src_t) >> 12) + src_t;\r\n\r\n        src_t = (std::max)(0, ((src_cb * -0x1604 + src_cr * -0x2db2) >> 14) + src_y);\r\n        dst_t = (std::max)(0, ((fix_cb * -0x1604 + fix_cr * -0x2db2) >> 14) + fix_y);\r\n        int g = dst_t - ((dst_t * src_t) >> 12) + src_t;\r\n\r\n        src_t = (std::max)(0, ((src_cb * 0x7168) >> 14) + src_y);\r\n        dst_t = (std::max)(0, ((fix_cb * 0x7168) >> 14) + fix_y);\r\n        int b = dst_t - ((dst_t * src_t) >> 12) + src_t;\r\n\r\n        src_y  = (r * 0x1322 + g *  0x2591 + b * 0x74b ) >> 14;\r\n        src_cb = (r * -0xad0 + g * -0x152f + b * 0x2000) >> 14;\r\n        src_cr = (r * 0x2000 + g * -0x1ad0 + b * -0x52f) >> 14;\r\n\r\n        blend_yca_normal(dst, src_y, src_cb, src_cr, src_a);\r\n    }\r\n\r\n    void __cdecl blend_t::blend_yca_overlay(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a) {\r\n        int fix_y  = (dst->y  * dst->a) >> 12;\r\n        int fix_cb = (dst->cb * dst->a) >> 12;\r\n        int fix_cr = (dst->cr * dst->a) >> 12;\r\n        int src_t = (std::max)(0, ((src_cr * 0x59ba) >> 14) + src_y);\r\n        int dst_t = (std::max)(0, ((fix_cr * 0x59ba) >> 14) + fix_y);\r\n        int r = (dst_t * src_t) >> 11;\r\n        if (0x800 <= dst_t) {\r\n            r = (dst_t + src_t) * 2 - 0x1000 - r;\r\n        }\r\n\r\n        src_t = (std::max)(0, ((src_cb * -0x1604 + src_cr * -0x2db2) >> 14) + src_y);\r\n        dst_t = (std::max)(0, ((fix_cb * -0x1604 + fix_cr * -0x2db2) >> 14) + fix_y);\r\n        int g = (dst_t * src_t) >> 11;\r\n        if (0x800 <= dst_t) {\r\n            g = (dst_t + src_t) * 2 - 0x1000 - g;\r\n        }\r\n\r\n        src_t = (std::max)(0, ((src_cb * 0x7168) >> 14) + src_y);\r\n        dst_t = (std::max)(0, ((fix_cb * 0x7168) >> 14) + fix_y);\r\n        int b = (dst_t * src_t) >> 11;\r\n        if (0x800 <= dst_t) {\r\n            b = (dst_t + src_t) * 2 - 0x1000 - b;\r\n        }\r\n\r\n        src_y  = (r * 0x1322 + g *  0x2591 + b * 0x74b ) >> 14;\r\n        src_cb = (r * -0xad0 + g * -0x152f + b * 0x2000) >> 14;\r\n        src_cr = (r * 0x2000 + g * -0x1ad0 + b * -0x52f) >> 14;\r\n\r\n        blend_yca_normal(dst, src_y, src_cb, src_cr, src_a);\r\n    }\r\n\r\n    void __cdecl blend_t::blend_yca_cmpmax(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a) {\r\n        int fix_y  = (dst->y  * dst->a) >> 12;\r\n        int fix_cb = (dst->cb * dst->a) >> 12;\r\n        int fix_cr = (dst->cr * dst->a) >> 12;\r\n        int r = (std::max)(((src_cr * 0x59ba) >> 14) + src_y, ((fix_cr * 0x59ba) >> 14) + fix_y);\r\n        int g = (std::max)(((src_cb * -0x1604 + src_cr * -0x2db2) >> 14) + src_y, ((fix_cb * -0x1604 + fix_cr * -0x2db2) >> 14) + fix_y);\r\n        int b = (std::max)(((src_cb * 0x7168) >> 14) + src_y, ((fix_cb * 0x7168) >> 14) + fix_y);\r\n\r\n        src_y  = (r * 0x1322 + g *  0x2591 + b * 0x74b ) >> 14;\r\n        src_cb = (r * -0xad0 + g * -0x152f + b * 0x2000) >> 14;\r\n        src_cr = (r * 0x2000 + g * -0x1ad0 + b * -0x52f) >> 14;\r\n\r\n        blend_yca_normal(dst, src_y, src_cb, src_cr, src_a);\r\n    }\r\n\r\n    void __cdecl blend_t::blend_yca_cmpmin(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a) {\r\n        int fix_y  = (dst->y  * dst->a) >> 12;\r\n        int fix_cb = (dst->cb * dst->a) >> 12;\r\n        int fix_cr = (dst->cr * dst->a) >> 12;\r\n        int r = (std::min)(((src_cr * 0x59ba) >> 14) + src_y, ((fix_cr * 0x59ba) >> 14) + fix_y);\r\n        int g = (std::min)(((src_cb * -0x1604 + src_cr * -0x2db2) >> 14) + src_y, ((fix_cb * -0x1604 + fix_cr * -0x2db2) >> 14) + fix_y);\r\n        int b = (std::min)(((src_cb * 0x7168) >> 14) + src_y, ((fix_cb * 0x7168) >> 14) + fix_y);\r\n\r\n        src_y  = (r * 0x1322 + g *  0x2591 + b * 0x74b ) >> 14;\r\n        src_cb = (r * -0xad0 + g * -0x152f + b * 0x2000) >> 14;\r\n        src_cr = (r * 0x2000 + g * -0x1ad0 + b * -0x52f) >> 14;\r\n\r\n        blend_yca_normal(dst, src_y, src_cb, src_cr, src_a);\r\n    }\r\n\r\n\r\n    void __cdecl blend_t::blend_yca_luminance(ExEdit::PixelYCA* dst, short src_y, short src_cb, short src_cr, short src_a) {\r\n        if (0x1000 <= src_a) {\r\n            dst->y  = src_y;\r\n            dst->cb = (dst->cb * dst->a) >> 12;\r\n            dst->cr = (dst->cr * dst->a) >> 12;\r\n            dst->a  = 0x1000;\r\n        } else if (0x1000 <= dst->a) {\r\n            dst->y += ((src_y - dst->y) * src_a) >> 12;\r\n            dst->a = 0x1000;\r\n        } else if (dst->a <= 0) {\r\n            dst->y  = src_y;\r\n            dst->cb = 0;\r\n            dst->cr = 0;\r\n            dst->a  = src_a;\r\n        } else {\r\n            short new_a = (0x1000800 - (0x1000 - dst->a) * (0x1000 - src_a)) >> 12;\r\n            dst->y  = (((dst->y * dst->a) >> 12) * (0x1000 - src_a) + src_y * src_a) / new_a;\r\n            dst->cb = dst->cb * dst->a / new_a;\r\n            dst->cr = dst->cr * dst->a / new_a;\r\n            dst->a  = new_a;\r\n        }\r\n    }\r\n\r\n    void __cdecl blend_t::blend_yca_colordiff(ExEdit::PixelYCA* dst, short src_y, short src_cb, short src_cr, short src_a) {\r\n        if (0x1000 <= src_a) {\r\n            dst->y  = (dst->y * dst->a) >> 12;\r\n            dst->cb = src_cb;\r\n            dst->cr = src_cr;\r\n            dst->a  = 0x1000;\r\n        } else if (0x1000 <= dst->a) {\r\n            dst->cb += ((src_cb - dst->cb) * src_a) >> 12;\r\n            dst->cr += ((src_cr - dst->cr) * src_a) >> 12;\r\n            dst->a  = 0x1000;\r\n        } else if (dst->a <= 0) {\r\n            dst->y  = 0;\r\n            dst->cb = src_cb;\r\n            dst->cr = src_cr;\r\n            dst->a  = src_a;\r\n        } else {\r\n            int new_a = (0x1000800 - (0x1000 - dst->a) * (0x1000 - src_a)) >> 12;\r\n            int new_dst_a = (0x1000 - src_a) * dst->a / new_a;\r\n            int new_src_a = (src_a << 12) / new_a;\r\n            dst->y  = dst->y * dst->a / new_a;\r\n            dst->cb = (dst->cb * new_dst_a + src_cb * new_src_a) >> 12;\r\n            dst->cr = (dst->cr * new_dst_a + src_cr * new_src_a) >> 12;\r\n            dst->a = new_a;\r\n        }\r\n    }\r\n\r\n    void __cdecl blend_t::blend_yca_shadow(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a) {\r\n        int fix_y  = (dst->y  * dst->a) >> 12;\r\n        int fix_cb = (dst->cb * dst->a) >> 12;\r\n        int fix_cr = (dst->cr * dst->a) >> 12;\r\n        int src_t = (std::max)(0, ((src_cr * 0x59ba) >> 14) + src_y);\r\n        int dst_t = (std::max)(0, ((fix_cr * 0x59ba) >> 14) + fix_y);\r\n        int r = (std::max)(0, dst_t + src_t - 0x1000);\r\n\r\n        src_t = (std::max)(0, ((src_cb * -0x1604 + src_cr * -0x2db2) >> 14) + src_y);\r\n        dst_t = (std::max)(0, ((fix_cb * -0x1604 + fix_cr * -0x2db2) >> 14) + fix_y);\r\n        int g = (std::max)(0, dst_t + src_t - 0x1000);\r\n\r\n        src_t = (std::max)(0, ((src_cb * 0x7168) >> 14) + src_y);\r\n        dst_t = (std::max)(0, ((fix_cb * 0x7168) >> 14) + fix_y);\r\n        int b = (std::max)(0, dst_t + src_t - 0x1000);\r\n\r\n        src_y  = (r * 0x1322 + g *  0x2591 + b * 0x74b ) >> 14;\r\n        src_cb = (r * -0xad0 + g * -0x152f + b * 0x2000) >> 14;\r\n        src_cr = (r * 0x2000 + g * -0x1ad0 + b * -0x52f) >> 14;\r\n\r\n        blend_yca_normal(dst, src_y, src_cb, src_cr, src_a);\r\n    }\r\n\r\n    void __cdecl blend_t::blend_yca_lightdark(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a) {\r\n        int fix_y  = (dst->y  * dst->a) >> 12;\r\n        int fix_cb = (dst->cb * dst->a) >> 12;\r\n        int fix_cr = (dst->cr * dst->a) >> 12;\r\n        int src_t = ((src_cr * 0x59ba) >> 14) + src_y;\r\n        int dst_t = ((fix_cr * 0x59ba) >> 14) + fix_y;\r\n        int r = std::clamp(dst_t + src_t * 2 - 0x1000, 0, 0x2000);\r\n\r\n        src_t = ((src_cb * -0x1604 + src_cr * -0x2db2) >> 14) + src_y;\r\n        dst_t = ((fix_cb * -0x1604 + fix_cr * -0x2db2) >> 14) + fix_y;\r\n        int g = std::clamp(dst_t + src_t * 2 - 0x1000, 0, 0x2000);\r\n\r\n        src_t = ((src_cb * 0x7168) >> 14) + src_y;\r\n        dst_t = ((fix_cb * 0x7168) >> 14) + fix_y;\r\n        int b = std::clamp(dst_t + src_t * 2 - 0x1000, 0, 0x2000);\r\n\r\n        src_y  = (r * 0x1322 + g *  0x2591 + b * 0x74b ) >> 14;\r\n        src_cb = (r * -0xad0 + g * -0x152f + b * 0x2000) >> 14;\r\n        src_cr = (r * 0x2000 + g * -0x1ad0 + b * -0x52f) >> 14;\r\n\r\n        blend_yca_normal(dst, src_y, src_cb, src_cr, src_a);\r\n    }\r\n\r\n    void __cdecl blend_t::blend_yca_difference(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a) {\r\n        int sub_y  = src_y  - ((dst->y  * dst->a) >> 12);\r\n        int sub_cb = src_cb - ((dst->cb * dst->a) >> 12);\r\n        int sub_cr = src_cr - ((dst->cr * dst->a) >> 12);\r\n\r\n        int r = abs(((sub_cr * 0x59ba) >> 14) + sub_y);\r\n        int g = abs(((sub_cb * -0x1604 + sub_cr * -0x2db2) >> 14) + sub_y);\r\n        int b = abs(((sub_cb * 0x7168) >> 14) + sub_y);\r\n\r\n        src_y  = (r * 0x1322 + g *  0x2591 + b * 0x74b ) >> 14;\r\n        src_cb = (r * -0xad0 + g * -0x152f + b * 0x2000) >> 14;\r\n        src_cr = (r * 0x2000 + g * -0x1ad0 + b * -0x52f) >> 14;\r\n\r\n        blend_yca_normal(dst, src_y, src_cb, src_cr, src_a);\r\n    }\r\n\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_BLEND"
  },
  {
    "path": "patch/patch_blend.hpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_BLEND\r\n\r\n#include <memory>\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util.hpp\"\r\n#include \"restorable_patch.hpp\"\r\n\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch {\r\n\t// init at exedit load\r\n\t// 合成モード関数の修正(主にアルファチャンネル有りシーンオブジェクト)\r\n\tinline class blend_t {\r\n\t\tstatic void __cdecl blend_yca_add(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a);\r\n\t\tstatic void __cdecl blend_yca_sub(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a);\r\n\t\tstatic void __cdecl blend_yca_mul(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a);\r\n\t\tstatic void __cdecl blend_yca_screen(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a);\r\n\t\tstatic void __cdecl blend_yca_overlay(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a);\r\n\t\tstatic void __cdecl blend_yca_cmpmax(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a);\r\n\t\tstatic void __cdecl blend_yca_cmpmin(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a);\r\n\t\tstatic void __cdecl blend_yca_luminance(ExEdit::PixelYCA* dst, short src_y, short src_cb, short src_cr, short src_a);\r\n\t\tstatic void __cdecl blend_yca_colordiff(ExEdit::PixelYCA* dst, short src_y, short src_cb, short src_cr, short src_a);\r\n\t\tstatic void __cdecl blend_yca_shadow(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a);\r\n\t\tstatic void __cdecl blend_yca_lightdark(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a);\r\n\t\tstatic void __cdecl blend_yca_difference(ExEdit::PixelYCA* dst, int src_y, int src_cb, int src_cr, int src_a);\r\n\r\n\t\tbool enabled = true;\r\n\t\tbool enabled_i;\r\n\r\n\t\tinline static const char key[] = \"blend\";\r\n\r\n\r\n\tpublic:\r\n\r\n\t\tinline static void(__cdecl* blend_yca_normal)(void* dst, int src_y, int src_cb, int src_cr, int src_a);\r\n\r\n\t\tvoid init() {\r\n\t\t\tenabled_i = enabled;\r\n\r\n\t\t\tif (!enabled_i)return;\r\n\r\n\t\t\tblend_yca_normal = reinterpret_cast<decltype(blend_yca_normal)>(GLOBAL::exedit_base + OFS::ExEdit::blend_yca_normal_func);\r\n\t\t\t{\r\n\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x9fbb4, 48);\r\n\t\t\t\th.store_i32(0, &blend_yca_add);\r\n\t\t\t\th.store_i32(4, &blend_yca_sub);\r\n\t\t\t\th.store_i32(8, &blend_yca_mul);\r\n\t\t\t\th.store_i32(12, &blend_yca_screen);\r\n\t\t\t\th.store_i32(16, &blend_yca_overlay);\r\n\t\t\t\th.store_i32(20, &blend_yca_cmpmax);\r\n\t\t\t\th.store_i32(24, &blend_yca_cmpmin);\r\n\t\t\t\th.store_i32(28, &blend_yca_luminance);\r\n\t\t\t\th.store_i32(32, &blend_yca_colordiff);\r\n\t\t\t\th.store_i32(36, &blend_yca_shadow);\r\n\t\t\t\th.store_i32(40, &blend_yca_lightdark);\r\n\t\t\t\th.store_i32(44, &blend_yca_difference);\r\n\t\t\t}\r\n\r\n            char blend_yca_normal_bin[] = {\r\n                \"\\x8b\\x4c\\x24\\x04\"         // mov     ecx,dword ptr [esp+04]\r\n                \"\\x8b\\x54\\x24\\x14\"         // mov     edx,dword ptr [esp+14]\r\n                \"\\xb8\\x00\\x10\\x00\\x00\"     // mov     eax,00001000\r\n                \"\\x3b\\xd0\"                 // cmp     edx,eax\r\n                \"\\x7c\\x1f\"                 // jl      10007e20\r\n                \"\\x66\\x89\\x41\\x06\"         // mov     [ecx+06],ax\r\n                \"\\x66\\x8b\\x44\\x24\\x08\"     // mov     ax,[esp+08]\r\n                \"\\x66\\x8b\\x54\\x24\\x0c\"     // mov     dx,[esp+0c]\r\n                \"\\x66\\x89\\x01\"             // mov     [ecx],ax\r\n                \"\\x66\\x8b\\x44\\x24\\x10\"     // mov     ax,[esp+10]\r\n                \"\\x66\\x89\\x51\\x02\"         // mov     [ecx+02],dx\r\n                \"\\x66\\x89\\x41\\x04\"         // mov     [ecx+04],ax\r\n                \"\\xc3\"                     // ret\r\n                \"\\x56\"                     // push    esi\r\n                \"\\x0f\\xbf\\x71\\x06\"         // movsx   esi,dword ptr [ecx+06]\r\n                \"\\x3b\\xf0\"                 // cmp     esi,eax\r\n                \"\\x7c\\x40\"                 // jl      10007e69\r\n                \"\\x66\\x89\\x41\\x06\"         // mov     [ecx+06],ax\r\n                \"\\x0f\\xbf\\x31\"             // movsx   esi,dword ptr [ecx]\r\n                \"\\x8b\\x44\\x24\\x0c\"         // mov     eax,dword ptr [esp+0c]\r\n                \"\\x2b\\xc6\"                 // sub     eax,esi\r\n                \"\\x0f\\xaf\\xc2\"             // imul    eax,edx\r\n                \"\\xc1\\xf8\\x0c\"             // sar     eax,0c\r\n                \"\\x66\\x01\\x01\"             // add     [ecx],ax\r\n                \"\\x0f\\xbf\\x71\\x02\"         // movsx   esi,dword ptr [ecx+02]\r\n                \"\\x8b\\x44\\x24\\x10\"         // mov     eax,dword ptr [esp+10]\r\n                \"\\x2b\\xc6\"                 // sub     eax,esi\r\n                \"\\x0f\\xaf\\xc2\"             // imul    eax,edx\r\n                \"\\xc1\\xf8\\x0c\"             // sar     eax,0c\r\n                \"\\x66\\x01\\x41\\x02\"         // add     [ecx+02],ax\r\n                \"\\x0f\\xbf\\x71\\x04\"         // movsx   esi,dword ptr [ecx+04]\r\n                \"\\x8b\\x44\\x24\\x14\"         // mov     eax,dword ptr [esp+14]\r\n                \"\\x2b\\xc6\"                 // sub     eax,esi\r\n                \"\\x0f\\xaf\\xc2\"             // imul    eax,edx\r\n                \"\\xc1\\xf8\\x0c\"             // sar     eax,0c\r\n                \"\\x66\\x01\\x41\\x04\"         // add     [ecx+04],ax\r\n                \"\\x5e\"                     // pop     esi\r\n                \"\\xc3\"                     // ret\r\n                \"\\x85\\xf6\"                 // test    esi,esi\r\n                \"\\x7f\\x20\"                 // jg      10007e90\r\n                \"\\x66\\x89\\x51\\x06\"         // mov     [ecx+06],dx\r\n                \"\\x66\\x8b\\x44\\x24\\x0c\"     // mov     ax,[esp+0c]\r\n                \"\\x66\\x8b\\x54\\x24\\x10\"     // mov     dx,[esp+10]\r\n                \"\\x66\\x89\\x01\"             // mov     [ecx],ax\r\n                \"\\x66\\x8b\\x44\\x24\\x14\"     // mov     ax,[esp+14]\r\n                \"\\x66\\x89\\x51\\x02\"         // mov     [ecx+02],dx\r\n                \"\\x66\\x89\\x41\\x04\"         // mov     [ecx+04],ax\r\n                \"\\x5e\"                     // pop     esi\r\n                \"\\xc3\"                     // ret\r\n                \"\\x53\"                     // push    ebx\r\n                \"\\x8b\\xd8\"                 // mov     ebx,eax\r\n                \"\\x2b\\xde\"                 // sub     ebx,esi\r\n                \"\\x2b\\xc2\"                 // sub     eax,edx\r\n                \"\\x0f\\xaf\\xd8\"             // imul    ebx,eax\r\n                \"\\x0f\\xaf\\xc6\"             // imul    eax,esi\r\n                \"\\xbe\\x00\\x08\\x00\\x01\"     // mov     esi,01000800\r\n                \"\\x2b\\xf3\"                 // sub     esi,ebx\r\n                \"\\xc1\\xfe\\x0c\"             // sar     esi,0c\r\n                \"\\x66\\x89\\x71\\x06\"         // mov     [ecx+06],si\r\n                \"\\x99\"                     // cdq\r\n                \"\\xf7\\xfe\"                 // idiv    esi\r\n                \"\\x8b\\xd8\"                 // mov     ebx,eax\r\n                \"\\x8b\\x44\\x24\\x1c\"         // mov     eax,dword ptr [esp+1c]\r\n                \"\\xc1\\xe0\\x0c\"             // shl     eax,0c\r\n                \"\\x99\"                     // cdq\r\n                \"\\xf7\\xfe\"                 // idiv    esi\r\n                \"\\x0f\\xbf\\x11\"             // movsx   edx,dword ptr [ecx]\r\n                \"\\x0f\\xaf\\xd3\"             // imul    edx,ebx\r\n                \"\\x8b\\x74\\x24\\x10\"         // mov     esi,dword ptr [esp+10]\r\n                \"\\x0f\\xaf\\xf0\"             // imul    esi,eax\r\n                \"\\x03\\xd6\"                 // add     edx,esi\r\n                \"\\xc1\\xfa\\x0c\"             // sar     edx,0c\r\n                \"\\x66\\x89\\x11\"             // mov     [ecx],dx\r\n                \"\\x0f\\xbf\\x51\\x02\"         // movsx   edx,dword ptr [ecx+02]\r\n                \"\\x0f\\xaf\\xd3\"             // imul    edx,ebx\r\n                \"\\x8b\\x74\\x24\\x14\"         // mov     esi,dword ptr [esp+14]\r\n                \"\\x0f\\xaf\\xf0\"             // imul    esi,eax\r\n                \"\\x03\\xd6\"                 // add     edx,esi\r\n                \"\\xc1\\xfa\\x0c\"             // sar     edx,0c\r\n                \"\\x66\\x89\\x51\\x02\"         // mov     [ecx+02],dx\r\n                \"\\x0f\\xbf\\x51\\x04\"         // movsx   edx,dword ptr [ecx+04]\r\n                \"\\x0f\\xaf\\xd3\"             // imul    edx,ebx\r\n                \"\\x8b\\x74\\x24\\x18\"         // mov     esi,dword ptr [esp+18]\r\n                \"\\x0f\\xaf\\xf0\"             // imul    esi,eax\r\n                \"\\x03\\xd6\"                 // add     edx,esi\r\n                \"\\xc1\\xfa\\x0c\"             // sar     edx,0c\r\n                \"\\x66\\x89\\x51\\x04\"         // mov     [ecx+04],dx\r\n                \"\\x5b\"                     // pop     ebx\r\n                \"\\x5e\"                     // pop     esi\r\n                \"\\xc3\"                     // ret\r\n            };\r\n            {\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::blend_yca_normal_func, sizeof(blend_yca_normal_bin) - 1);\r\n                memcpy(reinterpret_cast<void*>(h.address()), blend_yca_normal_bin, sizeof(blend_yca_normal_bin) - 1);\r\n            }\r\n            {\r\n                char blend_yc_normal_bin[] = {\r\n                    \"\\x8b\\x4c\\x24\\x04\"         // mov     ecx,dword ptr [esp+04]\r\n                    \"\\x8b\\x54\\x24\\x14\"         // mov     edx,dword ptr [esp+14]\r\n                    \"\\x81\\xfa\\x00\\x10\\x00\\x00\" // cmp     edx,00001000\r\n                    \"\\x7c\\x1b\"                 // jl      10007f4b\r\n                    \"\\x66\\x8b\\x44\\x24\\x08\"     // mov     ax,[esp+08]\r\n                    \"\\x66\\x8b\\x54\\x24\\x0c\"     // mov     dx,[esp+0c]\r\n                    \"\\x66\\x89\\x01\"             // mov     [ecx],ax\r\n                    \"\\x66\\x8b\\x44\\x24\\x10\"     // mov     ax,[esp+10]\r\n                    \"\\x66\\x89\\x51\\x02\"         // mov     [ecx+02],dx\r\n                    \"\\x66\\x89\\x41\\x04\"         // mov     [ecx+04],ax\r\n                    \"\\xc3\"                     // ret\r\n                    \"\\x56\"                     // push    esi\r\n                };\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::blend_yc_normal_func, 104);\r\n                memcpy(reinterpret_cast<void*>(h.address()), blend_yc_normal_bin, sizeof(blend_yc_normal_bin) - 1);\r\n                memcpy(reinterpret_cast<void*>(h.address() + sizeof(blend_yc_normal_bin) - 1), &blend_yca_normal_bin[61], 60);\r\n            }\r\n\r\n\r\n\t\t}\r\n\t\tvoid switching(bool flag) {\r\n\t\t\tenabled = flag;\r\n\t\t}\r\n\r\n\t\tbool is_enabled() { return enabled; }\r\n\t\tbool is_enabled_i() { return enabled_i; }\r\n\r\n\t\tvoid switch_load(ConfigReader& cr) {\r\n\t\t\tcr.regist(key, [this](json_value_s* value) {\r\n\t\t\t\tConfigReader::load_variable(value, enabled);\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tvoid switch_store(ConfigWriter& cw) {\r\n\t\t\tcw.append(key, enabled);\r\n\t\t}\r\n\r\n\t} blend;\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_BLEND\r\n"
  },
  {
    "path": "patch/patch_colorpalette_cache.hpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n#ifdef PATCH_SWITCH_COLORPALETTE_CACHE\r\n\r\n#include \"global.hpp\"\r\n#include \"config_rw.hpp\"\r\n#include \"util.hpp\"\r\n\r\nnamespace patch {\r\n\r\n\t// bmpのキャッシュをとる際に、カラーパレット分のデータ容量を取り忘れているのを修正\r\n\tinline class colorpalette_cache_t {\r\n\r\n\r\n\t\tinline static int __cdecl fix_size_2a6a(uintptr_t avi_file_handle) {\r\n\t\t\tint video_decode_w = *(int*)(avi_file_handle + 20);\r\n\t\t\tint video_decode_h = *(int*)(avi_file_handle + 24);\r\n\t\t\tshort video_decode_bit = *(short*)(avi_file_handle + 30);\r\n\r\n\t\t\tint size = (video_decode_bit * video_decode_w + 7) >> 3;\r\n\t\t\tsize = (size + 3 & 0xfffffffc) * video_decode_h;\r\n\r\n\t\t\tswitch (video_decode_bit) {\r\n\t\t\tcase 32:case 24:case 16:\r\n\t\t\t\tsize += 16;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 8:\r\n\t\t\t\tsize += 1040;\r\n\t\t\t\tbreak;\r\n\t\t\tcase 4:\r\n\t\t\t\tsize += 80;\r\n\t\t\t\tbreak;\r\n\t\t\tdefault:\r\n\t\t\t\tsize += 24;\r\n\t\t\t}\r\n\t\t\treturn size;\r\n\t\t}\r\n\t\tbool enabled = true;\r\n\t\tbool enabled_i;\r\n\r\n\t\tinline static const char key[] = \"colorpalette_cache\";\r\n\r\n\tpublic:\r\n\t\tvoid switching(bool flag) {\r\n\t\t\tenabled = flag;\r\n\t\t}\r\n\r\n\t\tbool is_enabled() { return enabled; }\r\n\t\tbool is_enabled_i() { return enabled_i; }\r\n\r\n\t\tvoid init() {\r\n\t\t\tenabled_i = enabled;\r\n\t\t\tif (!enabled_i)return;\r\n\r\n\t\t\t{\r\n\t\t\t\t/*\r\n\t\t\t\t\t00402a68 89442418           mov     dword ptr [esp+18],eax\r\n\t\t\t\t\t00402a6c 8d0c8510000000     lea     ecx,dword ptr [eax*4+00000010]\r\n\t\t\t\t\t00402a73 51                 push    ecx\r\n\t\t\t\t\t↓\r\n\t\t\t\t\t00402a68 56                 push    esi ; avi_file_handle\r\n\t\t\t\t\t00402a69 e8xxxxxxxx         call    fix_size_2a6a()\r\n\t\t\t\t\t00402a6e 5e                 pop     esi\r\n\t\t\t\t\t00402a6f 89442418           mov     dword ptr [esp+18],eax\r\n\t\t\t\t\t00402a73 50                 push    eax\r\n\r\n\r\n\t\t\t\t\t00402a88 c1e102             shl     ecx,02\r\n\t\t\t\t\t↓\r\n\t\t\t\t\t00402a88 83e910             sub     ecx,10\r\n\r\n\t\t\t\t*/\r\n\r\n\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::aviutl_base + 0x2a68, 35);\r\n\t\t\t\th.store_i16(0, '\\x56\\xe8');\r\n\t\t\t\th.replaceNearJmp(2, &fix_size_2a6a);\r\n\t\t\t\th.store_i32(6, '\\x5e\\x89\\x44\\x24');\r\n\t\t\t\th.store_i16(10, '\\x18\\x50');\r\n\r\n\t\t\t\th.store_i16(32, '\\x83\\xe9');\r\n\t\t\t\th.store_i8(34, '\\x10');\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tvoid switch_load(ConfigReader& cr) {\r\n\t\t\tcr.regist(key, [this](json_value_s* value) {\r\n\t\t\t\tConfigReader::load_variable(value, enabled);\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tvoid switch_store(ConfigWriter& cw) {\r\n\t\t\tcw.append(key, enabled);\r\n\t\t}\r\n\r\n\r\n\t} colorpalette_cache;\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_COLORPALETTE_CACHE\r\n"
  },
  {
    "path": "patch/patch_console.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_console.hpp\"\n#ifdef PATCH_SWITCH_DEBUGSTRING\n\n#include <chrono>\n#include <format>\n#include \"patch_console.hpp\"\n\nnamespace patch {\n\n\tvoid __stdcall console_t::debug_print_override(LPCSTR lpOutputString) {\n\t\tif (!lpOutputString)return;\n\t\tconsole.setConsoleTextAttribute(FOREGROUND_BLUE | FOREGROUND_INTENSITY);\n\t\tif (console.debug_string_time) console.writeConsole(\"[{}]\\t\"_fmt(get_local_time_string()));\n\t\tconsole.writeConsole(lpOutputString);\n\t\tconsole.setConsoleTextAttribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);\n\t\tconsole.writeConsole(\"\\n\");\n\t}\n\n\tvoid __stdcall console_t::exedit_lua_error_override(LPCSTR lpOutputString) {\n\t\tif (!lpOutputString)return;\n\t\tconsole.setConsoleTextAttribute(FOREGROUND_RED | FOREGROUND_INTENSITY);\n\t\tif (console.debug_string_time) console.writeConsole(\"[{}]\\t\"_fmt(get_local_time_string()));\n\t\tconsole.writeConsole(lpOutputString);\n\t\tconsole.setConsoleTextAttribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);\n\t\tconsole.writeConsole(\"\\n\");\n\t}\n\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_DEBUGSTRING\n"
  },
  {
    "path": "patch/patch_console.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_CONSOLE\n\n#include <cstdio>\n#include <iostream>\n\n#include <Windows.h>\n#include <oleacc.h>\n\n#include \"global.hpp\"\n#include \"util.hpp\"\n\n#include \"config_rw.hpp\"\n\nnamespace patch {\n\t// init at dllload\n\t// コンソール関連\n\tinline class console_t {\n\t\tHANDLE h_stdout;\n\t\tHWND console_hwnd;\n\t\tbool valid;\n\n\t\tbool enabled = true;\n\t\tbool enabled_i;\n\n\t\tinline static const char key[] = \"console\";\n\n\t\tinline static const char key_escape[] = \"console.escape\";\n\t\tinline static const char key_input[] = \"console.input\";\n\t\tinline static const char key_debug_string[] = \"console.debug_string\";\n\t\tinline static const char key_debug_string_time[] = \"console.debug_string.time\";\n\n\t\tbool escape = true;\n\t\tbool input = false;\n\t\tbool debug_string = true;\n\t\tbool debug_string_time = true;\n\n\t\tinline static const char key_visible[] = \"visible\";\n\t\tinline static const char key_rect[] = \"rect\";\n\n\t\tbool visible = false;\n\t\tstd::optional<RECT> rect;\n\n\t\tstatic void __stdcall debug_print_override(LPCSTR lpOutputString);\n\t\tstatic void __stdcall exedit_lua_error_override(LPCSTR lpOutputString);\n\n\t\tinline static constexpr auto* debug_print_override_ptr = &debug_print_override;\n\t\tinline static constexpr auto* exedit_lua_error_override_ptr = &exedit_lua_error_override;\n\n\n\tpublic:\n\t\tfriend class aviutl_wndproc_override_t;\n\t\tvoid exit() {\n\t\t\twriteConsole(\"bye\");\n\t\t\tFreeConsole();\n\t\t}\n\n\t\tvoid init() {\n\t\t\tenabled_i = enabled;\n\t\t\tif (!enabled_i)return;\n\n\t\t\tif (AllocConsole() != TRUE) {\n\t\t\t\tpatch_resource_message_w(PATCH_RS_PATCH_FAILED_TO_INIT_CONSOLE, MB_TASKMODAL | MB_ICONERROR);\n\t\t\t\tvalid = false;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconsole_hwnd = GetConsoleWindow();\n\n\t\t\tif (rect) {\n\t\t\t\tSetWindowPos(console_hwnd, NULL, rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top, SWP_NOZORDER | SWP_NOACTIVATE);\n\t\t\t}\n\t\t\tupdate_showwindow();\n\n\t\t\tSetConsoleTitleA(\"Console Window\");\n\n\t\t\th_stdout = GetStdHandle(STD_OUTPUT_HANDLE);\n\n\t\t\tif (escape) {\n\t\t\t\tDWORD consoleMode;\n\t\t\t\tGetConsoleMode(h_stdout, &consoleMode);\n\t\t\t\tSetConsoleMode(h_stdout, consoleMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);\n\t\t\t}\n\n\t\t\tFILE* fp;\n\t\t\tif (input) {\n\t\t\t\tfreopen_s(&fp, \"CONIN$\", \"r\", stdin);\n\t\t\t}\n\t\t\tfreopen_s(&fp, \"CONOUT$\", \"w\", stderr);\n\t\t\tfreopen_s(&fp, \"CONOUT$\", \"w\", stdout);\n\n\t\t\tsetConsoleTextAttribute(BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY);\n\t\t\t\n\t\t\twriteConsole(\"patch.aul\\n\");\n\t\t\tsetConsoleTextAttribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);\n\n\t\t\tvalid = true;\n\t\t}\n\n\t\tvoid init_at_exedit_init() {\n#ifdef PATCH_SWITCH_DEBUGSTRING\n\t\t\tif (debug_string) {\n\t\t\t\tOverWriteOnProtectHelper(GLOBAL::exedit_base + OFS::ExEdit::OutputDebugString_calling_err1, 4).store_i32(0, &exedit_lua_error_override_ptr);\n\t\t\t\tOverWriteOnProtectHelper(GLOBAL::exedit_base + OFS::ExEdit::OutputDebugString_calling_err2, 4).store_i32(0, &exedit_lua_error_override_ptr);\n\t\t\t\tOverWriteOnProtectHelper(GLOBAL::exedit_base + OFS::ExEdit::OutputDebugString_calling_err3, 4).store_i32(0, &exedit_lua_error_override_ptr);\n\t\t\t\tOverWriteOnProtectHelper(GLOBAL::exedit_base + OFS::ExEdit::OutputDebugString_calling_dbg, 4).store_i32(0, &debug_print_override_ptr);\n\t\t\t}\n#endif\n\t\t}\n\n\t\tvoid switching(bool flag) {\n\t\t\tenabled = flag;\n\t\t}\n\n\t\tbool is_enabled() { return enabled; }\n\t\tbool is_enabled_i() { return enabled_i; }\n\n\t\tvoid config_load(ConfigReader& cr) {\n\t\t\tcr.regist(key_visible, [this](json_value_s* value) { ConfigReader::load_variable(value, visible); });\n\t\t\tcr.regist(key_rect, [this](json_value_s* value) { ConfigReader::load_variable(value, rect); });\n\t\t}\n\n\t\tvoid config_store(ConfigWriter& cw) {\n\t\t\tcw.append(key_visible, visible);\n\t\t\t\n\t\t\tif (!IsIconic(console_hwnd)) {\n\t\t\t\tRECT rect;\n\t\t\t\tif (GetWindowRect(console_hwnd, &rect) == TRUE) {\n\t\t\t\t\tcw.append(key_rect, rect);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tvoid switch_load(ConfigReader& cr) {\n\t\t\tcr.regist(key, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, enabled);\n\t\t\t});\n\t\t\tcr.regist(key_escape, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, escape);\n\t\t\t});\n\t\t\tcr.regist(key_input, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, input);\n\t\t\t});\n\t\t\tcr.regist(key_debug_string, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, debug_string);\n\t\t\t});\n\t\t\tcr.regist(key_debug_string_time, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, debug_string_time);\n\t\t\t});\n\t\t}\n\n\t\tvoid switch_store(ConfigWriter& cw) {\n\t\t\tcw.append(key, enabled);\n\t\t\tcw.append(key_escape, escape);\n\t\t\tcw.append(key_input, input);\n\t\t\tcw.append(key_debug_string, debug_string);\n\t\t\tcw.append(key_debug_string_time, debug_string_time);\n\t\t}\n\n\n\t\tbool is_valid() const {\n\t\t\treturn valid;\n\t\t}\n\n\t\t// コンソールの表示 メニューが押されたときに呼ばれる関数\n\t\tvoid menu_console(HMENU aviutl_hmwnu_disp) {\n\t\t\tif (!enabled_i) {\n\t\t\t\tpatch_resource_message_w(PATCH_RS_PATCH_CONSOLE_IS_DIABLED, MB_TOPMOST | MB_ICONINFORMATION);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tbool& console_flag = visible;\n\t\t\tif (GetKeyState(VK_LCONTROL) & 0x8000 | GetKeyState(VK_RCONTROL) & 0x8000) {\n\t\t\t\tconsole_flag = true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tconsole_flag = !console_flag;\n\t\t\t}\n\n\t\t\tmodify_menuitem_check(aviutl_hmwnu_disp, 20002, FALSE, [console_flag](bool state) {\n\t\t\t\treturn console_flag;\n\t\t\t});\n\n\t\t\tupdate_showwindow();\n\t\t}\n\n\t\tDWORD writeConsole(std::string_view str) {\n\t\t\tDWORD written;\n\t\t\tWriteConsoleA(h_stdout, str.data(), str.length(), &written, NULL);\n\t\t\treturn written;\n\t\t}\n\n\t\tvoid setConsoleTextAttribute(WORD wAttributes) {\n\t\t\tSetConsoleTextAttribute(h_stdout, wAttributes);\n\t\t}\n\n\t\tvoid showWindow(int nCmdShow) {\n\t\t\tShowWindow(console_hwnd, nCmdShow);\n\t\t}\n\n\t\t// コンソールウィンドウを前面に移動させる\n\t\tvoid front() const {\n\t\t\tSetWindowPos(console_hwnd, HWND_NOTOPMOST, NULL, NULL, NULL, NULL, SWP_NOSIZE | SWP_NOMOVE);\n\t\t}\n\n\t\tvoid update_visible_state(HMENU aviutl_hmwnu_disp) {\n\t\t\tmodify_menuitem_check(aviutl_hmwnu_disp, 20002, FALSE, [this](bool state) -> bool {\n\t\t\t\tif (input) {\n\t\t\t\t\tvisible = !IsIconic(console_hwnd);\n\t\t\t\t}\n\t\t\t\treturn visible;\n\t\t\t});\n\t\t}\n\n\t\tvoid console_get_setting_rect(std::optional<RECT>& rect) const {\n\t\t\tif (!IsIconic(console_hwnd)) {\n\t\t\t\trect = RECT{};\n\t\t\t\tif (GetWindowRect(console_hwnd, &rect.value()) == FALSE) rect = std::nullopt;\n\t\t\t}\n\t\t}\n\n\t\tvoid update_showwindow() {\n\t\t\tbool& console_flag = visible;\n\t\t\tif (input) {\n\t\t\t\tif (console_flag) {\n\t\t\t\t\tshowWindow(SW_RESTORE);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tconsole_get_setting_rect(rect);\n\t\t\t\t\tshowWindow(SW_MINIMIZE);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (console_flag) {\n\t\t\t\t\tshowWindow(SW_RESTORE);\n\t\t\t\t\tshowWindow(SW_SHOW);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tshowWindow(SW_HIDE);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t} console;\n} // namespace patch\n\n\n#endif // ifdef PATCH_SWITCH_CONSOLE\n"
  },
  {
    "path": "patch/patch_copybuffer_smem.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_LUA_COPYBUFFER_SMEM\n\n#include <string>\n#include <string_view>\n#include <memory>\n#include <map>\n#include <unordered_map>\n#include <algorithm>\n#include <variant>\n#include <optional>\n#include <compare>\n\n#include <aviutl.hpp>\n#include <exedit.hpp>\n\n#include \"mylua.hpp\"\n\nnamespace patch {\n\tusing namespace std::literals::string_literals;\n\n\t// init at exedit load\n\t// obj.copybufferによるキャッシュを共有メモリに確保する\n\tinline struct copybuffer_smem_t {\n\tprivate:\n\n\t\tstruct YCABuffer {\n\t\t\tint w, h;\n\t\t\tExEdit::PixelYCA buf[];\n\t\t};\n\n\t\tinline static std::unordered_map<std::string, std::unique_ptr<YCABuffer>> smem;\n\n\t\tstruct BufferBasic{};\n\t\tstruct BufferNamed : public BufferBasic {\n\t\t\tstd::string name;\n\t\t};\n\t\tstruct BufferObj : public BufferBasic {};\n\t\tstruct BufferFrm : public BufferBasic {};\n\t\tstruct BufferTmp : public BufferBasic {};\n\t\tstruct BufferCache : public BufferNamed {};\n\t\tstruct BufferImage : public BufferNamed {};\n\t\tusing Buffer = std::variant<std::monostate, BufferObj, BufferFrm, BufferTmp, BufferCache, BufferImage>;\n\n\t\tenum class BufferId {\n\t\t\tObj, Tmp, Frm, Cache, Image,\n\t\t\tInvalid = -1\n\t\t};\n\n\t\tinline static Buffer getBufferIdAll(std::string_view name) {\n\t\t\tif (auto cmp = ::strnicmp(name.data(), \"image:\", 6) <=> 0; cmp < 0) {\n\t\t\t\tif (auto cmp = ::stricmp(name.data(), \"frm\") <=> 0; cmp < 0) {\n\t\t\t\t\tif (auto cmp = ::strnicmp(name.data(), \"cache:\", 6) <=> 0; cmp != 0) return std::monostate{};\n\t\t\t\t\treturn BufferCache{ BufferNamed{ .name = { name.begin() + 6, name.end() } } };\n\t\t\t\t}\n\t\t\t\telse if(cmp == 0){\n\t\t\t\t\t// frm\n\t\t\t\t\treturn BufferFrm{};\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if(cmp == 0) {\n\t\t\t\t// image:\n\t\t\t\treturn BufferImage{ BufferNamed{ .name = { name.begin() + 6, name.end() } } };\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (auto cmp = ::stricmp(name.data(), \"obj\") <=> 0; cmp == 0) {\n\t\t\t\t\t// obj\n\t\t\t\t\treturn BufferObj{};\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// tmp\n\t\t\t\t\tif (auto cmp = ::stricmp(name.data(), \"tmp\") <=> 0; cmp != 0) return std::monostate{};\n\t\t\t\t\treturn BufferTmp{}; \n\t\t\t\t}\n\t\t\t}\n\t\t\treturn std::monostate{};\n\t\t}\n\n\t\tinline static Buffer getBufferIdDst(std::string_view name) {\n\t\t\tif (auto cmp = ::stricmp(name.data(), \"obj\") <=> 0; cmp < 0) {\n\t\t\t\t// cache:\n\t\t\t\tif (auto cmp = ::strnicmp(name.data(), \"cache:\", 6) <=> 0; cmp != 0) return std::monostate{};\n\t\t\t\treturn BufferCache{ BufferNamed{ .name = { name.begin() + 6, name.end() } } };\n\t\t\t}\n\t\t\telse if(cmp == 0) {\n\t\t\t\t// obj:\n\t\t\t\treturn BufferObj{};\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// tmp\n\t\t\t\tif (auto cmp = ::stricmp(name.data(), \"tmp\") <=> 0; cmp != 0) return std::monostate{};\n\t\t\t\treturn BufferTmp{};\n\t\t\t}\n\t\t\treturn std::monostate{};\n\t\t}\n\n\t\tstatic Buffer getBufferIdFromReadonly(std::string_view name) {\n\t\t\tif (auto cmp = ::stricmp(name.data(), \"obj\") <=> 0; cmp == 0) {\n\t\t\t\t// obj:\n\t\t\t\treturn BufferObj{};\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// tmp\n\t\t\t\tif (auto cmp = ::stricmp(name.data(), \"tmp\") <=> 0; cmp != 0) return std::monostate{};\n\t\t\t\treturn BufferTmp{};\n\t\t\t}\n\t\t\treturn std::monostate{};\n\t\t}\n\n\t\tstruct VisitorSrc {\n\t\t\tstd::string_view dst_name;\n\t\t\tbool operator()(std::monostate) { return false; }\n\t\t\tbool operator()(BufferObj) {\n\t\t\t\tauto dst = getBufferIdDst(dst_name);\n\t\t\t\tif(std::holds_alternative<std::monostate>(dst)) return false;\n\t\t\t\tif(std::holds_alternative<BufferObj>(dst)) return true;\n\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tbool operator()(BufferTmp) {\n\t\t\t\tauto dst = getBufferIdDst(dst_name);\n\t\t\t\tif(std::holds_alternative<std::monostate>(dst)) return false;\n\t\t\t\tif(std::holds_alternative<BufferTmp>(dst)) return true;\n\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tbool operator()(BufferFrm) {\n\t\t\t\tauto dst = getBufferIdFromReadonly(dst_name);\n\t\t\t\tif(std::holds_alternative<std::monostate>(dst)) return false;\n\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tbool operator()(BufferCache src) {\n\t\t\t\tif(src.name.empty()) return false;\n\t\t\t\tauto dst = getBufferIdDst(dst_name);\n\t\t\t\tif(std::holds_alternative<std::monostate>(dst)) return false;\n\t\t\t\tif(std::holds_alternative<BufferCache>(dst)) {\n\t\t\t\t\treturn std::get<BufferCache>(dst).name == src.name;\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tbool operator()(BufferImage src) {\n\t\t\t\tif(src.name.empty()) return false;\n\t\t\t\tauto dst = getBufferIdFromReadonly(dst_name);\n\t\t\t\tif(std::holds_alternative<std::monostate>(dst)) return false;\n\t\t\t\t\n\t\t\t\treturn true;\n\t\t\t}\n\t\t};\n\n\t\tstatic int copybuffer_override(lua_State* L) {\n\t\t\tauto src = getBufferIdAll(lua_tostring(L, 2));\n\n\t\t\tlua_pushboolean(L, std::visit(VisitorSrc{lua_tostring(L, 1)}, src));\n\n\t\t\treturn 1;\n\t\t}\n\n\tpublic:\n\t\tvoid operator()() {\n\n\t\t}\n\t} copybuffer_smem;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_LUA_COPYBUFFER_SMEM\n"
  },
  {
    "path": "patch/patch_dialog_new_file.hpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_DIALOG_NEW_FILE\r\n\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"util.hpp\"\r\n\r\nnamespace patch {\r\n\r\n    // init at exedit load\r\n    // 新規プロジェクト作成ダイアログの画像サイズ入力欄の幅を上げる\r\n    inline class dlg_newfile_t {\r\n        bool enabled = true;\r\n        bool enabled_i;\r\n        inline static const char key[] = \"new_project_editbox\";\r\n    public:\r\n        void init() {\r\n            enabled_i = enabled;\r\n\r\n            if (!enabled_i)return;\r\n\r\n\r\n            {\r\n                DLGITEMTEMPLATE* width_edit= (DLGITEMTEMPLATE*)(GLOBAL::exedit_base + 0x252d88);\r\n                OverWriteOnProtectHelper h((int)width_edit, sizeof(DLGITEMTEMPLATE));\r\n                width_edit->x = 51; // original = 60\r\n                width_edit->cx = 27; // original = 20\r\n            }\r\n            {\r\n                DLGITEMTEMPLATE* times_static = (DLGITEMTEMPLATE*)(GLOBAL::exedit_base + 0x252da4);\r\n                OverWriteOnProtectHelper h((int)times_static, sizeof(DLGITEMTEMPLATE));\r\n                times_static->x = 78; // original = 81\r\n            }\r\n            {\r\n                DLGITEMTEMPLATE* height_edit = (DLGITEMTEMPLATE*)(GLOBAL::exedit_base + 0x252dc0);\r\n                OverWriteOnProtectHelper h((int)height_edit, sizeof(DLGITEMTEMPLATE));\r\n                height_edit->x = 85; // original = 89\r\n                height_edit->cx = 27; // original = 20\r\n            }\r\n\r\n\r\n        }\r\n\r\n        void switching(bool flag) {\r\n            enabled = flag;\r\n        }\r\n\r\n        bool is_enabled() { return enabled; }\r\n        bool is_enabled_i() { return enabled_i; }\r\n\r\n        void switch_load(ConfigReader& cr) {\r\n            cr.regist(key, [this](json_value_s* value) {\r\n                ConfigReader::load_variable(value, enabled);\r\n                });\r\n        }\r\n\r\n        void switch_store(ConfigWriter& cw) {\r\n            cw.append(key, enabled);\r\n        }\r\n    } dialog_new_file;\r\n} // namespace patch\r\n\r\n#endif // ifdef PATCH_SWITCH_DIALOG_NEW_FILE\r\n"
  },
  {
    "path": "patch/patch_exception_history.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include <cstdint>\n#include <unordered_map>\n#include <chrono>\n#include <mutex>\n\nnamespace patch {\n    // ExceptionHistory の要素型\n    // オフセットアドレスと例外コード\n    struct ExceptionHistoryEntry {\n        uint32_t address;\n        uint32_t code;\n        struct Hash {\n            using result_type = uint32_t;\n\n            result_type operator()(const ExceptionHistoryEntry& history) const {\n                return history.address ^ history.code;\n            }\n        };\n\n        bool operator==(const ExceptionHistoryEntry& x) const {\n            return this->address == x.address && this->code == x.code;\n        }\n    };\n\n    // しばらく同種のメッセージの表示を停止する のためのもの\n    // 過去に出た例外のコードとオフセットアドレスを連想配列に記憶する\n    inline struct ExceptionHistory {\n        std::mutex mtx;\n        std::unordered_map<ExceptionHistoryEntry, std::chrono::system_clock::time_point, ExceptionHistoryEntry::Hash> map;\n\n        // 過去10分以内に出たことのある例外ならtrueを返す\n        [[nodiscard]] bool check(const ExceptionHistoryEntry& key) {\n            using namespace std::chrono_literals;\n            \n            std::lock_guard lock(mtx);\n\n            if (auto itr = map.find(key); itr != map.end()) {\n                if (std::chrono::system_clock::now() - itr->second < std::chrono::system_clock::duration(10min)) {\n                    return true;\n                }\n                map.erase(itr);\n            }\n            return false;\n        }\n    } exception_history;\n} // namespace patch\n"
  },
  {
    "path": "patch/patch_exception_log.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_exception_log.hpp\"\n\n#include \"patch_exception_history.hpp\"\n#include \"moduledata.hpp\"\n#include \"util_resource.hpp\"\n\n#ifdef PATCH_SWITCH_EXCEPTION_LOG\nnamespace patch {\n\n\tBOOL __stdcall exception_log_t::override_exception_catch(EXCEPTION_POINTERS* pExp, const char* plugin_name, const char* func_name) {\n\t\t// [esp - 128, esp + 256)\n\t\tuint32_t stack[96];\n\t\t{\n\t\t\tOverWriteOnProtectHelper h(pExp->ContextRecord->Esp - 128, 384);\n\t\t\tfor (int i = 0; i < 96; i++) {\n\t\t\t\tstack[95 - i] = load_i32<uint32_t>(pExp->ContextRecord->Esp - i * 4 + 252);\n\t\t\t}\n\t\t}\n\n\t\tauto [log_name_a, log_name_w] = get_log_name();\n\t\t\n\t\tstd::unique_lock lock(ModulesData::mtx);\n\t\tModulesData::update();\n\t\tauto& modulesdata = ModulesData::get();\n\t\tlock.unlock();\n\t\t\n\n\t\tauto detail = format_detail(pExp, plugin_name, func_name, modulesdata);\n\t\twrite_logfile(log_name_w, detail, pExp, modulesdata, stack);\n\n\t\ttry {\n\t\t\twindow_gate.wait();\n\n\t\t\tif (exception_history.check({\n\t\t\t\t.address = reinterpret_cast<uint32_t>(pExp->ExceptionRecord->ExceptionAddress),\n\t\t\t\t.code = static_cast<uint32_t>(pExp->ExceptionRecord->ExceptionCode)\n\t\t\t})) return TRUE;\n\n \t\t\texception_log_dialog_window_t::Param param = {\n\t\t\t\t.link = L\"<a>log/{}</a>\"_fmt(log_name_w),\n\t\t\t\t.info_dir = log_dir,\n\t\t\t\t.info_path = log_name_w,\n\t\t\t\t.detail = detail,\n\t\t\t\t.pExp = pExp\n\t\t\t};\n\t\t\texception_log_dialog_window_t window(&param);\n\t\t\t\n\t\t\twindow_gate.open();\n\t\t}\n\t\tcatch (const std::runtime_error& e) {\n\t\t\tpatch_resource_message_a(\n\t\t\t\tPATCH_RS_PATCH_FAILED_TO_CREATE_EXCEPTION_DIALOG, MB_ICONERROR | MB_TASKMODAL,\n\t\t\t\te.what(),\n\t\t\t\tlog_name_a,\n\t\t\t\tdetail\n\t\t\t);\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_EXCEPTION_LOG\n"
  },
  {
    "path": "patch/patch_exception_log.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_EXCEPTION_LOG\n\n#include <unordered_map>\n#include <sstream>\n#include <fstream>\n#include <string>\n#include <format>\n#include <variant>\n\n#include <Windows.h>\n\n#include <TlHelp32.h>\n\n#include <Shlwapi.h>\n#pragma comment(lib, \"shlwapi.lib\")\n\n#include <boost/scope_exit.hpp>\n\n#include <winwrap.hpp>\n\n#include \"global.hpp\"\n#include \"util.hpp\"\n#include \"resource.h\"\n#include \"hash.hpp\"\n#include \"moduledata.hpp\"\n#include \"gate.hpp\"\n\n#include \"patch_exception_log_dialog.hpp\"\n\nnamespace patch {\n\t// init at dllload\n\tinline class exception_log_t {\n#define exception_code_name_macro(name) { name, #name }\n\t\t// 例外コードを文字列にするための連想配列\n\t\tstatic inline const std::unordered_map<DWORD, std::string_view> exception_code_name{\n\t\t\texception_code_name_macro(STILL_ACTIVE),\n\t\t\texception_code_name_macro(EXCEPTION_GUARD_PAGE),\n\t\t\texception_code_name_macro(EXCEPTION_DATATYPE_MISALIGNMENT),\n\t\t\texception_code_name_macro(EXCEPTION_BREAKPOINT),\n\t\t\texception_code_name_macro(EXCEPTION_SINGLE_STEP),\n\t\t\texception_code_name_macro(EXCEPTION_ACCESS_VIOLATION),\n\t\t\texception_code_name_macro(EXCEPTION_IN_PAGE_ERROR),\n\t\t\texception_code_name_macro(EXCEPTION_INVALID_HANDLE),\n\t\t\texception_code_name_macro(EXCEPTION_ILLEGAL_INSTRUCTION),\n\t\t\texception_code_name_macro(EXCEPTION_NONCONTINUABLE_EXCEPTION),\n\t\t\texception_code_name_macro(EXCEPTION_INVALID_DISPOSITION),\n\t\t\texception_code_name_macro(EXCEPTION_ARRAY_BOUNDS_EXCEEDED),\n\t\t\texception_code_name_macro(EXCEPTION_FLT_DENORMAL_OPERAND),\n\t\t\texception_code_name_macro(EXCEPTION_FLT_DIVIDE_BY_ZERO),\n\t\t\texception_code_name_macro(EXCEPTION_FLT_INEXACT_RESULT),\n\t\t\texception_code_name_macro(EXCEPTION_FLT_INVALID_OPERATION),\n\t\t\texception_code_name_macro(EXCEPTION_FLT_OVERFLOW),\n\t\t\texception_code_name_macro(EXCEPTION_FLT_STACK_CHECK),\n\t\t\texception_code_name_macro(EXCEPTION_FLT_UNDERFLOW),\n\t\t\texception_code_name_macro(EXCEPTION_INT_DIVIDE_BY_ZERO),\n\t\t\texception_code_name_macro(EXCEPTION_INT_OVERFLOW),\n\t\t\texception_code_name_macro(EXCEPTION_PRIV_INSTRUCTION),\n\t\t\texception_code_name_macro(EXCEPTION_STACK_OVERFLOW),\n\t\t\texception_code_name_macro(CONTROL_C_EXIT),\n\t\t\t{ 0xe0434352L, \"* .Net exception\" },\n\t\t\t{ 0xc06d007eL, \"* DLL delay load failed\" },\n\t\t\t{ 0xe06d7363L, \"* C++ exception\" },\n\t\t\t{ 0x80000100L, \"* Unimplemented function\" },\n\t\t};\n#undef exception_code_name_macro\n\n\t\t// 例外コードごとに何か特別なフォーマットをしたいとき用の関数を置く連想配列\n\t\tstatic inline const std::unordered_map<DWORD, std::string(*)(PEXCEPTION_RECORD)> exception_format{\n\t\t\t{ EXCEPTION_ACCESS_VIOLATION, [](PEXCEPTION_RECORD erp){\n\t\t\t\treturn \"read/write : {}\\r\\naccessed address : 0x{:08x}\\r\\n\"_fmt(\n\t\t\t\t\terp->ExceptionInformation[0],\n\t\t\t\t\terp->ExceptionInformation[1]\n\t\t\t\t);\n\t\t\t}},\n\t\t\t{ EXCEPTION_IN_PAGE_ERROR, [](PEXCEPTION_RECORD erp) {\n\t\t\t\treturn \"read/write : {}\\r\\naccessed address : 0x{:08x}\\r\\nNTSTATUS : {:08x}\\r\\n\"_fmt(\n\t\t\t\t\terp->ExceptionInformation[0],\n\t\t\t\t\terp->ExceptionInformation[1],\n\t\t\t\t\terp->ExceptionInformation[2]\n\t\t\t\t);\n\t\t\t}},\n\t\t\t{ 0xe06d7363L, [](PEXCEPTION_RECORD erp) {\n\t\t\t\tuint32_t d1 = load_i32(erp->ExceptionInformation[2] + 12);\n\t\t\t\tuint32_t d2 = load_i32(d1 + 4);\n\t\t\t\tuint32_t d3 = load_i32(d2 + 4);\n\t\t\t\tauto class_name = reinterpret_cast<const char*>(d3 + 8);\n\t\t\t\tauto exception = erp->ExceptionInformation[1];\n\t\t\t\treturn \"Information[0] : {:08x}\\r\\nclass_name : {}\\r\\nexception ptr : {:08x}\\r\\n\"_fmt(\n\t\t\t\t\terp->ExceptionInformation[0],\n\t\t\t\t\tclass_name,\n\t\t\t\t\texception\n\t\t\t\t);\n\t\t\t}},\n\t\t};\n\t\t\n\t\t// デフォルトの例外コードフォーマット\n\t\tstatic std::string exception_format_default(PEXCEPTION_RECORD erp) {\n\t\t\tstd::ostringstream ss;\n\t\t\tfor(DWORD i = 0; i < erp->NumberParameters; i++){\n\t\t\t\tformat_to_os(ss, \"[{}] : {:08x}\\r\\n\", i, erp->ExceptionInformation[i]);\n\t\t\t}\n\t\t\treturn ss.str();\n\t\t}\n\n\t\tstatic std::string format_eflags(DWORD eflags) {\n\t\t\tstd::ostringstream ss;\n\t\t\tss << \"(\";\n\t\t\tint c = 0;\n\t\t\t#define def(shift, name) if (eflags & (1 << shift)) { if(c++) ss << \"|\"; ss << #name; }\n\t\t\tdef(0, CF);\n\t\t\tdef(2, PF);\n\t\t\tdef(4, AF);\n\t\t\tdef(6, ZF);\n\t\t\tdef(7, SF);\n\t\t\tdef(8, TF);\n\t\t\tdef(9, IF);\n\t\t\tdef(10, DF);\n\t\t\tdef(11, OF);\n\t\t\t#undef def\n\t\t\tif(c++) ss << \"|\"; ss << \"IOPL\" << ((eflags >> 12) & 0b11);\n\t\t\t#define def(shift, name) if (eflags & (1 << shift)) {  ss << \"|\" << #name; }\n\t\t\tdef(14, NT);\n\t\t\tdef(16, RF);\n\t\t\tdef(17, VM);\n\t\t\tdef(18, AC);\n\t\t\tdef(19, VIF);\n\t\t\tdef(20, VIP);\n\t\t\tdef(21, ID);\n\t\t\t#undef def\n\t\t\tss << \")\";\n\t\t\treturn ss.str();\n\t\t}\n\n\t\tstatic std::string format_registers(PCONTEXT cp) {\n\t\t\tstd::ostringstream ss;\n\t\t\tss << \"registers\\r\\n\";\n\t\t\t\n\t\t\tformat_to_os(ss, \"{} : {:08x}\\r\\n\", \"eax\", cp->Eax);\n\t\t\tformat_to_os(ss, \"{} : {:08x}\\r\\n\", \"ecx\", cp->Ecx);\n\t\t\tformat_to_os(ss, \"{} : {:08x}\\r\\n\", \"edx\", cp->Edx);\n\t\t\tformat_to_os(ss, \"{} : {:08x}\\r\\n\", \"ebx\", cp->Ebx);\n\t\t\tformat_to_os(ss, \"{} : {:08x}\\r\\n\", \"esi\", cp->Esi);\n\t\t\tformat_to_os(ss, \"{} : {:08x}\\r\\n\", \"edi\", cp->Edi);\n\n\t\t\tformat_to_os(ss, \"{} : {:08x}\\r\\n\", \"ebp\", cp->Ebp);\n\t\t\tformat_to_os(ss, \"{} : {:08x}\\r\\n\", \"esp\", cp->Esp);\n\t\t\tformat_to_os(ss, \"{} : {:08x}\\r\\n\", \"eip\", cp->Eip);\n\n\t\t\tformat_to_os(ss, \"{} : {:08x} {}\\r\\n\", \"flag\", cp->EFlags, format_eflags(cp->EFlags));\n\n\n\t\t\tformat_to_os(ss, \"{} : {:08x}\\r\\n\", \"cs\", cp->SegCs);\n\t\t\tformat_to_os(ss, \"{} : {:08x}\\r\\n\", \"ds\", cp->SegDs);\n\t\t\tformat_to_os(ss, \"{} : {:08x}\\r\\n\", \"ss\", cp->SegSs);\n\t\t\tformat_to_os(ss, \"{} : {:08x}\\r\\n\", \"es\", cp->SegEs);\n\t\t\tformat_to_os(ss, \"{} : {:08x}\\r\\n\", \"fs\", cp->SegFs);\n\t\t\tformat_to_os(ss, \"{} : {:08x}\\r\\n\", \"gs\", cp->SegGs);\n\t\t\t\n\t\t\tss << \"extend : \";\n\t\t\tfor(size_t i = 0; i < sizeof(cp->ExtendedRegisters); i++){\n\t\t\t\tformat_to_os(ss, \"{:08x}\", cp->ExtendedRegisters[i]);\n\t\t\t}\n\t\t\tss << '\\n' << '\\n';\n\n\t\t\treturn ss.str();\n\t\t}\n\n\t\tstatic std::tuple<std::string, DWORD> get_module_address(void* address, const std::vector<ModulesDataEntry>& data) {\n\t\t\tauto addr = reinterpret_cast<uintptr_t>(address);\n\t\t\tModulesDataEntry d{0u,addr,\"\"};\n\t\t\tauto itr = std::lower_bound(data.begin(),data.end(),d,[](auto a, auto b){ return a.end < b.end; });\n\t\t\tif(itr!=data.end()){\n\t\t\t\tif(itr->begin <= addr && addr < itr->end) {\n\t\t\t\t\treturn { itr->name, addr - itr->begin };\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { \"\", 0 };\n\t\t}\n\n\t\tstatic inline std::wstring log_dir;\n\n\t\tstatic auto get_log_name() {\n\t\t\tauto tid = GetCurrentThreadId();\n\t\t\tSYSTEMTIME st;\n\t\t\tGetLocalTime(&st);\n\t\t\treturn std::make_tuple(\n\t\t\t\t\"{:04}-{:02}-{:02}_{:02}-{:02}-{:02}-{}_{}.txt\"_fmt(\n\t\t\t\t\tst.wYear, st.wMonth,  st.wDay,\n\t\t\t\t\tst.wHour, st.wMinute, st.wSecond, st.wMilliseconds,\n\t\t\t\t\ttid\n\t\t\t\t),\n\t\t\t\tL\"{:04}-{:02}-{:02}_{:02}-{:02}-{:02}-{}_{}.txt\"_fmt(\n\t\t\t\t\tst.wYear, st.wMonth, st.wDay,\n\t\t\t\t\tst.wHour, st.wMinute, st.wSecond, st.wMilliseconds,\n\t\t\t\t\ttid\n\t\t\t\t)\n\t\t\t);\n\t\t}\n\n\t\tinline static std::string format_detail(EXCEPTION_POINTERS* pExp, const char* plugin_name, const char* func_name, const std::vector<ModulesDataEntry>& data) {\n\t\t\tconst auto code = pExp->ExceptionRecord->ExceptionCode;\n\t\t\tstd::ostringstream ss;\n\t\t\tss << \"code : \";\n\t\t\tif(auto itr = exception_code_name.find(code); itr != exception_code_name.end()) {\n\t\t\t\tformat_to_os(ss, \"{} (0x{:08x})\\r\\n\", itr->second, code);\n\t\t\t}else{\n\t\t\t\tformat_to_os(ss, \"unknown (0x{:08x})\\r\\n\", code);\n\t\t\t}\n\t\t\tformat_to_os(ss, \"address : 0x{:08x}\", reinterpret_cast<uintptr_t>(pExp->ExceptionRecord->ExceptionAddress));\n\t\t\tif (data.size()) {\n\t\t\t\tauto [modname, offset] = get_module_address(pExp->ExceptionRecord->ExceptionAddress, data);\n\t\t\t\tif(modname.size()) format_to_os(ss, \" ({} + 0x{:08x})\", modname, offset);\n\t\t\t}\n\t\t\tss << \"\\r\\n\";\n\t\t\tformat_to_os(ss, \"plugin_name : {}\\r\\n\", plugin_name);\n\t\t\tformat_to_os(ss, \"func_name : {}\\r\\n\", func_name);\n\n\t\t\tif (auto itr = exception_format.find(code); itr != exception_format.end()) {\n\t\t\t\tss << itr->second(pExp->ExceptionRecord);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tss << exception_format_default(pExp->ExceptionRecord);\n\t\t\t}\n\t\t\treturn ss.str();\n\t\t}\n\n\t\tinline static std::string format_stack(uint32_t start, uint8_t* stack, uint32_t length) {\n\t\t\tauto esp_mod16 = start & 0xf;\n\n\t\t\tstd::ostringstream ss;\n\n\t\t\tss << \"stack\\r\\n\";\n\n\t\t\tauto esp = start & ~0xf;\n\t\t\tif (esp_mod16) {\n\t\t\t\tformat_to_os(ss, \"{:08x} \", esp);\n\t\t\t\tfor (uint32_t i = 0; i < esp_mod16 * 2; i++) ss << ' ';\n\t\t\t\tfor (uint32_t i = 0; i < 16 - esp_mod16; i++) {\n\t\t\t\t\tformat_to_os(ss, \"{:02x}\", stack[i]);\n\t\t\t\t}\n\t\t\t\tss << \"\\r\\n\";\n\t\t\t\tesp += 16;\n\t\t\t}\n\t\t\tfor (uint32_t i = 0; i < (length - esp_mod16) / 16; i++) {\n\t\t\t\tformat_to_os(ss, \"{:08x} \", esp);\n\t\t\t\tfor (int j = 0; j < 16; j++) format_to_os(ss, \"{:02x}\", stack[i * 16 + j + esp_mod16]);\n\t\t\t\tss << \"\\r\\n\";\n\t\t\t\tesp += 16;\n\t\t\t}\n\t\t\t\n\t\t\tif (esp_mod16) {\n\t\t\t\tformat_to_os(ss, \"{:08x} \", esp);\n\t\t\t\tfor (uint32_t i = length - esp_mod16; i < length; i++) {\n\t\t\t\t\tformat_to_os(ss, \"{:02x}\", stack[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tss << \"\\r\\n\";\n\n\t\t\treturn ss.str();\n\t\t}\n\n\t\ttemplate<size_t N>\n\t\tstatic bool write_logfile(std::wstring& filename, std::string_view detail, EXCEPTION_POINTERS* pExp, const std::vector<ModulesDataEntry>& data, const uint32_t (&stack)[N]) {\n\t\t\tif(!PathFileExistsW(log_dir.c_str())) {\n\t\t\t\tif(!CreateDirectoryW(log_dir.c_str(), NULL)){\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tauto filepath = log_dir + filename;\n\t\t\tauto hfile = CreateFileW(filepath.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);\n\t\t\tif(hfile == INVALID_HANDLE_VALUE) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tconst auto code = pExp->ExceptionRecord->ExceptionCode;\n\n\t\t\tstd::ostringstream ss;\n\t\t\tss << \"patch.aul (\" PATCH_VERSION_STR \") debug info file\\r\\n\\r\\n\";\n\n\t\t\tss << detail;\n\t\t\t\n\t\t\tss << \"\\r\\n\";\n\n\t\t\tss << \"modules\\r\\n\";\n\t\t\tif (data.size()) {\n\t\t\t\tfor(const auto& d : data) {\n\t\t\t\t\tif (d.hash.has_value()) {\n\t\t\t\t\t\tformat_to_os(ss, \"{:08x}-{:08x}:{} ({})\\r\\n\", d.begin, d.end, d.name, d.hash->tostring());\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tformat_to_os(ss, \"{:08x}-{:08x}:{}\\r\\n\", d.begin, d.end, d.name);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tss << \"(Failed to get modules info)\\r\\n\";\n\t\t\t}\n\t\t\tss << \"\\r\\n\";\n\n\t\t\tss << format_registers(pExp->ContextRecord);\n\t\t\tss << \"\\r\\n\";\n\n\n\t\t\tss << format_stack(pExp->ContextRecord->Esp - 128, (uint8_t*)&stack, N * 4);\n\t\t\tss << \"\\r\\n\";\n\n\n\t\t\tauto str = ss.str();\n\t\t\tDWORD written;\n\t\t\tWriteFile(hfile, str.c_str(), str.size(), &written, NULL);\n\n\t\t\tCloseHandle(hfile);\n\t\t\treturn true;\n\t\t\t\n\t\t\t// todo: ヒープ情報の出力\n\t\t}\n\t\t\n\t\tinline static Gate window_gate{ true };\n\n\t\tstatic BOOL __stdcall override_exception_catch(EXCEPTION_POINTERS* pExp, const char* plugin_name, const char* func_name);\n\t\tinline static const auto exception_catch_ptr = &override_exception_catch;\n\n\t\tinline static bool dialog_init = false;\n\n\tpublic:\n\t\tvoid operator()() {\n\t\t\tlog_dir = WinWrap::Module{}.getFileNameW();\n\t\t\tlog_dir.resize(log_dir.find_last_of(L\"/\\\\\") + 1);\n\t\t\tlog_dir += L\"log\\\\\";\n\n\t\t\tOverWriteOnProtectHelper h(GLOBAL::aviutl_base + 0x5b8b0, 13);\n\t\t\th.store_i32(0, '\\xff\\x74\\x24\\x04'); // push [esp+4]\n\t\t\th.store_i32(4, '\\x52\\x51\\xff\\x15'); // push edx ; push ecx ; call [(i32)]\n\t\t\th.store_i32(8, &exception_catch_ptr);\n\t\t\th.store_i8(12, '\\xc3'); // ret\n\n\t\t\tdialog_init = exception_log_dialog_window_t::init();\n\n\t\t\t//if (!dialog_init)return;\n\n\t\t}\n\t} exception_log;\n} // namespace patch\n\n#endif // ifdef PATCH_SWITCH_EXCEPTION_LOG\n"
  },
  {
    "path": "patch/patch_exception_log_dialog.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#define ISOLATION_AWARE_ENABLED 1\n#include <Windows.h>\n#include \"patch_exception_log_dialog.hpp\"\n\n#ifdef PATCH_SWITCH_EXCEPTION_LOG\n\n#include <optional>\n#include <format>\n\n#include <Shlwapi.h>\n#pragma comment(lib, \"shlwapi.lib\")\n\n#include \"offset_address.hpp\"\n#include \"patch_exception_history.hpp\"\n#include \"util_others.hpp\"\n\nnamespace patch {\n\n    exception_log_dialog_window_t::exception_log_dialog_window_t(const Param* param) {\n        this->param = param;\n        INT_PTR ret;\n        std::thread th([this, &ret] {\n            MessageBeep(MB_ICONEXCLAMATION);\n            auto current_hmod = load_i32<HMODULE>(GLOBAL::aviutl_base + OFS::AviUtl::current_resource_hmod);\n            const auto RT_DIALOG_W = (LPWSTR)(RT_DIALOG);\n            if (FindResourceW(current_hmod, L\"PATCH_DIALOG_EXCEPTION\", RT_DIALOG_W)) \n                ret = IsolationAwareDialogBoxParamW(current_hmod, L\"PATCH_DIALOG_EXCEPTION\", NULL, dialog_proc, (LPARAM)this);\n            else\n                ret = IsolationAwareDialogBoxParamW(GLOBAL::patchaul_hinst, L\"PATCH_DIALOG_EXCEPTION\", NULL, dialog_proc, (LPARAM)this);\n        });\n        if (th.joinable()) {\n            th.join();\n        }\n        else {\n            throw std::runtime_error(\"Failed to start a thread.\");\n        }\n        if (ret == 0 || ret == -1) throw std::runtime_error(\"Failed to create a dialog.\");\n    }\n\n    // 48 144 2 130\n    INT_PTR CALLBACK exception_log_dialog_window_t::dialog_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {\n        auto this_ = reinterpret_cast<exception_log_dialog_window_t*>(GetWindowLong(hwnd, GWL_USERDATA));\n\n        switch (message) {\n            case WM_INITDIALOG: {\n                SetWindowLong(hwnd, GWL_USERDATA, lparam);\n                this_ = reinterpret_cast<exception_log_dialog_window_t*>(lparam);\n\n                this_->hwnd_detail_text = GetDlgItem(hwnd, PATCH_ID_EXCEPTION_DETAIL_TEXT);\n                this_->hwnd_link = GetDlgItem(hwnd, PATCH_ID_EXCEPTION_LINK);\n                this_->hwnd_button_ok = GetDlgItem(hwnd, PATCH_ID_EXCEPTION_OK);\n                this_->hwnd_button_detail = GetDlgItem(hwnd, PATCH_ID_EXCEPTION_DETAIL_BUTTON);\n                this_->hwnd_check_stopmes = GetDlgItem(hwnd, PATCH_ID_EXCEPTION_STOPMES);\n                this_->hwnd_button_save_project = GetDlgItem(hwnd, PATCH_ID_EXCEPTION_SAVE_PROJECT);\n                this_->hwnd_save_text = GetDlgItem(hwnd, PATCH_ID_EXCEPTION_LABEL2);\n\n                RECT rect_detail_text; GetWindowRect(this_->hwnd_detail_text, &rect_detail_text);\n\n                RECT rect_check_stopmes; GetWindowRect(this_->hwnd_check_stopmes, &rect_check_stopmes);\n\n                this_->resize_ofs = rect_check_stopmes.top - rect_detail_text.top;\n\n                SetWindowTextW(this_->hwnd_link, this_->param->link.c_str());\n                if (!this_->detail_showed) {\n                    ShowWindow(this_->hwnd_detail_text, SW_HIDE);\n                    this_->update_window_detail(hwnd, false);\n                }\n                SetWindowTextA(this_->hwnd_detail_text, this_->param->detail.c_str());\n\n                ShowWindow(hwnd, SW_SHOW);\n                SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);\n\n                return TRUE;\n            }\n            case WM_CLOSE:\n                EndDialog(hwnd, 1);\n                return TRUE;\n\n            case WM_COMMAND: switch(LOWORD(wparam)){\n                case PATCH_ID_EXCEPTION_OK:\n                    if(SendMessageA(this_->hwnd_check_stopmes, BM_GETCHECK, 0, 0) == BST_CHECKED) {\n                        auto record = this_->param->pExp->ExceptionRecord;\n                        exception_history.map.insert_or_assign(ExceptionHistoryEntry{\n                            .address = reinterpret_cast<uint32_t>(record->ExceptionAddress),\n                            .code = static_cast<uint32_t>(record->ExceptionCode)\n                        }, std::chrono::system_clock::now());\n                    }\n                \n                    EndDialog(hwnd, 1);\n                    return TRUE;\n\n                case PATCH_ID_EXCEPTION_DETAIL_BUTTON:\n                    if(this_->detail_showed){\n                        this_->update_window_detail(hwnd, false);\n                        this_->detail_showed = false;\n                    }else{\n                        this_->update_window_detail(hwnd, true);\n                        this_->detail_showed = true;\n                    }\n                    return TRUE;\n                case PATCH_ID_EXCEPTION_SAVE_PROJECT: {\n                    save_project(hwnd);\n                }\n                return TRUE;\n            }break;\n\n            case WM_NOTIFY: switch(const auto& nmhdr = *reinterpret_cast<LPNMHDR>(lparam); nmhdr.code) {\n                case NM_CLICK:\n                case NM_RETURN:\n                switch(nmhdr.idFrom){\n                    case PATCH_ID_EXCEPTION_LINK:{\n                        STARTUPINFOW si={.cb=sizeof(STARTUPINFOW)};\n                        PROCESS_INFORMATION pi;\n                        auto commandline = L\"explorer.exe /select,{}{}\"_fmt(this_->param->info_dir, this_->param->info_path);\n                        auto ret = CreateProcessW(NULL, commandline.data(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);\n                        if(ret){\n                            CloseHandle(pi.hProcess);\n                            CloseHandle(pi.hThread);\n                        }\n                        return TRUE;\n                    }\n                }\n                break;\n            }break;\n        }\n        return FALSE;\n    }\n} // namespace patch\n\n#endif // ifdef PATCH_SWITCH_EXCEPTION_LOG\n"
  },
  {
    "path": "patch/patch_exception_log_dialog.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_EXCEPTION_LOG\n\n#include <string>\n#include <unordered_map>\n#include <thread>\n\n#include <Windows.h>\n\n#include <CommCtrl.h>\n#pragma comment(linker,\"/manifestdependency:\\\"type='win32' \\\n  name='Microsoft.Windows.Common-Controls' \\\n  version='6.0.0.0' \\\n  processorArchitecture='x86' \\\n  publicKeyToken='6595b64144ccf1df' \\\n  language='*'\\\"\") \n#pragma comment(lib, \"comctl32.lib\")\n\n#include <aviutl.hpp>\n\n#include \"resource.h\"\n#include \"global.hpp\"\n\nnamespace patch {\n\tclass exception_log_dialog_window_t {\n\tpublic:\n\t\tstruct Param {\n\t\t\tstd::wstring link; // SysLink用のコード文字列\n\t\t\tstd::wstring info_dir; // 表示する文字列\n\t\t\tstd::wstring info_path; // 飛ばすパス\n\t\t\tstd::string detail; // 例外の詳細\n\t\t\tEXCEPTION_POINTERS* pExp;\n\n\t\t\tParam& operator=(const Param& x) {\n\t\t\t\tthis->link = x.link;\n\t\t\t\tthis->info_dir = x.info_dir;\n\t\t\t\tthis->info_path = x.info_path;\n\t\t\t\tthis->detail = x.detail;\n\t\t\t\tthis->pExp = x.pExp;\n\n\t\t\t\treturn *this;\n\t\t\t}\n\t\t};\n\n\t\t// ウィンドウを生成する\n\t\texception_log_dialog_window_t(const Param* param);\n\n\t\t// コモンコントロール初期化など\n\t\tstatic bool init() {\n\t\t\tINITCOMMONCONTROLSEX icc{\n\t\t\t\t.dwSize = sizeof(INITCOMMONCONTROLSEX),\n\t\t\t\t.dwICC = ICC_LINK_CLASS\n\t\t\t};\n\t\t\treturn InitCommonControlsEx(&icc);\n\t\t}\n\n\tprivate:\n\t\tHWND hwnd;\n\n\t\tbool detail_showed;\n\t\tHWND hwnd_detail_text;\n\t\tHWND hwnd_save_text;\n\t\tHWND hwnd_link;\n\t\tHWND hwnd_button_ok;\n\t\tHWND hwnd_button_detail;\n\t\tHWND hwnd_check_stopmes;\n\t\tHWND hwnd_button_save_project;\n\t\tDWORD resize_ofs;\n\t\tconst Param* param;\n\n\t\tvoid update_window_detail(HWND hwnd, bool flag) {\n\t\t\tShowWindow(hwnd_detail_text, flag ? SW_SHOW : SW_HIDE);\n\n\t\t\tint ofs = flag ? static_cast<int>(resize_ofs) : -static_cast<int>(resize_ofs);\n\n\t\t\tRECT rect;\n\t\t\tPOINT point;\n\t\t\tGetWindowRect(hwnd, &rect);\n\t\t\tSetWindowPos(hwnd, NULL, 0, 0, rect.right - rect.left, rect.bottom - rect.top + ofs, SWP_NOMOVE | SWP_NOZORDER);\n\n\t\t\tGetWindowRect(hwnd_button_ok, &rect);\n\t\t\tpoint = { rect.left, static_cast<LONG>(rect.top + ofs) };\n\t\t\tScreenToClient(hwnd, &point);\n\t\t\tSetWindowPos(hwnd_button_ok, NULL, point.x, point.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);\n\n\t\t\tGetWindowRect(hwnd_button_detail, &rect);\n\t\t\tpoint = { rect.left, static_cast<LONG>(rect.top + ofs) };\n\t\t\tScreenToClient(hwnd, &point);\n\t\t\tSetWindowPos(hwnd_button_detail, NULL, point.x, point.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);\n\n\t\t\tGetWindowRect(hwnd_check_stopmes, &rect);\n\t\t\tpoint = { rect.left, static_cast<LONG>(rect.top + ofs) };\n\t\t\tScreenToClient(hwnd, &point);\n\t\t\tSetWindowPos(hwnd_check_stopmes, NULL, point.x, point.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);\n\n\t\t\tGetWindowRect(hwnd_button_save_project, &rect);\n\t\t\tpoint = { rect.left, static_cast<LONG>(rect.top + ofs) };\n\t\t\tScreenToClient(hwnd, &point);\n\t\t\tSetWindowPos(hwnd_button_save_project, NULL, point.x, point.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);\n\n\t\t\tGetWindowRect(hwnd_save_text, &rect);\n\t\t\tpoint = { rect.left, static_cast<LONG>(rect.top + ofs) };\n\t\t\tScreenToClient(hwnd, &point);\n\t\t\tSetWindowPos(hwnd_save_text, NULL, point.x, point.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);\n\t\t};\n\n\tprivate:\n\t\tconstexpr static UINT UPDATE_PARAM = WM_APP + 1;\n\n\t\tstatic INT_PTR CALLBACK dialog_proc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);\n\n\t};\n\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_EXCEPTION_LOG\n"
  },
  {
    "path": "patch/patch_exeditwindow_sizing.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_EXEDITWINDOW_SIZING\n#include <Windows.h>\n\n#include \"global.hpp\"\n#include \"util_magic.hpp\"\n\n#include \"config_rw.hpp\"\n\nnamespace patch {\n\t// call at v_func_WncProc WM_SIZING\n\t// 拡張編集ウィンドウの上部を正常にドラッグできるようにする\n\tinline class exeditwindow_sizing_t {\n\n\t\tbool enabled = true;\n\t\tinline static const char key[] = \"exeditwindow_sizing\";\n\n\tpublic:\n\t\tBOOL wndproc(WPARAM wparam, LPARAM lparam) {\n\t\t\tif (!enabled) return -1;\n\n\t\t\tauto LayerHeightState = load_i32<int>(GLOBAL::exedit_base + 0x0a3e20);\n\t\t\tauto DAT_101a530c = load_i32<int>(GLOBAL::exedit_base + 0x1a530c);\n\n\t\t\tauto rect = (RECT*)lparam;\n\t\t\tif (rect->right < rect->left + 128) rect->right = rect->left + 128;\n\n\t\t\tauto top = rect->top;\n\t\t\tauto layer_count = (rect->bottom - rect->top - DAT_101a530c + LayerHeightState / 2) / LayerHeightState;\n\n\t\t\tbool is_top;\n\t\t\tswitch (wparam) {\n\t\t\t\tcase WMSZ_TOP:\n\t\t\t\tcase WMSZ_TOPLEFT:\n\t\t\t\tcase WMSZ_TOPRIGHT:\n\t\t\t\t\tis_top = true;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tis_top = false;\n\t\t\t}\n\n\t\t\tif (layer_count < 1) layer_count = 1;\n\t\t\telse if (100 < layer_count) layer_count = 100;\n\n\t\t\tif (is_top) {\n\t\t\t\trect->top = rect->bottom - (DAT_101a530c + LayerHeightState * layer_count);\n\t\t\t}\n\t\t\telse {\n\t\t\t\trect->bottom = rect->top + DAT_101a530c + LayerHeightState * layer_count;\n\t\t\t}\n\t\t\treturn 0;\n\t\t}\n\n\t\tvoid switching(bool flag) {\n\t\t\tenabled = flag;\n\t\t}\n\n\t\tbool is_enabled() { return enabled; }\n\t\tbool is_enabled_i() { return enabled; }\n\n\t\tvoid switch_load(ConfigReader& cr) {\n\t\t\tcr.regist(key, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, enabled);\n\t\t\t});\n\t\t}\n\n\t\tvoid switch_store(ConfigWriter& cw) {\n\t\t\tcw.append(key, enabled);\n\t\t}\n\t} exeditwindow_sizing;\n\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_EXEDITWINDOW_SIZING\n"
  },
  {
    "path": "patch/patch_exo_aviutlfilter.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n\n#ifdef PATCH_SWITCH_EXO_AVIUTL_FILTER\n#include <memory>\n\n#include <exedit.hpp>\n\n#include \"global.hpp\"\n#include \"offset_address.hpp\"\n#include \"util.hpp\"\n\n#include \"restorable_patch.hpp\"\n#include \"config_rw.hpp\"\n\nnamespace patch {\n\n\t// init at exedit load\n\t// 拡張編集以外のフィルタを使ったフィルタオブジェクトを正常にオブジェクトファイルに出力できない\n\tinline class exo_aviutlfilter_t {\n\n\t\tbool enabled = true;\n\t\tinline static const char key[] = \"exo_aviutlfilter\";\n\n\t\tstd::optional<restorable_patch> rp1;\n\t\tstd::optional<restorable_patch> rp2;\n\t\tstd::optional<restorable_patch> rp3;\n\n\tpublic:\n\t\tvoid init() {\n\t\t\t\n\t\t\tif (!enabled)return;\n\n\t\t\tauto& cursor = GLOBAL::executable_memory_cursor;\n\n\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::ConvertFilter2Exo_TrackScaleJudge_RangeBegin, 30);\n\t\t\t/*\n\t\t\t\t10028a84 MOV EAX, DWORD PTR [ESI + CCH] ; filter_param_ptr->track_scale\n\t\t\t\t↓\n\n\t\t\t\t10028a84 NOP\n\t\t\t\t10028a85 CALL func\n\n\t\t\t\tfunc\t MOV AL, BYTE PTR [ESI + 3H]\n\t\t\t\t\t\t TEST AL, 04H\n\t\t\t\t\t\t JNZ SKIP, 03H\n\t\t\t\t\t\t XOR EAX, EAX\n\t\t\t\t\t\t RET\n\t\t\t\t\t\t MOV EAX, DWORD PTR [ESI + CCH] ; filter_param_ptr->track_scale\n\t\t\t\t\t\t RET\n\t\t\t*/\n\n\t\t\tstatic const char code_put[] =\n\t\t\t\t\"\\x8a\\x46\\x03\"\t\t\t\t// MOV AL, BYTE PTR [ESI + 3H]\n\t\t\t\t\"\\xa8\\x04\"\t\t\t\t\t// TEST AL, 04H\n\t\t\t\t\"\\x75\\x03\"\t\t\t\t\t// JNZ SKIP, 03H\n\t\t\t\t\"\\x33\\xc0\"\t\t\t\t\t// XOR EAX, EAX\n\t\t\t\t\"\\xc3\"\t\t\t\t\t\t// RET\n\t\t\t\t\"\\x8b\\x86\\xcc\\x00\\x00\\x00\"\t// MOV EAX, DWORD PTR [ESI + CCH] ; filter_param_ptr->track_scale\n\t\t\t\t\"\\xc3\"\t\t\t\t\t\t// RET\n\t\t\t\t;\n\t\t\tmemcpy(cursor, code_put, sizeof(code_put) - 1);\n\n\t\t\tauto apply = [&cursor](uint32_t ofs, std::optional<restorable_patch>& rp) {\n\t\t\t\tchar injection[6];\n\t\t\t\tinjection[0] = '\\x90'; // nop\n\t\t\t\tinjection[1] = '\\xe8'; // call rel32\n\t\t\t\tstore_i32(&injection[2], CalcNearJmp(ofs + 2, reinterpret_cast<i32>(cursor)));\n\t\t\t\trp.emplace(ofs, injection, sizeof(injection));\n\t\t\t};\n\n\t\t\tapply(GLOBAL::exedit_base + OFS::ExEdit::ConvertFilter2Exo_TrackScaleJudge_Overwrite1, rp1);\n\t\t\tapply(GLOBAL::exedit_base + OFS::ExEdit::ConvertFilter2Exo_TrackScaleJudge_Overwrite2, rp2);\n\t\t\tapply(GLOBAL::exedit_base + OFS::ExEdit::ConvertFilter2Exo_TrackScaleJudge_Overwrite3, rp3);\n\n\t\t\tcursor += sizeof(code_put) - 1;\n\n\t\t\trp1->switching(enabled);\n\t\t\trp2->switching(enabled);\n\t\t\trp3->switching(enabled);\n\t\t}\n\n\n\t\tvoid switching(bool flag) {\n\t\t\tenabled = flag;\n\t\t\trp1->switching(enabled);\n\t\t\trp2->switching(enabled);\n\t\t\trp3->switching(enabled);\n\t\t}\n\n\t\tbool is_enabled() { return enabled; }\n\t\tbool is_enabled_i() { return enabled; }\n\n\n\t\tvoid switch_load(ConfigReader& cr) {\n\t\t\tcr.regist(key, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, enabled);\n\t\t\t});\n\t\t}\n\n\t\tvoid switch_store(ConfigWriter& cw) {\n\t\t\tcw.append(key, enabled);\n\t\t}\n\n\n\t} exo_aviutlfilter;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_EXO_AVIUTL_FILTER\n"
  },
  {
    "path": "patch/patch_exo_fold_gui.hpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_EXO_FOLD_GUI\r\n#include <memory>\r\n\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"util.hpp\"\r\n\r\nnamespace patch {\r\n\r\n    // init at exedit load\r\n    // exa,exo生成時、設定ダイアログの▼（折り畳み）とマウスマーク（GUI表示）の情報を追加する\r\n    inline class exo_fold_gui_t {\r\n        bool enabled = true;\r\n        bool enabled_i;\r\n        inline static const char key[] = \"exa_fold_gui\";\r\n\r\n        inline static const char fold_gui_write[] = \"_fold_gui=%d\\r\\n\";\r\n        inline static const char fold_gui_read[] = \"_fold_gui\";\r\n\r\n    public:\r\n        void init() {\r\n            enabled_i = enabled;\r\n\r\n            if (!enabled_i)return;\r\n\r\n            auto& cursor = GLOBAL::executable_memory_cursor;\r\n\r\n            { // exo_write\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x0288b1, 5);\r\n                h.store_i8(0, '\\xe9');\r\n                h.replaceNearJmp(1, cursor);\r\n                /*\r\n                    100288b1 2401               and     al,01\r\n                    100288b3 84c0               test    al,al\r\n                    100288b5 750f               jnz     100288c6\r\n                    ↓\r\n                    100288b1 e9XxXxXxXx         jmp     executable_memory_cursor\r\n\r\n                */\r\n\r\n                static const char code_put_write[] =\r\n                    \"\\x8b\\xc8\"                 // mov     ecx,eax\r\n                    \"\\x50\"                     // push    eax\r\n                    \"\\x83\\xe1\\x07\"             // and     ecx,07\r\n                    \"\\xc1\\xe9\\x01\"             // shr     ecx,01\r\n                    \"\\x83\\xf1\\x02\"             // xor     ecx,02\r\n                    \"\\x85\\xc9\"                 // test    ecx,ecx\r\n                    \"\\x74\\x0e\"                 // jz      skip 0e\r\n                    \"\\x51\"                     // push    ecx\r\n                    \"\\x68XXXX\"                 // push    \"_fold_gui=%d\\r\\n\"\r\n                    \"\\x55\"                     // push    ebp\r\n                    \"\\xff\\xd3\"                 // call    ebx\r\n                    \"\\x83\\xc4\\x0c\"             // add     esp,0c\r\n                    \"\\x03\\xe8\"                 // add     ebp,eax\r\n                    \"\\x58\"                     // pop     eax\r\n                    \"\\x24\\x01\"                 // and     al,01\r\n                    \"\\x84\\xc0\"                 // test    al,al\r\n                    \"\\x0f\\x84XXXX\"             // jz      exedit + 0x288b7\r\n                    \"\\xe9\"// & XXXX            // jmp     exedit + 0x288c6\r\n                    ;\r\n\r\n                memcpy(cursor, code_put_write, sizeof(code_put_write) - 1);\r\n                store_i32(cursor + 18, &fold_gui_write);\r\n                cursor += sizeof(code_put_write) - 1 + 4;\r\n                store_i32(cursor - 9, GLOBAL::exedit_base + 0x0288b7 - ((int)cursor - 5));\r\n                store_i32(cursor - 4, GLOBAL::exedit_base + 0x0288c6 - (int)cursor);\r\n            }\r\n\r\n            { // exo_read\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x029b21, 5);\r\n                h.store_i8(0, '\\xe9');\r\n                h.replaceNearJmp(1, cursor);\r\n                /*\r\n                    10029b21 8b542414           mov     edx,dword ptr [esp+14]\r\n                    10029b25 52                 push    edx\r\n                    ↓\r\n                    100288b1 e9XxXxXxXx         jmp     executable_memory_cursor\r\n\r\n                */\r\n\r\n                static const char code_put_read[] =\r\n                    \"\\x8b\\x54\\x24\\x14\"         // mov     edx,dword ptr [esp+14]\r\n                    \"\\x52\"                     // push    edx\r\n                    \"\\x68XXXX\"                 // push    \"_fold_gui\"\r\n                    \"\\xff\\xd6\"                 // call    esi\r\n                    \"\\x85\\xc0\"                 // test    eax,eax\r\n                    \"\\x75\\x1f\"                 // jnz     skip,1f\r\n                    \"\\x53\"                     // push    ebx\r\n                    \"\\xe8XXXX\"                 // call    100918ab\r\n                    \"\\x83\\xc4\\x04\"             // add     esp,04\r\n                    \"\\x85\\xc0\"                 // test    eax,eax\r\n                    \"\\x74\\x12\"                 // jz      skip,12\r\n                    \"\\x83\\xe0\\x03\"             // and     eax,03\r\n                    \"\\xc1\\xe0\\x01\"             // shl     eax,01\r\n                    \"\\x8b\\x4c\\x24\\x48\"         // mov     ecx,dword ptr [esp+48]\r\n                    \"\\x03\\xcd\"                 // add     ecx,ebp\r\n                    \"\\x83\\xc1\\x72\"             // add     ecx,+72\r\n                    \"\\x30\\x41\\x72\"             // xor     byte ptr [ecx+72],al\r\n                    \"\\x8b\\x54\\x24\\x14\"         // mov     edx,dword ptr [esp+14]\r\n                    \"\\x52\"                     // push    edx\r\n                    \"\\xe9\"// & XXXX            // jmp     exedit + 0x29b26\r\n                    ;\r\n\r\n                memcpy(cursor, code_put_read, sizeof(code_put_read) - 1);\r\n                store_i32(cursor + 6, &fold_gui_read);\r\n                store_i32(cursor + 18, GLOBAL::exedit_base + 0x0918ab - ((int)cursor + 22));\r\n                cursor += sizeof(code_put_read) - 1 + 4;\r\n                store_i32(cursor - 4, GLOBAL::exedit_base + 0x029b26 - (int)cursor);\r\n            }\r\n\r\n        }\r\n\r\n        void switching(bool flag) {\r\n            enabled = flag;\r\n        }\r\n\r\n        bool is_enabled() { return enabled; }\r\n        bool is_enabled_i() { return enabled_i; }\r\n\r\n        void switch_load(ConfigReader& cr) {\r\n            cr.regist(key, [this](json_value_s* value) {\r\n                ConfigReader::load_variable(value, enabled);\r\n                });\r\n        }\r\n\r\n        void switch_store(ConfigWriter& cw) {\r\n            cw.append(key, enabled);\r\n        }\r\n    } exo_fold_gui;\r\n} // namespace patch\r\n\r\n#endif // ifdef PATCH_SWITCH_EXO_FOLD_GUI\r\n"
  },
  {
    "path": "patch/patch_exo_midpt_and_tra.hpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n#ifdef PATCH_SWITCH_EXO_MIDPT_AND_TRA\r\n#include <exedit.hpp>\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch {\r\n\t// init at exedit load\r\n\t/* 中間点有りで.traスクリプト変化方式のあるオブジェクトがあると正常に読み込めないことがあるのを修正\r\n\t発生条件：\r\n\t・aviutl.exeを開いた後、一度も使用していない.traスクリプト変化方式が含まれること\r\n\t・中間点有りオブジェクトであること\r\n\t*/\r\n\tinline class exo_midpt_and_tra_t {\r\n\r\n\t\tbool enabled = true;\r\n\t\tbool enabled_i;\r\n\t\tinline static const char key[] = \"exo_midpt_and_tra\";\r\n\r\n\r\n\tpublic:\r\n\r\n\t\tvoid init() {\r\n\t\t\tenabled_i = enabled;\r\n\t\t\tif (!enabled_i)return;\r\n\r\n\t\t\tauto& cursor = GLOBAL::executable_memory_cursor;\r\n\r\n\t\t\t// 100345d9 e8d2030000         call    exedit+349b0\r\n\r\n\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x0345da, 4);\r\n\t\t\th.replaceNearJmp(0, cursor);\r\n\r\n\t\t\tstatic const char code_put[] =\r\n\t\t\t\t\"\\x8b\\x84\\x24\\x40\\x01\\x00\\x00\" // mov     eax,dword ptr [esp+140] ; flag\r\n\t\t\t\t\"\\x85\\xc0\"                     // test    eax,eax\r\n\t\t\t\t\"\\x0f\\x84XXXX\"                 // jz      exedit+349b0\r\n\t\t\t\t\"\\xc3\"                         // ret\r\n\t\t\t\t;\r\n\r\n\t\t\tmemcpy(cursor, code_put, sizeof(code_put) - 1);\r\n\t\t\tstore_i32(cursor + 11, GLOBAL::exedit_base + 0x0349b0 - (uint32_t)(cursor + 15));\r\n\t\t\t\r\n\t\t\tcursor += sizeof(code_put) - 1;\r\n\r\n\t\t}\r\n\r\n\t\tvoid switching(bool flag) { enabled = flag; }\r\n\r\n\t\tbool is_enabled() { return enabled; }\r\n\t\tbool is_enabled_i() { return enabled_i; }\r\n\r\n\t\tvoid switch_load(ConfigReader& cr) {\r\n\t\t\tcr.regist(key, [this](json_value_s* value) {\r\n\t\t\t\tConfigReader::load_variable(value, enabled);\r\n\t\t\t\t});\r\n\t\t}\r\n\r\n\t\tvoid switch_store(ConfigWriter& cw) {\r\n\t\t\tcw.append(key, enabled);\r\n\t\t}\r\n\r\n\t} exo_midpt_and_tra;\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_EXO_MIDPT_AND_TRA\r\n"
  },
  {
    "path": "patch/patch_exo_sceneidx.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_EXO_SCENEIDX\n#include \"global.hpp\"\n#include \"offset_address.hpp\"\n#include \"util.hpp\"\n\n#include \"restorable_patch.hpp\"\n\nnamespace patch {\n\t// init at exedit load\n\t// オブジェクトファイルにシーン・シーン(音声)のシーン番号が正しく入出力されない\n\tinline class exo_sceneidx_t {\n\n\t\tbool enabled = true;\n\t\tinline static const char key[] = \"exo_sceneidx\";\n\n\t\tstd::optional<restorable_patch_i16> rp1;\n\t\tstd::optional<restorable_patch_i32> rp2;\n\t\tstd::optional<restorable_patch_i32> rp3;\n\n\t\tinline static const char scene_name[] = \"scene\";\n\tpublic:\n\t\tvoid init() {\n\n\t\t\trp1.emplace(GLOBAL::exedit_base + OFS::ExEdit::efSceneAudio_exdatause_idx_type, (i16)1);\n\t\t\trp2.emplace(GLOBAL::exedit_base + OFS::ExEdit::efSceneAudio_exdatause_idx_name, &scene_name);\n\t\t\trp3.emplace(GLOBAL::exedit_base + OFS::ExEdit::efScene_exdatause_idx_name, &scene_name);\n\n\t\t\trp1->switching(enabled);\n\t\t\trp2->switching(enabled);\n\t\t\trp3->switching(enabled);\n\t\t}\n\n        void switching(bool flag) {\n\t\t\tenabled = flag;\n            rp1->switching(enabled);\n\t\t\trp2->switching(enabled);\n\t\t\trp3->switching(enabled);\n        }\n\n        bool is_enabled() { return enabled; }\n\t\tbool is_enabled_i() { return enabled; }\n        \n\t\tvoid switch_load(ConfigReader& cr) {\n\t\t\tcr.regist(key, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, enabled);\n\t\t\t});\n\t\t}\n\n\t\tvoid switch_store(ConfigWriter& cw) {\n\t\t\tcw.append(key, enabled);\n\t\t}\n\t} exo_sceneidx;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_EXO_SCENEIDX\n"
  },
  {
    "path": "patch/patch_exo_specialcolorconv.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_EXO_SPECIALCOLORCONV\n\n#include \"global.hpp\"\n#include \"offset_address.hpp\"\n#include \"util_magic.hpp\"\n\nnamespace patch {\n\t// init at exedit load\n\t// 特定色域変換の拡張データ領域にstatusが2つある問題\n\tinline class exo_specialcolorconv_t {\n\t\tinline static const char status2_name[] = \"status2\";\n\n        bool enabled = true;\n        inline static const char key[] = \"exo_specialcolorconv\";\n\n        std::optional<restorable_patch_i32> rp;\n\n\tpublic:\n\t\tvoid init() {\n\t\t\trp.emplace(GLOBAL::exedit_base + OFS::ExEdit::specialcolorconv_status2, &status2_name);\n\n            rp->switching(enabled);\n\t\t}\n\n        void switching(bool flag) {\n            rp->switching(enabled = flag);\n        }\n\n        bool is_enabled() { return enabled; }\n        bool is_enabled_i() { return enabled; }\n\n        void switch_load(ConfigReader& cr) {\n            cr.regist(key, [this](json_value_s* value) {\n                ConfigReader::load_variable(value, enabled);\n           });\n        }\n\n        void switch_store(ConfigWriter& cw) {\n            cw.append(key, enabled);\n        }\n\t} exo_specialcolorconv;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_EXO_SPECIALCOLORCONV\n"
  },
  {
    "path": "patch/patch_exo_trackminusval.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_exo_trackminusval.hpp\"\n\n#ifdef PATCH_SWITCH_EXO_TRACK_MINUSVAL\nnamespace patch {\n\tint __cdecl exo_trackminusval_t::exo_trackminusval_insteadfunc(char** strp, ExEdit::Filter* efp, int track_idx) {\n\t\tif (!has_flag(efp->flag, ExEdit::Filter::Flag::ExEditFilter) || efp->track_scale == nullptr || efp->track_scale[track_idx] <= 1) {\n\t\t\tauto ret = reinterpret_cast<int(__cdecl*)(char*)>(GLOBAL::exedit_base + OFS::ExEdit::str2int2)(*strp);\n\t\t\tauto itr = *strp;\n\t\t\twhile (*itr != '\\0' && *itr != ',') itr++;\n\t\t\t*strp = itr;\n\t\t\treturn ret;\n\t\t}\n\t\telse {\n\t\t\tauto itr = *strp;\n\t\t\tbool is_neg = false;\n\t\t\tif (*itr == '-') {\n\t\t\t\tis_neg = true;\n\t\t\t\titr++;\n\t\t\t\t(*strp)++;\n\t\t\t}\n\t\t\twhile (*itr) {\n\t\t\t\tif (*itr == '.') {\n\t\t\t\t\t*itr = '\\0';\n\t\t\t\t\titr++;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\titr++;\n\t\t\t}\n\t\t\tauto scale = efp->track_scale[track_idx];\n\t\t\tauto ret = reinterpret_cast<int(__cdecl*)(char*)>(GLOBAL::exedit_base + OFS::ExEdit::str2int2)(*strp) * scale;\n\t\t\twhile (scale /= 10, '0' <= *itr && *itr <= '9') {\n\t\t\t\tret += (*itr - '0') * scale;\n\t\t\t\titr++;\n\t\t\t}\n\t\t\tif (is_neg)ret = -ret;\n\t\t\twhile (*itr != '\\0' && *itr != ',') itr++;\n\t\t\t*strp = itr;\n\t\t\treturn ret;\n\t\t}\n\t}\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_EXO_TRACK_MINUSVAL\n"
  },
  {
    "path": "patch/patch_exo_trackminusval.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n\n#ifdef PATCH_SWITCH_EXO_TRACK_MINUSVAL\n\n#include <memory>\n#include <exedit.hpp>\n\n#include \"global.hpp\"\n#include \"offset_address.hpp\"\n#include \"util.hpp\"\n#include \"restorable_patch.hpp\"\n\n#include \"config_rw.hpp\"\n\nnamespace patch {\n\t// init at exedit load\n\t// オブジェクトファイルからの入力で，(-1,0)の値の正負が逆転する\n\tinline class exo_trackminusval_t {\n\t\tstatic int __cdecl exo_trackminusval_insteadfunc(char** strp, ExEdit::Filter* efp, int track_idx);\n\n\t\tbool enabled = true;\n\n\t\tinline static const char key[] = \"exo_track_minusval\";\n\n        std::optional<restorable_patch_function> rpf;\n\n\tpublic:\n\n\t\tvoid init() {\n            rpf.emplace(GLOBAL::exedit_base + OFS::ExEdit::exo_readtrack, exo_trackminusval_insteadfunc);\n            rpf->switching(enabled);\n\t\t}\n\n        void switching(bool flag) {\n            rpf->switching(enabled = flag);\n        }\n\n        bool is_enabled() { return enabled; }\n\t\tbool is_enabled_i() { return enabled; }\n        \n\t\tvoid switch_load(ConfigReader& cr) {\n\t\t\tcr.regist(key, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, enabled);\n\t\t\t});\n\t\t}\n\n\t\tvoid switch_store(ConfigWriter& cw) {\n\t\t\tcw.append(key, enabled);\n\t\t}\n\n\t} exo_trackminusval;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_EXO_TRACK_MINUSVAL\n"
  },
  {
    "path": "patch/patch_exo_trackparam.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_EXO_TRACKPARAM\n\n#include \"global.hpp\"\n#include \"offset_address.hpp\"\n#include \"util.hpp\"\n#include \"config_rw.hpp\"\n\nnamespace patch {\n\t// init at exedit load\n\t// オブジェクトファイルへの出力で，ascii文字以外が含まれたスクリプトのパラメータが0になる\n    inline class exo_trackparam_t {\n        std::optional<restorable_patch_i8> rp;\n\n        bool enabled = true;\n        inline static const char key[] = \"exo_trackparam\";\n    public:\n        void init() {\n            rp.emplace(GLOBAL::exedit_base + OFS::ExEdit::exo_trackparam_overwrite, 0x73);\n\n            rp->switching(enabled);\n        }\n\n        void switching(bool flag) {\n            rp->switching(enabled = flag);\n        }\n\n        bool is_enabled() { return enabled; }\n        bool is_enabled_i() { return enabled; }\n\n        void switch_load(ConfigReader& cr) {\n            cr.regist(key, [this](json_value_s* value) {\n                ConfigReader::load_variable(value, enabled);\n           });\n        }\n\n        void switch_store(ConfigWriter& cw) {\n            cw.append(key, enabled);\n        }\n    } exo_trackparam;\n} // namespace patch\n#endif // #ifdef PATCH_SWITCH_EXO_TRACKPARAM\n"
  },
  {
    "path": "patch/patch_failed_file_drop.hpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_FAILED_LONGER_PATH\r\n\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"util.hpp\"\r\n\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch {\r\n\r\n    // init at exedit load\r\n    // ドロップ処理で最終的に何も行われなかったときにメッセージを出力する\r\n\r\n    inline class failed_file_drop_t {\r\n\r\n        inline static const char str_failed_drop_msg[] = \"拡張編集へドロップされたファイルの種類が判別できませんでした\\nexedit.iniを確認してください\";\r\n\r\n\r\n\r\n        bool enabled = true;\r\n        bool enabled_i;\r\n        inline static const char key[] = \"failed_file_drop\";\r\n    public:\r\n        void init() {\r\n            enabled_i = enabled;\r\n\r\n            if (!enabled_i)return;\r\n\r\n\r\n\r\n            auto& cursor = GLOBAL::executable_memory_cursor;\r\n\r\n            OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x03c454, 4);\r\n            h.replaceNearJmp(0, cursor);\r\n            /*\r\n                 1003c452 0f84f4760000        jz      10043b4c\r\n                 ↓\r\n                 1003c452 0f84XxXxXxXx        jz      executable_memory_cursor\r\n\r\n\r\n\r\n            */\r\n\r\n            char code_put[] =\r\n                \"\\x8d\\x8c\\x24\\xd0\\x00\\x00\\x00\"//  lea     ecx,dword ptr [esp+000000d0]\r\n                \"\\x51\"                        //  push    ecx\r\n                \"\\xe8XXXX\"                    //  call    1004e1d0 ; ExtractExtension\r\n                \"\\x83\\xc4\\x04\"                //  add     esp,+04\r\n                \"\\x68\\x30\\x20\\x04\\x00\"        //  push    0x42030\r\n                \"\\x50\"                        //  push    eax\r\n                \"\\x68XXXX\"                    //  push    &str_failed_drop_msg\r\n                \"\\xa1\\x44\\x7a\\x17\\x00\"        //  mov     eax,[exedit+exedit_hwnd]\r\n                \"\\x50\"                        //  push    eax\r\n                \"\\xff\\x15\\x20\\xa3\\x09\\x00\"    //  call    dword ptr [exedit+MessageBoxA]\r\n                \"\\xe9\"                        //  jmp     10043b4c\r\n                ;\r\n\r\n            memcpy(cursor, code_put, sizeof(code_put) - 1);\r\n            store_i32(cursor + 9, GLOBAL::exedit_base + 0x04e1d0 - (int)cursor - 13);\r\n            store_i32(cursor + 23, &str_failed_drop_msg);\r\n            store_i32(cursor + 28, GLOBAL::exedit_base + OFS::ExEdit::exedit_hwnd);\r\n            store_i32(cursor + 35, GLOBAL::exedit_base + 0x09a320);\r\n            cursor += sizeof(code_put) - 1 + 4;\r\n            store_i32(cursor - 4, GLOBAL::exedit_base + 0x043b4c - (int)cursor);\r\n\r\n\r\n        }\r\n\r\n        void switching(bool flag) {\r\n            enabled = flag;\r\n        }\r\n\r\n        bool is_enabled() { return enabled; }\r\n        bool is_enabled_i() { return enabled_i; }\r\n\r\n        void switch_load(ConfigReader& cr) {\r\n            cr.regist(key, [this](json_value_s* value) {\r\n                ConfigReader::load_variable(value, enabled);\r\n                });\r\n        }\r\n\r\n        void switch_store(ConfigWriter& cw) {\r\n            cw.append(key, enabled);\r\n        }\r\n    } failed_file_drop;\r\n} // namespace patch\r\n\r\n#endif // ifdef PATCH_SWITCH_FAILED_FILE_DROP\r\n"
  },
  {
    "path": "patch/patch_failed_longer_path.cpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"patch_failed_longer_path.hpp\"\r\n#ifdef PATCH_SWITCH_FAILED_LONGER_PATH\r\n\r\n\r\nnamespace patch {\r\n    BOOL __cdecl failed_longer_path_t::dlg_get_load_name_wrap(AviUtl::ExFunc* a_exfunc, LPSTR name, LPSTR filter, LPSTR def) {\r\n        char temp[264];\r\n        if (!a_exfunc->dlg_get_load_name(temp, filter, def))return FALSE;\r\n        if (258 < lstrlenA(temp)) {\r\n            HWND* settingdialog_hwnd = (HWND*)(GLOBAL::exedit_base + OFS::ExEdit::settingdialog_hwnd);\r\n            MessageBoxA(*settingdialog_hwnd, str_new_longer_msg, temp, MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_TOPMOST);\r\n            lstrcpyA(name, def);\r\n            return FALSE;\r\n        }\r\n        lstrcpyA(name, temp);\r\n        return TRUE;\r\n    }\r\n\r\n    UINT __stdcall failed_longer_path_t::DragQueryFileA_exedit_wrap(HDROP hDrop, UINT iFile, LPSTR lpszFile, UINT cch) {\r\n        UINT path_len = DragQueryFileA(hDrop, iFile, lpszFile, cch);\r\n        if (258 < path_len) {\r\n            auto exedit_hwnd = (HWND*)(GLOBAL::exedit_base + OFS::ExEdit::exedit_hwnd);\r\n            MessageBoxA(*exedit_hwnd, str_new_longer_msg, lpszFile, MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_TOPMOST);\r\n            return 0;\r\n        }\r\n        return path_len;\r\n    }\r\n\r\n    UINT __stdcall failed_longer_path_t::DragQueryFileA_settingdialog_wrap(HDROP hDrop, UINT iFile, LPSTR lpszFile, UINT cch) {\r\n        UINT path_len = DragQueryFileA(hDrop, iFile, lpszFile, cch);\r\n        if (258 < path_len) {\r\n            auto settingdialog_hwnd = (HWND*)(GLOBAL::exedit_base + OFS::ExEdit::settingdialog_hwnd);\r\n            MessageBoxA(*settingdialog_hwnd, str_new_longer_msg, lpszFile, MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_TOPMOST);\r\n            return 0;\r\n        }\r\n        return path_len;\r\n    }\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_FAILED_LONGER_PATH\r\n"
  },
  {
    "path": "patch/patch_failed_longer_path.hpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_FAILED_LONGER_PATH\r\n\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"util.hpp\"\r\n\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch {\r\n\r\n    // init at exedit load\r\n    // 読み込もうとしたファイルパスが長くて失敗するときにメッセージを出す/エラーが発生するのを修正\r\n\r\n    // 安全性のために読み込める最大数を1バイト減らしています（260バイトを読み込ませた場合、合成モードなどと繋がってバグる）\r\n\r\n    inline class failed_longer_path_t {\r\n\r\n        inline static const char str_new_longer_msg[] = \"ファイルパスが長いため失敗しました\\nファイルやフォルダ名を短くするか、Cドライブ直下などの浅い階層に移動して下さい\";\r\n        \r\n        static BOOL __cdecl dlg_get_load_name_wrap(AviUtl::ExFunc* a_exfunc, LPSTR name, LPSTR filter, LPSTR def);\r\n        static UINT __stdcall DragQueryFileA_exedit_wrap(HDROP hDrop, UINT iFile, LPSTR lpszFile, UINT cch);\r\n        static UINT __stdcall DragQueryFileA_settingdialog_wrap(HDROP hDrop, UINT iFile, LPSTR lpszFile, UINT cch);\r\n\r\n\r\n        bool enabled = true;\r\n        bool enabled_i;\r\n        inline static const char key[] = \"failed_longer_path\";\r\n    public:\r\n        void init() {\r\n            enabled_i = enabled;\r\n\r\n            if (!enabled_i)return;\r\n\r\n            { // exedit_dlg_get_load_name\r\n                /*\r\n                        1002093b ff9280000000   call     dword ptr [edx + 0x80] ; aviutl_exfunc->dlg_get_load_name\r\n                        10020941 83c40c         add      esp,0xc\r\n                        ↓\r\n                        1002093b 52             push     edx\r\n                        1002093c e8XxXxXxXx     call     new_func\r\n                        10020941 83c410         add      esp,0x10\r\n                */\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x02093b, 9);\r\n                h.store_i16(0, '\\x52\\xe8'); // push edx; call (rel32)\r\n                h.replaceNearJmp(2, &dlg_get_load_name_wrap);\r\n                h.store_i8(8, '\\x10');\r\n            }\r\n            \r\n            { // ExEdit D&D\r\n                /*\r\n                        1003be8f ff15c8a10910   call     dword ptr [DragQueryFileA]\r\n                        ↓\r\n                        1003be8f 90             nop\r\n                        1003be90 e8XxXxXxXx     call     new_func\r\n                */\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x03be8f, 6);\r\n                h.store_i16(0, '\\x90\\xe8'); // nop; call (rel32)\r\n                h.replaceNearJmp(2, &DragQueryFileA_exedit_wrap);\r\n            }\r\n\r\n            { // SettingDialog D&D\r\n                /*\r\n                        1002e330 ff15c8a10910   call     dword ptr [DragQueryFileA]\r\n                        ↓\r\n                        1002e330 90             nop\r\n                        1002e331 e8XxXxXxXx     call     new_func\r\n                */\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x02e330, 6);\r\n                h.store_i16(0, '\\x90\\xe8'); // nop; call (rel32)\r\n                h.replaceNearJmp(2, &DragQueryFileA_settingdialog_wrap);\r\n            }\r\n\r\n        }\r\n\r\n        void switching(bool flag) {\r\n            enabled = flag;\r\n        }\r\n\r\n        bool is_enabled() { return enabled; }\r\n        bool is_enabled_i() { return enabled_i; }\r\n\r\n        void switch_load(ConfigReader& cr) {\r\n            cr.regist(key, [this](json_value_s* value) {\r\n                ConfigReader::load_variable(value, enabled);\r\n                });\r\n        }\r\n\r\n        void switch_store(ConfigWriter& cw) {\r\n            cw.append(key, enabled);\r\n        }\r\n    } failed_longer_path;\r\n} // namespace patch\r\n\r\n#endif // ifdef PATCH_SWITCH_FAILED_LONGER_PATH\r\n"
  },
  {
    "path": "patch/patch_failed_sjis_msgbox.cpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"patch_failed_sjis_msgbox.hpp\"\r\n#ifdef PATCH_SWITCH_FAILED_SJIS_MSGBOX\r\n\r\n\r\nnamespace patch {\r\n    int __stdcall failed_sjis_msgbox_t::MessageBoxA_1(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) {\r\n        auto end = lpCaption + strlen(lpCaption);\r\n        // sjisに0x3fは含まれないのでこれでよい\r\n        if (std::find(lpCaption, end, '?') != end) {\r\n            lpText = str_new_failed_msg;\r\n        }\r\n        return MessageBoxA(hWnd, lpText, lpCaption, uType);\r\n    }\r\n\r\n    int __stdcall failed_sjis_msgbox_t::MessageBoxA_2(LPCSTR path, HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) {\r\n        int ret = MessageBoxA_1(hWnd, lpText, path, uType);\r\n        *(char*)path = '\\0';\r\n        return ret;\r\n    }\r\n\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_FAILED_SJIS_MSGBOX\r\n"
  },
  {
    "path": "patch/patch_failed_sjis_msgbox.hpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_FAILED_SJIS_MSGBOX\r\n\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"util.hpp\"\r\n\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch {\r\n\r\n    // init at exedit load\r\n    // ファイル名（パス）が原因で読み込み失敗のエラー表記を変更する\r\n\r\n    // **ファイルの読み込みに失敗しました 対応していないフォーマットの可能性があります\r\n    // ↓\r\n    // パス(ファイルもしくはフォルダ名)に使用できない文字が含まれています\r\n\r\n    inline class failed_sjis_msgbox_t {\r\n\r\n        inline static const char str_new_failed_msg[] = \"ファイルパスに使用できない文字が含まれています\\nファイル名やフォルダ名を確認してください\";\r\n        static int __stdcall MessageBoxA_1(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);\r\n        static int __stdcall MessageBoxA_2(LPCSTR path, HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);\r\n\r\n        bool enabled = true;\r\n        bool enabled_i;\r\n        inline static const char key[] = \"failed_sjis_msgbox\";\r\n    public:\r\n        void init() {\r\n            enabled_i = enabled;\r\n\r\n            if (!enabled_i)return;\r\n\r\n            { // audio & movie\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x00522b, 6);\r\n                h.store_i16(0, '\\x90\\xe8'); // nop; call (rel32)\r\n                h.replaceNearJmp(2, &MessageBoxA_1);\r\n            }\r\n\r\n            { // image_file_wndproc\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x00e173, 11);\r\n                h.store_i32(0, '\\x8d\\x44\\x24\\x24'); // lea  eax,dword ptr [esp+24]\r\n                h.store_i32(4, '\\x50\\x90\\xe8\\x00'); // push eax, nop, call (rel32)\r\n                h.replaceNearJmp(7, &MessageBoxA_2);\r\n            }\r\n            { // border_wndproc\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x0521c3, 11);\r\n                h.store_i32(0, '\\x8d\\x44\\x24\\x24'); // lea  eax,dword ptr [esp+24]\r\n                h.store_i32(4, '\\x50\\x90\\xe8\\x00'); // push eax, nop, call (rel32)\r\n                h.replaceNearJmp(7, &MessageBoxA_2);\r\n            }\r\n            { // shadow_wndproc\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x088ef6, 11);\r\n                h.store_i32(0, '\\x8d\\x44\\x24\\x24'); // lea  eax,dword ptr [esp+24]\r\n                h.store_i32(4, '\\x50\\x90\\xe8\\x00'); // push eax, nop, call (rel32)\r\n                h.replaceNearJmp(7, &MessageBoxA_2);\r\n            }\r\n        }\r\n\r\n        void switching(bool flag) {\r\n            enabled = flag;\r\n        }\r\n\r\n        bool is_enabled() { return enabled; }\r\n        bool is_enabled_i() { return enabled_i; }\r\n\r\n        void switch_load(ConfigReader& cr) {\r\n            cr.regist(key, [this](json_value_s* value) {\r\n                ConfigReader::load_variable(value, enabled);\r\n            });\r\n        }\r\n\r\n        void switch_store(ConfigWriter& cw) {\r\n            cw.append(key, enabled);\r\n        }\r\n    } failed_sjis_msgbox;\r\n} // namespace patch\r\n\r\n#endif // ifdef PATCH_SWITCH_FAILED_SJIS_MSGBOX\r\n"
  },
  {
    "path": "patch/patch_fast.hpp",
    "content": "#pragma once\n\nnamespace patch::fast {\n\tinline class fast_t {\n\n\t\tbool enabled = true;\n\t\tbool enabled_i;\n\t\tinline static const char key[] = \"fast\";\n\n\tpublic:\n\t\tvoid init() {\n            enabled_i = enabled;\n        }\n\n        void switching(bool flag) {\n            enabled = flag;\n        }\n\n        bool is_enabled() { return enabled; }\n        bool is_enabled_i() { return enabled_i; }\n\n        void switch_load(ConfigReader& cr) {\n            cr.regist(key, [this](json_value_s* value) {\n                ConfigReader::load_variable(value, enabled);\n            });\n        }\n\n        void switch_store(ConfigWriter& cw) {\n            cw.append(key, enabled);\n        }\n\n\t} fast;\n}\n"
  },
  {
    "path": "patch/patch_fast_border.cpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"patch_fast_border.hpp\"\r\n#ifdef PATCH_SWITCH_FAST_BORDER\r\n\r\n#include <numbers>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util_int.hpp\"\r\n#include \"debug_log.hpp\"\r\n#include <immintrin.h>\r\n\r\n//#define PATCH_STOPWATCH\r\n#include \"stopwatch.hpp\"\r\n\r\nnamespace patch::fast {\r\n\r\n\r\n    // AVX2が有効かどうかを判定する関数を追加してください\r\n    // AVX2が無効の場合でも縁取り関連のバグ修正は行われるようになっています\r\n    BOOL enable_avx2() {\r\n        auto cpucmdset = get_CPUCmdSet();\r\n        return has_flag(cpucmdset, CPUCmdSet::F_AVX2);\r\n    }\r\n\r\n\r\n    void efBorder_horizontal_convolution_alpha_simd(int thread_id, int thread_num, void* param1, void* param2);\r\n    void efBorder_horizontal_convolution_alpha_simd2(int thread_id, int thread_num, void* param1, void* param2);\r\n    void efBorder_vertical_convolution_alpha_and_put_color_simd(int thread_id, int thread_num, void* param1, void* param2);\r\n    void efBorder_vertical_convolution_alpha_and_put_color_simd2(int thread_id, int thread_num, void* param1, void* param2);\r\n    void efBorder_vertical_convolution_alpha_simd(int thread_id, int thread_num, void* param1, void* param2);\r\n    void efBorder_vertical_convolution_alpha_simd2(int thread_id, int thread_num, void* param1, void* param2);\r\n\r\n    BOOL Border_t::func_proc(ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\r\n        if constexpr (true) {\r\n            static stopwatch_mem sw{};\r\n            sw.start();\r\n\r\n            auto& border = *(reinterpret_cast<efBorder_var*>(GLOBAL::exedit_base + OFS::ExEdit::efBorder_var_ptr));\r\n            auto& ExEditMemory = *(void**)(GLOBAL::exedit_base + OFS::ExEdit::memory_ptr);\r\n\r\n            if (efp->track[0] <= 0) return TRUE;\r\n\r\n            auto exdata = (ExEdit::Exdata::efBorder*)efp->exdata_ptr;\r\n\r\n            int obj_w = efpip->obj_w;\r\n            int obj_h = efpip->obj_h;\r\n\r\n            int temp;\r\n            int add_size = efp->track[0] * 2;\r\n\r\n            border.inv_range = 0x1000 - efp->track[1] * 4096 / 1000;\r\n\r\n\r\n            add_size = (std::min)({ add_size, efpip->obj_line - obj_w, efpip->obj_max_h - obj_h });\r\n            add_size &= 0xfffffffe;\r\n\r\n            obj_w += add_size;\r\n            obj_h += add_size;\r\n\r\n            // efpip->obj_tempに画像を読み込む\r\n            int file_w = 0;\r\n            int file_h = 0;\r\n            if (exdata->file[0] != '\\0') {\r\n                if (efp->exfunc->load_image((ExEdit::PixelYCA*)ExEditMemory, exdata->file, &file_w, &file_h, 0, 0)) {\r\n                    for (int i = 0; i < obj_h; i += file_h) {\r\n                        for (int j = 0; j < obj_w; j += file_w) {\r\n                            efp->exfunc->bufcpy(efpip->obj_temp, j, i, ExEditMemory, 0, 0, file_w, file_h, 0, 0x13000003);\r\n                        }\r\n                    }\r\n                }\r\n            }\r\n\r\n\r\n            border.ExEditMemory = (unsigned short*)ExEditMemory;\r\n            border.add_size = add_size;\r\n            border.alpha = (int)round(65536.0 / ((double)efp->track[1] * add_size * 0.01 + 1.0));\r\n            temp = border.alpha;\r\n            int sft = 0;\r\n            while (sft < 16 && 64 < temp) {\r\n                temp >>= 1;\r\n                sft++;\r\n            }\r\n            border.alpha = temp;\r\n            border._alpha_shift = 16 - sft;\r\n\r\n            reinterpret_cast<void(__cdecl*)(short*, short*, short*, int)>(GLOBAL::exedit_base + OFS::ExEdit::rgb2yc)(&border.color_y, &border.color_cb, &border.color_cr, *(int*)&exdata->color & 0xffffff);\r\n\r\n            if (efpip->obj_w <= add_size) {\r\n                efp->aviutl_exfunc->exec_multi_thread_func(efBorder_horizontal_convolution_alpha_simd2, efp, efpip);\r\n            } else {\r\n                efp->aviutl_exfunc->exec_multi_thread_func(efBorder_horizontal_convolution_alpha_simd, efp, efpip);\r\n            }\r\n\r\n            if (efpip->obj_h <= add_size) {\r\n                if (file_w == 0 || file_h == 0) { // 画像なし\r\n                    efp->aviutl_exfunc->exec_multi_thread_func(efBorder_vertical_convolution_alpha_and_put_color_simd2, efp, efpip);\r\n                } else { // 画像あり\r\n                    efp->aviutl_exfunc->exec_multi_thread_func(efBorder_vertical_convolution_alpha_simd2, efp, efpip);\r\n                }\r\n            } else {\r\n                if (file_w == 0 || file_h == 0) { // 画像なし\r\n                    efp->aviutl_exfunc->exec_multi_thread_func(efBorder_vertical_convolution_alpha_and_put_color_simd, efp, efpip);\r\n                } else { // 画像あり\r\n                    efp->aviutl_exfunc->exec_multi_thread_func(efBorder_vertical_convolution_alpha_simd, efp, efpip);\r\n                }\r\n            }\r\n\r\n\r\n            efp->exfunc->bufcpy(efpip->obj_temp, add_size / 2, add_size / 2, efpip->obj_edit, 0, 0, efpip->obj_w, efpip->obj_h, 0, 3);\r\n\r\n            std::swap(efpip->obj_temp, efpip->obj_edit);\r\n\r\n            efpip->obj_w = obj_w;\r\n            efpip->obj_h = obj_h;\r\n\r\n\r\n            sw.stop();\r\n            return TRUE;\r\n        }\r\n        else {\r\n            static stopwatch_mem sw{};\r\n            sw.start();\r\n            auto ret = ((decltype(ExEdit::Filter::func_proc))(GLOBAL::exedit_base + OFS::ExEdit::efBorder_func_proc_ptr))(efp, efpip);\r\n            sw.stop();\r\n            return ret;\r\n        }\r\n    }\r\n\r\n\r\n\r\n#define ALPHA_TEMP_MAX 0xFFFF\r\n\r\n    void efBorder_horizontal_convolution_alpha_simd(int thread_id, int thread_num, void* param1, void* param2) {\r\n        auto& border = *reinterpret_cast<Border_t::efBorder_var*>(GLOBAL::exedit_base + OFS::ExEdit::efBorder_var_ptr);\r\n        auto efp = static_cast<ExEdit::Filter*>(param1);\r\n        auto efpip = static_cast<ExEdit::FilterProcInfo*>(param2);\r\n\r\n        int begin_thread = efpip->obj_h * thread_id / thread_num;\r\n        int end_thread = efpip->obj_h * (thread_id + 1) / thread_num;\r\n\r\n        int y = begin_thread;\r\n\r\n        if (enable_avx2()) {\r\n            __m256i offset256 = _mm256_mullo_epi32(_mm256_set_epi32(14, 12, 10, 8, 6, 4, 2, 0), _mm256_set1_epi32(efpip->obj_line));\r\n            __m256i border_alpha256 = _mm256_set1_epi32(border.alpha);\r\n            __m256i a_mem_max256 = _mm256_set1_epi32(ALPHA_TEMP_MAX);\r\n            int end_y = end_thread - 7;\r\n            for (; y < end_y; y += 8) {\r\n\r\n                int* pix1 = (int*)((ExEdit::PixelYCA*)efpip->obj_edit + y * efpip->obj_line) + 1;\r\n                int* pix2 = pix1;\r\n                unsigned short* mem = border.ExEditMemory + y * efpip->obj_line;\r\n\r\n                __m256i a_sum256 = _mm256_setzero_si256();\r\n                int x;\r\n                for (x = 0; x <= border.add_size; x++) {\r\n                    __m256i a256 = _mm256_srli_epi32(_mm256_i32gather_epi32(pix1, offset256, 4), 16);\r\n                    a_sum256 = _mm256_add_epi32(a_sum256, a256);\r\n                    a256 = _mm256_mullo_epi32(a_sum256, border_alpha256);\r\n                    a256 = _mm256_srli_epi32(a256, border._alpha_shift);\r\n                    a256 = _mm256_min_epu32(a256, a_mem_max256);\r\n\r\n                    for (int i = 0; i < 8; i++) {\r\n                        mem[i * efpip->obj_line] = (unsigned short)a256.m256i_u32[i];\r\n                    }\r\n\r\n                    pix1 += 2;\r\n                    mem++;\r\n                }\r\n\r\n\r\n                for (; x < efpip->obj_w; x++) {\r\n                    __m256i a256 = _mm256_srli_epi32(_mm256_i32gather_epi32(pix2, offset256, 4), 16);\r\n                    a_sum256 = _mm256_sub_epi32(a_sum256, a256);\r\n                    a256 = _mm256_srli_epi32(_mm256_i32gather_epi32(pix1, offset256, 4), 16);\r\n                    a_sum256 = _mm256_add_epi32(a_sum256, a256);\r\n                    a256 = _mm256_mullo_epi32(a_sum256, border_alpha256);\r\n                    a256 = _mm256_srli_epi32(a256, border._alpha_shift);\r\n                    a256 = _mm256_min_epu32(a256, a_mem_max256);\r\n\r\n                    for (int i = 0; i < 8; i++) {\r\n                        mem[i * efpip->obj_line] = (unsigned short)a256.m256i_u32[i];\r\n                    }\r\n\r\n                    pix1 += 2;\r\n                    pix2 += 2;\r\n                    mem++;\r\n                }\r\n                int end_x = efpip->obj_w + border.add_size;\r\n                for (; x < end_x; x++) {\r\n                    __m256i a256 = _mm256_srli_epi32(_mm256_i32gather_epi32(pix2, offset256, 4), 16);\r\n                    a_sum256 = _mm256_sub_epi32(a_sum256, a256);\r\n                    a256 = _mm256_mullo_epi32(a_sum256, border_alpha256);\r\n                    a256 = _mm256_srli_epi32(a256, border._alpha_shift);\r\n                    a256 = _mm256_min_epu32(a256, a_mem_max256);\r\n\r\n                    for (int i = 0; i < 8; i++) {\r\n                        mem[i * efpip->obj_line] = (unsigned short)a256.m256i_u32[i];\r\n                    }\r\n\r\n                    pix2 += 2;\r\n                    mem++;\r\n                }\r\n            }\r\n        }\r\n\r\n        for (; y < end_thread; y++) {\r\n            short* pixa1 = (short*)((ExEdit::PixelYCA*)efpip->obj_edit + y * efpip->obj_line) + 3;\r\n            short* pixa2 = pixa1;\r\n            unsigned short* mem = border.ExEditMemory + y * efpip->obj_line;\r\n            int a_sum = 0;\r\n\r\n            int x;\r\n            for (x = 0; x <= border.add_size; x++) {\r\n                a_sum += *pixa1;\r\n                *mem = (unsigned short)min(a_sum * border.alpha >> border._alpha_shift, ALPHA_TEMP_MAX);\r\n\r\n                pixa1 += 4;\r\n                mem++;\r\n            }\r\n\r\n            for (; x < efpip->obj_w; x++) {\r\n                a_sum += *pixa1 - *pixa2;\r\n                *mem = (unsigned short)min(a_sum * border.alpha >> border._alpha_shift, ALPHA_TEMP_MAX);\r\n\r\n                pixa1 += 4;\r\n                pixa2 += 4;\r\n                mem++;\r\n            }\r\n            for (x = 0; x < border.add_size; x++) {\r\n                a_sum -= *pixa2;\r\n                *mem = (unsigned short)min(a_sum * border.alpha >> border._alpha_shift, ALPHA_TEMP_MAX);\r\n\r\n                pixa2 += 4;\r\n                mem++;\r\n            }\r\n        }\r\n    }\r\n\r\n    void efBorder_horizontal_convolution_alpha_simd2(int thread_id, int thread_num, void* param1, void* param2) { // 51ae0\r\n        auto& border = *reinterpret_cast<Border_t::efBorder_var*>(GLOBAL::exedit_base + OFS::ExEdit::efBorder_var_ptr);\r\n        auto efp = static_cast<ExEdit::Filter*>(param1);\r\n        auto efpip = static_cast<ExEdit::FilterProcInfo*>(param2);\r\n\r\n        int begin_thread = efpip->obj_h * thread_id / thread_num;\r\n        int end_thread = efpip->obj_h * (thread_id + 1) / thread_num;\r\n\r\n        int y = begin_thread;\r\n\r\n        if (enable_avx2()) {\r\n            __m256i offset256 = _mm256_mullo_epi32(_mm256_set_epi32(14, 12, 10, 8, 6, 4, 2, 0), _mm256_set1_epi32(efpip->obj_line));\r\n            __m256i border_alpha256 = _mm256_set1_epi32(border.alpha);\r\n            __m256i a_mem_max256 = _mm256_set1_epi32(ALPHA_TEMP_MAX);\r\n            int end_y = end_thread - 7;\r\n            for (; y < end_y; y += 8) {\r\n\r\n                int* pix1 = (int*)((ExEdit::PixelYCA*)efpip->obj_edit + y * efpip->obj_line) + 1;\r\n                int* pix2 = pix1;\r\n                unsigned short* mem = border.ExEditMemory + y * efpip->obj_line;\r\n\r\n                __m256i a_sum256 = _mm256_setzero_si256();\r\n                __m256i a256;\r\n                int x;\r\n                for (x = 0; x < efpip->obj_w; x++) {\r\n                    a256 = _mm256_srli_epi32(_mm256_i32gather_epi32(pix1, offset256, 4), 16);\r\n                    a_sum256 = _mm256_add_epi32(a_sum256, a256);\r\n                    a256 = _mm256_mullo_epi32(a_sum256, border_alpha256);\r\n                    a256 = _mm256_srli_epi32(a256, border._alpha_shift);\r\n                    a256 = _mm256_min_epu32(a256, a_mem_max256);\r\n\r\n                    for (int i = 0; i < 8; i++) {\r\n                        mem[i * efpip->obj_line] = (unsigned short)a256.m256i_u32[i];\r\n                    }\r\n\r\n                    pix1 += 2;\r\n                    mem++;\r\n                }\r\n\r\n                for (; x < border.add_size; x++) {\r\n                    for (int i = 0; i < 8; i++) {\r\n                        mem[i * efpip->obj_line] = (unsigned short)a256.m256i_u32[i];\r\n                    }\r\n                    mem++;\r\n                }\r\n                for (x = 0; x < efpip->obj_w; x++) {\r\n                    a256 = _mm256_srli_epi32(_mm256_i32gather_epi32(pix2, offset256, 4), 16);\r\n                    a_sum256 = _mm256_sub_epi32(a_sum256, a256);\r\n                    a256 = _mm256_mullo_epi32(a_sum256, border_alpha256);\r\n                    a256 = _mm256_srli_epi32(a256, border._alpha_shift);\r\n                    a256 = _mm256_min_epu32(a256, a_mem_max256);\r\n\r\n                    for (int i = 0; i < 8; i++) {\r\n                        mem[i * efpip->obj_line] = (unsigned short)a256.m256i_u32[i];\r\n                    }\r\n\r\n                    pix2 += 2;\r\n                    mem++;\r\n                }\r\n            }\r\n        }\r\n\r\n        for (; y < end_thread; y++) {\r\n            short* pixa1 = (short*)((ExEdit::PixelYCA*)efpip->obj_edit + y * efpip->obj_line) + 3;\r\n            short* pixa2 = pixa1;\r\n            unsigned short* mem = border.ExEditMemory + y * efpip->obj_line;\r\n            unsigned int a_sum = 0;\r\n            unsigned short a;\r\n\r\n            int x;\r\n            for (x = 0; x < efpip->obj_w; x++) {\r\n                a_sum += *pixa1;\r\n                *mem = a = (unsigned short)min(a_sum * border.alpha >> border._alpha_shift, ALPHA_TEMP_MAX);\r\n\r\n                pixa1 += 4;\r\n                mem++;\r\n            }\r\n\r\n            for (; x < border.add_size; x++) {\r\n                *mem = a;\r\n                mem++;\r\n            }\r\n            for (x = 0; x < efpip->obj_w; x++) {\r\n                a_sum -= *pixa2;\r\n                *mem = (unsigned short)min(a_sum * border.alpha >> border._alpha_shift, ALPHA_TEMP_MAX);\r\n\r\n                pixa2 += 4;\r\n                mem++;\r\n            }\r\n        }\r\n    }\r\n\r\n    void efBorder_vertical_convolution_alpha_and_put_color_simd(int thread_id, int thread_num, void* param1, void* param2) {\r\n        auto& border = *reinterpret_cast<Border_t::efBorder_var*>(GLOBAL::exedit_base + OFS::ExEdit::efBorder_var_ptr);\r\n        auto efp = static_cast<ExEdit::Filter*>(param1);\r\n        auto efpip = static_cast<ExEdit::FilterProcInfo*>(param2);\r\n\r\n        ExEdit::PixelYCA* pix;\r\n        ExEdit::PixelYCA color = { border.color_y, border.color_cb, border.color_cr,0 };\r\n\r\n        unsigned short* mem1;\r\n        unsigned short* mem2;\r\n\r\n        int begin_thread = (efpip->obj_w + border.add_size) * thread_id / thread_num;\r\n        int end_thread = (efpip->obj_w + border.add_size) * (thread_id + 1) / thread_num;\r\n\r\n        int x = begin_thread;\r\n\r\n        if (enable_avx2()) {\r\n            __m256i color256 = _mm256_set1_epi64x(*(long long*)&color);\r\n            __m256i border_alpha256 = _mm256_set1_epi64x(border.alpha);\r\n            __m256i a_pix_max256 = _mm256_set1_epi64x(0x1000);\r\n            int end_x = end_thread - 3;\r\n            for (; x < end_x; x += 4) {\r\n                pix = (ExEdit::PixelYCA*)efpip->obj_temp + x;\r\n                mem1 = mem2 = border.ExEditMemory + x;\r\n\r\n                __m256i a_sum256 = _mm256_setzero_si256();\r\n\r\n                int y;\r\n                for (y = 0; y <= border.add_size; y++) {\r\n                    a_sum256 = _mm256_add_epi64(a_sum256, _mm256_cvtepu16_epi64(*(__m128i*)mem1));\r\n                    __m256i pix256 = _mm256_mullo_epi32(a_sum256, border_alpha256);\r\n                    pix256 = _mm256_srli_epi32(pix256, border._alpha_shift);\r\n                    pix256 = _mm256_min_epi32(pix256, a_pix_max256);\r\n                    pix256 = _mm256_slli_epi64(pix256, 48);\r\n                    *(__m256i*)pix = _mm256_or_si256(pix256, color256);\r\n\r\n                    pix += efpip->obj_line;\r\n                    mem1 += efpip->obj_line;\r\n                }\r\n                for (; y < efpip->obj_h; y++) {\r\n                    a_sum256 = _mm256_sub_epi64(a_sum256, _mm256_cvtepu16_epi64(*(__m128i*)mem2));\r\n                    a_sum256 = _mm256_add_epi64(a_sum256, _mm256_cvtepu16_epi64(*(__m128i*)mem1));\r\n                    __m256i pix256 = _mm256_mullo_epi32(a_sum256, border_alpha256);\r\n                    pix256 = _mm256_srli_epi32(pix256, border._alpha_shift);\r\n                    pix256 = _mm256_min_epi32(pix256, a_pix_max256);\r\n                    pix256 = _mm256_slli_epi64(pix256, 48);\r\n                    *(__m256i*)pix = _mm256_or_si256(pix256, color256);\r\n\r\n                    pix += efpip->obj_line;\r\n                    mem1 += efpip->obj_line;\r\n                    mem2 += efpip->obj_line;\r\n                }\r\n\r\n                for (y = 0; y < border.add_size; y++) {\r\n                    a_sum256 = _mm256_sub_epi64(a_sum256, _mm256_cvtepu16_epi64(*(__m128i*)mem2));\r\n                    __m256i pix256 = _mm256_mullo_epi32(a_sum256, border_alpha256);\r\n                    pix256 = _mm256_srli_epi32(pix256, border._alpha_shift);\r\n                    pix256 = _mm256_min_epi32(pix256, a_pix_max256);\r\n                    pix256 = _mm256_slli_epi64(pix256, 48);\r\n                    *(__m256i*)pix = _mm256_or_si256(pix256, color256);\r\n\r\n                    pix += efpip->obj_line;\r\n                    mem2 += efpip->obj_line;\r\n                }\r\n            }\r\n        }\r\n\r\n        for (; x < end_thread; x++) {\r\n            pix = (ExEdit::PixelYCA*)efpip->obj_temp + x;\r\n            mem1 = mem2 = border.ExEditMemory + x;\r\n\r\n            unsigned int a_sum = 0;\r\n            int y;\r\n            for (y = 0; y <= border.add_size; y++) {\r\n                a_sum += *mem1;\r\n                if (a_sum == 0) {\r\n                    pix->a = 0;\r\n                } else {\r\n                    color.a = (short)min(a_sum * border.alpha >> border._alpha_shift, 0x1000);\r\n                    *pix = color;\r\n                }\r\n\r\n                pix += efpip->obj_line;\r\n                mem1 += efpip->obj_line;\r\n            }\r\n            for (; y < efpip->obj_h; y++) {\r\n                a_sum += *mem1 - *mem2;\r\n                if (a_sum == 0) {\r\n                    pix->a = 0;\r\n                } else {\r\n                    color.a = (short)min(a_sum * border.alpha >> border._alpha_shift, 0x1000);\r\n                    *pix = color;\r\n                }\r\n\r\n                pix += efpip->obj_line;\r\n                mem1 += efpip->obj_line;\r\n                mem2 += efpip->obj_line;\r\n            }\r\n\r\n            for (y = 0; y < border.add_size; y++) {\r\n                a_sum -= *mem2;\r\n                if (a_sum == 0) {\r\n                    pix->a = 0;\r\n                } else {\r\n                    color.a = (short)min(a_sum * border.alpha >> border._alpha_shift, 0x1000);\r\n                    *pix = color;\r\n                }\r\n\r\n                pix += efpip->obj_line;\r\n                mem2 += efpip->obj_line;\r\n            }\r\n        }\r\n    }\r\n\r\n    void efBorder_vertical_convolution_alpha_and_put_color_simd2(int thread_id, int thread_num, void* param1, void* param2) {\r\n        auto& border = *reinterpret_cast<Border_t::efBorder_var*>(GLOBAL::exedit_base + OFS::ExEdit::efBorder_var_ptr);\r\n        auto efp = static_cast<ExEdit::Filter*>(param1);\r\n        auto efpip = static_cast<ExEdit::FilterProcInfo*>(param2);\r\n\r\n        ExEdit::PixelYCA* pix;\r\n        ExEdit::PixelYCA color = { border.color_y, border.color_cb, border.color_cr,0 };\r\n\r\n        unsigned short* mem1;\r\n        unsigned short* mem2;\r\n\r\n        int begin_thread = (efpip->obj_w + border.add_size) * thread_id / thread_num;\r\n        int end_thread = (efpip->obj_w + border.add_size) * (thread_id + 1) / thread_num;\r\n\r\n        int x = begin_thread;\r\n\r\n        if (enable_avx2()) {\r\n            __m256i color256 = _mm256_set1_epi64x(*(long long*)&color);\r\n            __m256i border_alpha256 = _mm256_set1_epi64x(border.alpha);\r\n            __m256i a_pix_max256 = _mm256_set1_epi64x(0x1000);\r\n            int end_x = end_thread - 3;\r\n            for (; x < end_x; x += 4) {\r\n                pix = (ExEdit::PixelYCA*)efpip->obj_temp + x;\r\n                mem1 = mem2 = border.ExEditMemory + x;\r\n\r\n                __m256i a_sum256 = _mm256_setzero_si256();\r\n                __m256i pix256;\r\n\r\n                int y;\r\n                for (y = 0; y < efpip->obj_h; y++) {\r\n                    a_sum256 = _mm256_add_epi64(a_sum256, _mm256_cvtepu16_epi64(*(__m128i*)mem1));\r\n                    pix256 = _mm256_mullo_epi32(a_sum256, border_alpha256);\r\n                    pix256 = _mm256_srli_epi32(pix256, border._alpha_shift);\r\n                    pix256 = _mm256_min_epi32(pix256, a_pix_max256);\r\n                    pix256 = _mm256_slli_epi64(pix256, 48);\r\n                    *(__m256i*)pix = pix256 = _mm256_or_si256(pix256, color256);\r\n\r\n                    pix += efpip->obj_line;\r\n                    mem1 += efpip->obj_line;\r\n                }\r\n                for (; y < border.add_size; y++) {\r\n                    *(__m256i*)pix = pix256;\r\n                    pix += efpip->obj_line;\r\n                }\r\n\r\n                for (y = 0; y < efpip->obj_h; y++) {\r\n                    a_sum256 = _mm256_sub_epi64(a_sum256, _mm256_cvtepu16_epi64(*(__m128i*)mem2));\r\n                    pix256 = _mm256_mullo_epi32(a_sum256, border_alpha256);\r\n                    pix256 = _mm256_srli_epi32(pix256, border._alpha_shift);\r\n                    pix256 = _mm256_min_epi32(pix256, a_pix_max256);\r\n                    pix256 = _mm256_slli_epi64(pix256, 48);\r\n                    *(__m256i*)pix = _mm256_or_si256(pix256, color256);\r\n\r\n                    pix += efpip->obj_line;\r\n                    mem2 += efpip->obj_line;\r\n                }\r\n            }\r\n        }\r\n\r\n        for (; x < end_thread; x++) {\r\n            pix = (ExEdit::PixelYCA*)efpip->obj_temp + x;\r\n            mem1 = mem2 = border.ExEditMemory + x;\r\n\r\n            unsigned int a_sum = 0;\r\n\r\n            int y;\r\n            for (y = 0; y < efpip->obj_h; y++) {\r\n                a_sum += *mem1;\r\n                if (a_sum == 0) {\r\n                    pix->a = color.a = 0;\r\n                } else {\r\n                    color.a = (short)min(a_sum * border.alpha >> border._alpha_shift, 0x1000);\r\n                    *pix = color;\r\n                }\r\n\r\n                pix += efpip->obj_line;\r\n                mem1 += efpip->obj_line;\r\n            }\r\n\r\n            for (; y < border.add_size; y++) {\r\n                *pix = color;\r\n                pix += efpip->obj_line;\r\n            }\r\n\r\n            for (y = 0; y < efpip->obj_h; y++) {\r\n                a_sum -= *mem2;\r\n                if (a_sum == 0) {\r\n                    pix->a = 0;\r\n                } else {\r\n                    color.a = (short)min(a_sum * border.alpha >> border._alpha_shift, 0x1000);\r\n                    *pix = color;\r\n                }\r\n\r\n                pix += efpip->obj_line;\r\n                mem2 += efpip->obj_line;\r\n            }\r\n        }\r\n    }\r\n\r\n    void efBorder_vertical_convolution_alpha_simd(int thread_id, int thread_num, void* param1, void* param2) {\r\n        auto& border = *reinterpret_cast<Border_t::efBorder_var*>(GLOBAL::exedit_base + OFS::ExEdit::efBorder_var_ptr);\r\n        auto efp = static_cast<ExEdit::Filter*>(param1);\r\n        auto efpip = static_cast<ExEdit::FilterProcInfo*>(param2);\r\n\r\n        unsigned short* mem1;\r\n        unsigned short* mem2;\r\n\r\n        int begin_thread = (efpip->obj_w + border.add_size) * thread_id / thread_num;\r\n        int end_thread = (efpip->obj_w + border.add_size) * (thread_id + 1) / thread_num;\r\n\r\n        int x = begin_thread;\r\n\r\n        if (enable_avx2()) {\r\n            __m256i offset256 = _mm256_set_epi32(14, 12, 10, 8, 6, 4, 2, 0);\r\n            __m256i border_alpha256 = _mm256_set1_epi32(border.alpha);\r\n            __m256i a_pix_max256 = _mm256_set1_epi32(0x1000);\r\n            int end_x = end_thread - 7;\r\n            for (; x < end_x; x += 8) {\r\n                int* pixa = (int*)((ExEdit::PixelYCA*)efpip->obj_temp + x) + 1;\r\n\r\n                mem1 = mem2 = border.ExEditMemory + x;\r\n\r\n                __m256i a_sum256 = _mm256_setzero_si256();\r\n\r\n                int y;\r\n                for (y = 0; y <= border.add_size; y++) {\r\n                    a_sum256 = _mm256_add_epi32(a_sum256, _mm256_cvtepu16_epi32(*(__m128i*)mem1));\r\n                    __m256i a256 = _mm256_mullo_epi32(a_sum256, border_alpha256);\r\n                    a256 = _mm256_srli_epi32(a256, border._alpha_shift);\r\n                    a256 = _mm256_min_epu32(a256, a_pix_max256);\r\n                    __m256i pixa256 = _mm256_srli_epi32(_mm256_i32gather_epi32(pixa, offset256, 4), 16);\r\n                    a256 = _mm256_mullo_epi32(a256, pixa256);\r\n                    a256 = _mm256_srli_epi32(a256, 12);\r\n                    short* pixas = (short*)pixa + 1;\r\n                    for (int i = 0; i < 8; i++) {\r\n                        pixas[i * 4] = (unsigned short)a256.m256i_u32[i];\r\n                    }\r\n\r\n                    pixa += efpip->obj_line * 2;\r\n                    mem1 += efpip->obj_line;\r\n                }\r\n\r\n                for (; y < efpip->obj_h; y++) {\r\n                    a_sum256 = _mm256_add_epi32(a_sum256, _mm256_cvtepu16_epi32(*(__m128i*)mem1));\r\n                    a_sum256 = _mm256_sub_epi32(a_sum256, _mm256_cvtepu16_epi32(*(__m128i*)mem2));\r\n                    __m256i a256 = _mm256_mullo_epi32(a_sum256, border_alpha256);\r\n                    a256 = _mm256_srli_epi32(a256, border._alpha_shift);\r\n                    a256 = _mm256_min_epu32(a256, a_pix_max256);\r\n                    __m256i pixa256 = _mm256_srli_epi32(_mm256_i32gather_epi32(pixa, offset256, 4), 16);\r\n                    a256 = _mm256_mullo_epi32(a256, pixa256);\r\n                    a256 = _mm256_srli_epi32(a256, 12);\r\n                    short* pixas = (short*)pixa + 1;\r\n                    for (int i = 0; i < 8; i++) {\r\n                        pixas[i * 4] = (unsigned short)a256.m256i_u32[i];\r\n                    }\r\n\r\n                    pixa += efpip->obj_line * 2;\r\n                    mem1 += efpip->obj_line;\r\n                    mem2 += efpip->obj_line;\r\n                }\r\n\r\n                for (y = 0; y < border.add_size; y++) {\r\n                    a_sum256 = _mm256_sub_epi32(a_sum256, _mm256_cvtepu16_epi32(*(__m128i*)mem2));\r\n                    __m256i a256 = _mm256_mullo_epi32(a_sum256, border_alpha256);\r\n                    a256 = _mm256_srli_epi32(a256, border._alpha_shift);\r\n                    a256 = _mm256_min_epu32(a256, a_pix_max256);\r\n                    __m256i pixa256 = _mm256_srli_epi32(_mm256_i32gather_epi32(pixa, offset256, 4), 16);\r\n                    a256 = _mm256_mullo_epi32(a256, pixa256);\r\n                    a256 = _mm256_srli_epi32(a256, 12);\r\n                    short* pixas = (short*)pixa + 1;\r\n                    for (int i = 0; i < 8; i++) {\r\n                        pixas[i * 4] = (unsigned short)a256.m256i_u32[i];\r\n                    }\r\n\r\n                    pixa += efpip->obj_line * 2;\r\n                    mem2 += efpip->obj_line;\r\n                }\r\n            }\r\n        }\r\n\r\n\r\n        for (; x < end_thread; x++) {\r\n            short* pixa = (short*)((ExEdit::PixelYCA*)efpip->obj_temp + x) + 3;\r\n            mem1 = mem2 = border.ExEditMemory + x;\r\n\r\n            int a;\r\n            unsigned int a_sum = 0;\r\n\r\n            int y;\r\n            for (y = 0; y <= border.add_size; y++) {\r\n                a_sum += *mem1;\r\n                a = a_sum * border.alpha >> border._alpha_shift;\r\n                if (a < 0x1000) {\r\n                    *pixa = (short)(*pixa * a >> 12);\r\n                }\r\n\r\n                pixa += efpip->obj_line * 4;\r\n                mem1 += efpip->obj_line;\r\n            }\r\n\r\n            for (; y < efpip->obj_h; y++) {\r\n                a_sum += *mem1 - *mem2;\r\n                a = a_sum * border.alpha >> border._alpha_shift;\r\n                if (a < 0x1000) {\r\n                    *pixa = (short)(*pixa * a >> 12);\r\n                }\r\n\r\n                pixa += efpip->obj_line * 4;\r\n                mem1 += efpip->obj_line;\r\n                mem2 += efpip->obj_line;\r\n            }\r\n\r\n            for (y = 0; y < border.add_size; y++) {\r\n                a_sum -= *mem2;\r\n                a = a_sum * border.alpha >> border._alpha_shift;\r\n                if (a < 0x1000) {\r\n                    *pixa = (short)(*pixa * a >> 12);\r\n                }\r\n\r\n                pixa += efpip->obj_line * 4;\r\n                mem2 += efpip->obj_line;\r\n            }\r\n        }\r\n    }\r\n\r\n    void efBorder_vertical_convolution_alpha_simd2(int thread_id, int thread_num, void* param1, void* param2) {\r\n        auto& border = *reinterpret_cast<Border_t::efBorder_var*>(GLOBAL::exedit_base + OFS::ExEdit::efBorder_var_ptr);\r\n        auto efp = static_cast<ExEdit::Filter*>(param1);\r\n        auto efpip = static_cast<ExEdit::FilterProcInfo*>(param2);\r\n\r\n        unsigned short* mem1;\r\n        unsigned short* mem2;\r\n\r\n        int begin_thread = (efpip->obj_w + border.add_size) * thread_id / thread_num;\r\n        int end_thread = (efpip->obj_w + border.add_size) * (thread_id + 1) / thread_num;\r\n\r\n        int x = begin_thread;\r\n\r\n        if (enable_avx2()) {\r\n            __m256i offset256 = _mm256_set_epi32(14, 12, 10, 8, 6, 4, 2, 0);\r\n            __m256i border_alpha256 = _mm256_set1_epi32(border.alpha);\r\n            __m256i a_pix_max256 = _mm256_set1_epi32(0x1000);\r\n            int end_x = end_thread - 7;\r\n            for (; x < end_x; x += 8) {\r\n                int* pixa = (int*)((ExEdit::PixelYCA*)efpip->obj_temp + x) + 1;\r\n\r\n                mem1 = mem2 = border.ExEditMemory + x;\r\n\r\n                __m256i a_sum256 = _mm256_setzero_si256();\r\n                __m256i a256;\r\n\r\n                int y;\r\n                for (y = 0; y < efpip->obj_h; y++) {\r\n                    a_sum256 = _mm256_add_epi32(a_sum256, _mm256_cvtepu16_epi32(*(__m128i*)mem1));\r\n                    a256 = _mm256_mullo_epi32(a_sum256, border_alpha256);\r\n                    a256 = _mm256_srli_epi32(a256, border._alpha_shift);\r\n                    a256 = _mm256_min_epu32(a256, a_pix_max256);\r\n                    __m256i pixa256 = _mm256_srli_epi32(_mm256_i32gather_epi32(pixa, offset256, 4), 16);\r\n                    pixa256 = _mm256_mullo_epi32(a256, pixa256);\r\n                    pixa256 = _mm256_srli_epi32(pixa256, 12);\r\n                    short* pixas = (short*)pixa + 1;\r\n                    for (int i = 0; i < 8; i++) {\r\n                        pixas[i * 4] = (unsigned short)pixa256.m256i_u32[i];\r\n                    }\r\n\r\n                    pixa += efpip->obj_line * 2;\r\n                    mem1 += efpip->obj_line;\r\n                }\r\n\r\n                for (; y < border.add_size; y++) {\r\n                    __m256i pixa256 = _mm256_srli_epi32(_mm256_i32gather_epi32(pixa, offset256, 4), 16);\r\n                    pixa256 = _mm256_mullo_epi32(a256, pixa256);\r\n                    pixa256 = _mm256_srli_epi32(pixa256, 12);\r\n                    short* pixas = (short*)pixa + 1;\r\n                    for (int i = 0; i < 8; i++) {\r\n                        pixas[i * 4] = (unsigned short)pixa256.m256i_u32[i];\r\n                    }\r\n\r\n                    pixa += efpip->obj_line * 2;\r\n                }\r\n\r\n                for (y = 0; y < efpip->obj_h; y++) {\r\n                    a_sum256 = _mm256_sub_epi32(a_sum256, _mm256_cvtepu16_epi32(*(__m128i*)mem2));\r\n                    a256 = _mm256_mullo_epi32(a_sum256, border_alpha256);\r\n                    a256 = _mm256_srli_epi32(a256, border._alpha_shift);\r\n                    a256 = _mm256_min_epu32(a256, a_pix_max256);\r\n                    __m256i pixa256 = _mm256_srli_epi32(_mm256_i32gather_epi32(pixa, offset256, 4), 16);\r\n                    pixa256 = _mm256_mullo_epi32(a256, pixa256);\r\n                    pixa256 = _mm256_srli_epi32(pixa256, 12);\r\n                    short* pixas = (short*)pixa + 1;\r\n                    for (int i = 0; i < 8; i++) {\r\n                        pixas[i * 4] = (unsigned short)pixa256.m256i_u32[i];\r\n                    }\r\n\r\n                    pixa += efpip->obj_line * 2;\r\n                    mem2 += efpip->obj_line;\r\n                }\r\n            }\r\n        }\r\n\r\n        for (; x < end_thread; x++) {\r\n            short* pixa = (short*)((ExEdit::PixelYCA*)efpip->obj_temp + x) + 3;\r\n            mem1 = mem2 = border.ExEditMemory + x;\r\n\r\n            int a;\r\n            unsigned int a_sum = 0;\r\n\r\n            int y;\r\n            for (y = 0; y < efpip->obj_h; y++) {\r\n                a_sum += *mem1;\r\n                a = a_sum * border.alpha >> border._alpha_shift;\r\n                if (a < 0x1000) {\r\n                    *pixa = (short)(*pixa * a >> 12);\r\n                }\r\n\r\n                pixa += efpip->obj_line * 4;\r\n                mem1 += efpip->obj_line;\r\n            }\r\n            \r\n            if (a < 0x1000) {\r\n                for (; y < border.add_size; y++) {\r\n                    *pixa = (short)(*pixa * a >> 12);\r\n                    pixa += efpip->obj_line * 4;\r\n                }\r\n            } else {\r\n                pixa += efpip->obj_line * 4 * (border.add_size - efpip->obj_h);\r\n            }\r\n\r\n            for (y = 0; y < efpip->obj_h; y++) {\r\n                a_sum -= *mem2;\r\n                a = a_sum * border.alpha >> border._alpha_shift;\r\n                if (a < 0x1000) {\r\n                    *pixa = (short)(*pixa * a >> 12);\r\n                }\r\n\r\n                pixa += efpip->obj_line * 4;\r\n                mem2 += efpip->obj_line;\r\n            }\r\n        }\r\n    }\r\n\r\n}\r\n#endif // ifdef PATCH_SWITCH_FAST_BORDER\r\n"
  },
  {
    "path": "patch/patch_fast_border.hpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n#ifdef PATCH_SWITCH_FAST_BORDER\r\n\r\n#include <aviutl.hpp>\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util.hpp\"\r\n#include \"global.hpp\"\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch::fast {\r\n\t// init at exedit load\r\n\t// 縁取りのバグ修正＆ちょっとだけ高速化\r\n\tinline class Border_t {\r\n\t\tstatic BOOL func_proc(ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\r\n\r\n\t\tbool enabled = true;\r\n\t\tbool enabled_i;\r\n\t\tinline static const char key[] = \"fast.border\";\r\n\r\n\tpublic:\r\n\r\n\t\tstruct efBorder_var { // 1b1e30\r\n\t\t\tunsigned short* ExEditMemory;\r\n\t\t\tint add_size;\r\n\t\t\tint inv_range;\r\n\t\t\tint shift_x;\r\n\t\t\tint shift_y;\r\n\t\t\tint _undefined;\r\n\t\t\tchar _exdata_def[260]; // 1b1e48 - 1b1f4b\r\n\t\t\tshort color_cb; // 1b1f4c\r\n\t\t\tshort color_cr;\r\n\t\t\tshort color_y;\r\n\t\t\tshort _alpha_shift;// short _padding;\r\n\t\t\tint alpha;\r\n\t\t};\r\n\r\n\r\n\t\tvoid init() {\r\n\t\t\tenabled_i = enabled;\r\n\t\t\tif (!enabled_i)return;\r\n\r\n\t\t\tstore_i32(GLOBAL::exedit_base + OFS::ExEdit::efBorder_func_proc_var_ptr, &func_proc);\r\n\t\t}\r\n\r\n\t\tvoid switching(bool flag) { enabled = flag; }\r\n\r\n\t\tbool is_enabled() { return enabled; }\r\n\t\tbool is_enabled_i() { return enabled_i; }\r\n\r\n\t\tvoid switch_load(ConfigReader& cr) {\r\n\t\t\tcr.regist(key, [this](json_value_s* value) {\r\n\t\t\t\tConfigReader::load_variable(value, enabled);\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tvoid switch_store(ConfigWriter& cw) {\r\n\t\t\tcw.append(key, enabled);\r\n\t\t}\r\n\r\n\t} Border;\r\n} // namespace patch::fast\r\n#endif // ifdef PATCH_SWITCH_FAST_BORDER\r\n"
  },
  {
    "path": "patch/patch_fast_cl.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tThis program is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_CL\n#include <string_view>\n#include <new>\n#include <delayimp.h>\n\n#include \"debug_log.hpp\"\n\n#define __CL_ENABLE_EXCEPTIONS\n#define CL_USE_DEPRECATED_OPENCL_1_2_APIS\n#define CL_VERSION_1_0                              1\n#define CL_VERSION_1_1                              1\n#define CL_VERSION_1_2                              1\n#define CL_VERSION_2_0                              0\n#define CL_VERSION_2_1                              0\n#define CL_VERSION_2_2                              0\n#define CL_VERSION_3_0                              0\n#pragma warning(push)\n#pragma warning(disable: 4005)\n#include <CL/cl.hpp>\n#pragma warning(pop)\n#pragma comment(lib, \"opencl.lib\")\n\n#include \"cryptostring.hpp\"\n#include \"util.hpp\"\n#include \"debug_log.hpp\"\n#include \"config_rw.hpp\"\n\nnamespace patch::fast {\n\ninline class cl_t {\n#pragma region clprogram\n\tinline static auto program_str = make_cryptostring(R\"(\nkernel void PolorTransform(global short* dst, global short* src, int obj_w, int obj_h, int obj_line,\n\tint center_length, int radius, float angle, float uzu, float uzu_a){\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\t\n\tint x_dist = x - radius;\n\tint y_dist = y - radius;\n\tfloat dist = sqrt((float)(x_dist * x_dist + y_dist * y_dist));\n\n\tint range = (int)round((float)obj_w / max(dist, 1.0f) * 57.6115417480468f + uzu_a);\n\t\t\t\t\n\tint yy_t256 = (int)round((float)(((obj_h + center_length) << 8) / radius) * dist);\n\tint yy_range_fr = 0x100 - (yy_t256 & 0xff);\n\tint yy_begin = (yy_t256 >> 8) - center_length;\n\t\t\t\t\n\tint xx_t256 = (int)round((((float)radius - dist) * uzu + angle - atan2((float)y_dist, (float)x_dist)) * (float)obj_w * 40.7436637878417f) - range / 2;\n\tint xx_range_fr = 0x100 - (xx_t256 & 0xff);\n\tint xx_begin = (xx_t256 >> 8) % obj_w;\n\t\t\t\t\n\trange = max(0x100,range);\n\tint yy = yy_begin;\n\n\tint sum_y = 0;\n\tint sum_cb = 0;\n\tint sum_cr = 0;\n\tint sum_a = 0;\n\n\tglobal short* pix;\n\tint src_a;\n\n\tif (0 <= yy && yy < obj_h) {\n\t\tint range_remain = range;\n\t\tint xx = xx_begin;\n\t\tif (xx_range_fr) {\n\t\t\tpix = src + (xx + yy * obj_line) * 4;\n\t\t\tsum_a = pix[3] * xx_range_fr * yy_range_fr >> 16;\n\t\t\tsum_y = pix[0] * sum_a >> 12;\n\t\t\tsum_cb = pix[1] * sum_a >> 12;\n\t\t\tsum_cr = pix[2] * sum_a >> 12;\n\t\t\trange_remain -= xx_range_fr;\n\t\t\txx++;\n\t\t\txx %= obj_w;\n\t\t}\n\t\tint pix_range = range_remain >> 8;\n\t\tfor(int i=0;i<pix_range;i++){\n\t\t\tpix = src + (xx + yy * obj_line) * 4;\n\t\t\tsrc_a = pix[3] * yy_range_fr >> 8;\n\t\t\tsum_y += pix[0] * src_a >> 12;\n\t\t\tsum_cb += pix[1] * src_a >> 12;\n\t\t\tsum_cr += pix[2] * src_a >> 12;\n\t\t\tsum_a += src_a;\n\t\t\txx++;\n\t\t\txx %= obj_w;\n\t\t}\n\t\trange_remain &= 0xff;\n\t\tif (range_remain) {\n\t\t\tpix = src + (xx + yy * obj_line) * 4;\n\t\t\tsrc_a = pix[3] * range_remain * yy_range_fr >> 16;\n\t\t\tsum_y += pix[0] * src_a >> 12;\n\t\t\tsum_cb += pix[1] * src_a >> 12;\n\t\t\tsum_cr += pix[2] * src_a >> 12;\n\t\t\tsum_a += src_a;\n\t\t}\n\t}\n\tyy++;\n\tyy_range_fr = 0x100 - yy_range_fr;\n\tif (0 <= yy && yy < obj_h) {\n\t\tint range_remain = range;\n\t\tint xx = xx_begin;\n\t\tif (xx_range_fr != 0x100) {\n\t\t\tpix = src + (xx + yy * obj_line) * 4;\n\t\t\tsrc_a = pix[3] * xx_range_fr * yy_range_fr >> 16;\n\t\t\tsum_y += pix[0] * src_a >> 12;\n\t\t\tsum_cb += pix[1] * src_a >> 12;\n\t\t\tsum_cr += pix[2] * src_a >> 12;\n\t\t\tsum_a += src_a;\n\t\t\trange_remain -= xx_range_fr;\n\t\t\txx++;\n\t\t\txx %= obj_w;\n\t\t}\n\t\tint pix_range = range_remain >> 8;\n\t\tfor(int i=0;i<pix_range;i++){\n\t\t\tpix = src + (xx + yy * obj_line) * 4;\n\t\t\tsrc_a = pix[3] * yy_range_fr >> 8;\n\t\t\tsum_y += pix[0] * src_a>> 12;\n\t\t\tsum_cb += pix[1] * src_a >> 12;\n\t\t\tsum_cr += pix[2] * src_a >> 12;\n\t\t\tsum_a += src_a;\n\t\t\txx++;\n\t\t\txx %= obj_w;\n\t\t}\n\t\trange_remain &= 0xff;\n\t\tif (range_remain) {\n\t\t\tpix = src + (xx + yy * obj_line) * 4;\n\t\t\tsrc_a = pix[3] * range_remain * yy_range_fr >> 16;\n\t\t\tsum_y += pix[0] * src_a >> 12;\n\t\t\tsum_cb += pix[1] * src_a >> 12;\n\t\t\tsum_cr += pix[2] * src_a >> 12;\n\t\t\tsum_a += src_a;\n\t\t}\n\t}\n\tdst += (x + y * obj_line) * 4;\n\tif (sum_a) {\n\t\tfloat a_float = 4096.0f / (float)sum_a;\n\t\tdst[0] = (short)round((float)sum_y * a_float);\n\t\tdst[1] = (short)round((float)sum_cb * a_float);\n\t\tdst[2] = (short)round((float)sum_cr * a_float);\n\t\tdst[3] = (short)((sum_a << 8) / range);\n\t} else {\n\t\tdst[0] = dst[1] = dst[2] = dst[3] = 0;\n\t}\n}\n)\" R\"(\nkernel void DisplacementMap_move(global short* dst, global short* src, global short* mem,\n\tint obj_w, int obj_h, int obj_line, int param0, int param1, int ox, int oy) {\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\n\tdst += (x + y * obj_line) * 4;\n\tmem += (x + y * obj_line) * 4;\n\n\tint p0 = min(mem[0], mem[obj_line * 4]);\n\tint p1 = max(mem[4], mem[obj_line * 4 + 4]);\n\tp0 = (p0 - 0x800) * param0 / 5;\n\tp1 = (p1 - 0x800) * param0 / 5 + 0x1000;\n\tif (p1 < p0) {\n\t\tint tmp = p0;\n\t\tp0 = p1;\n\t\tp1 = tmp;\n\t}\n\tint xx_range = p1 - p0;\n\tint xx_begin = p0 + (x << 12);\n\tint xx_end = xx_range + xx_begin;\n\n\tp0 = min(mem[1], mem[5]);\n\tp1 = max(mem[obj_line * 4 + 1], mem[obj_line * 4 + 5]);\n\tp0 = (p0 - 0x800) * param1 / 5;\n\tp1 = (p1 - 0x800) * param1 / 5 + 0x1000;\n\tif (p1 < p0) {\n\t\tint tmp = p0;\n\t\tp0 = p1;\n\t\tp1 = tmp;\n\t}\n\tint yy_range = p1 - p0;\n\tint yy_begin = p0 + (y << 12);\n\tint yy_end = yy_range + yy_begin;\n\n\tif (xx_range < 0x1000) {\n\t\txx_begin += (xx_range - 0x1000) >> 1;\n\t\txx_end = xx_begin + 0x1000;\n\t\txx_range = 0x1000;\n\t}\n\tif (yy_range < 0x1000) {\n\t\tyy_begin += (yy_range - 0x1000) >> 1;\n\t\tyy_end = yy_begin + 0x1000;\n\t\tyy_range = 0x1000;\n\t}\n\n\tint xx_level = 12;\n\tint yy_level = 12;\n\twhile (0x20000 < xx_range) {\n\t\txx_begin >>= 1;\n\t\txx_end++;\n\t\txx_end >>= 1;\n\t\txx_range = xx_end - xx_begin;\n\t\txx_level--;\n\t}\n\twhile (0x20000 < yy_range) {\n\t\tyy_begin >>= 1;\n\t\tyy_end++;\n\t\tyy_end >>= 1;\n\t\tyy_range = yy_end - yy_begin;\n\t\tyy_level--;\n\t}\n\txx_level &= 0x1f;\n\tyy_level &= 0x1f;\n\n\txx_begin = max(xx_begin, 0);\n\txx_end = min(xx_end, obj_w << xx_level);\n\tyy_begin = max(yy_begin, 0);\n\tyy_end = min(yy_end, obj_h << yy_level);\n\n\tfloat dsum_y = 0.0f;\n\tfloat dsum_cb = 0.0f;\n\tfloat dsum_cr = 0.0f;\n\tfloat dsum_a = 0.0f;\n\tint yy = yy_begin;\n\twhile (yy < yy_end) {\n\t\tint yy_itr = yy >> yy_level;\n\t\tint sum_y = 0;\n\t\tint sum_cb = 0;\n\t\tint sum_cr = 0;\n\t\tint sum_a = 0;\n\t\tint xx = xx_begin;\n\t\twhile (xx < xx_end) {\n\t\t\tint xx_itr = xx >> xx_level;\n\t\t\tint fraction;\n\t\t\tif (xx & 0xfff) {\n\t\t\t\tfraction = -xx & 0xfff;\n\t\t\t} else {\n\t\t\t\tfraction = min(xx_end - xx, 0x1000);\n\t\t\t}\n\n\t\t\tglobal short* srct = src + (xx_itr + yy_itr * obj_line) * 4;\n\t\t\tint src_a = srct[3] * fraction >> 8;\n\t\t\tsum_y += srct[0] * src_a >> 16;\n\t\t\tsum_cb += srct[1] * src_a >> 16;\n\t\t\tsum_cr += srct[2] * src_a >> 16;\n\t\t\tsum_a += src_a;\n\t\t\txx += fraction;\n\t\t}\n\t\tint fraction;\n\t\tif (yy & 0xfff) {\n\t\t\tfraction = -yy & 0xfff;\n\t\t} else {\n\t\t\tfraction = min(yy_end - yy, 0x1000);\n\t\t}\n\t\tfloat fraction_rate = (float)fraction * 0.000244140625f;\n\t\tdsum_y += (float)sum_y * fraction_rate;\n\t\tdsum_cb += (float)sum_cb * fraction_rate;\n\t\tdsum_cr += (float)sum_cr * fraction_rate;\n\t\tdsum_a += (float)sum_a * fraction_rate;\n\t\tyy += fraction;\n\t}\n\n\tif (256.0f <= dsum_a) {\n\t\tfloat inv_a = 65536.0f / dsum_a;\n\t\tdst[0] = (short)round(dsum_y * inv_a);\n\t\tdst[1] = (short)round(dsum_cb * inv_a);\n\t\tdst[2] = (short)round(dsum_cr * inv_a);\n\t\tdst[3] = (short)round(dsum_a / ((float)yy_range / 1024.0f) / ((float)xx_range / 1024.0f));\n\t} else {\n\t\tdst[0] = dst[1] = dst[2] = dst[3] = 0;\n\t}\n}\nkernel void DisplacementMap_zoom(global short* dst, global short* src, global short* mem,\n\tint obj_w, int obj_h, int obj_line, int param0, int param1, int ox, int oy){\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\n\tdst += (x + y * obj_line) * 4;\n\tmem += (x + y * obj_line) * 4;\n\n\tint xx_min, xx_max, yy_min, yy_max;\n\tint xx_temp, yy_temp;\n\n\tfloat zoom;\n\tfloat xxd = (float)(x * 0x1000 - ox);\n\tif (0 < param0) {\n\t\tzoom = (1024.0f / (float)(param0 + 1000) - 1.0) * 0.00048828125f;\n\t} else {\n\t\tzoom = (float)param0 * -0.00000048828125f;\n\t}\n\tfloat temp = xxd * zoom;\n\txx_min = xx_max = x * 0x1000 + (int)((float)(mem[0] - 0x800) * temp);\n\n\txx_temp = x * 0x1000 + (int)((float)(mem[obj_line * 4] - 0x800) * temp);\n\txx_min = min(xx_min, xx_temp);\n\txx_max = max(xx_max, xx_temp);\n\n\ttemp = (xxd + 4096.0f) * zoom;\n\txx_temp = (x + 1) * 0x1000 + (int)((float)(mem[4] - 0x800) * temp);\n\txx_min = min(xx_min, xx_temp);\n\txx_max = max(xx_max, xx_temp);\n\n\txx_temp = (x + 1) * 0x1000 + (int)((float)(mem[(obj_line + 1) * 4] - 0x800) * temp);\n\tint xx_begin = min(xx_min, xx_temp);\n\tint xx_end = max(xx_max, xx_temp);\n\n\n\tfloat yyd = (float)(y * 0x1000 - oy);\n\tif (0 < param1) {\n\t\tzoom = (1024.0f / (float)(param1 + 1000) - 1.0) * 0.00048828125f;\n\t} else {\n\t\tzoom = (float)param1 * -0.00000048828125f;\n\t}\n\ttemp = yyd * zoom;\n\tyy_min = yy_max = y * 0x1000 + (int)((float)(mem[1] - 0x800) * temp);\n\n\tyy_temp = y * 0x1000 + (int)((float)(mem[5] - 0x800) * temp);\n\tyy_min = min(yy_min, yy_temp);\n\tyy_max = max(yy_max, yy_temp);\n\n\ttemp = (yyd + 4096.0f) * zoom;\n\tyy_temp = (y + 1) * 0x1000 + (int)((float)(mem[(obj_line + 1) * 4] - 0x800) * temp);\n\tyy_min = min(yy_min, yy_temp);\n\tyy_max = max(yy_max, yy_temp);\n\n\tyy_temp = (y + 1) * 0x1000 + (int)((float)(mem[obj_line * 4 + 5] - 0x800) * temp);\n\tint yy_begin = min(yy_min, yy_temp);\n\tint yy_end = max(yy_max, yy_temp);\n\n\tint xx_range = xx_end - xx_begin;\n\tint yy_range = yy_end - yy_begin;\n\n\tif (xx_range < 0x1000) {\n\t\txx_begin += (xx_range - 0x1000) >> 1;\n\t\txx_end = xx_begin + 0x1000;\n\t\txx_range = 0x1000;\n\t}\n\tif (yy_range < 0x1000) {\n\t\tyy_begin += (yy_range - 0x1000) >> 1;\n\t\tyy_end = yy_begin + 0x1000;\n\t\tyy_range = 0x1000;\n\t}\n\n\tint xx_level = 12;\n\tint yy_level = 12;\n\twhile (0x20000 < xx_range) {\n\t\txx_begin >>= 1;\n\t\txx_end++;\n\t\txx_end >>= 1;\n\t\txx_range = xx_end - xx_begin;\n\t\txx_level--;\n\t}\n\twhile (0x20000 < yy_range) {\n\t\tyy_begin >>= 1;\n\t\tyy_end++;\n\t\tyy_end >>= 1;\n\t\tyy_range = yy_end - yy_begin;\n\t\tyy_level--;\n\t}\n\txx_level &= 0x1f;\n\tyy_level &= 0x1f;\n\n\txx_begin = max(xx_begin, 0);\n\txx_end = min(xx_end, obj_w << xx_level);\n\tyy_begin = max(yy_begin, 0);\n\tyy_end = min(yy_end, obj_h << yy_level);\n\n\tfloat dsum_y = 0.0f;\n\tfloat dsum_cb = 0.0f;\n\tfloat dsum_cr = 0.0f;\n\tfloat dsum_a = 0.0f;\n\tint yy = yy_begin;\n\twhile (yy < yy_end) {\n\t\tint yy_itr = yy >> yy_level;\n\t\tint sum_y = 0;\n\t\tint sum_cb = 0;\n\t\tint sum_cr = 0;\n\t\tint sum_a = 0;\n\t\tint xx = xx_begin;\n\t\twhile (xx < xx_end) {\n\t\t\tint xx_itr = xx >> xx_level;\n\t\t\tint fraction;\n\t\t\tif (xx & 0xfff) {\n\t\t\t\tfraction = -xx & 0xfff;\n\t\t\t} else {\n\t\t\t\tfraction = min(xx_end - xx, 0x1000);\n\t\t\t}\n\n\t\t\tglobal short* srct = src + (xx_itr + yy_itr * obj_line) * 4;\n\t\t\tint src_a = srct[3] * fraction >> 8;\n\t\t\tsum_y += srct[0] * src_a >> 16;\n\t\t\tsum_cb += srct[1] * src_a >> 16;\n\t\t\tsum_cr += srct[2] * src_a >> 16;\n\t\t\tsum_a += src_a;\n\t\t\txx += fraction;\n\t\t}\n\t\tint fraction;\n\t\tif (yy & 0xfff) {\n\t\t\tfraction = -yy & 0xfff;\n\t\t} else {\n\t\t\tfraction = min(yy_end - yy, 0x1000);\n\t\t}\n\t\tfloat fraction_rate = (float)fraction * 0.000244140625f;\n\t\tdsum_y += (float)sum_y * fraction_rate;\n\t\tdsum_cb += (float)sum_cb * fraction_rate;\n\t\tdsum_cr += (float)sum_cr * fraction_rate;\n\t\tdsum_a += (float)sum_a * fraction_rate;\n\t\tyy += fraction;\n\t}\n\n\tif (256.0f <= dsum_a) {\n\t\tfloat inv_a = 65536.0f / dsum_a;\n\t\tdst[0] = (short)round(dsum_y * inv_a);\n\t\tdst[1] = (short)round(dsum_cb * inv_a);\n\t\tdst[2] = (short)round(dsum_cr * inv_a);\n\t\tdst[3] = (short)round(dsum_a / ((float)yy_range / 1024.0f) / ((float)xx_range / 1024.0f));\n\t} else {\n\t\tdst[0] = dst[1] = dst[2] = dst[3] = 0;\n\t}\n}\nkernel void DisplacementMap_rot(global short* dst, global short* src, global short* mem,\n\tint obj_w, int obj_h, int obj_line, int param0, int param1, int ox, int oy){\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\n\tdst += (x + y * obj_line) * 4;\n\tmem += (x + y * obj_line) * 4;\n\n\tint xx_min, xx_max, yy_min, yy_max;\n\tint xx_temp, yy_temp;\n\n\tfloat xxd = (float)((x << 12) - ox);\n\tfloat yyd = (float)((y << 12) - oy);\n\tfloat xxd_next = xxd + 4096.0f;\n\tfloat yyd_next = yyd + 4096.0f;\n\tfloat paramrad = (float)param0 * (float)-0.000003067961642955197f;\n\n\tfloat rad = (float)(mem[0] - 0x800) * paramrad;\n\tfloat sinv = sin(rad);\n\tfloat cosv = cos(rad);\n\txx_min = xx_max = (int)(xxd * cosv - yyd * sinv);\n\tyy_min = yy_max = (int)(xxd * sinv + yyd * cosv);\n\n\trad = (float)(mem[4] - 0x800) * paramrad;\n\tsinv = sin(rad);\n\tcosv = cos(rad);\n\txx_temp = (int)(xxd_next * cosv - yyd * sinv);\n\tyy_temp = (int)(xxd_next * sinv + yyd * cosv);\n\txx_min = min(xx_min, xx_temp);\n\txx_max = max(xx_max, xx_temp);\n\tyy_min = min(yy_min, yy_temp);\n\tyy_max = max(yy_max, yy_temp);\n\n\trad = (float)(mem[obj_line * 4] - 0x800) * paramrad;\n\tsinv = sin(rad);\n\tcosv = cos(rad);\n\txx_temp = (int)(xxd * cosv - yyd_next * sinv);\n\tyy_temp = (int)(xxd * sinv + yyd_next * cosv);\n\txx_min = min(xx_min, xx_temp);\n\txx_max = max(xx_max, xx_temp);\n\tyy_min = min(yy_min, yy_temp);\n\tyy_max = max(yy_max, yy_temp);\n\n\trad = (float)(mem[(obj_line + 1) * 4] - 0x800) * paramrad;\n\tsinv = sin(rad);\n\tcosv = cos(rad);\n\txx_temp = (int)(xxd_next * cosv - yyd_next * sinv);\n\tyy_temp = (int)(xxd_next * sinv + yyd_next * cosv);\n\tint xx_begin = min(xx_min, xx_temp) + ox;\n\tint xx_end = max(xx_max, xx_temp) + ox;\n\tint yy_begin = min(yy_min, yy_temp) + oy;\n\tint yy_end = max(yy_max, yy_temp) + oy;\n\n\tint xx_range = xx_end - xx_begin;\n\tint yy_range = yy_end - yy_begin;\n\n\tif (xx_range < 0x1000) {\n\t\txx_begin += (xx_range - 0x1000) >> 1;\n\t\txx_end = xx_begin + 0x1000;\n\t\txx_range = 0x1000;\n\t}\n\tif (yy_range < 0x1000) {\n\t\tyy_begin += (yy_range - 0x1000) >> 1;\n\t\tyy_end = yy_begin + 0x1000;\n\t\tyy_range = 0x1000;\n\t}\n\n\tint xx_level = 12;\n\tint yy_level = 12;\n\twhile (0x20000 < xx_range) {\n\t\txx_begin >>= 1;\n\t\txx_end++;\n\t\txx_end >>= 1;\n\t\txx_range = xx_end - xx_begin;\n\t\txx_level--;\n\t}\n\twhile (0x20000 < yy_range) {\n\t\tyy_begin >>= 1;\n\t\tyy_end++;\n\t\tyy_end >>= 1;\n\t\tyy_range = yy_end - yy_begin;\n\t\tyy_level--;\n\t}\n\txx_level &= 0x1f;\n\tyy_level &= 0x1f;\n\n\txx_begin = max(xx_begin, 0);\n\txx_end = min(xx_end, obj_w << xx_level);\n\tyy_begin = max(yy_begin, 0);\n\tyy_end = min(yy_end, obj_h << yy_level);\n\n\tfloat dsum_y = 0.0f;\n\tfloat dsum_cb = 0.0f;\n\tfloat dsum_cr = 0.0f;\n\tfloat dsum_a = 0.0f;\n\tint yy = yy_begin;\n\twhile (yy < yy_end) {\n\t\tint yy_itr = yy >> yy_level;\n\t\tint sum_y = 0;\n\t\tint sum_cb = 0;\n\t\tint sum_cr = 0;\n\t\tint sum_a = 0;\n\t\tint xx = xx_begin;\n\t\twhile (xx < xx_end) {\n\t\t\tint xx_itr = xx >> xx_level;\n\t\t\tint fraction;\n\t\t\tif (xx & 0xfff) {\n\t\t\t\tfraction = -xx & 0xfff;\n\t\t\t} else {\n\t\t\t\tfraction = min(xx_end - xx, 0x1000);\n\t\t\t}\n\n\t\t\tglobal short* srct = src + (xx_itr + yy_itr * obj_line) * 4;\n\t\t\tint src_a = srct[3] * fraction >> 8;\n\t\t\tsum_y += srct[0] * src_a >> 16;\n\t\t\tsum_cb += srct[1] * src_a >> 16;\n\t\t\tsum_cr += srct[2] * src_a >> 16;\n\t\t\tsum_a += src_a;\n\t\t\txx += fraction;\n\t\t}\n\t\tint fraction;\n\t\tif (yy & 0xfff) {\n\t\t\tfraction = -yy & 0xfff;\n\t\t} else {\n\t\t\tfraction = min(yy_end - yy, 0x1000);\n\t\t}\n\t\tfloat fraction_rate = (float)fraction * 0.000244140625f;\n\t\tdsum_y += (float)sum_y * fraction_rate;\n\t\tdsum_cb += (float)sum_cb * fraction_rate;\n\t\tdsum_cr += (float)sum_cr * fraction_rate;\n\t\tdsum_a += (float)sum_a * fraction_rate;\n\t\tyy += fraction;\n\t}\n\n\tif (256.0f <= dsum_a) {\n\t\tfloat inv_a = 65536.0f / dsum_a;\n\t\tdst[0] = (short)round(dsum_y * inv_a);\n\t\tdst[1] = (short)round(dsum_cb * inv_a);\n\t\tdst[2] = (short)round(dsum_cr * inv_a);\n\t\tdst[3] = (short)round(dsum_a / ((float)yy_range / 1024.0f) / ((float)xx_range / 1024.0f));\n\t} else {\n\t\tdst[0] = dst[1] = dst[2] = dst[3] = 0;\n\t}\n}\n)\" R\"(\nkernel void RadiationalBlur_Media(\n\tglobal short* dst, global short* src, int src_w, int src_h, int buffer_line,\n\tint rb_blur_cx, int rb_blur_cy, int rb_obj_cx, int rb_obj_cy, int rb_range, int rb_pixel_range) {\n\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\tint pixel_itr = x + y * buffer_line;\n\n\tx += rb_obj_cx;\n\ty += rb_obj_cy;\n\tint cx = rb_blur_cx - x;\n\tint cy = rb_blur_cy - y;\n\tint c_dist_times8 = (int)round(sqrt((float)(cx * cx + cy * cy)) * 8.0f);\n\tint range = rb_range * c_dist_times8 / 1000;\n\n\tif (rb_pixel_range < c_dist_times8) {\n\t\trange = rb_pixel_range * rb_range / 1000;\n\t\tc_dist_times8 = rb_pixel_range;\n\t} else if (8 < c_dist_times8) {\n\t\tc_dist_times8 *= 8;\n\t\trange *= 8;\n\t} else if (4 < c_dist_times8) {\n\t\tc_dist_times8 *= 4;\n\t\trange *= 4;\n\t} else if (2 < c_dist_times8) {\n\t\tc_dist_times8 *= 2;\n\t\trange *= 2;\n\t}\n\n\tif (2 <= c_dist_times8 && 2 <= range) {\n\t\tint sum_a = 0;\n\t\tint sum_cr = 0;\n\t\tint sum_cb = 0;\n\t\tint sum_y = 0;\n\n\t\tfor (int i = 0; i < range; i++) {\n\t\t\tint x_itr = x + i * cx / c_dist_times8;\n\t\t\tint y_itr = y + i * cy / c_dist_times8;\n\t\t\tif (0 <= x_itr && x_itr < src_w && 0 <= y_itr && y_itr < src_h) {\n\t\t\t\tshort4 itr = vload4(x_itr + y_itr * buffer_line, src);\n\t\t\t\tint itr_a = itr.w;\n\t\t\t\tsum_a += itr_a;\n\t\t\t\tif (0x1000 < itr_a) {\n\t\t\t\t\titr_a = 0x1000;\n\t\t\t\t}\n\t\t\t\tsum_y += itr.x * itr_a / 4096;\n\t\t\t\tsum_cb += itr.y * itr_a / 4096;\n\t\t\t\tsum_cr += itr.z * itr_a / 4096;\n\t\t\t\t\n\t\t\t}\n\t\t}\n\t\tif (sum_a != 0) {\n\t\t\tvstore4(\n\t\t\t\t(short4)(\n\t\t\t\t\tround(sum_y * 4096.0f / sum_a),\n\t\t\t\t\tround(sum_cb * 4096.0f / sum_a),\n\t\t\t\t\tround(sum_cr * 4096.0f / sum_a),\n\t\t\t\t\tsum_a / range\n\t\t\t\t\t),\n\t\t\t\tpixel_itr, dst\n\t\t\t);\n\t\t} else {\n\t\t\tdst[pixel_itr * 4 + 3] = 0;\n\t\t}\n\t} else {\n\t\tif (x < 0 || y < 0 || src_w <= x || src_h <= y) {\n\t\t\tvstore4((short4)(0, 0, 0, 0), pixel_itr, dst);\n\t\t} else {\n\t\t\tvstore4(vload4(x + y * buffer_line, src), pixel_itr, dst);\n\t\t}\n\t}\n}\n\nkernel void RadiationalBlur_Filter(\n\tglobal short* dst, global short* src, int buffer_line,\n\tint rb_blur_cx, int rb_blur_cy, int rb_range, int rb_pixel_range) {\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\n\tint cx = rb_blur_cx - x;\n\tint cy = rb_blur_cy - y;\n\tint c_dist_times8 = (int)round(sqrt((float)(cx * cx + cy * cy)) * 8.0f);\n\tint range = rb_range * c_dist_times8 / 1000;\n\tif (rb_pixel_range < c_dist_times8) {\n\t\trange = (rb_pixel_range * rb_range) / 1000;\n\t\tc_dist_times8 = rb_pixel_range;\n\t} else if (8 < c_dist_times8) {\n\t\tc_dist_times8 *= 8;\n\t\trange *= 8;\n\t} else if (4 < c_dist_times8) {\n\t\tc_dist_times8 *= 4;\n\t\trange *= 4;\n\t} else if (2 < c_dist_times8) {\n\t\tc_dist_times8 *= 2;\n\t\trange *= 2;\n\t}\n\n\tint offset = (x + y * buffer_line) * 3;\n\tif (2 <= c_dist_times8 && 2 <= range) {\n\t\tint sum_y = 0;\n\t\tint sum_cb = 0;\n\t\tint sum_cr = 0;\n\t\tfor (int i = 0; i < range; i++) {\n\t\t\tint x_itr = x + i * cx / c_dist_times8;\n\t\t\tint y_itr = y + i * cy / c_dist_times8;\n\t\t\tint pix_offset = (x_itr + y_itr * buffer_line) * 3;\n\t\t\tsum_y += src[pix_offset];\n\t\t\tsum_cb += src[++pix_offset];\n\t\t\tsum_cr += src[++pix_offset];\n\t\t}\n\n\t\tdst[offset] = (short)(sum_y / range);\n\t\tdst[++offset] = (short)(sum_cb / range);\n\t\tdst[++offset] = (short)(sum_cr / range);\n\t} else {\n\t\tdst[offset] = src[offset];\n\t\tdst[offset + 1] = src[offset + 1];\n\t\tdst[offset + 2] = src[offset + 2];\n\t}\n}\nkernel void RadiationalBlur_Filter_Far(\n\tglobal short* dst, global short* src, int scene_w, int scene_h, int buffer_line,\n\tint rb_blur_cx, int rb_blur_cy, int rb_range, int rb_pixel_range) {\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\n\tint cx = rb_blur_cx - x;\n\tint cy = rb_blur_cy - y;\n\tint c_dist_times8 = (int)round(sqrt((float)(cx * cx + cy * cy)) * 8.0f);\n\tint range = rb_range * c_dist_times8 / 1000;\n\tif (rb_pixel_range < c_dist_times8) {\n\t\trange = (rb_pixel_range * rb_range) / 1000;\n\t\tc_dist_times8 = rb_pixel_range;\n\t} else if (8 < c_dist_times8) {\n\t\tc_dist_times8 *= 8;\n\t\trange *= 8;\n\t} else if (4 < c_dist_times8) {\n\t\tc_dist_times8 *= 4;\n\t\trange *= 4;\n\t} else if (2 < c_dist_times8) {\n\t\tc_dist_times8 *= 2;\n\t\trange *= 2;\n\t}\n\n\tint offset = (x + y * buffer_line) * 3;\n\tif (2 <= c_dist_times8 && 2 <= range) {\n\t\tint sum_y = 0;\n\t\tint sum_cb = 0;\n\t\tint sum_cr = 0;\n\t\tfor (int i = 0; i < range; i++) {\n\t\t\tint x_itr = x + i * cx / c_dist_times8;\n\t\t\tint y_itr = y + i * cy / c_dist_times8;\n\t\t\tif (0 <= x_itr && 0 <= y_itr && x_itr < scene_w && y_itr < scene_h) {\n\t\t\t\tint pix_offset = (x_itr + y_itr * buffer_line) * 3;\n\t\t\t\tsum_y += src[pix_offset];\n\t\t\t\tsum_cb += src[++pix_offset];\n\t\t\t\tsum_cr += src[++pix_offset];\n\t\t\t}\n\t\t}\n\n\t\tdst[offset] = (short)(sum_y / range);\n\t\tdst[++offset] = (short)(sum_cb / range);\n\t\tdst[++offset] = (short)(sum_cr / range);\n\t} else {\n\t\tdst[offset] = src[offset];\n\t\tdst[offset + 1] = src[offset + 1];\n\t\tdst[offset + 2] = src[offset + 2];\n\t}\n}\n)\" R\"(\nkernel void Flash(global short* dst, global short* src, int src_w, int src_h, int exedit_buffer_line,\n\tint g_cx,\n\tint g_cy,\n\tint g_range,\n\tint g_pixel_range,\n\tint g_temp_x,\n\tint g_temp_y,\n\tint g_r_intensity\n) {\n\n\tint xi = get_global_id(0);\n\tint yi = get_global_id(1);\n\n\tint x = xi + g_temp_x;\n\tint y = yi + g_temp_y;\n\n\tint pixel_itr = xi + yi * exedit_buffer_line;\n\n\tint cx = g_cx - x;\n\tint cy = g_cy - y;\n\tint c_dist_times8 = (int)round(sqrt((float)(cx * cx + cy * cy)) * 8.0f);\n\tint range = g_range * c_dist_times8 / 1000;\n\n\tif (g_pixel_range < c_dist_times8) {\n\t\trange = g_pixel_range * g_range / 1000;\n\t\tc_dist_times8 = g_pixel_range;\n\t} else if (8 < c_dist_times8) {\n\t\tc_dist_times8 *= 8;\n\t\trange *= 8;\n\t} else if (4 < c_dist_times8) {\n\t\tc_dist_times8 *= 4;\n\t\trange *= 4;\n\t} else if (2 < c_dist_times8) {\n\t\tc_dist_times8 *= 2;\n\t\trange *= 2;\n\t}\n\n\tint sum_y, sum_cb, sum_cr;\n\n\tif (2 <= c_dist_times8 && 2 <= range) {\n\t\tsum_y = sum_cb = sum_cr = 0;\n\t\tfor (int i = 0; i < range; i++) {\n\t\t\tint x_itr = x + i * cx / c_dist_times8;\n\t\t\tint y_itr = y + i * cy / c_dist_times8;\n\n\t\t\tif (0 <= x_itr && 0 <= y_itr && x_itr < src_w && y_itr < src_h) {\n\t\t\t\tshort4 itr = vload4(x_itr + y_itr * exedit_buffer_line, src);\n\t\t\t\tif (itr.w != 0) {\n\t\t\t\t\tif (itr.w < 4096) {\n\t\t\t\t\t\tsum_y += itr.x * itr.w / 4096;\n\t\t\t\t\t\tsum_cb += itr.y * itr.w / 4096;\n\t\t\t\t\t\tsum_cr += itr.z * itr.w / 4096;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsum_y += itr.x;\n\t\t\t\t\t\tsum_cb += itr.y;\n\t\t\t\t\t\tsum_cr += itr.z;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tsum_y /= range;\n\t\tsum_cb /= range;\n\t\tsum_cr /= range;\n\t} else {\n\t\tif (x < 0 || y < 0 || src_w <= x || src_h <= y) {\n\t\t\tvstore4((short4)(0, 0, 0, 0), pixel_itr, dst);\n\t\t\treturn;\n\t\t} else {\n\t\t\tshort4 itr = vload4(x + y * exedit_buffer_line, src);\n\t\t\tsum_y = itr.x * itr.w / 4096;\n\t\t\tsum_cb = itr.y * itr.w / 4096;\n\t\t\tsum_cr = itr.z * itr.w / 4096;\n\t\t}\n\t}\n\n\tint ya = sum_y - g_r_intensity;\n\tif (ya < 1) {\n\t\tvstore4((short4)(0, 0, 0, 0), pixel_itr, dst);\n\t} else {\n\t\tsum_cb -= g_r_intensity * sum_cb / sum_y;\n\t\tsum_cr -= g_r_intensity * sum_cr / sum_y;\n\t\tif (ya < 4096) {\n\t\t\tvstore4(\n\t\t\t\t(short4)(\n\t\t\t\t\t4096,\n\t\t\t\t\tsum_cb * 4096 / ya,\n\t\t\t\t\tsum_cr * 4096 / ya,\n\t\t\t\t\tya\n\t\t\t\t\t),\n\t\t\t\tpixel_itr, dst\n\t\t\t);\n\t\t} else {\n\t\t\tvstore4(\n\t\t\t\t(short4)(\n\t\t\t\t\tya,\n\t\t\t\t\tsum_cb,\n\t\t\t\t\tsum_cr,\n\t\t\t\t\t4096\n\t\t\t\t\t),\n\t\t\t\tpixel_itr, dst\n\t\t\t);\n\t\t}\n\t}\n}\nkernel void FlashColor(global short* dst, global short* src, int src_w, int src_h, int exedit_buffer_line,\n\tint g_cx,\n\tint g_cy,\n\tint g_range,\n\tint g_pixel_range,\n\tint g_temp_x,\n\tint g_temp_y,\n\tint g_r_intensity,\n\tshort g_color_y,\n\tshort g_color_cb,\n\tshort g_color_cr\n) {\n\n\tint xi = get_global_id(0);\n\tint yi = get_global_id(1);\n\n\tint x = xi + g_temp_x;\n\tint y = yi + g_temp_y;\n\n\tint pixel_itr = xi + yi * exedit_buffer_line;\n\n\tint cx = g_cx - x;\n\tint cy = g_cy - y;\n\tint c_dist_times8 = (int)round(sqrt((float)(cx * cx + cy * cy)) * 8.0f);\n\tint range = g_range * c_dist_times8 / 1000;\n\tif (g_pixel_range < c_dist_times8) {\n\t\trange = g_pixel_range * g_range / 1000;\n\t\tc_dist_times8 = g_pixel_range;\n\t} else if (8 < c_dist_times8) {\n\t\tc_dist_times8 *= 8;\n\t\trange *= 8;\n\t} else if (4 < c_dist_times8) {\n\t\tc_dist_times8 *= 4;\n\t\trange *= 4;\n\t} else if (2 < c_dist_times8) {\n\t\tc_dist_times8 *= 2;\n\t\trange *= 2;\n\t}\n\tint itr_y, itr_cb, itr_cr;\n\n\tif (2 <= c_dist_times8 && 2 <= range) {\n\t\tint sum_a = 0;\n\t\tfor (int i = 0; i < range; i++) {\n\t\t\tint x_itr = x + i * cx / c_dist_times8;\n\t\t\tint y_itr = y + i * cy / c_dist_times8;\n\n\t\t\tif (0 <= x_itr && 0 <= y_itr && x_itr < src_w && y_itr < src_h) {\n\t\t\t\tshort4 itr = vload4(x_itr + y_itr * exedit_buffer_line, src);\n\t\t\t\tint itr_a = itr.w;\n\t\t\t\tif (itr_a != 0) {\n\t\t\t\t\tif (itr_a < 4096) {\n\t\t\t\t\t\tsum_a += itr_a;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsum_a += 4096;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tsum_a /= range;\n\t\titr_y = g_color_y * sum_a / 4096;\n\t\titr_cb = g_color_cb * sum_a / 4096;\n\t\titr_cr = g_color_cr * sum_a / 4096;\n\t} else {\n\t\tif (x < 0 || y < 0 || src_w <= x || src_h <= y) {\n\t\t\tvstore4((short4)(0, 0, 0, 0), pixel_itr, dst);\n\t\t\treturn;\n\t\t} else {\n\t\t\tshort4 itr = vload4(x + y * exedit_buffer_line, src);\n\t\t\tint itr_a = itr.w;\n\t\t\titr_y = g_color_y * itr_a / 4096;\n\t\t\titr_cb = g_color_cb * itr_a / 4096;\n\t\t\titr_cr = g_color_cr * itr_a / 4096;\n\t\t}\n\t}\n\n\tint ya = itr_y - g_r_intensity;\n\tif (ya < 1) {\n\t\tvstore4((short4)(0, 0, 0, 0), pixel_itr, dst);\n\t} else {\n\t\titr_cb -= g_r_intensity * itr_cb / itr_y;\n\t\titr_cr -= g_r_intensity * itr_cr / itr_y;\n\t\tif (ya < 4096) {\n\t\t\tvstore4(\n\t\t\t\t(short4)(\n\t\t\t\t\t4096,\n\t\t\t\t\titr_cb * 4096 / ya,\n\t\t\t\t\titr_cr * 4096 / ya,\n\t\t\t\t\tya\n\t\t\t\t\t),\n\t\t\t\tpixel_itr, dst\n\t\t\t);\n\t\t} else {\n\t\t\tvstore4(\n\t\t\t\t(short4)(\n\t\t\t\t\tya,\n\t\t\t\t\titr_cb,\n\t\t\t\t\titr_cr,\n\t\t\t\t\t4096\n\t\t\t\t\t),\n\t\t\t\tpixel_itr, dst\n\t\t\t);\n\t\t}\n\t}\n}\n)\" R\"(\nkernel void DirectionalBlur_Media(global short* dst, global short* src, int obj_w, int obj_h, int obj_line,\n\tint x_begin, int x_end, int x_step, int y_begin, int y_end, int y_step, int range) {\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\tint pix_range = range * 2 + 1;\n\n\tdst += (x + y * obj_line) * 4;\n\n\tint sum_y = 0;\n\tint sum_cb = 0;\n\tint sum_cr = 0;\n\tint sum_a = 0;\n\n\tint x_itr = ((x + x_begin) << 16) + 0x8000 - range * x_step;\n\tint y_itr = ((y + y_begin) << 16) + 0x8000 - range * y_step;\n\n\tfor (int n = 0; n < pix_range; n++) {\n\t\tint xx = x_itr >> 16;\n\t\tint yy = y_itr >> 16;\n\t\tif (0 <= xx && xx < obj_w && 0 <= yy && yy < obj_h) {\n\t\t\tglobal short* pix = src + (xx + yy * obj_line) * 4;\n\t\t\tint src_a = min((int)pix[3], 0x1000);\n\t\t\tsum_y += pix[0] * src_a >> 12;\n\t\t\tsum_cb += pix[1] * src_a >> 12;\n\t\t\tsum_cr += pix[2] * src_a >> 12;\n\t\t\tsum_a += src_a;\n\t\t}\n\t\tx_itr += x_step;\n\t\ty_itr += y_step;\n\t}\n\tif (0 < sum_a) {\n\t\tfloat a_float = 4096.0f / (float)sum_a;\n\t\tdst[0] = (short)round((float)sum_y * a_float);\n\t\tdst[1] = (short)round((float)sum_cb * a_float);\n\t\tdst[2] = (short)round((float)sum_cr * a_float);\n\t} else {\n\t\tdst[0] = dst[1] = dst[2] = 0;\n\t}\n\tdst[3] = (short)(sum_a / pix_range);\n}\nkernel void DirectionalBlur_original_size(global short* dst, global short* src, int obj_w, int obj_h, int obj_line,\n\tint x_step, int y_step, int range) {\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\tint pix_range = range * 2 + 1;\n\n\tdst += (x + y * obj_line) * 4;\n\n\tint x_itr = (x << 16) + 0x8000 - range * x_step;\n\tint y_itr = (y << 16) + 0x8000 - range * y_step;\n\n\tint sum_y = 0;\n\tint sum_cb = 0;\n\tint sum_cr = 0;\n\tint sum_a = 0;\n\tint cnt = 0;\n\n\tfor (int n = 0; n < pix_range; n++) {\n\t\tint xx = x_itr >> 16;\n\t\tint yy = y_itr >> 16;\n\t\tif (0 <= xx && xx < obj_w && 0 <= yy && yy < obj_h) {\n\t\t\tglobal short* pix = src + (xx + yy * obj_line) * 4;\n\t\t\tint src_a = min((int)pix[3], 0x1000);\n\t\t\tsum_y += pix[0] * src_a >> 12;\n\t\t\tsum_cb += pix[1] * src_a >> 12;\n\t\t\tsum_cr += pix[2] * src_a >> 12;\n\t\t\tsum_a += src_a;\n\t\t\tcnt++;\n\t\t}\n\t\tx_itr += x_step;\n\t\ty_itr += y_step;\n\t}\n\tif(cnt == 0) cnt = 0xffffff;\n\tif (0 < sum_a) {\n\t\tfloat a_float = 4096.0f / (float)sum_a;\n\t\tdst[0] = (short)round((float)sum_y * a_float);\n\t\tdst[1] = (short)round((float)sum_cb * a_float);\n\t\tdst[2] = (short)round((float)sum_cr * a_float);\n\t} else {\n\t\tdst[0] = dst[1] = dst[2] = 0;\n\t}\n\tdst[3] = (short)(sum_a / cnt);\n}\nkernel void DirectionalBlur_Filter(global short* dst, global short* src, int scene_w, int scene_h, int scene_line,\n\tint x_step, int y_step, int range) {\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\tint pix_range = range * 2 + 1;\n\n\tdst += (x + y * scene_line) * 3;\n\n\tint x_itr = (x << 16) + 0x8000 - range * x_step;\n\tint y_itr = (y << 16) + 0x8000 - range * y_step;\n\n\tint sum_y = 0;\n\tint sum_cb = 0;\n\tint sum_cr = 0;\n\tint cnt = 0;\n\tfor (int n = 0; n < pix_range; n++) {\n\t\tint xx = x_itr >> 16;\n\t\tint yy = y_itr >> 16;\n\t\tif (0 <= xx && xx < scene_w && 0 <= yy && yy < scene_h) {\n\t\t\tglobal short* pix = src + (xx + yy * scene_line) * 3;\n\t\t\tsum_y += pix[0];\n\t\t\tsum_cb += pix[1];\n\t\t\tsum_cr += pix[2];\n\t\t\tcnt++;\n\t\t}\n\t\tx_itr += x_step;\n\t\ty_itr += y_step;\n\t}\n\tif(cnt == 0) cnt = 0xffffff;\n\tdst[0] = (short)(sum_y / cnt);\n\tdst[1] = (short)(sum_cb / cnt);\n\tdst[2] = (short)(sum_cr / cnt);\n}\n)\" R\"(\nkernel void LensBlur_Media(global char* dst, global char* src, int obj_w, int obj_h, int obj_line,\n\tint range, int rangep05_sqr, int range_t3m1, int rangem1_sqr) {\n\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\n\tint top = -min(y, range);\n\tint bottom = min(obj_h - y - 1, range);\n\tint left = -min(x, range);\n\tint right = min(obj_w - x - 1, range);\n\n\tfloat sum_y = 0.0f;\n\tint sum_cb = 0;\n\tint sum_cr = 0;\n\tint sum_a = 0;\n\n\tint cor_sum = 0;\n\n\tint offset = (x + left + (y + top) * obj_line) * 8;\n\n\tfor (int yy = top; yy <= bottom; yy++) {\n\t\tint sqr = yy * yy + left * left;\n\t\tint offset2 = offset;\n\t\tfor (int xx = left; xx <= right; xx++) {\n\t\t\tif (sqr < rangep05_sqr) {\n\t\t\t\tint cor_a;\n\t\t\t\tif (rangem1_sqr < sqr) {\n\t\t\t\t\tcor_a = ((rangep05_sqr - sqr) << 12) / range_t3m1;\n\t\t\t\t} else {\n\t\t\t\t\tcor_a = 4096;\n\t\t\t\t}\n\t\t\t\tcor_sum += cor_a;\n\t\t\t\tcor_a = *(global short*)&src[offset2 + 6] * cor_a >> 12;\n\t\t\t\tsum_y += *(global float*)&src[offset2] * (float)cor_a;\n\t\t\t\tsum_cb += src[offset2 + 4] * cor_a;\n\t\t\t\tsum_cr += src[offset2 + 5] * cor_a;\n\t\t\t\tsum_a += cor_a;\n\t\t\t}\n\t\t\tsqr += 1 + xx * 2;\n\t\t\toffset2 += 8;\n\t\t}\n\t\toffset += obj_line * 8;\n\t}\n\n\tdst += (x + y * obj_line) * 8;\n\tif (0 < sum_a) {\n\t\t*(global float*)dst = sum_y / (float)sum_a;\n\t\tdst[4] = (char)(((sum_a >> 1) + sum_cb) / sum_a);\n\t\tdst[5] = (char)(((sum_a >> 1) + sum_cr) / sum_a);\n\t\t*(global short*)&dst[6] = (short)round((float)sum_a * (4096.0f / (float)cor_sum));\n\t} else {\n\t\t*(global int*)dst = 0;\n\t\t*(global int*)&dst[4] = 0;\n\t}\n}\n\nkernel void LensBlur_Filter(global char* dst, global char* src, int scene_w, int scene_h, int scene_line,\n\tint range, int rangep05_sqr, int range_t3m1, int rangem1_sqr) {\n\n\tint x = get_global_id(0);\n\tint y = get_global_id(1);\n\n\tint top = -min(y, range);\n\tint bottom = min(scene_h - y - 1, range);\n\tint left = -min(x, range);\n\tint right = min(scene_w - x - 1, range);\n\n\tshort tofloat[2];\n\tfloat sum_y = 0.0f;\n\tint sum_cb = 0;\n\tint sum_cr = 0;\n\tint sum_a = 0;\n\n\tint offset = (x + left + (y + top) * scene_line) * 6;\n\n\tfor (int yy = top; yy <= bottom; yy++) {\n\n\t\tint sqr = yy * yy + left * left;\n\t\tint offset2 = offset;\n\n\t\tfor (int xx = left; xx <= right; xx++) {\n\t\t\tif (sqr < rangep05_sqr) {\n\t\t\t\tint cor_a;\n\t\t\t\tif (rangem1_sqr < sqr) {\n\t\t\t\t\tcor_a = ((rangep05_sqr - sqr) << 12) / range_t3m1;\n\t\t\t\t} else {\n\t\t\t\t\tcor_a = 4096;\n\t\t\t\t}\n\t\t\t\ttofloat[0] = *(global short*)&src[offset2];\n\t\t\t\ttofloat[1] = *(global short*)&src[offset2 + 2];\n\t\t\t\tsum_y += *(float*)tofloat * (float)cor_a;\n\t\t\t\tsum_cb += src[offset2 + 4] * cor_a;\n\t\t\t\tsum_cr += src[offset2 + 5] * cor_a;\n\t\t\t\tsum_a += cor_a;\n\t\t\t}\n\t\t\tsqr += 1 + xx * 2;\n\t\t\toffset2 += 6;\n\t\t}\n\t\toffset += scene_line * 6;\n\t}\n\n\tdst += (x + y * scene_line) * 6;\n\t*(float*)tofloat = sum_y / (float)sum_a;\n\t*(global short*)&dst[0] = tofloat[0];\n\t*(global short*)&dst[2] = tofloat[1];\n\tdst[4] = (char)(((sum_a >> 1) + sum_cb) / sum_a);\n\tdst[5] = (char)(((sum_a >> 1) + sum_cr) / sum_a);\n}\n)\");\n#pragma endregion\n\n\ttemplate<size_t i, class Head>\n\tstatic void KernelSetArg(cl::Kernel& kernel, Head head) {\n\t\tkernel.setArg(i, head);\n\t}\n\n\ttemplate<size_t i, class Head, class... Tail>\n\tstatic void KernelSetArg(cl::Kernel& kernel, Head head, Tail... tail) {\n\t\tkernel.setArg(i, head);\n\t\tKernelSetArg<i + 1>(kernel, tail...);\n\t}\n\n\tbool enabled = true;\n\tbool enabled_i;\n\tinline static const char key[] = \"fast.cl\";\n\npublic:\n\tcl::Platform platform;\n\tstd::vector<cl::Device> devices;\n\tcl::Context context;\n\n\tstd::byte program_mem[sizeof(cl::Program)];\n\tbool program_opt;\n\tcl::CommandQueue queue;\n\n\tHMODULE CLLib;\n\n\tenum class State {\n\t\tNotYet,\n\t\tOK,\n\t\tFailed\n\t} state;\n\n\tcl_t() :state(State::NotYet), CLLib(NULL) {}\n\t~cl_t() {\n\t\tFreeLibrary(CLLib);\n\t\tif (program_opt) {\n\t\t\tauto program = reinterpret_cast<cl::Program*>(program_mem);\n\t\t\tprogram->~Program();\n\t\t}\n\t}\n\n\tbool init() {\n\t\tenabled_i = enabled;\n\n\t\tif (!enabled_i)return true;\n\n\t\tif (![]() {\n\t\t\t__try {\n\t\t\t\tauto load_ret = __HrLoadAllImportsForDll(\"OpenCL.dll\");\n\t\t\t\t\tif (FAILED(load_ret)) {\n\t\t\t\t\t\t[load_ret]() {\n\t\t\t\t\t\t\tdebug_log(\"OpenCL not available {}\", \"delay load failed {}\"_fmt(load_ret));\n\t\t\t\t\t\t}();\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\t__except ([](int code) {\n\t\t\t\tif (\n\t\t\t\t\tcode == VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND) ||\n\t\t\t\t\tcode == VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND)\n\t\t\t\t) {\n\t\t\t\t\treturn EXCEPTION_EXECUTE_HANDLER;\n\t\t\t\t}\n\t\t\t\treturn EXCEPTION_CONTINUE_SEARCH;\n\t\t\t} (GetExceptionCode())) {\n\t\t\t\tdebug_log(\"OpenCL not available {}\\n\", \"delay load exception\");\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}()) {\n\t\t\tstate = State::Failed;\n\t\t\treturn false;\n\t\t}\n\n\n\t\tswitch (state) {\n\t\tcase State::NotYet:\n\t\t\ttry {\n\t\t\t\tcl::Platform::get(&platform);\n\t\t\t\tplatform.getDevices(CL_DEVICE_TYPE_ALL, &devices);\n\t\t\t\tcontext = cl::Context(devices);\n\t\t\t\tnew (&program_mem[0]) cl::Program(context, program_str.get(), false);\n\t\t\t\tprogram_opt = true;\n\t\t\t\treinterpret_cast<cl::Program*>(program_mem)->build();\n\t\t\t\tprogram_str.re_encrypt();\n\n\t\t\t\tstruct DeviceInfo {\n\t\t\t\t\tcl::Device device;\n\t\t\t\t\tcl_device_type device_type;\n\t\t\t\t\t//std::string version;\n\n\t\t\t\t\tconstexpr bool operator<(const DeviceInfo& rhs) {\n\t\t\t\t\t\t//if (auto cmpver = version <=> rhs.version; cmpver != 0) return cmpver < 0;\n\t\t\t\t\t\treturn this->device_type < rhs.device_type;\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tstd::vector<DeviceInfo> device_info;\n\t\t\t\tfor (const auto& d : devices) {\n\t\t\t\t\tdevice_info.emplace_back(\n\t\t\t\t\t\td,\n\t\t\t\t\t\td.getInfo<CL_DEVICE_TYPE>()\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tstd::sort(device_info.rbegin(), device_info.rend());\n\t\t\t\tauto device_itr = devices.begin();\n\t\t\t\tfor (const auto& di : device_info) {\n\t\t\t\t\t*device_itr = di.device;\n\t\t\t\t\tdevice_itr++;\n\t\t\t\t}\n\n\t\t\t\tqueue = cl::CommandQueue(context, devices[0]);\n\t\t\t}\n\t\t\tcatch (const cl::Error& err) {\n\t\t\t\tprogram_str.re_encrypt();\n\n\t\t\t\tif (err.err() == CL_BUILD_PROGRAM_FAILURE) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (program_opt) {\n\t\t\t\t\t\t\tauto program = reinterpret_cast<cl::Program*>(program_mem);\n\t\t\t\t\t\t\tif (auto status = program->getBuildInfo<CL_PROGRAM_BUILD_STATUS>(devices[0]); status == CL_BUILD_ERROR) {\n\t\t\t\t\t\t\t\tdebug_log(\n\t\t\t\t\t\t\t\t\t\"OpenCL Error (CL_BUILD_PROGRAM_FAILURE : CL_BUILD_ERROR)\\n{}\",\n\t\t\t\t\t\t\t\t\tprogram->getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[0]).c_str()\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tdebug_log(\"OpenCL Error (CL_BUILD_PROGRAM_FAILURE)\\nstatus: {}\", status);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tprogram_opt = false;\n\t\t\t\t\t\t\tprogram->~Program();\n\t\t\t\t\t\t\tstate = State::Failed;\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcatch (const cl::Error& err) {\n\t\t\t\t\t\tdebug_log(\"OpenCL Error\\n({}) {}\", err.err(), err.what());\n\t\t\t\t\t\tstate = State::Failed;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdebug_log(\"OpenCL Error\\n({}) {}\", err.err(), err.what());\n\t\t\t\tstate = State::Failed;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tstate = State::OK;\n\t\t\t[[fallthrough]];\n\t\tcase State::OK:\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t\t}\n\t}\n\n\ttemplate<class... Args>\n\tcl::Kernel readyKernel(std::string_view name, Args&&... args) {\n\t\tauto program = reinterpret_cast<cl::Program*>(program_mem);\n\t\tcl::Kernel kernel(*program, name.data());\n\t\tKernelSetArg<0>(kernel, args...);\n\t\treturn kernel;\n\t}\n\n\tvoid switching(bool flag) {\n\t\tenabled = flag;\n\t}\n\n\tbool is_enabled() { return enabled; }\n\tbool is_enabled_i() { return enabled_i; }\n\t\n\tvoid switch_load(ConfigReader& cr) {\n\t\tcr.regist(key, [this](json_value_s* value) {\n\t\t\tConfigReader::load_variable(value, enabled);\n\t\t});\n\t}\n\n\tvoid switch_store(ConfigWriter& cw) {\n\t\tcw.append(key, enabled);\n\t}\n} cl;\n\n} // namespace patch::fast\n\n#endif\n"
  },
  {
    "path": "patch/patch_fast_create_figure.cpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"patch_fast_create_figure.hpp\"\r\n#ifdef PATCH_SWITCH_FAST_CREATE_FIGURE\r\n\r\n#include \"debug_log.hpp\"\r\n\r\n//#define PATCH_STOPWATCH\r\n#include \"stopwatch.hpp\"\r\n\r\nnamespace patch::fast {\r\n    static stopwatch_mem sw;\r\n\r\n    void __cdecl CreateFigure_t::CreateFigure_circle(int thread_id, int thread_num, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) { // 73d20\r\n        auto& figure = *reinterpret_cast<CreateFigure_var*>(GLOBAL::exedit_base + OFS::ExEdit::CreateFigure_var_ptr);\r\n\r\n        int begin_thread = thread_id * (efpip->obj_h + 1 >> 1) / thread_num;\r\n        int end_thread = (thread_id + 1) * (efpip->obj_h + 1 >> 1) / thread_num;\r\n        int obj_half_w = efpip->obj_w + 1 >> 1;\r\n        ExEdit::PixelYCA yca = { figure.color_y, figure.color_cb, figure.color_cr, 0 };\r\n\r\n        int inner = 0;\r\n        int sizesq = figure.size * figure.size;\r\n        int size_t8 = sizesq * 8 / efpip->obj_w * figure.size / efpip->obj_h;\r\n\r\n        if (figure.line_width) {\r\n            inner = figure.size - figure.line_width * 2 - 1;\r\n            if (inner < 0) {\r\n                inner = 0;\r\n            }\r\n        }\r\n\r\n        int yy = begin_thread * 2 - efpip->obj_h + 1;\r\n\r\n\r\n        if (inner) {\r\n            int inner_t8 = (((figure.size * inner * 8) / efpip->obj_w) * figure.size) / efpip->obj_h;\r\n            int innersq = inner * inner;\r\n            for (int y = begin_thread; y < end_thread; y++) {\r\n                int yysq = yy * figure.size / efpip->obj_h;\r\n                yysq *= yysq;\r\n                int innersq_myyaq = yysq + inner_t8 - innersq;\r\n\r\n                ExEdit::PixelYCA* pixlt = (ExEdit::PixelYCA*)efpip->obj_edit + efpip->obj_line * y;\r\n                ExEdit::PixelYCA* pixlb = (ExEdit::PixelYCA*)efpip->obj_edit + efpip->obj_line * (efpip->obj_h - 1 - y);\r\n                ExEdit::PixelYCA* pixrt = pixlt + efpip->obj_w - 1;\r\n                ExEdit::PixelYCA* pixrb = pixlb + efpip->obj_w - 1;\r\n                int xx = 1 - efpip->obj_w;\r\n                for (int x = 0; x < obj_half_w; x++) {\r\n                    int xxsq = xx * figure.size / efpip->obj_w;\r\n                    xxsq *= xxsq;\r\n                    int a = sizesq - yysq - xxsq;\r\n                    if (a <= 0) {\r\n                        a = 0;\r\n                    } else if (a < size_t8) {\r\n                        a = a * 0x1000 / size_t8;\r\n                    } else {\r\n                        a = 0x1000;\r\n                    }\r\n                    int a_inner = xxsq + innersq_myyaq;\r\n                    if (a_inner < 0) {\r\n                        a = 0;\r\n                    } else if (a_inner < inner_t8) {\r\n                        a = a * a_inner / inner_t8;\r\n                    }\r\n\r\n                    yca.a = (short)a;\r\n                    *pixlt = *pixrt = *pixlb = *pixrb = yca;\r\n                    pixlt++; pixrt--; pixlb++; pixrb--;\r\n                    xx += 2;\r\n                }\r\n                yy += 2;\r\n            }\r\n        } else {\r\n            for (int y = begin_thread; y < end_thread; y++) {\r\n                int yysq = yy * figure.size / efpip->obj_h;\r\n                yysq *= yysq;\r\n                ExEdit::PixelYCA* pixlt = (ExEdit::PixelYCA*)efpip->obj_edit + efpip->obj_line * y;\r\n                ExEdit::PixelYCA* pixlb = (ExEdit::PixelYCA*)efpip->obj_edit + efpip->obj_line * (efpip->obj_h - 1 - y);\r\n                ExEdit::PixelYCA* pixrt = pixlt + efpip->obj_w - 1;\r\n                ExEdit::PixelYCA* pixrb = pixlb + efpip->obj_w - 1;\r\n                int xx = 1 - efpip->obj_w;\r\n                int x;\r\n                for (x = 0; x < obj_half_w; x++) {\r\n                    int xxsq = xx * figure.size / efpip->obj_w;\r\n                    xxsq *= xxsq;\r\n                    int a = sizesq - yysq - xxsq;\r\n                    if (a <= 0) {\r\n                        a = 0;\r\n                    } else if (a < size_t8) {\r\n                        a = a * 0x1000 / size_t8;\r\n                    } else {\r\n                        break;\r\n                    }\r\n                    yca.a = (short)a;\r\n                    *pixlt = *pixrt = *pixlb = *pixrb = yca;\r\n                    pixlt++; pixrt--; pixlb++; pixrb--;\r\n                    xx += 2;\r\n                }\r\n                yca.a = 0x1000;\r\n                for (; x < obj_half_w; x++) {\r\n                    *pixlt = *pixrt = *pixlb = *pixrb = yca;\r\n                    pixlt++; pixrt--; pixlb++; pixrb--;\r\n                }\r\n                yy += 2;\r\n            }\r\n        }\r\n    }\r\n\r\n\r\n    void __cdecl CreateFigure_t::CreateFigure_polygons(int thread_id, int thread_num, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\r\n        auto& figure = *reinterpret_cast<CreateFigure_var*>(GLOBAL::exedit_base + OFS::ExEdit::CreateFigure_var_ptr);\r\n        \r\n        int xp[10];\r\n        int xylen[10];\r\n        int yp[10];\r\n\r\n        int inner = 0;\r\n        if (figure.type == 10) {\r\n            double angle = 0.0;\r\n            double sina0 = 0.0;\r\n            double cosa0 = 1.0;\r\n            for (int i = 0; i < 10; i += 2) {\r\n                angle += 1.256637061435917;\r\n                double sina1 = sin(angle);\r\n                double cosa1 = cos(angle);\r\n                double xx0 = sina1 * 65536.0;\r\n                xp[i] = (int)xx0;\r\n                double yy0 = cosa1 * 65536.0;\r\n                yp[i] = (int)-yy0;\r\n                double xx1 = sina0 * 65536.0;\r\n                xp[i + 1] = (int)xx1;\r\n                double yy1 = cosa0 * 65536.0;\r\n                yp[i + 1] = (int)-yy1;\r\n                xylen[i] = (int)((sina0 * xx0 + cosa0 * yy0) * (double)figure.size) + 0x20000;\r\n                xylen[i + 1] = (int)((sina1 * xx1 + cosa1 * yy1) * (double)figure.size) + 0x20000;\r\n                sina0 = sina1;\r\n                cosa0 = cosa1;\r\n            }\r\n            if (figure.line_width) {\r\n                inner = (int)((double)figure.line_width * 40642.48062015503876) + 0x20000;\r\n            }\r\n        } else {\r\n            double angle_rate = 3.141592653589793 / (double)figure.type;\r\n            double angle0 = 0.0;\r\n            for (int i = 0; i < figure.type; i++) {\r\n                double angle1 = angle_rate + angle0;\r\n                double xx = sin(angle1) * 65536.0;\r\n                xp[i] = (int)xx;\r\n                double yy = cos(angle1) * 65536.0;\r\n                yp[i] = (int)-yy;\r\n                xylen[i] = (int)((sin(angle0) * xx + cos(angle0) * yy) * (double)figure.size) + 0x20000;\r\n                angle0 = angle1 + angle_rate;\r\n            }\r\n            if (figure.line_width) {\r\n                inner = (int)((double)(figure.line_width << 17) * cos(angle_rate)) + 0x20000;\r\n            }\r\n        }\r\n\r\n\r\n        int thread_begin = thread_id * efpip->obj_h / thread_num;\r\n        int thread_end = (thread_id + 1) * efpip->obj_h / thread_num;\r\n        int obj_half_w = efpip->obj_w + 1 >> 1;\r\n        int a;\r\n        ExEdit::PixelYCA yca = { figure.color_y, figure.color_cb, figure.color_cr, 0 };\r\n\r\n        double angle_rate = (double)figure.type / 6.283185307179586;\r\n        int yy = (thread_begin * 2 - efpip->obj_h) + 1;\r\n        for (int y = thread_begin; y < thread_end; y++) {\r\n\r\n            ExEdit::PixelYCA* pixl = (ExEdit::PixelYCA*)efpip->obj_edit + efpip->obj_line * y;\r\n            ExEdit::PixelYCA* pixr = pixl + efpip->obj_w - 1;\r\n\r\n            int xx = 1 - efpip->obj_w;\r\n            for (int x = 0; x < obj_half_w; x++) {\r\n                int pt = (int)((atan2((double)-xx, (double)yy) + 3.141592653589793) * angle_rate) % figure.type;\r\n                int dist = xylen[pt] - xp[pt] * xx - yp[pt] * yy;\r\n                if (0x40000 <= dist) {\r\n                    a = 0x1000;\r\n                } else if (dist <= 0) {\r\n                    a = 0;\r\n                } else {\r\n                    a = dist >> 6;\r\n                }\r\n\r\n                if (inner) {\r\n                    int subinner = dist - inner;\r\n                    if (0 < subinner) {\r\n                        if (subinner < 0x40000) {\r\n                            a = a * (0x40000 - subinner) >> 18;\r\n                        } else {\r\n                            a = 0;\r\n                        }\r\n                    }\r\n                }\r\n                yca.a = (short)a;\r\n                *pixl = *pixr = yca;\r\n                pixl++; pixr--;\r\n                xx += 2;\r\n            }\r\n            yy += 2;\r\n        }\r\n    }\r\n\r\n} // namespace patch::fast\r\n#endif // ifdef PATCH_SWITCH_FAST_CREATE_FIGURE\r\n"
  },
  {
    "path": "patch/patch_fast_create_figure.hpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n#ifdef PATCH_SWITCH_FAST_CREATE_FIGURE\r\n\r\n#include <aviutl.hpp>\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util.hpp\"\r\n#include \"global.hpp\"\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch::fast {\r\n\t// init at exedit load\r\n\t// ＜図形、部分フィルタ、マスク、ディスプレイスメントマップ＞の図形（円、三角、五角、六角、星）の計算を効率化し少しだけ速度アップ\r\n\tinline class CreateFigure_t {\r\n\t\tstatic void __cdecl CreateFigure_circle(int thread_id, int thread_num, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\r\n\t\tstatic void __cdecl CreateFigure_polygons(int thread_id, int thread_num, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\r\n\r\n\t\tbool enabled = true;\r\n\t\tbool enabled_i;\r\n\t\tinline static const char key[] = \"fast.create_figure\";\r\n\r\n\tpublic:\r\n\r\n\t\tstruct CreateFigure_var { // 1e4798\r\n\t\t\tint type;\r\n\t\t\tint _padding1;\r\n\t\t\tchar _module_path[260];\r\n\t\t\tint type_num;\r\n\t\t\tshort color_cb; // 1e48a8\r\n\t\t\tshort _padding2;\r\n\t\t\tint line_width;\r\n\t\t\tshort color_cr;\r\n\t\t\tshort _padding3;\r\n\t\t\tHMENU popup;\r\n\t\t\tshort color_y;\r\n\t\t\tshort _padding4;\r\n\t\t\tint size;\r\n\t\t};\r\n\r\n\r\n\r\n\t\tvoid init() {\r\n\t\t\tenabled_i = enabled;\r\n\t\t\tif (!enabled_i)return;\r\n\r\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + OFS::ExEdit::CreateFigure_circle_func_call, &CreateFigure_circle);\r\n\t\t\t{\r\n\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::CreateFigure_circle_func_mt_call, 4);\r\n\t\t\t\th.store_i32(0, &CreateFigure_circle);\r\n\t\t\t}\r\n\r\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + OFS::ExEdit::CreateFigure_polygons_func_call, &CreateFigure_polygons);\r\n\t\t\t{\r\n\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::CreateFigure_polygons_func_mt_call, 4);\r\n\t\t\t\th.store_i32(0, &CreateFigure_polygons);\r\n\t\t\t}\r\n\t\t\t\r\n\r\n\t\t}\r\n\r\n\t\tvoid switching(bool flag) { enabled = flag; }\r\n\r\n\t\tbool is_enabled() { return enabled; }\r\n\t\tbool is_enabled_i() { return enabled_i; }\r\n\r\n\t\tvoid switch_load(ConfigReader& cr) {\r\n\t\t\tcr.regist(key, [this](json_value_s* value) {\r\n\t\t\t\tConfigReader::load_variable(value, enabled);\r\n\t\t\t\t});\r\n\t\t}\r\n\r\n\t\tvoid switch_store(ConfigWriter& cw) {\r\n\t\t\tcw.append(key, enabled);\r\n\t\t}\r\n\r\n\t} create_figure;\r\n} // namespace patch::fast\r\n#endif // ifdef PATCH_SWITCH_FAST_CREATE_FIGURE\r\n"
  },
  {
    "path": "patch/patch_fast_directionalblur.cpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"patch_fast_directionalblur.hpp\"\r\n#ifdef PATCH_SWITCH_FAST_DIRECTIONALBLUR\r\n\r\n#include \"debug_log.hpp\"\r\n#include \"patch_fast_cl.hpp\"\r\n\r\n//#define PATCH_STOPWATCH\r\n#include \"stopwatch.hpp\"\r\n\r\nnamespace patch::fast {\r\n    static stopwatch_mem sw;\r\n\r\n    BOOL __cdecl DirectionalBlur_t::func_proc(ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\r\n        efDirectionalBlur_var& dblur = *(efDirectionalBlur_var*)uintptr_t(reinterpret_cast<efDirectionalBlur_var*>(GLOBAL::exedit_base + OFS::ExEdit::efDirectionalBlur_var_ptr));\r\n\r\n        int range = efp->track[0];\r\n        if (range == 0) {\r\n            return TRUE;\r\n        }\r\n\r\n        double rad = efp->track[1] * 0.00174532925199433;\r\n        int x_step = (int)(sin(rad) * -65536.0); // PI / 1800\r\n        int y_step = (int)(cos(rad) * 65536.0);\r\n\r\n        int temp_range = range * std::abs(x_step) >> 16;\r\n        dblur.x_begin = -temp_range;\r\n        dblur.x_end = efpip->obj_w + temp_range;\r\n\r\n        temp_range = range * std::abs(y_step) >> 16;\r\n        dblur.y_begin = -temp_range;\r\n        dblur.y_end = efpip->obj_h + temp_range;\r\n\r\n        if (range < 16) {\r\n            x_step = (int)(x_step + (x_step >> 0x1f & 3)) >> 2;\r\n            y_step = (int)(y_step + (y_step >> 0x1f & 3)) >> 2;\r\n            range <<= 2;\r\n        } else if (range < 32) {\r\n            x_step >>= 1;\r\n            y_step >>= 1;\r\n            range <<= 1;\r\n        } else if (128 < range) {\r\n            x_step *= range;\r\n            y_step *= range;\r\n            x_step = (int)(x_step + (x_step >> 0x1f & 0x7f)) >> 7;\r\n            y_step = (int)(y_step + (y_step >> 0x1f & 0x7f)) >> 7;\r\n            range = 128;\r\n        }\r\n\r\n        if (has_flag(efpip->flag, ExEdit::FilterProcInfo::Flag::fast_preview) && 50 < range) {\r\n            dblur.range = 50;\r\n            dblur.x_step = (x_step * range) / 50;\r\n            dblur.y_step = (y_step * range) / 50;\r\n        } else {\r\n            dblur.range = range;\r\n            dblur.x_step = x_step;\r\n            dblur.y_step = y_step;\r\n        }\r\n        if (efp->check[0] == 0) {\r\n\r\n            int oversize = dblur.x_end - dblur.x_begin - efpip->obj_line;\r\n            if (0 < oversize) {\r\n                oversize++;\r\n                oversize >>= 1;\r\n                dblur.x_begin += oversize;\r\n                dblur.x_end -= oversize;\r\n            }\r\n\r\n            oversize = dblur.y_end - dblur.y_begin - efpip->obj_max_h;\r\n            if (0 < oversize) {\r\n                oversize++;\r\n                oversize >>= 1;\r\n                dblur.y_begin += oversize;\r\n                dblur.y_end -= oversize;\r\n            }\r\n\r\n\r\n            try {\r\n                const auto src_size = efpip->obj_line * efpip->obj_h * sizeof(ExEdit::PixelYCA);\r\n                cl::Buffer clmem_src(cl.context, CL_MEM_READ_ONLY, src_size);\r\n                cl.queue.enqueueWriteBuffer(clmem_src, CL_TRUE, 0, src_size, efpip->obj_edit);\r\n\r\n                const auto dst_size = efpip->obj_line * (dblur.y_end - dblur.y_begin) * sizeof(ExEdit::PixelYCA);\r\n                cl::Buffer clmem_dst(cl.context, CL_MEM_WRITE_ONLY, dst_size);\r\n\r\n                cl::Kernel kernel;\r\n                kernel = cl.readyKernel(\r\n                    \"DirectionalBlur_Media\",\r\n                    clmem_dst,\r\n                    clmem_src,\r\n                    efpip->obj_w,\r\n                    efpip->obj_h,\r\n                    efpip->obj_line,\r\n                    dblur.x_begin,\r\n                    dblur.x_end,\r\n                    dblur.x_step,\r\n                    dblur.y_begin,\r\n                    dblur.y_end,\r\n                    dblur.y_step,\r\n                    dblur.range\r\n                );\r\n                cl.queue.enqueueNDRangeKernel(kernel, { 0,0 }, { (size_t)(dblur.x_end - dblur.x_begin), (size_t)(dblur.y_end - dblur.y_begin) });\r\n\r\n                cl.queue.enqueueReadBuffer(clmem_dst, CL_TRUE, 0, dst_size, efpip->obj_temp);\r\n            }\r\n            catch (const cl::Error& err) {\r\n                debug_log(\"OpenCL Error\\n({}) {}\", err.err(), err.what());\r\n                efp->aviutl_exfunc->exec_multi_thread_func(reinterpret_cast<void(__cdecl*)(int, int, void*, void*)>(GLOBAL::exedit_base + 0xc4a0), efp, efpip);\r\n                return TRUE;\r\n            }\r\n\r\n            \r\n\r\n            efpip->obj_data.cx += (efpip->obj_w - dblur.x_end - dblur.x_begin) * 0x800;\r\n            efpip->obj_data.cy += (efpip->obj_h - dblur.y_end - dblur.y_begin) * 0x800;\r\n            efpip->obj_w = dblur.x_end - dblur.x_begin;\r\n            efpip->obj_h = dblur.y_end - dblur.y_begin;\r\n\r\n        } else { // サイズ固定\r\n            dblur.x_begin = 0;\r\n            dblur.y_begin = 0;\r\n            dblur.x_end = efpip->obj_w;\r\n            dblur.y_end = efpip->obj_h;\r\n\r\n            try {\r\n                const auto src_size = efpip->obj_line * efpip->obj_h * sizeof(ExEdit::PixelYCA);\r\n                cl::Buffer clmem_src(cl.context, CL_MEM_READ_ONLY, src_size);\r\n                cl.queue.enqueueWriteBuffer(clmem_src, CL_TRUE, 0, src_size, efpip->obj_edit);\r\n\r\n                cl::Buffer clmem_dst(cl.context, CL_MEM_WRITE_ONLY, src_size);\r\n\r\n                cl::Kernel kernel;\r\n                kernel = cl.readyKernel(\r\n                    \"DirectionalBlur_original_size\",\r\n                    clmem_dst,\r\n                    clmem_src,\r\n                    efpip->obj_w,\r\n                    efpip->obj_h,\r\n                    efpip->obj_line,\r\n                    dblur.x_step,\r\n                    dblur.y_step,\r\n                    dblur.range\r\n                );\r\n                cl.queue.enqueueNDRangeKernel(kernel, { 0,0 }, { (size_t)efpip->obj_w, (size_t)efpip->obj_h });\r\n\r\n                cl.queue.enqueueReadBuffer(clmem_dst, CL_TRUE, 0, src_size, efpip->obj_temp);\r\n            }\r\n            catch (const cl::Error& err) {\r\n                debug_log(\"OpenCL Error\\n({}) {}\", err.err(), err.what());\r\n                efp->aviutl_exfunc->exec_multi_thread_func(reinterpret_cast<void(__cdecl*)(int, int, void*, void*)>(GLOBAL::exedit_base + 0xc720), efp, efpip);\r\n                return TRUE;\r\n            }\r\n            \r\n\r\n        }\r\n        std::swap(efpip->obj_temp, efpip->obj_edit);\r\n\r\n        return TRUE;\r\n    }\r\n\r\n\r\n\r\n    void __cdecl DirectionalBlur_t::filter_mt_wrap00cae8(AviUtl::MultiThreadFunc func, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\r\n        efDirectionalBlur_var& dblur = *(efDirectionalBlur_var*)uintptr_t(reinterpret_cast<efDirectionalBlur_var*>(GLOBAL::exedit_base + OFS::ExEdit::efDirectionalBlur_var_ptr));\r\n\r\n        try {\r\n            const auto src_size = efpip->scene_line * efpip->scene_h * sizeof(ExEdit::PixelYC);\r\n            cl::Buffer clmem_src(cl.context, CL_MEM_READ_ONLY, src_size);\r\n            cl.queue.enqueueWriteBuffer(clmem_src, CL_TRUE, 0, src_size, efpip->frame_edit);\r\n\r\n            cl::Buffer clmem_dst(cl.context, CL_MEM_WRITE_ONLY, src_size);\r\n\r\n            cl::Kernel kernel;\r\n            kernel = cl.readyKernel(\r\n                \"DirectionalBlur_Filter\",\r\n                clmem_dst,\r\n                clmem_src,\r\n                efpip->scene_w,\r\n                efpip->scene_h,\r\n                efpip->scene_line,\r\n                dblur.x_step,\r\n                dblur.y_step,\r\n                dblur.range\r\n            );\r\n            cl.queue.enqueueNDRangeKernel(kernel, { 0,0 }, { (size_t)efpip->scene_w, (size_t)efpip->scene_h });\r\n\r\n            cl.queue.enqueueReadBuffer(clmem_dst, CL_TRUE, 0, src_size, efpip->frame_temp);\r\n        }\r\n        catch (const cl::Error& err) {\r\n            debug_log(\"OpenCL Error\\n({}) {}\", err.err(), err.what());\r\n            efp->aviutl_exfunc->exec_multi_thread_func(func, efp, efpip);\r\n        }\r\n    }\r\n\r\n\r\n\r\n} // namespace patch::fast\r\n#endif // ifdef PATCH_SWITCH_FAST_DIRECTIONALBLUR\r\n"
  },
  {
    "path": "patch/patch_fast_directionalblur.hpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n#ifdef PATCH_SWITCH_FAST_DIRECTIONALBLUR\r\n#include <exedit.hpp>\r\n#include \"util_magic.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"global.hpp\"\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch::fast {\r\n    // init at exedit load\r\n    // 方向ブラーの高速化\r\n    inline class DirectionalBlur_t {\r\n        static BOOL func_proc(ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\r\n        static void __cdecl filter_mt_wrap00cae8(AviUtl::MultiThreadFunc func, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\r\n\r\n        bool enabled = true;\r\n        bool enabled_i;\r\n        inline static const char key[] = \"fast.directionalblur\";\r\n    public:\r\n\r\n        struct efDirectionalBlur_var { // d75cc\r\n            int x_step; \r\n            int y_step;\r\n            int x_end;\r\n            int y_end;\r\n            int x_begin;\r\n            int range;\r\n            int y_begin;\r\n        };\r\n\r\n\r\n        void init() {\r\n            enabled_i = enabled;\r\n\r\n            if (!enabled_i)return;\r\n\r\n            store_i32(GLOBAL::exedit_base + OFS::ExEdit::efDirectionalBlur_func_proc_ptr, &func_proc);\r\n\r\n            OverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::efDirectionalBlur_Filter_mt_func_call, 6);\r\n            h.store_i16(0, '\\x90\\xe8'); // nop; call (rel32)\r\n            h.replaceNearJmp(2, &filter_mt_wrap00cae8);\r\n\r\n\r\n        }\r\n\r\n        void switch_load(ConfigReader& cr) {\r\n            cr.regist(key, [this](json_value_s* value) {\r\n                ConfigReader::load_variable(value, enabled);\r\n                });\r\n        }\r\n\r\n        void switch_store(ConfigWriter& cw) {\r\n            cw.append(key, enabled);\r\n        }\r\n\r\n    } DirectionalBlur;\r\n} // namespace patch::fast\r\n#endif // ifdef PATCH_SWITCH_FAST_DIRECTIONALBLUR\r\n"
  },
  {
    "path": "patch/patch_fast_displacementmap.cpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"patch_fast_displacementmap.hpp\"\r\n#ifdef PATCH_SWITCH_FAST_DISPLACEMENTMAP\r\n\r\n#include <numbers>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util_int.hpp\"\r\n#include \"patch_fast_cl.hpp\"\r\n#include \"debug_log.hpp\"\r\n\r\n//#define PATCH_STOPWATCH\r\n#include \"stopwatch.hpp\"\r\nstatic stopwatch_mem sw;\r\n\r\nnamespace patch::fast {\r\n    BOOL DisplacementMap_t::mt_func(AviUtl::MultiThreadFunc original_func_ptr, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\r\n        if constexpr (true) {\r\n            if (256 < efpip->obj_w * efpip->obj_h) {\r\n                sw.start();\r\n                try {\r\n\r\n                    efDisplacementMap_var& dmap = *reinterpret_cast<efDisplacementMap_var*>(GLOBAL::exedit_base + OFS::ExEdit::efDisplacementMap_var_ptr);\r\n                    auto& ExEditMemory = *(void**)(GLOBAL::exedit_base + OFS::ExEdit::memory_ptr);\r\n\r\n                    const auto buf_size = efpip->obj_line * efpip->obj_h * sizeof(ExEdit::PixelYCA);\r\n                    cl::Buffer clmem_src1(cl.context, CL_MEM_READ_ONLY, buf_size);\r\n                    cl.queue.enqueueWriteBuffer(clmem_src1, CL_TRUE, 0, buf_size, efpip->obj_edit);\r\n\r\n                    cl::Buffer clmem_src2(cl.context, CL_MEM_READ_ONLY, buf_size);\r\n                    cl.queue.enqueueWriteBuffer(clmem_src2, CL_TRUE, 0, buf_size, ExEditMemory);\r\n\r\n                    cl::Buffer clmem_dst(cl.context, CL_MEM_WRITE_ONLY, buf_size);\r\n\r\n                    int calc_id = ((ExEdit::Exdata::efDisplacementMap*)efp->exdata_ptr)->calc;\r\n                    if (calc_id < 0 && 2 < calc_id) {\r\n                        calc_id = 0;\r\n                    }\r\n\r\n                    auto kernel = cl.readyKernel(\r\n                        cl_func_name[calc_id],\r\n                        clmem_dst,\r\n                        clmem_src1,\r\n                        clmem_src2,\r\n                        efpip->obj_w,\r\n                        efpip->obj_h,\r\n                        efpip->obj_line,\r\n                        dmap.param0,\r\n                        dmap.param1,\r\n                        dmap.ox,\r\n                        dmap.oy\r\n                    );\r\n                    cl.queue.enqueueNDRangeKernel(kernel, { 0,0 }, { (size_t)efpip->obj_w ,(size_t)efpip->obj_h });\r\n\r\n                    cl.queue.enqueueReadBuffer(clmem_dst, CL_TRUE, 0, buf_size, efpip->obj_temp);\r\n                }\r\n                catch (const cl::Error& err) {\r\n                    debug_log(\"OpenCL Error\\n({}) {}\", err.err(), err.what());\r\n                    return efp->aviutl_exfunc->exec_multi_thread_func(original_func_ptr, efp, efpip);\r\n                }\r\n                sw.stop();\r\n                return TRUE;\r\n            } else {\r\n                return efp->aviutl_exfunc->exec_multi_thread_func(original_func_ptr, efp, efpip);\r\n            }\r\n        } else {\r\n            sw.start();\r\n            const auto ret = efp->aviutl_exfunc->exec_multi_thread_func(original_func_ptr, efp, efpip);\r\n            sw.stop();\r\n            return ret;\r\n        }\r\n    }\r\n}\r\n#endif // ifdef PATCH_SWITCH_FAST_DISPLACEMENTMAP\r\n"
  },
  {
    "path": "patch/patch_fast_displacementmap.hpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n#ifdef PATCH_SWITCH_FAST_DISPLACEMENTMAP\r\n\r\n#include <aviutl.hpp>\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util.hpp\"\r\n#include \"global.hpp\"\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch::fast {\r\n\t// init at exedit load\r\n\t// ディスプレイスメントマップの高速化\r\n\tinline class DisplacementMap_t {\r\n\t\tstatic BOOL mt_func(AviUtl::MultiThreadFunc original_func_ptr, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\r\n\r\n\t\tinline static const char* cl_func_name[3] = { \"DisplacementMap_move\",\"DisplacementMap_zoom\",\"DisplacementMap_rot\" };\r\n\r\n\t\tbool enabled = true;\r\n\t\tbool enabled_i;\r\n\t\tinline static const char key[] = \"fast.displacementmap\";\r\n\r\n\tpublic:\r\n\r\n\t\tstruct efDisplacementMap_var { // 11effc\r\n\t\t\tint ox; // 11effc\r\n\t\t\tint oy; // 11f000\r\n\t\t\tvoid** mode_func; // 11f004\r\n\t\t\tint param1; // 11f008\r\n\t\t\tint param0; // 11f00c\r\n\t\t};\r\n\r\n\t\tvoid init() {\r\n\t\t\tenabled_i = enabled;\r\n\t\t\tif (!enabled_i)return;\r\n\r\n\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::efDisplacementMap_mt_func_call, 6);\r\n\t\t\th.store_i16(0, '\\x90\\xe8'); // nop; call (rel32)\r\n\t\t\th.replaceNearJmp(2, &mt_func);\r\n\r\n\t\t}\r\n\r\n\t\tvoid switching(bool flag) { enabled = flag; }\r\n\r\n\t\tbool is_enabled() { return enabled; }\r\n\t\tbool is_enabled_i() { return enabled_i; }\r\n\r\n\t\tvoid switch_load(ConfigReader& cr) {\r\n\t\t\tcr.regist(key, [this](json_value_s* value) {\r\n\t\t\t\tConfigReader::load_variable(value, enabled);\r\n\t\t\t\t});\r\n\t\t}\r\n\r\n\t\tvoid switch_store(ConfigWriter& cw) {\r\n\t\t\tcw.append(key, enabled);\r\n\t\t}\r\n\r\n\t} DisplacementMap;\r\n} // namespace patch::fast\r\n#endif // ifdef PATCH_SWITCH_FAST_DISPLACEMENTMAP\r\n"
  },
  {
    "path": "patch/patch_fast_exeditwindow.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_fast_exeditwindow.hpp\"\n#ifdef PATCH_SWITCH_FAST_EXEDITWINDOW\n#pragma comment(lib, \"Msimg32.lib\")\n\n#include \"util_others.hpp\"\n\n//#define PATCH_STOPWATCH\n#include \"stopwatch.hpp\"\n\nnamespace patch {\n\tstatic stopwatch_mem sw;\n\n\tvoid __cdecl fast_exeditwindow_t::FUN_10036a70_Wrap_gradation(HDC hDC, LPRECT prect, int r1, int g1, int b1, int r2, int g2, int b2, int gradation_left, int gradation_right) {\n\t\tstatic GRADIENT_RECT gr[] = { { .UpperLeft = 0, .LowerRight = 1 } };\n\n\t\tTRIVERTEX tv[2];\n\t\ttv[0].y = prect->top;\n\t\ttv[1].y = prect->bottom;\n\t\ttv[0].Alpha = 0;\n\t\ttv[1].Alpha = 0;\n\n\t\tint64_t real_diff = static_cast<int64_t>(gradation_right) - gradation_left;\n\t\tif (prect->left < gradation_left) {\n\t\t\tif (prect->right < gradation_left) {\n\t\t\t\tSetDCBrushColor(hDC, RGB(r1, g1, b1));\n\t\t\t\tFillRect(hDC, prect, (HBRUSH)GetStockObject(DC_BRUSH));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tSetDCBrushColor(hDC, RGB(r1, g1, b1));\n\t\t\tRECT rect{\n\t\t\t\tprect->left, prect->top,\n\t\t\t\tgradation_left, prect->bottom\n\t\t\t};\n\t\t\tFillRect(hDC, prect, (HBRUSH)GetStockObject(DC_BRUSH));\n\n\t\t\tconst auto cr1 = r1 << 8, cg1 = g1 << 8, cb1 = b1 << 8;\n\t\t\tconst auto cr2 = r2 << 8, cg2 = g2 << 8, cb2 = b2 << 8;\n\n\t\t\ttv[0].x = gradation_left;\n\t\t\ttv[0].Red   = static_cast<COLOR16>(cr1);\n\t\t\ttv[0].Green = static_cast<COLOR16>(cg1);\n\t\t\ttv[0].Blue  = static_cast<COLOR16>(cb1);\n\n\t\t\tif (gradation_right < prect->right) {\n\t\t\t\tSetDCBrushColor(hDC, RGB(r2, g2, b2));\n\t\t\t\tRECT rect{\n\t\t\t\t\tgradation_right, prect->top,\n\t\t\t\t\tprect->right, prect->bottom\n\t\t\t\t};\n\t\t\t\tFillRect(hDC, &rect, (HBRUSH)GetStockObject(DC_BRUSH));\n\t\t\t\ttv[1].x = gradation_right;\n\t\t\t\ttv[1].Red   = static_cast<COLOR16>(cr2);\n\t\t\t\ttv[1].Green = static_cast<COLOR16>(cg2);\n\t\t\t\ttv[1].Blue  = static_cast<COLOR16>(cb2);\n\t\t\t}\n\t\t\telse {\n\t\t\t\ttv[1].x = prect->right;\n\t\t\t\tif (real_diff == 0) {\n\t\t\t\t\ttv[1].Red   = static_cast<COLOR16>(cr2);\n\t\t\t\t\ttv[1].Green = static_cast<COLOR16>(cg2);\n\t\t\t\t\ttv[1].Blue  = static_cast<COLOR16>(cb2);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\ttv[1].Red   = static_cast<COLOR16>(cr1 + static_cast<int64_t>(cr2 - cr1) * (static_cast<int64_t>(prect->right) - gradation_left) / real_diff);\n\t\t\t\t\ttv[1].Green = static_cast<COLOR16>(cg1 + static_cast<int64_t>(cg2 - cg1) * (static_cast<int64_t>(prect->right) - gradation_left) / real_diff);\n\t\t\t\t\ttv[1].Blue  = static_cast<COLOR16>(cb1 + static_cast<int64_t>(cb2 - cb1) * (static_cast<int64_t>(prect->right) - gradation_left) / real_diff);\n\t\t\t\t}\n\t\t\t}\n\t\t\tGradientFill(hDC, tv, std::size(tv), &gr, std::size(gr), GRADIENT_FILL_RECT_H);\n\t\t}\n\t\telse {\n\t\t\tif (gradation_right < prect->left) {\n\t\t\t\tSetDCBrushColor(hDC, RGB(r2, g2, b2));\n\t\t\t\tFillRect(hDC, prect, (HBRUSH)GetStockObject(DC_BRUSH));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst auto cr1 = r1 << 8, cg1 = g1 << 8, cb1 = b1 << 8;\n\t\t\tconst auto cr2 = r2 << 8, cg2 = g2 << 8, cb2 = b2 << 8;\n\n\t\t\ttv[0].x = prect->left;\n\t\t\tif (real_diff == 0) {\n\t\t\t\ttv[0].Red   = cr1;\n\t\t\t\ttv[0].Green = cg1;\n\t\t\t\ttv[0].Blue  = cb1;\n\t\t\t}\n\t\t\telse {\n\t\t\t\ttv[0].Red   = static_cast<COLOR16>(cr1 + static_cast<int64_t>(cr2 - cr1) * (static_cast<int64_t>(prect->left) - gradation_left) / real_diff);\n\t\t\t\ttv[0].Green = static_cast<COLOR16>(cg1 + static_cast<int64_t>(cg2 - cg1) * (static_cast<int64_t>(prect->left) - gradation_left) / real_diff);\n\t\t\t\ttv[0].Blue  = static_cast<COLOR16>(cb1 + static_cast<int64_t>(cb2 - cb1) * (static_cast<int64_t>(prect->left) - gradation_left) / real_diff);\n\t\t\t}\n\n\t\t\tif (gradation_right < prect->right) {\n\t\t\t\tSetDCBrushColor(hDC, RGB(r2, g2, b2));\n\t\t\t\tRECT rect{\n\t\t\t\t\tgradation_right, prect->top,\n\t\t\t\t\tprect->right, prect->bottom\n\t\t\t\t};\n\t\t\t\tFillRect(hDC, &rect, (HBRUSH)GetStockObject(DC_BRUSH));\n\t\t\t\ttv[1].x = gradation_right;\n\t\t\t\ttv[1].Red   = static_cast<COLOR16>(cr2);\n\t\t\t\ttv[1].Green = static_cast<COLOR16>(cg2);\n\t\t\t\ttv[1].Blue  = static_cast<COLOR16>(cb2);\n\t\t\t}\n\t\t\telse {\n\t\t\t\ttv[1].x = prect->right;\n\t\t\t\tif (real_diff == 0) {\n\t\t\t\t\ttv[1].Red   = static_cast<COLOR16>(cr2);\n\t\t\t\t\ttv[1].Green = static_cast<COLOR16>(cg2);\n\t\t\t\t\ttv[1].Blue  = static_cast<COLOR16>(cb2);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\ttv[1].Red   = static_cast<COLOR16>(cr1 + static_cast<int64_t>(cr2 - cr1) * (static_cast<int64_t>(prect->right) - gradation_left) / real_diff);\n\t\t\t\t\ttv[1].Green = static_cast<COLOR16>(cg1 + static_cast<int64_t>(cg2 - cg1) * (static_cast<int64_t>(prect->right) - gradation_left) / real_diff);\n\t\t\t\t\ttv[1].Blue  = static_cast<COLOR16>(cb1 + static_cast<int64_t>(cb2 - cb1) * (static_cast<int64_t>(prect->right) - gradation_left) / real_diff);\n\t\t\t\t}\n\t\t\t}\n\t\t\tGradientFill(hDC, tv, std::size(tv), &gr, std::size(gr), GRADIENT_FILL_RECT_H);\n\t\t}\n\t}\n\n\tvoid __cdecl fast_exeditwindow_t::FUN_10036a70_Wrap_step(HDC hDC, LPRECT prect, int r1, int g1, int b1, int r2, int g2, int b2, int gradation_left, int gradation_right) {\n\t\tauto steps = patch::fast_exeditwindow.step;\n\n\t\tauto brush = (HBRUSH)GetStockObject(DC_BRUSH);\n\n\t\tif (steps == 1) {\n\t\t\tSetDCBrushColor(hDC, RGB(r1, g1, b1));\n\t\t\tFillRect(hDC, prect, brush);\n\t\t\treturn;\n\t\t}\n\n\t\tauto real_diff = gradation_right - gradation_left;\n\t\tif (prect->left < gradation_left) {\n\t\t\tif (prect->right < gradation_left) {\n\t\t\t\tSetDCBrushColor(hDC, RGB(r1, g1, b1));\n\t\t\t\tFillRect(hDC, prect, brush);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tSetDCBrushColor(hDC, RGB(r1, g1, b1));\n\t\t\tRECT rect{\n\t\t\t\tprect->left, prect->top,\n\t\t\t\tgradation_left, prect->bottom\n\t\t\t};\n\t\t\tFillRect(hDC, prect, brush);\n\t\t\t\n\t\t\tif (gradation_right < prect->right) {\n\t\t\t\tSetDCBrushColor(hDC, RGB(r2, g2, b2));\n\t\t\t\tRECT rect{\n\t\t\t\t\tgradation_right, prect->top,\n\t\t\t\t\tprect->right, prect->bottom\n\t\t\t\t};\n\t\t\t\tFillRect(hDC, &rect, brush);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif (gradation_right < prect->left) {\n\t\t\t\tSetDCBrushColor(hDC, RGB(r2, g2, b2));\n\t\t\t\tFillRect(hDC, prect, brush);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (gradation_right < prect->right) {\n\t\t\t\tSetDCBrushColor(hDC, RGB(r2, g2, b2));\n\t\t\t\tRECT rect{\n\t\t\t\t\tgradation_right, prect->top,\n\t\t\t\t\tprect->right, prect->bottom\n\t\t\t\t};\n\t\t\t\tFillRect(hDC, &rect, brush);\n\t\t\t}\n\t\t}\n\n\t\tLONG L, R;\n\t\tR = gradation_left;\n\n\t\tRECT rect;\n\t\trect.top = prect->top;\n\t\trect.bottom = prect->bottom;\n\n\t\tfor (int i = 0; i < steps; i++) {\n\t\t\tL = R;\n\t\t\tR = static_cast<int32_t>(gradation_left + static_cast<uint64_t>(gradation_right - gradation_left) * (i + 1) / steps);\n\n\t\t\tif (R < prect->left) continue;\n\t\t\tif (prect->right < L) continue;\n\n\t\t\tint dL = std::max<>(prect->left, L);\n\t\t\tint dR = std::min<>(prect->right, R);\n\n\t\t\tSetDCBrushColor(hDC, RGB(\n\t\t\t\tr1 + (r2 - r1) * i / (steps - 1),\n\t\t\t\tg1 + (g2 - g1) * i / (steps - 1),\n\t\t\t\tb1 + (b2 - b1) * i / (steps - 1)\n\t\t\t));\n\t\t\trect.left = dL;\n\t\t\trect.right = dR;\n\t\t\tFillRect(hDC, &rect, brush);\n\t\t}\n\t}\n\n\tstatic HDC frontdc;\n\tstatic HBITMAP bitmap;\n\tstatic HBITMAP bitmap_old;\n\tstatic int width, height;\n\n#define DO 1\n\tHDC WINAPI fast_exeditwindow_t::GetDC_Wrap(HWND hwnd) {\n\t\tsw.start();\n#if DO\n\t\tfrontdc = GetDC(hwnd);\n\n\t\tRECT rect;\n\t\tGetClientRect(hwnd, &rect);\n\t\twidth = rect.right - rect.left;\n\t\theight = rect.bottom - rect.top;\n\n\t\tauto backdc = CreateCompatibleDC(frontdc);\n\t\tbitmap = CreateCompatibleBitmap(frontdc, width, height);\n\t\tbitmap_old = (HBITMAP)SelectObject(backdc, bitmap);\n\t\tBitBlt(backdc, 0, 0, width, height, frontdc, 0, 0, SRCCOPY);\n\n\t\treturn backdc;\n#else\n\t\treturn GetDC(hwnd);\n#endif\n\t}\n\tint WINAPI fast_exeditwindow_t::ReleaseDC_Wrap(HWND hwnd, HDC hdc) {\n#if DO\n\t\tBitBlt(frontdc, 0, 0, width, height, hdc, 0, 0, SRCCOPY);\n\t\tSelectObject(hdc, bitmap_old);\n\t\tDeleteObject(bitmap);\n\t\tDeleteObject(hdc);\n#endif\n\t\tsw.stop();\n\t\treturn ReleaseDC(hwnd, frontdc);\n\t}\n\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_FAST_EXEDITWINDOW\n"
  },
  {
    "path": "patch/patch_fast_exeditwindow.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_FAST_EXEDITWINDOW\n#include <Windows.h>\n#include \"util_magic.hpp\"\n#include \"global.hpp\"\n#include \"config_rw.hpp\"\n\nnamespace patch {\n\t// init at exedit load\n\t// 拡張編集ウィンドウの高速化\n\tinline class fast_exeditwindow_t {\n\t\tstatic void __cdecl FUN_10036a70_Wrap_gradation(HDC hDC, LPRECT prect, int r1, int g1, int b1, int r2, int g2, int b2, int real_left, int real_right);\n\t\tstatic void __cdecl FUN_10036a70_Wrap_step(HDC hDC, LPRECT prect, int r1, int g1, int b1, int r2, int g2, int b2, int real_left, int real_right);\n\n\n\t\tstatic HDC WINAPI GetDC_Wrap(HWND hwnd);\n\t\tstatic int WINAPI ReleaseDC_Wrap(HWND hwnd, HDC hdc);\n\n\t\tinline static auto GetDC_Wrap_ptr = &GetDC_Wrap;\n\t\tinline static auto ReleaseDC_Wrap_ptr = &ReleaseDC_Wrap;\n\n\t\tbool enabled = true;\n\t\tbool enabled_i;\n\n\t\tint step = 0;\n\t\tint step_i;\n\n\t\tinline static const char key[] = \"fast.exeditwindow\";\n\t\tinline static const char c_step_name[] = \"step\";\n\n\tpublic:\n\t\tvoid init() {\n\t\t\tenabled_i = enabled;\n\t\t\tstep_i = step;\n\n\t\t\tif (!enabled_i)return;\n\n\n\t\t\tif (step >= 0) {\n\t\t\t\tdecltype(&FUN_10036a70_Wrap_gradation) f_036a70_ptr;\n\t\t\t\tif (step == 0) {\n\t\t\t\t\tf_036a70_ptr = &FUN_10036a70_Wrap_gradation;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tf_036a70_ptr = &FUN_10036a70_Wrap_step;\n\t\t\t\t}\n\n\t\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x0374fb, f_036a70_ptr);\n\t\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x037563, f_036a70_ptr);\n\t\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x0375bb, f_036a70_ptr);\n\t\t\t}\n\n\t\t\tOverWriteOnProtectHelper(GLOBAL::exedit_base + 0x0387fd, 4).store_i32(0, &GetDC_Wrap_ptr);\n\t\t\tOverWriteOnProtectHelper(GLOBAL::exedit_base + 0x038927, 4).store_i32(0, &ReleaseDC_Wrap_ptr);\n\n\t\t\tOverWriteOnProtectHelper(GLOBAL::exedit_base + 0x039309, 4).store_i32(0, &GetDC_Wrap_ptr);\n\t\t\tOverWriteOnProtectHelper(GLOBAL::exedit_base + 0x039350, 4).store_i32(0, &ReleaseDC_Wrap_ptr);\n\n\t\t\tOverWriteOnProtectHelper(GLOBAL::exedit_base + 0x0392a8, 4).store_i32(0, &GetDC_Wrap_ptr);\n\t\t\tOverWriteOnProtectHelper(GLOBAL::exedit_base + 0x0392e1, 4).store_i32(0, &ReleaseDC_Wrap_ptr);\n\n\t\t\tOverWriteOnProtectHelper(GLOBAL::exedit_base + 0x039379, 4).store_i32(0, &GetDC_Wrap_ptr);\n\t\t\tOverWriteOnProtectHelper(GLOBAL::exedit_base + 0x0393f0, 4).store_i32(0, &ReleaseDC_Wrap_ptr);\n\t\t\t\n\t\t\tOverWriteOnProtectHelper(GLOBAL::exedit_base + 0x0394d6, 4).store_i32(0, &GetDC_Wrap_ptr);\n\t\t\tOverWriteOnProtectHelper(GLOBAL::exedit_base + 0x03953c, 4).store_i32(0, &ReleaseDC_Wrap_ptr);\n\t\t\t\n\t\t\t//OverWriteOnProtectHelper(GLOBAL::exedit_base + 0x03943c, 4).store_i32(0, &GetDC_Wrap_ptr);\n\t\t\t//OverWriteOnProtectHelper(GLOBAL::exedit_base + 0x039483, 4).store_i32(0, &ReleaseDC_Wrap_ptr);\n\t\t}\n\n        void switching(bool flag) { enabled = flag; }\n\n        bool is_enabled() { return enabled; }\n        bool is_enabled_i() { return enabled_i; }\n\n\t\tvoid set_step(int x) { step = x; }\n\n\t\tint get_step() { return step; }\n\t\tint get_step_i() { return step_i; }\n\n        void switch_load(ConfigReader& cr) {\n            cr.regist(key, [this](json_value_s* value) {\n                ConfigReader::load_variable(value, enabled);\n            });\n        }\n\n        void switch_store(ConfigWriter& cw) {\n            cw.append(key, enabled);\n        }\n\n\t\tvoid config_load(ConfigReader& cr) {\n\t\t\tcr.regist(c_step_name, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, step);\n\t\t\t});\n\t\t}\n\n\t\tvoid config_store(ConfigWriter& cw) {\n\t\t\tcw.append(c_step_name, step);\n\t\t}\n\n\t} fast_exeditwindow;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_FAST_EXEDITWINDOW\n"
  },
  {
    "path": "patch/patch_fast_flash.cpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"patch_fast_flash.hpp\"\r\n#ifdef PATCH_SWITCH_FAST_FLASH\r\n\r\n#include \"debug_log.hpp\"\r\n#include \"patch_fast_cl.hpp\"\r\n\r\n//#define PATCH_STOPWATCH\r\n#include \"stopwatch.hpp\"\r\n\r\nnamespace patch::fast {\r\n    static stopwatch_mem sw;\r\n\r\n\r\n    BOOL Flash_t::func_proc(ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\r\n        if constexpr (true) {\r\n            sw.start();\r\n\r\n            auto exedit_max_w = load_i32<int>(GLOBAL::exedit_base + OFS::ExEdit::exedit_max_w);\r\n            auto exedit_max_h = load_i32<int>(GLOBAL::exedit_base + OFS::ExEdit::exedit_max_h);\r\n            auto exedit_buffer_line = load_i32<int>(GLOBAL::exedit_base + OFS::ExEdit::exedit_buffer_line);\r\n            efFlash_var& flash = *(efFlash_var*)uintptr_t(reinterpret_cast<efFlash_var*>(GLOBAL::exedit_base + OFS::ExEdit::efFlash_var_ptr));\r\n\r\n            int intensity = efp->track[0];\r\n            int cx = efp->track[1];\r\n            int cy = efp->track[2];\r\n            flash.range = 750;\r\n\r\n\r\n            unsigned int* exdata = (unsigned int*)efp->exdata_ptr;\r\n\r\n            int pixel_range, temp_range;\r\n\r\n\r\n            if (intensity == 0) {\r\n                return TRUE;\r\n            }\r\n            flash.corrected_intensity = (intensity * 4096) / 1000;\r\n\r\n            flash.r_intensity = 4096 - flash.corrected_intensity;\r\n            if (flash.r_intensity < 0) {\r\n                flash.r_intensity = 0;\r\n            }\r\n            flash.cx = cx + efpip->obj_w / 2;\r\n            flash.cy = cy + efpip->obj_h / 2;\r\n\r\n\r\n            pixel_range = (std::max)({ std::abs(flash.cx), std::abs(flash.cy), std::abs(flash.cx - efpip->obj_w), std::abs(flash.cy - efpip->obj_h) });\r\n\r\n            temp_range = (int)round(sqrt(efpip->obj_h * efpip->obj_h + efpip->obj_w * efpip->obj_w));\r\n            if (temp_range < pixel_range) {\r\n                pixel_range = temp_range;\r\n            }\r\n\r\n            if (has_flag(efpip->flag, ExEdit::FilterProcInfo::Flag::fast_preview))\r\n                if (50 < pixel_range) pixel_range = 50;\r\n\r\n\r\n            flash.pixel_range = pixel_range / 4 + pixel_range / 2;\r\n\r\n\r\n            if (efp->check[2]) { // サイズ固定\r\n                flash.temp_x = 0;\r\n                flash.temp_y = 0;\r\n                flash.temp_w = efpip->obj_w;\r\n                flash.temp_h = efpip->obj_h;\r\n            } else {\r\n                int tx, ty, tw, th;\r\n                if (flash.cx < 0) {\r\n                    tx = 0;\r\n                } else {\r\n                    tx = -3 * flash.cx;\r\n                }\r\n                if (flash.cy < 0) {\r\n                    ty = 0;\r\n                } else {\r\n                    ty = -3 * flash.cy;\r\n                }\r\n                if (efpip->obj_w < flash.cx) {\r\n                    tw = 0;\r\n                } else {\r\n                    tw = 3 * (efpip->obj_w - flash.cx);\r\n                }\r\n                if (efpip->obj_h < flash.cy) {\r\n                    th = 0;\r\n                } else {\r\n                    th = 3 * (efpip->obj_h - flash.cy);\r\n                }\r\n\r\n                tx = tx * flash.corrected_intensity / 4096;\r\n                ty = ty * flash.corrected_intensity / 4096;\r\n                tw = (tw * flash.corrected_intensity / 4096) + efpip->obj_w;\r\n                th = (th * flash.corrected_intensity / 4096) + efpip->obj_h;\r\n\r\n                int tmin = (std::min)({ exedit_max_w, efpip->scene_w + efpip->obj_w * 2 });\r\n                int sub1 = tw - tx - tmin;\r\n                if (0 < sub1) {\r\n                    int sub2 = efpip->obj_w - tx - tw;\r\n                    if (0 < sub2) {\r\n                        if (sub2 < sub1) {\r\n                            tx += sub2;\r\n                            sub1 -= sub2;\r\n                        } else {\r\n                            tx += sub1;\r\n                            sub1 = 0;\r\n                        }\r\n                    } else {\r\n                        if (-sub2 < sub1) {\r\n                            tw += sub2;\r\n                            sub1 += sub2;\r\n                        } else {\r\n                            tw -= sub1;\r\n                            sub1 = 0;\r\n                        }\r\n                    }\r\n                    if (sub1 & 1) {\r\n                        tw--;\r\n                        sub1--;\r\n                    }\r\n                    if (0 < sub1) {\r\n                        tx += sub1 / 2;\r\n                        tw -= sub1 / 2;\r\n                    }\r\n                }\r\n                tmin = (std::min)({ exedit_max_h, efpip->scene_h + efpip->obj_h * 2 });\r\n                sub1 = th - ty - tmin;\r\n                if (0 < sub1) {\r\n                    int sub2 = efpip->obj_h - ty - th;\r\n                    if (0 < sub2) {\r\n                        if (sub2 < sub1) {\r\n                            ty += sub2;\r\n                            sub1 -= sub2;\r\n                        } else {\r\n                            ty += sub1;\r\n                            sub1 = 0;\r\n                        }\r\n                    } else {\r\n                        if (-sub2 < sub1) {\r\n                            th += sub2;\r\n                            sub1 += sub2;\r\n                        } else {\r\n                            th -= sub1;\r\n                            sub1 = 0;\r\n                        }\r\n                    }\r\n                    if (sub1 & 1) {\r\n                        th--;\r\n                        sub1--;\r\n                    }\r\n                    if (0 < sub1) {\r\n                        ty += sub1 / 2;\r\n                        th -= sub1 / 2;\r\n                    }\r\n                }\r\n                flash.temp_x = tx;\r\n                flash.temp_y = ty;\r\n                flash.temp_w = tw;\r\n                flash.temp_h = th;\r\n            }\r\n            const auto dst_w = flash.temp_w - flash.temp_x;\r\n            const auto dst_h = flash.temp_h - flash.temp_y;\r\n\r\n            reinterpret_cast<void(__cdecl*)(short*,short*,short*,int)>(GLOBAL::exedit_base + OFS::ExEdit::rgb2yc)(&flash.color_y, &flash.color_cb, &flash.color_cr, exdata[0] & 0xffffff);\r\n            try {\r\n                const auto src_size = exedit_buffer_line * efpip->obj_h * sizeof(ExEdit::PixelYCA);\r\n                cl::Buffer clmem_src(cl.context, CL_MEM_READ_ONLY, src_size);\r\n                cl.queue.enqueueWriteBuffer(clmem_src, CL_TRUE, 0, src_size, efpip->obj_edit);\r\n\r\n                const auto dst_size = exedit_buffer_line * dst_h * sizeof(ExEdit::PixelYCA);\r\n                cl::Buffer clmem_dst(cl.context, CL_MEM_WRITE_ONLY, dst_size);\r\n\r\n                cl::Kernel kernel;\r\n                if (exdata[0] & 0x1000000) { // 指定なし(元画像の色)\r\n                    kernel = cl.readyKernel(\r\n                        \"Flash\",\r\n                        clmem_dst,\r\n                        clmem_src,\r\n                        efpip->obj_w,\r\n                        efpip->obj_h,\r\n                        exedit_buffer_line,\r\n                        flash.cx,\r\n                        flash.cy,\r\n                        flash.range,\r\n                        flash.pixel_range,\r\n                        flash.temp_x,\r\n                        flash.temp_y,\r\n                        flash.r_intensity\r\n                    );\r\n                } else {\r\n                    kernel = cl.readyKernel(\r\n                        \"FlashColor\",\r\n                        clmem_dst,\r\n                        clmem_src,\r\n                        efpip->obj_w,\r\n                        efpip->obj_h,\r\n                        exedit_buffer_line,\r\n                        flash.cx,\r\n                        flash.cy,\r\n                        flash.range,\r\n                        flash.pixel_range,\r\n                        flash.temp_x,\r\n                        flash.temp_y,\r\n                        flash.r_intensity,\r\n                        flash.color_y,\r\n                        flash.color_cb,\r\n                        flash.color_cr\r\n                    );\r\n                }\r\n                cl.queue.enqueueNDRangeKernel(kernel, { 0,0 }, { (size_t)dst_w, (size_t)dst_h });\r\n\r\n                cl.queue.enqueueReadBuffer(clmem_dst, CL_TRUE, 0, dst_size, efpip->obj_temp);\r\n            }\r\n            catch (const cl::Error& err) {\r\n                debug_log(\"OpenCL Error\\n({}) {}\", err.err(), err.what());\r\n                return FALSE;\r\n            }\r\n\r\n\r\n            switch (exdata[1]) { //合成モード\r\n            case 0: // 前方に合成\r\n                efp->exfunc->bufcpy(efpip->obj_temp, -flash.temp_x, -flash.temp_y, efpip->obj_edit, 0, 0, efpip->obj_w, efpip->obj_h, 0, 0x11000003);\r\n                break;\r\n            case 1: // 後方に合成\r\n                efp->exfunc->bufcpy(efpip->obj_temp, -flash.temp_x, -flash.temp_y, efpip->obj_edit, 0, 0, efpip->obj_w, efpip->obj_h, 0, 3);\r\n                break;\r\n                //  case 2: // 光成分のみ\r\n            }\r\n\r\n            std::swap(efpip->obj_temp, efpip->obj_edit);\r\n\r\n            efpip->obj_data.cx += (efpip->obj_w - flash.temp_w - flash.temp_x) * 2048;\r\n            efpip->obj_data.cy += (efpip->obj_h - flash.temp_h - flash.temp_y) * 2048;\r\n            efpip->obj_w = flash.temp_w - flash.temp_x;\r\n            efpip->obj_h = flash.temp_h - flash.temp_y;\r\n\r\n            sw.stop();\r\n            return TRUE;\r\n        } else {\r\n            sw.start();\r\n            const auto ret = ((BOOL(*)(ExEdit::Filter*, ExEdit::FilterProcInfo*))(GLOBAL::exedit_base + OFS::ExEdit::efRadiationalBlur_func_proc))(efp, efpip);\r\n            sw.stop();\r\n            return ret;\r\n        }\r\n    }\r\n} // namespace patch::fast\r\n#endif // ifdef PATCH_SWITCH_FAST_FLASH\r\n"
  },
  {
    "path": "patch/patch_fast_flash.hpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n#ifdef PATCH_SWITCH_FAST_FLASH\r\n#include <exedit.hpp>\r\n#include \"util_magic.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"global.hpp\"\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch::fast {\r\n    // init at exedit load\r\n    // 閃光の高速化\r\n    inline class Flash_t {\r\n        static BOOL func_proc(ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\r\n\r\n        bool enabled = true;\r\n        bool enabled_i;\r\n        inline static const char key[] = \"fast.flash\";\r\n    public:\r\n\r\n        struct efFlash_var { // 1a6b7c\r\n            int r_intensity;\r\n            int cx;\r\n            int cy;\r\n            int temp_w;\r\n            int temp_h;\r\n            short color_cb;\r\n            short _padding1;\r\n            int corrected_intensity;\r\n            int pixel_range;\r\n            short color_cr;\r\n            short _padding2;\r\n            int temp_x;\r\n            int range;\r\n            int temp_y;\r\n            short color_y;\r\n        };\r\n\r\n        void init() {\r\n            enabled_i = enabled;\r\n\r\n            if (!enabled_i)return;\r\n\r\n            store_i32(GLOBAL::exedit_base + OFS::ExEdit::efFlash_func_proc_ptr, &func_proc);\r\n        }\r\n\r\n        void switch_load(ConfigReader& cr) {\r\n            cr.regist(key, [this](json_value_s* value) {\r\n                ConfigReader::load_variable(value, enabled);\r\n            });\r\n        }\r\n\r\n        void switch_store(ConfigWriter& cw) {\r\n            cw.append(key, enabled);\r\n        }\r\n\r\n    } Flash;\r\n} // namespace patch::fast\r\n#endif // ifdef PATCH_SWITCH_FAST_FLASH\r\n"
  },
  {
    "path": "patch/patch_fast_getputpixeldata.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_fast_getputpixeldata.hpp\"\n#ifdef PATCH_SWITCH_FAST_GETPUTPIXELDATA\n\n#include <ppl.h>\n\n#include <exedit.hpp>\n#include \"multi_threading.hpp\"\n\nnamespace patch::fast {\n\tstatic BOOL BufCpyBGRA2YCA(void* dst, void* src, int w, int h, int line) {\n\n\n\t}\n\n\tstatic BOOL BufCpyYCA2BGRA(void* dst, void* src, int w, int h, int line) {\n\n\n\t}\n\n\tint getputpixeldata_t::avx_getpixeldata(lua_State* L) {\n\t\tauto n = lua_gettop(L);\n\t\tbool is_alloc = false;\n\t\tbool is_work = false;\n\t\tfor (int i = 0; i < n; i++) {\n\t\t\tauto s = lua_tostring(L, i + 1);\n\t\t\tif (lstrcmpiA(s, \"alloc\") == 0)is_alloc = true;\n\t\t\tif (lstrcmpiA(s, \"work\") == 0)is_work = true;\n\t\t}\n\t\tauto efpip_g = load_i32<ExEdit::FilterProcInfo*>(GLOBAL::exedit_base + OFS::ExEdit::efpip_g);\n\n\t\tif (is_work) {\n\t\t\tif (is_alloc) {\n\t\t\t\tlua_newuserdata(L, efpip_g->obj_w * efpip_g->obj_h * 4 + 16);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tlua_pushlightuserdata(L, reinterpret_cast<BYTE*>(efpip_g->obj_temp) + load_i32<int>(GLOBAL::exedit_base + OFS::ExEdit::exedit_max_h_add8) * load_i32<int>(GLOBAL::exedit_base + OFS::ExEdit::exedit_buffer_line) * 4);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tExEdit::PixelBGRA* ptr;\n\t\t\tif (is_alloc) {\n\t\t\t\tptr = static_cast<ExEdit::PixelBGRA*>(lua_newuserdata(L, efpip_g->obj_w * efpip_g->obj_h * 4 + 16));\n\t\t\t}\n\t\t\telse {\n\t\t\t\tptr = static_cast<ExEdit::PixelBGRA*>(static_cast<void*>(efpip_g->obj_temp)) + load_i32<int>(GLOBAL::exedit_base + OFS::ExEdit::exedit_max_h_add8) * load_i32<int>(GLOBAL::exedit_base + OFS::ExEdit::exedit_buffer_line);\n\t\t\t\tlua_pushlightuserdata(L, ptr);\n\t\t\t}\n\t\t\t\n\t\t\tconstexpr static __m256i y_c = { .m256i_i16 = {\n\t\t\t\t16320, 16320, 16320, 0,\n\t\t\t\t16320, 16320, 16320, 0,\n\t\t\t\t16320, 16320, 16320, 0,\n\t\t\t\t16320, 16320, 16320, 0\n\t\t\t} };\n\n\t\t\tconstexpr static __m256i cb_c = { .m256i_i16 = {\n\t\t\t\t28919, -5616, 0, 0,\n\t\t\t\t28919, -5616, 0, 0,\n\t\t\t\t28919, -5616, 0, 0,\n\t\t\t\t28919, -5616, 0, 0\n\t\t\t} };\n\n\t\t\tconstexpr static __m256i cr_c = { .m256i_i16 = {\n\t\t\t\t0, -11655, 22881, 16320,\n\t\t\t\t0, -11655, 22881, 16320,\n\t\t\t\t0, -11655, 22881, 16320,\n\t\t\t\t0, -11655, 22881, 16320\n\t\t\t} };\n\n\t\t\t//concurrency::parallel_for(0, efpip_g->obj_h, [=](int y) {\n\t\t\tfor (int y = 0; y < efpip_g->obj_h; y++) {\n\t\t\t\tauto src_itr = efpip_g->obj_edit + y * efpip_g->obj_line;\n\t\t\t\tauto dst_itr = ptr + y * efpip_g->obj_w;\n\t\t\t\tfor (int x = 0; x < efpip_g->obj_w / 4; x++) {\n\t\t\t\t\tauto src = _mm256_loadu_epi16(src_itr);\n\t\t\t\t\tauto dst = dst_itr;\n\n\t\t\t\t\tauto m_y  = _mm256_shufflehi_epi16(_mm256_shufflelo_epi16(src, 0b1100'0000), 0b1100'0000);\n\t\t\t\t\tauto m_cb = _mm256_shufflehi_epi16(_mm256_shufflelo_epi16(src, 0b1101'0101), 0b1101'0101);\n\t\t\t\t\tauto m_cr = _mm256_shufflehi_epi16(_mm256_shufflelo_epi16(src, 0b1110'1010), 0b1110'1010);\n\n\t\t\t\t\tm_y  = _mm256_mulhi_epi16(m_y , y_c);\n\t\t\t\t\tm_cb = _mm256_mulhi_epi16(m_cb, cb_c);\n\t\t\t\t\tm_cr = _mm256_mulhi_epi16(m_cr, cr_c);\n\n\t\t\t\t\tauto result_i16 = _mm256_adds_epi16(m_cb, m_cr);\n\t\t\t\t\tresult_i16 = _mm256_adds_epi16(result_i16, m_y);\n \t\t\t\t\tresult_i16 = _mm256_adds_epi16(result_i16, _mm256_set1_epi16(3));\n\t\t\t\t\tresult_i16 = _mm256_srai_epi16(result_i16, 2);\n\n\t\t\t\t\tauto result_i8 = _mm_packus_epi16(_mm256_extracti128_si256(result_i16, 0), _mm256_extracti128_si256(result_i16, 1));\n\t\t\t\t\t_mm_storeu_epi8(dst, result_i8);\n\n\t\t\t\t\tsrc_itr += 4;\n\t\t\t\t\tdst_itr += 4;\n\t\t\t\t}\n\t\t\t\tif (auto mod = efpip_g->obj_w % 4; mod) {\n\t\t\t\t\tauto src = _mm256_loadu_epi16(src_itr);\n\t\t\t\t\tauto dst = dst_itr;\n\n\t\t\t\t\tauto m_y  = _mm256_shufflehi_epi16(_mm256_shufflelo_epi16(src, 0b1100'0000), 0b1100'0000);\n\t\t\t\t\tauto m_cb = _mm256_shufflehi_epi16(_mm256_shufflelo_epi16(src, 0b1101'0101), 0b1101'0101);\n\t\t\t\t\tauto m_cr = _mm256_shufflehi_epi16(_mm256_shufflelo_epi16(src, 0b1110'1010), 0b1110'1010);\n\n\t\t\t\t\tm_y  = _mm256_mulhi_epi16(m_y , y_c);\n\t\t\t\t\tm_cb = _mm256_mulhi_epi16(m_cb, cb_c);\n\t\t\t\t\tm_cr = _mm256_mulhi_epi16(m_cr, cr_c);\n\n\t\t\t\t\tauto result_i16 = _mm256_adds_epi16(m_cb, m_cr);\n\t\t\t\t\tresult_i16 = _mm256_adds_epi16(result_i16, m_y);\n \t\t\t\t\tresult_i16 = _mm256_adds_epi16(result_i16, _mm256_set1_epi16(3));\n\t\t\t\t\tresult_i16 = _mm256_srai_epi16(result_i16, 2);\n\n\t\t\t\t\tauto result_i8 = _mm_packus_epi16(_mm256_extracti128_si256(result_i16, 0), _mm256_extracti128_si256(result_i16, 1));\n\n\t\t\t\t\tswitch (mod) {\n\t\t\t\t\tcase 1:\n\t\t\t\t\t\t_mm_storeu_si32(dst, result_i8);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 2:\n\t\t\t\t\t\t_mm_storeu_si64(dst, result_i8);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 3:\n\t\t\t\t\t\t_mm_maskstore_epi32(reinterpret_cast<int*>(dst), _mm_set_epi32(0, -1, -1, -1), result_i8);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t//});\n\t\t\t}\n\t\t}\n\t\tlua_pushinteger(L, efpip_g->obj_w);\n\t\tlua_pushinteger(L, efpip_g->obj_h);\n\t\treturn 3;\n\t}\n\n\tint getputpixeldata_t::avx_putpixeldata(lua_State* L) {\n\t\tif (!lua_isuserdata(L, 1)) return 0;\n\t\tauto pixelp = static_cast<ExEdit::PixelBGRA*>(lua_touserdata(L, 1));\n\t\tif (pixelp == nullptr)return 0;\n\n\n\n\t\treturn 0;\n\t}\n\n#if 0\n\tint avx_putpixeldata_old(lua_State* L) {\n\t\tstatic constexpr m128_256 y_ef = { .m256 = {\n\t\t\t\t0.299f / 255.f * 4096.f, 0.587f / 255.f * 4096.f, 0.114f / 255.f * 4096.f, 0.f,\n\t\t\t\t0.299f / 255.f * 4096.f, 0.587f / 255.f * 4096.f, 0.114f / 255.f * 4096.f, 0.f,\n\t\t\t}\n\t\t};\n\t\tstatic constexpr m128_256 cb_ef = { .m256 = {\n\t\t\t\t-0.169f / 255.f * 4096.f, -0.331f / 255.f * 4096.f, 0.5f / 255.f * 4096.f, 0.f,\n\t\t\t\t-0.169f / 255.f * 4096.f, -0.331f / 255.f * 4096.f, 0.5f / 255.f * 4096.f, 0.f,\n\t\t\t}\n\t\t};\n\t\tstatic constexpr m128_256 cr_ef = { .m256 = {\n\t\t\t\t0.5f / 255.f * 4096.f, -0.419f / 255.f * 4096.f, -0.081f / 255.f * 4096.f, 0.f,\n\t\t\t\t0.5f / 255.f * 4096.f, -0.419f / 255.f * 4096.f, -0.081f / 255.f * 4096.f, 0.f,\n\t\t\t}\n\t\t};\n\t\tstatic constexpr m128_256 a_ef = { .m256 = {\n\t\t\t\t0.f,0.f,0.f,1.f / 255.f * 4096.f,\n\t\t\t\t0.f,0.f,0.f,1.f / 255.f * 4096.f,\n\t\t\t}\n\t\t};\n\n\t\tauto n = lua_gettop(L);\n\t\tif (auto data = static_cast<ExEdit::PixelBGRA*>(lua_touserdata(L, 1)); data) {\n\t\t\tauto efpip = *reinterpret_cast<ExEdit::FilterProcInfo**>(GLOBAL::exedit_base + OFS::ExEdit::efpip_g);\n\n\t\t\tmulti_threading([data, efpip](size_t i, size_t n) {\n\t\t\t\tconst auto w = efpip->obj_w;\n\t\t\t\tconst auto h = efpip->obj_h;\n\n\t\t\t\tconst auto y_min = h * i / n;\n\t\t\t\tconst auto y_max = h * (i + 1) / n;\n\n\t\t\t\tfor (int y = y_min; std::cmp_less(y, h); y++) {\n\t\t\t\t\tfor (int x = 0; std::cmp_less(x, w - (w & 1)); x += 2) {\n\t\t\t\t\t\tauto p128 = _mm_loadu_si64(data + x + y * efpip->obj_h);\n\t\t\t\t\t\tauto p256i = _mm256_cvtepu8_epi32(p128);\n\t\t\t\t\t\t/*\n\t\t\t\t\t\tauto p256ps = _mm256_cvtepi32_ps(p256i);\n\n\t\t\t\t\t\tauto ry = _mm256_dp_ps(p256ps, y_ef.m256, 0b01110001);\n\t\t\t\t\t\tauto rcb = _mm256_dp_ps(p256ps, cb_ef.m256, 0b01110010);\n\t\t\t\t\t\tauto rcr = _mm256_dp_ps(p256ps, cr_ef.m256, 0b01110100);\n\t\t\t\t\t\tauto ra = _mm256_dp_ps(p256ps, a_ef.m256, 0b01111000);\n\n\t\t\t\t\t\tauto rycb = _mm256_or_ps(ry, rcb);\n\t\t\t\t\t\tauto rcra = _mm256_or_ps(rcr, ra);\n\t\t\t\t\t\tauto r256ps = _mm256_or_ps(rycb, rcra);\n\n\t\t\t\t\t\tr256ps = _mm256_round_ps(r256ps, 0);\n\n\t\t\t\t\t\tauto r256i = _mm256_cvtps_epi32(r256ps);\n\t\t\t\t\t\t*/\n\t\t\t\t\t\tauto pr = _mm256_shuffle_epi32(p256i, 0b00000000);\n\t\t\t\t\t\tpr = _mm256_mullo_epi32(pr, _mm256_set_epi32(4918, -2775, 8224, 0, 4918, -2775, 8224, 0));\n\t\t\t\t\t\tpr = _mm256_add_epi32(pr, _mm256_set_epi32(354, 240, 256, 0, 354, 240, 256, 0));\n\t\t\t\t\t\tpr = _mm256_srai_epi32(pr, 10);\n\n\t\t\t\t\t\tauto pg = _mm256_shuffle_epi32(p256i, 0b01010101);\n\t\t\t\t\t\tpg = _mm256_mullo_epi32(pg, _mm256_set_epi32(9655, -5449, -6887, 0, 9655, -5449, -6887, 0));\n\t\t\t\t\t\tpg = _mm256_add_epi32(pg, _mm256_set_epi32(585, 515, 110, 0, 585, 515, 110, 0));\n\t\t\t\t\t\tpg = _mm256_srai_epi32(pg, 10);\n\n\t\t\t\t\t\tauto pb = _mm256_shuffle_epi32(p256i, 0b10101010);\n\t\t\t\t\t\tpb = _mm256_mullo_epi32(pb, _mm256_set_epi32(1875, 8224, -1337, 0, 1875, 8224, -1337, 0));\n\t\t\t\t\t\tpb = _mm256_add_epi32(pb, _mm256_set_epi32(512, 256, 646, 0, 512, 256, 646, 0));\n\t\t\t\t\t\tpb = _mm256_srai_epi32(pb, 10);\n\n\t\t\t\t\t\tauto pa = _mm256_shuffle_epi32(p256i, 0b11111111);\n\t\t\t\t\t\tpa = _mm256_mullo_epi32(pa, _mm256_set1_epi32(4096));\n\t\t\t\t\t\tpa = _mm256_div_epi32(pa, _mm256_set1_epi32(255));\n\n\t\t\t\t\t\tauto r = _mm256_add_epi32(pr, pg);\n\t\t\t\t\t\tr = _mm256_add_epi32(r, pb);\n\t\t\t\t\t\tr = _mm256_blend_epi32(r, pa, 0b10001000);\n\n\t\t\t\t\t\tauto r128 = _mm256_extracti128_si256(_mm256_packs_epi32(r, r), 0);\n\t\t\t\t\t\t_mm_storeu_si128((__m128i*)(efpip->obj_edit + efpip->obj_line * y + x), r128);\n\t\t\t\t\t}\n\t\t\t\t\tif (w & 1) {\n\t\t\t\t\t\tauto p128 = _mm_loadu_si64(data + w - 1 + y * efpip->obj_h);\n\t\t\t\t\t\tauto p128i = _mm_cvtepu8_epi32(p128);\n\t\t\t\t\t\tauto p128ps = _mm_cvtepi32_ps(p128i);\n\n\t\t\t\t\t\tauto ry = _mm_dp_ps(p128ps, y_ef.m128, 0b01110001);\n\t\t\t\t\t\tauto rcb = _mm_dp_ps(p128ps, cb_ef.m128, 0b01110010);\n\t\t\t\t\t\tauto rcr = _mm_dp_ps(p128ps, cr_ef.m128, 0b01110100);\n\t\t\t\t\t\tauto ra = _mm_dp_ps(p128ps, a_ef.m128, 0b01111000);\n\n\t\t\t\t\t\tauto rycb = _mm_or_ps(ry, rcb);\n\t\t\t\t\t\tauto rcra = _mm_or_ps(rcr, ra);\n\t\t\t\t\t\tauto r128ps = _mm_or_ps(rycb, rcra);\n\n\t\t\t\t\t\tr128ps = _mm_round_ps(r128ps, 0);\n\n\t\t\t\t\t\tauto r128i = _mm_cvtps_epi32(r128ps);\n\t\t\t\t\t\tauto r128 = _mm_cvtepi32_epi16(r128i);\n\n\t\t\t\t\t\t_mm_storeu_si64(efpip->obj_edit + efpip->obj_line * y + w - 1, r128);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\treturn 0;\n\t}\n\t\n#endif\n\n} // namespace patch::fast\n#endif // ifdef PATCH_SWITCH_FAST_GETPUTPIXELDATA\n"
  },
  {
    "path": "patch/patch_fast_getputpixeldata.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_FAST_GETPUTPIXELDATA\n\n#include <intrin.h>\n\n#include \"global.hpp\"\n#include \"offset_address.hpp\"\n#include \"mylua.hpp\"\n#include \"util_magic.hpp\"\n\nnamespace patch::fast {\n\t// init at ExEdit init\n\t// obj.getpixeldata/putpixeldata 他の動作を高速化\n\t// AVXを使用\n\tinline class getputpixeldata_t {\n\t\tstatic int avx_getpixeldata(lua_State* L);\n\n\t\tstatic int avx_putpixeldata(lua_State* L);\n\n\t\tstatic BOOL BufCpyBGRA2YCA(void* dst, void* src, int w, int h, int line);\n\t\tstatic BOOL BufCpyYCA2BGRA(void* dst, void* src, int w, int h, int line);\n\n\t\tunion m128_256 {\n\t\t\t__m256 m256;\n\t\t\t__m128 m128;\n\t\t};\n\n\tpublic:\n\t\tvoid operator()() {\n\t\t\tOverWriteOnProtectHelper(GLOBAL::exedit_base + OFS::ExEdit::getpixeldata, 4).store_i32(0, &avx_getpixeldata);\n\t\t}\n\t} getputpixeldata;\n} // namespace patch::fast\n#endif // ifdef PATCH_SWITCH_FAST_GETPUTPIXELDATA\n"
  },
  {
    "path": "patch/patch_fast_glow.cpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"patch_fast_glow.hpp\"\r\n#ifdef PATCH_SWITCH_FAST_GLOW\r\n\r\n#include <numbers>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util_int.hpp\"\r\n#include \"debug_log.hpp\"\r\n#include <immintrin.h>\r\n\r\n\r\nnamespace patch::fast {\r\n\r\n\r\n    void __cdecl Glow_t::lower_right_convolution1_wrap(int thread_id, int thread_num, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\r\n        thread_num *= 2;\r\n        int func_ptr = GLOBAL::exedit_base + 0x570d0;\r\n        reinterpret_cast<void(__cdecl*)(int, int, ExEdit::Filter*, ExEdit::FilterProcInfo*)>(func_ptr)(thread_id, thread_num, efp, efpip);\r\n        reinterpret_cast<void(__cdecl*)(int, int, ExEdit::Filter*, ExEdit::FilterProcInfo*)>(func_ptr)(thread_num - thread_id - 1, thread_num, efp, efpip);\r\n    }\r\n    void __cdecl Glow_t::lower_right_convolution2_wrap(int thread_id, int thread_num, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\r\n        thread_num *= 2;\r\n        int func_ptr = GLOBAL::exedit_base + 0x57730;\r\n        reinterpret_cast<void(__cdecl*)(int, int, ExEdit::Filter*, ExEdit::FilterProcInfo*)>(func_ptr)(thread_id, thread_num, efp, efpip);\r\n        reinterpret_cast<void(__cdecl*)(int, int, ExEdit::Filter*, ExEdit::FilterProcInfo*)>(func_ptr)(thread_num - thread_id - 1, thread_num, efp, efpip);\r\n    }\r\n    void __cdecl Glow_t::lower_left_convolution1_wrap(int thread_id, int thread_num, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\r\n        thread_num *= 2;\r\n        int func_ptr = GLOBAL::exedit_base + 0x57d90;\r\n        reinterpret_cast<void(__cdecl*)(int, int, ExEdit::Filter*, ExEdit::FilterProcInfo*)>(func_ptr)(thread_id, thread_num, efp, efpip);\r\n        reinterpret_cast<void(__cdecl*)(int, int, ExEdit::Filter*, ExEdit::FilterProcInfo*)>(func_ptr)(thread_num - thread_id - 1, thread_num, efp, efpip);\r\n    }\r\n    void __cdecl Glow_t::lower_left_convolution2_wrap(int thread_id, int thread_num, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\r\n        thread_num *= 2;\r\n        int func_ptr = GLOBAL::exedit_base + 0x58430;\r\n        reinterpret_cast<void(__cdecl*)(int, int, ExEdit::Filter*, ExEdit::FilterProcInfo*)>(func_ptr)(thread_id, thread_num, efp, efpip);\r\n        reinterpret_cast<void(__cdecl*)(int, int, ExEdit::Filter*, ExEdit::FilterProcInfo*)>(func_ptr)(thread_num - thread_id - 1, thread_num, efp, efpip);\r\n    }\r\n\r\n\r\n\r\n\r\n    struct fastGlow256 {\r\n        __m256i data;\r\n        __m256i y, cb, cr;\r\n        __m256i offset;\r\n    };\r\n\r\n\r\n    void __declspec(noinline) __fastcall fg256_add(fastGlow256* fg256, ExEdit::PixelYCA* src) {\r\n        __m256i ycb256 = _mm256_i32gather_epi32((int*)src, fg256->offset, 1);\r\n        __m256i y256 = _mm256_srai_epi32(_mm256_slli_epi32(ycb256, 16), 16);\r\n        fg256->y = _mm256_add_epi32(fg256->y, y256);\r\n        __m256i cb256 = _mm256_srai_epi32(ycb256, 16);\r\n        fg256->cb = _mm256_add_epi32(fg256->cb, cb256);\r\n        __m256i cbcr256 = _mm256_i32gather_epi32((int*)&src->cb, fg256->offset, 1);\r\n        __m256i cr256 = _mm256_srai_epi32(cbcr256, 16);\r\n        fg256->cr = _mm256_add_epi32(fg256->cr, cr256);\r\n    }\r\n    void __declspec(noinline) __fastcall fg256_sub(fastGlow256* fg256, ExEdit::PixelYCA* src) {\r\n        __m256i ycb256 = _mm256_i32gather_epi32((int*)src, fg256->offset, 1);\r\n        __m256i y256 = _mm256_srai_epi32(_mm256_slli_epi32(ycb256, 16), 16);\r\n        fg256->y = _mm256_sub_epi32(fg256->y, y256);\r\n        __m256i cb256 = _mm256_srai_epi32(ycb256, 16);\r\n        fg256->cb = _mm256_sub_epi32(fg256->cb, cb256);\r\n        __m256i cbcr256 = _mm256_i32gather_epi32((int*)&src->cb, fg256->offset, 1);\r\n        __m256i cr256 = _mm256_srai_epi32(cbcr256, 16);\r\n        fg256->cr = _mm256_sub_epi32(fg256->cr, cr256);\r\n    }\r\n\r\n    void __declspec(noinline) __fastcall fg256_put_average(fastGlow256* fg256, ExEdit::PixelYCA* dst, int n) {\r\n        __m256i ave_y256 = _mm256_div_epi32(fg256->y, fg256->data);\r\n        __m256i ave_cb256 = _mm256_div_epi32(fg256->cb, fg256->data);\r\n        __m256i ave_cr256 = _mm256_div_epi32(fg256->cr, fg256->data);\r\n        for (int i = 0; i < 16; i += 2) {\r\n            dst->y = ave_y256.m256i_i16[i];\r\n            dst->cb = ave_cb256.m256i_i16[i];\r\n            dst->cr = ave_cr256.m256i_i16[i];\r\n            dst = (ExEdit::PixelYCA*)((int)dst + n);\r\n        }\r\n    }\r\n\r\n\r\n    void __declspec(noinline) __fastcall fg_put256_weight(fastGlow256* fg256, ExEdit::PixelYCA* dst, int n) {\r\n        fastGlow256 fg256s;\r\n\r\n        __m256i y256 = _mm256_srai_epi32(fg256->y, 4);\r\n        y256 = _mm256_mullo_epi32(y256, fg256->data);\r\n        fg256s.y = _mm256_srai_epi32(y256, 10);\r\n\r\n        __m256i cb256 = _mm256_srai_epi32(fg256->cb, 4);\r\n        cb256 = _mm256_mullo_epi32(cb256, fg256->data);\r\n        fg256s.cb = _mm256_srai_epi32(cb256, 10);\r\n\r\n        __m256i cr256 = _mm256_srai_epi32(fg256->cr, 4);\r\n        cr256 = _mm256_mullo_epi32(cr256, fg256->data);\r\n        fg256s.cr = _mm256_srai_epi32(cr256, 10);\r\n\r\n        fg256s.offset = fg256->offset;\r\n        fg256_add(&fg256s, dst);\r\n\r\n        for (int i = 0; i < 8; i++) {\r\n            int y = fg256s.y.m256i_i32[i];\r\n            if (0x2000 < y) {\r\n                dst->y = 0x2000;\r\n                dst->cb = (short)((fg256s.cb.m256i_i32[i] << 13) / y);\r\n                dst->cr = (short)((fg256s.cr.m256i_i32[i] << 13) / y);\r\n            } else {\r\n                dst->y = (short)y;\r\n                dst->cb = fg256s.cb.m256i_i16[i * 2];\r\n                dst->cr = fg256s.cr.m256i_i16[i * 2];\r\n            }\r\n            dst = (ExEdit::PixelYCA*)((int)dst + n);\r\n        }\r\n    }\r\n\r\n\r\n    struct fastGlow128 {\r\n        __m128i data;\r\n        int y, cb, cr, a;\r\n    };\r\n    void __declspec(noinline) __fastcall fg_put128_weight(fastGlow128* fg128, ExEdit::PixelYCA* dst) {\r\n        __m128i yc128 = _mm_srai_epi32(_mm_loadu_si128((__m128i*)&fg128->y), 4);\r\n        yc128 = _mm_mullo_epi32(yc128, fg128->data);\r\n        yc128 = _mm_srai_epi32(yc128, 10);\r\n        yc128 = _mm_add_epi32(yc128, _mm_cvtepi16_epi32(_mm_loadu_epi64(dst)));\r\n\r\n        int y = yc128.m128i_i32[0];\r\n        if (0x2000 < y) {\r\n            dst->y = 0x2000;\r\n            dst->cb = (yc128.m128i_i32[1] << 13) / y;\r\n            dst->cr = (yc128.m128i_i32[2] << 13) / y;\r\n        } else {\r\n            dst->y = (short)y;\r\n            dst->cb = yc128.m128i_i16[2];\r\n            dst->cr = yc128.m128i_i16[4];\r\n        }\r\n    }\r\n\r\n\r\n    void __cdecl Glow_t::vertical_convolution(int thi, int thn, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\r\n        auto glow = (efGlow_var*)(GLOBAL::exedit_base + OFS::ExEdit::efGlow_var_ptr);\r\n\r\n        int w = glow->src_w + glow->diffusion_w * 2;\r\n        int h = glow->src_h + glow->diffusion_h * 2;\r\n        int blur = min(glow->blur, (h - 1) / 2);\r\n        int range = blur * 2 + 1;\r\n        int range_h = h - range;\r\n        int linesize = efpip->obj_line * sizeof(struct ExEdit::PixelYCA);\r\n        int x_end = (thi + 1) * w / thn;\r\n\r\n        fastGlow256 fg256;\r\n        fg256.data = _mm256_set1_epi32(range);\r\n        fg256.offset = _mm256_set_epi32(7 * sizeof(struct ExEdit::PixelYCA), 6 * sizeof(struct ExEdit::PixelYCA), 5 * sizeof(struct ExEdit::PixelYCA), 4 * sizeof(struct ExEdit::PixelYCA), 3 * sizeof(struct ExEdit::PixelYCA), 2 * sizeof(struct ExEdit::PixelYCA), sizeof(struct ExEdit::PixelYCA), 0);\r\n\r\n        int x = thi * w / thn;\r\n        int x_end256 = x_end - 7;\r\n        for (; x < x_end256; x += 8) {\r\n            auto pix1 = (ExEdit::PixelYCA*)((int)glow->buf_temp + x * sizeof(struct ExEdit::PixelYCA));\r\n            auto pix2 = pix1;\r\n            auto mem = (ExEdit::PixelYCA*)((int)glow->buf_temp2 + x * sizeof(struct ExEdit::PixelYCA));\r\n\r\n            fg256.y = _mm256_setzero_si256();\r\n            fg256.cb = _mm256_setzero_si256();\r\n            fg256.cr = _mm256_setzero_si256();\r\n            for (int y = 0; y < blur; y++) {\r\n                fg256_add(&fg256, pix1);\r\n                pix1 = (ExEdit::PixelYCA*)((int)pix1 + linesize);\r\n            }\r\n            for (int y = 0; y <= blur; y++) {\r\n                fg256_add(&fg256, pix1);\r\n                pix1 = (ExEdit::PixelYCA*)((int)pix1 + linesize);\r\n\r\n                fg256_put_average(&fg256, mem, sizeof(struct ExEdit::PixelYCA));\r\n                mem = (ExEdit::PixelYCA*)((int)mem + linesize);\r\n            }\r\n            for (int y = 0; y < range_h; y++) {\r\n                fg256_sub(&fg256, pix2);\r\n                pix2 = (ExEdit::PixelYCA*)((int)pix2 + linesize);\r\n\r\n                fg256_add(&fg256, pix1);\r\n                pix1 = (ExEdit::PixelYCA*)((int)pix1 + linesize);\r\n\r\n                fg256_put_average(&fg256, mem, sizeof(struct ExEdit::PixelYCA));\r\n                mem = (ExEdit::PixelYCA*)((int)mem + linesize);\r\n            }\r\n            for (int y = 0; y < blur; y++) {\r\n                fg256_sub(&fg256, pix2);\r\n                pix2 = (ExEdit::PixelYCA*)((int)pix2 + linesize);\r\n\r\n                fg256_put_average(&fg256, mem, sizeof(struct ExEdit::PixelYCA));\r\n                mem = (ExEdit::PixelYCA*)((int)mem + linesize);\r\n            }\r\n        }\r\n\r\n\r\n        for (; x < x_end; x++) {\r\n            auto pix1 = (ExEdit::PixelYCA*)((int)glow->buf_temp + x * sizeof(struct ExEdit::PixelYCA));\r\n            auto pix2 = pix1;\r\n            auto mem = (ExEdit::PixelYCA*)((int)glow->buf_temp2 + x * sizeof(struct ExEdit::PixelYCA));\r\n            int sum_y = 0;\r\n            int sum_cb = 0;\r\n            int sum_cr = 0;\r\n            for (int y = 0; y < blur; y++) {\r\n                sum_y += pix1->y;\r\n                sum_cb += pix1->cb;\r\n                sum_cr += pix1->cr;\r\n                pix1 = (ExEdit::PixelYCA*)((int)pix1 + linesize);\r\n            }\r\n            for (int y = 0; y <= blur; y++) {\r\n                sum_y += pix1->y;\r\n                sum_cb += pix1->cb;\r\n                sum_cr += pix1->cr;\r\n                pix1 = (ExEdit::PixelYCA*)((int)pix1 + linesize);\r\n                mem->y = (short)(sum_y / range);\r\n                mem->cb = (short)(sum_cb / range);\r\n                mem->cr = (short)(sum_cr / range);\r\n                mem = (ExEdit::PixelYCA*)((int)mem + linesize);\r\n            }\r\n            for (int y = 0; y < range_h; y++) {\r\n                sum_y += pix1->y - pix2->y;\r\n                sum_cb += pix1->cb - pix2->cb;\r\n                sum_cr += pix1->cr - pix2->cr;\r\n                pix1 = (ExEdit::PixelYCA*)((int)pix1 + linesize);\r\n                pix2 = (ExEdit::PixelYCA*)((int)pix2 + linesize);\r\n                mem->y = (short)(sum_y / range);\r\n                mem->cb = (short)(sum_cb / range);\r\n                mem->cr = (short)(sum_cr / range);\r\n                mem = (ExEdit::PixelYCA*)((int)mem + linesize);\r\n            }\r\n            for (int y = 0; y < blur; y++) {\r\n                sum_y -= pix2->y;\r\n                sum_cb -= pix2->cb;\r\n                sum_cr -= pix2->cr;\r\n                pix2 = (ExEdit::PixelYCA*)((int)pix2 + linesize);\r\n                mem->y = (short)(sum_y / range);\r\n                mem->cb = (short)(sum_cb / range);\r\n                mem->cr = (short)(sum_cr / range);\r\n                mem = (ExEdit::PixelYCA*)((int)mem + linesize);\r\n            }\r\n        }\r\n    }\r\n\r\n\r\n\r\n\r\n\r\n    void __cdecl Glow_t::horizontal_convolution(int thi, int thn, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\r\n        auto glow = (efGlow_var*)(GLOBAL::exedit_base + OFS::ExEdit::efGlow_var_ptr);\r\n\r\n        int h = glow->src_h + glow->diffusion_h * 2;\r\n        int w = glow->src_w + glow->diffusion_w * 2;\r\n        int blur = min(glow->blur, (w - 1) / 2);\r\n        int range = blur * 2 + 1;\r\n        int range_w = w - range;\r\n        int linesize = efpip->obj_line * sizeof(struct ExEdit::PixelYCA);\r\n        int y_begin = thi * h / thn;\r\n        int y_end = (thi + 1) * h / thn;\r\n        int offset = y_begin * linesize;\r\n\r\n        fastGlow256 fg256;\r\n        fg256.data = _mm256_set1_epi32(range);\r\n        fg256.offset = _mm256_mullo_epi32(_mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0), _mm256_set1_epi32(linesize));\r\n\r\n        int y = y_begin;\r\n        int y_end256 = y_end - 7;\r\n        for (; y < y_end256; y += 8) {\r\n            auto mem1 = (ExEdit::PixelYCA*)((int)glow->buf_temp2 + offset);\r\n            auto mem2 = mem1;\r\n            auto pix = (ExEdit::PixelYCA*)((int)glow->buf_temp + offset);\r\n\r\n            fg256.y = _mm256_setzero_si256();\r\n            fg256.cb = _mm256_setzero_si256();\r\n            fg256.cr = _mm256_setzero_si256();\r\n            for (int x = 0; x < blur; x++) {\r\n                fg256_add(&fg256, mem1);\r\n                mem1++;\r\n            }\r\n            for (int x = 0; x <= blur; x++) {\r\n                fg256_add(&fg256, mem1);\r\n                mem1++;\r\n\r\n                fg256_put_average(&fg256, pix, linesize);\r\n                pix++;\r\n            }\r\n            for (int x = 0; x < range_w; x++) {\r\n                fg256_sub(&fg256, mem2);\r\n                mem2++;\r\n\r\n                fg256_add(&fg256, mem1);\r\n                mem1++;\r\n\r\n                fg256_put_average(&fg256, pix, linesize);\r\n                pix++;\r\n            }\r\n            for (int x = 0; x < blur; x++) {\r\n                fg256_sub(&fg256, mem2);\r\n                mem2++;\r\n\r\n                fg256_put_average(&fg256, pix, linesize);\r\n                pix++;\r\n            }\r\n            offset += linesize * 8;\r\n        }\r\n\r\n        for (; y < y_end; y++) {\r\n            auto mem1 = (ExEdit::PixelYCA*)((int)glow->buf_temp2 + offset);\r\n            auto mem2 = mem1;\r\n            auto pix = (ExEdit::PixelYCA*)((int)glow->buf_temp + offset);\r\n            int sum_y = 0;\r\n            int sum_cb = 0;\r\n            int sum_cr = 0;\r\n            for (int x = 0; x < blur; x++) {\r\n                sum_y += mem1->y;\r\n                sum_cb += mem1->cb;\r\n                sum_cr += mem1->cr;\r\n                mem1++;\r\n            }\r\n            for (int x = 0; x <= blur; x++) {\r\n                sum_y += mem1->y;\r\n                sum_cb += mem1->cb;\r\n                sum_cr += mem1->cr;\r\n                mem1++;\r\n                pix->y = (short)(sum_y / range);\r\n                pix->cb = (short)(sum_cb / range);\r\n                pix->cr = (short)(sum_cr / range);\r\n                pix++;\r\n            }\r\n            for (int x = 0; x < range_w; x++) {\r\n                sum_y += mem1->y - mem2->y;\r\n                sum_cb += mem1->cb - mem2->cb;\r\n                sum_cr += mem1->cr - mem2->cr;\r\n                mem1++;\r\n                mem2++;\r\n                pix->y = (short)(sum_y / range);\r\n                pix->cb = (short)(sum_cb / range);\r\n                pix->cr = (short)(sum_cr / range);\r\n                pix++;\r\n            }\r\n            for (int x = 0; x < blur; x++) {\r\n                sum_y -= mem2->y;\r\n                sum_cb -= mem2->cb;\r\n                sum_cr -= mem2->cr;\r\n                mem2++;\r\n                pix->y = (short)(sum_y / range);\r\n                pix->cb = (short)(sum_cb / range);\r\n                pix->cr = (short)(sum_cr / range);\r\n                pix++;\r\n            }\r\n            offset += linesize;\r\n        }\r\n    }\r\n\r\n\r\n    void __cdecl Glow_t::horizontal_convolution_intensity_blur(int thi, int thn, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\r\n        auto glow = (efGlow_var*)(GLOBAL::exedit_base + OFS::ExEdit::efGlow_var_ptr);\r\n\r\n        int h = glow->src_h + glow->diffusion_h * 2;\r\n        int blur = glow->blur;\r\n        int range_w = glow->src_w + (glow->diffusion_w - blur) * 2 - 1;\r\n        int intensity = glow->intensity;\r\n        int linesize = efpip->obj_line * sizeof(struct ExEdit::PixelYCA);\r\n        int y_begin = thi * h / thn;\r\n        int y_end = (thi + 1) * h / thn;\r\n        int offset = y_begin * linesize;\r\n\r\n        fastGlow256 fg256;\r\n        fg256.data = _mm256_set1_epi32(intensity);\r\n        fg256.offset = _mm256_mullo_epi32(_mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0), _mm256_set1_epi32(linesize));\r\n\r\n        int y = y_begin;\r\n        int y_end256 = y_end - 7;\r\n        for (; y < y_end256; y += 8) {\r\n            auto mem1 = (ExEdit::PixelYCA*)((int)glow->buf_temp2 + offset);\r\n            auto mem2 = mem1;\r\n            auto pix = (ExEdit::PixelYCA*)((int)glow->buf_temp + offset);\r\n\r\n            fg256.y = _mm256_setzero_si256();\r\n            fg256.cb = _mm256_setzero_si256();\r\n            fg256.cr = _mm256_setzero_si256();\r\n            for (int x = 0; x < blur; x++) {\r\n                fg256_add(&fg256, mem1);\r\n                mem1++;\r\n            }\r\n            for (int x = 0; x <= blur; x++) {\r\n                fg256_add(&fg256, mem1);\r\n                mem1++;\r\n\r\n                fg_put256_weight(&fg256, pix, linesize);\r\n                pix++;\r\n            }\r\n            for (int x = 0; x < range_w; x++) {\r\n                fg256_sub(&fg256, mem2);\r\n                mem2++;\r\n\r\n                fg256_add(&fg256, mem1);\r\n                mem1++;\r\n\r\n                fg_put256_weight(&fg256, pix, linesize);\r\n                pix++;\r\n            }\r\n            for (int x = 0; x < blur; x++) {\r\n                fg256_sub(&fg256, mem2);\r\n                mem2++;\r\n\r\n                fg_put256_weight(&fg256, pix, linesize);\r\n                pix++;\r\n            }\r\n            offset += linesize * 8;\r\n        }\r\n\r\n\r\n        fastGlow128 fg128;\r\n        fg128.data = _mm_set1_epi32(intensity);\r\n        for (; y < y_end; y++) {\r\n            auto mem1 = (ExEdit::PixelYCA*)((int)glow->buf_temp2 + offset);\r\n            auto mem2 = mem1;\r\n            auto pix = (ExEdit::PixelYCA*)((int)glow->buf_temp + offset);\r\n            fg128.y = 0;\r\n            fg128.cb = 0;\r\n            fg128.cr = 0;\r\n            for (int x = 0; x < blur; x++) {\r\n                fg128.y += mem1->y;\r\n                fg128.cb += mem1->cb;\r\n                fg128.cr += mem1->cr;\r\n                mem1++;\r\n            }\r\n            for (int x = 0; x <= blur; x++) {\r\n                fg128.y += mem1->y;\r\n                fg128.cb += mem1->cb;\r\n                fg128.cr += mem1->cr;\r\n                mem1++;\r\n\r\n                fg_put128_weight(&fg128, pix);\r\n                pix++;\r\n            }\r\n            for (int x = 0; x < range_w; x++) {\r\n                fg128.y += mem1->y - mem2->y;\r\n                fg128.cb += mem1->cb - mem2->cb;\r\n                fg128.cr += mem1->cr - mem2->cr;\r\n                mem1++;\r\n                mem2++;\r\n\r\n                fg_put128_weight(&fg128, pix);\r\n                pix++;\r\n            }\r\n            for (int x = 0; x < blur; x++) {\r\n                fg128.y -= mem2->y;\r\n                fg128.cb -= mem2->cb;\r\n                fg128.cr -= mem2->cr;\r\n                mem2++;\r\n\r\n                fg_put128_weight(&fg128, pix);\r\n                pix++;\r\n            }\r\n            offset += linesize;\r\n        }\r\n    }\r\n\r\n\r\n\r\n    void vertical_convolution_intensity_main(int thi, int thn, int n, ExEdit::FilterProcInfo* efpip) {\r\n        auto glow = (Glow_t::efGlow_var*)(GLOBAL::exedit_base + OFS::ExEdit::efGlow_var_ptr);\r\n\r\n        int w = glow->src_w;\r\n        int h = glow->src_h;\r\n        int diff_h = glow->diffusion_h;\r\n        int diff = min(diff_h / n, (h - 1) / 2);\r\n        int diff2 = diff * 2;\r\n        int range = h - diff2 - 1;\r\n        int linesize = efpip->obj_line * sizeof(struct ExEdit::PixelYCA);\r\n        int intensity = glow->intensity * n;\r\n        int x_end = (thi + 1) * w / thn;\r\n\r\n        auto pix_temp = (ExEdit::PixelYCA*)((int)glow->buf_temp + (diff_h - diff) * linesize + glow->diffusion_w * sizeof(struct ExEdit::PixelYCA));\r\n\r\n        \r\n        fastGlow256 fg256;\r\n        fg256.data = _mm256_set1_epi32(intensity);\r\n        fg256.offset = _mm256_set_epi32(7 * sizeof(struct ExEdit::PixelYCA), 6 * sizeof(struct ExEdit::PixelYCA), 5 * sizeof(struct ExEdit::PixelYCA), 4 * sizeof(struct ExEdit::PixelYCA), 3 * sizeof(struct ExEdit::PixelYCA), 2 * sizeof(struct ExEdit::PixelYCA), sizeof(struct ExEdit::PixelYCA), 0);\r\n\r\n        int x = thi * w / thn;\r\n        int x_end256 = x_end - 7;\r\n        for (; x < x_end256; x += 8) {\r\n            auto mem1 = (ExEdit::PixelYCA*)((int)glow->buf_temp2 + x * sizeof(struct ExEdit::PixelYCA));\r\n            auto mem2 = mem1;\r\n            auto pix = (ExEdit::PixelYCA*)((int)pix_temp + x * sizeof(struct ExEdit::PixelYCA));\r\n\r\n            fg256.y = _mm256_setzero_si256();\r\n            fg256.cb = _mm256_setzero_si256();\r\n            fg256.cr = _mm256_setzero_si256();\r\n            for (int y = 0; y <= diff2; y++) {\r\n                fg256_add(&fg256, mem1);\r\n                mem1 = (ExEdit::PixelYCA*)((int)mem1 + linesize);\r\n\r\n                fg_put256_weight(&fg256, pix, sizeof(struct ExEdit::PixelYCA));\r\n                pix = (ExEdit::PixelYCA*)((int)pix + linesize);\r\n            }\r\n            for (int y = 0; y < range; y++) {\r\n                fg256_sub(&fg256, mem2);\r\n                mem2 = (ExEdit::PixelYCA*)((int)mem2 + linesize);\r\n                fg256_add(&fg256, mem1);\r\n                mem1 = (ExEdit::PixelYCA*)((int)mem1 + linesize);\r\n\r\n                fg_put256_weight(&fg256, pix, sizeof(struct ExEdit::PixelYCA));\r\n                pix = (ExEdit::PixelYCA*)((int)pix + linesize);\r\n            }\r\n            for (int y = 0; y < diff2; y++) {\r\n                fg256_sub(&fg256, mem2);\r\n                mem2 = (ExEdit::PixelYCA*)((int)mem2 + linesize);\r\n\r\n                fg_put256_weight(&fg256, pix, sizeof(struct ExEdit::PixelYCA));\r\n                pix = (ExEdit::PixelYCA*)((int)pix + linesize);\r\n            }\r\n        }\r\n        \r\n        fastGlow128 fg128;\r\n        fg128.data = _mm_set1_epi32(intensity);\r\n        for (; x < x_end; x++) {\r\n            auto mem1 = (ExEdit::PixelYCA*)((int)glow->buf_temp2 + x * sizeof(struct ExEdit::PixelYCA));\r\n            auto mem2 = mem1;\r\n            auto pix = (ExEdit::PixelYCA*)((int)pix_temp + x * sizeof(struct ExEdit::PixelYCA));\r\n            fg128.y = 0;\r\n            fg128.cb = 0;\r\n            fg128.cr = 0;\r\n            for (int y = 0; y <= diff2; y++) {\r\n                fg128.y += mem1->y;\r\n                fg128.cb += mem1->cb;\r\n                fg128.cr += mem1->cr;\r\n                mem1 = (ExEdit::PixelYCA*)((int)mem1 + linesize);\r\n\r\n                fg_put128_weight(&fg128, pix);\r\n                pix = (ExEdit::PixelYCA*)((int)pix + linesize);\r\n            }\r\n            for (int y = 0; y < range; y++) {\r\n                fg128.y += mem1->y - mem2->y;\r\n                fg128.cb += mem1->cb - mem2->cb;\r\n                fg128.cr += mem1->cr - mem2->cr;\r\n                mem1 = (ExEdit::PixelYCA*)((int)mem1 + linesize);\r\n                mem2 = (ExEdit::PixelYCA*)((int)mem2 + linesize);\r\n\r\n                fg_put128_weight(&fg128, pix);\r\n                pix = (ExEdit::PixelYCA*)((int)pix + linesize);\r\n            }\r\n            for (int y = 0; y < diff2; y++) {\r\n                fg128.y -= mem2->y;\r\n                fg128.cb -= mem2->cb;\r\n                fg128.cr -= mem2->cr;\r\n                mem2 = (ExEdit::PixelYCA*)((int)mem2 + linesize);\r\n\r\n                fg_put128_weight(&fg128, pix);\r\n                pix = (ExEdit::PixelYCA*)((int)pix + linesize);\r\n            }\r\n        }\r\n    }\r\n    void __cdecl Glow_t::vertical_convolution_intensity3(int thi, int thn, ExEdit::Filter * efp, ExEdit::FilterProcInfo * efpip) {\r\n        vertical_convolution_intensity_main(thi, thn, 1, efpip);\r\n        vertical_convolution_intensity_main(thi, thn, 2, efpip);\r\n        vertical_convolution_intensity_main(thi, thn, 4, efpip);\r\n    }\r\n\r\n\r\n\r\n    void horizontal_convolution_intensity_main(int thi, int thn, int n, ExEdit::FilterProcInfo* efpip) {\r\n        auto glow = (Glow_t::efGlow_var*)(GLOBAL::exedit_base + OFS::ExEdit::efGlow_var_ptr);\r\n\r\n        int w = glow->src_w;\r\n        int h = glow->src_h;\r\n        int diff_w = glow->diffusion_w;\r\n        int diff = min(diff_w / n, (w - 1) / 2);\r\n        int diff2 = diff * 2;\r\n        int range = w - diff2 - 1;\r\n        int linesize = efpip->obj_line * sizeof(struct ExEdit::PixelYCA);\r\n        int intensity = glow->intensity * n;\r\n        int y_begin = thi * h / thn;\r\n        int y_end = (thi + 1) * h / thn;\r\n        int offset = y_begin * linesize;\r\n\r\n        auto pix_temp = (ExEdit::PixelYCA*)((int)glow->buf_temp + glow->diffusion_h * linesize + (diff_w - diff) * sizeof(struct ExEdit::PixelYCA));\r\n\r\n\r\n        fastGlow256 fg256;\r\n        fg256.data = _mm256_set1_epi32(intensity);\r\n        fg256.offset = _mm256_mullo_epi32(_mm256_set_epi32(7, 6, 5, 4, 3, 2, 1, 0), _mm256_set1_epi32(linesize));\r\n\r\n        int y = y_begin;\r\n        int y_end256 = y_end - 7;\r\n        for (; y < y_end256; y += 8) {\r\n            auto mem1 = (ExEdit::PixelYCA*)((int)glow->buf_temp2 + offset);\r\n            auto mem2 = mem1;\r\n            auto pix = (ExEdit::PixelYCA*)((int)pix_temp + offset);\r\n\r\n            fg256.y = _mm256_setzero_si256();\r\n            fg256.cb = _mm256_setzero_si256();\r\n            fg256.cr = _mm256_setzero_si256();\r\n            for (int x = 0; x <= diff2; x++) {\r\n                fg256_add(&fg256, mem1);\r\n                mem1++;\r\n\r\n                fg_put256_weight(&fg256, pix, linesize);\r\n                pix++;\r\n            }\r\n            for (int x = 0; x < range; x++) {\r\n                fg256_sub(&fg256, mem2);\r\n                mem2++;\r\n                fg256_add(&fg256, mem1);\r\n                mem1++;\r\n\r\n                fg_put256_weight(&fg256, pix, linesize);\r\n                pix++;\r\n            }\r\n            for (int x = 0; x < diff2; x++) {\r\n                fg256_sub(&fg256, mem2);\r\n                mem2++;\r\n\r\n                fg_put256_weight(&fg256, pix, linesize);\r\n                pix++;\r\n            }\r\n            offset += linesize * 8;\r\n        }\r\n\r\n        fastGlow128 fg128;\r\n        fg128.data = _mm_set1_epi32(intensity);\r\n        for (; y < y_end; y++) {\r\n            auto mem1 = (ExEdit::PixelYCA*)((int)glow->buf_temp2 + offset);\r\n            auto mem2 = mem1;\r\n            auto pix = (ExEdit::PixelYCA*)((int)pix_temp + offset);\r\n            fg128.y = 0;\r\n            fg128.cb = 0;\r\n            fg128.cr = 0;\r\n            for (int x = 0; x <= diff2; x++) {\r\n                fg128.y += mem1->y;\r\n                fg128.cb += mem1->cb;\r\n                fg128.cr += mem1->cr;\r\n                mem1++;\r\n\r\n                fg_put128_weight(&fg128, pix);\r\n                pix++;\r\n            }\r\n            for (int x = 0; x < range; x++) {\r\n                fg128.y += mem1->y - mem2->y;\r\n                fg128.cb += mem1->cb - mem2->cb;\r\n                fg128.cr += mem1->cr - mem2->cr;\r\n                mem1++;\r\n                mem2++;\r\n\r\n                fg_put128_weight(&fg128, pix);\r\n                pix++;\r\n            }\r\n            for (int x = 0; x < diff2; x++) {\r\n                fg128.y -= mem2->y;\r\n                fg128.cb -= mem2->cb;\r\n                fg128.cr -= mem2->cr;\r\n                mem2++;\r\n\r\n                fg_put128_weight(&fg128, pix);\r\n                pix++;\r\n            }\r\n            offset += linesize;\r\n        }\r\n    }\r\n    void __cdecl Glow_t::horizontal_convolution_intensity3(int thi, int thn, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\r\n        horizontal_convolution_intensity_main(thi, thn, 1, efpip);\r\n        horizontal_convolution_intensity_main(thi, thn, 2, efpip);\r\n        horizontal_convolution_intensity_main(thi, thn, 4, efpip);\r\n    }\r\n\r\n}\r\n#endif // ifdef PATCH_SWITCH_FAST_GLOW\r\n"
  },
  {
    "path": "patch/patch_fast_glow.hpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n#ifdef PATCH_SWITCH_FAST_GLOW\r\n\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util.hpp\"\r\n#include \"global.hpp\"\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch::fast {\r\n\t// init at exedit load\r\n\t// グローちょっとだけ速度アップ\r\n\t// クロス斜め以外：AVX2を使用\r\n\t/* クロス斜め：マルチスレッド処理の効率が悪かった部分を修正（AVX2処理にするのは難しい部分）\r\n\t\tスレッドIDによってループ数に大きく差が出る部分があったのでなるべく均等になるように分担\r\n\t\t理想的な均等にするなら「正方形」と「残り」の形にしてから行う必要がある。（関数の作り変えも必要）\r\n\t\t簡易的に実装し元の関数を再利用する。(元より悪くなることは無いはず)\r\n\t*/\r\n\tinline class Glow_t {\r\n\r\n\t\tstatic void __cdecl lower_right_convolution1_wrap(int thi, int thn, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\r\n\t\tstatic void __cdecl lower_right_convolution2_wrap(int thi, int thn, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\r\n\t\tstatic void __cdecl lower_left_convolution1_wrap(int thi, int thn, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\r\n\t\tstatic void __cdecl lower_left_convolution2_wrap(int thi, int thn, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\r\n\r\n\r\n\t\tstatic void __cdecl vertical_convolution(int thi, int thn, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\r\n\t\tstatic void __cdecl horizontal_convolution(int thi, int thn, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\r\n\t\tstatic void __cdecl vertical_convolution_intensity3(int thi, int thn, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\r\n\t\tstatic void __cdecl horizontal_convolution_intensity3(int thi, int thn, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\r\n\t\tstatic void __cdecl horizontal_convolution_intensity_blur(int thi, int thn, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\r\n\r\n\t\tbool enabled = true;\r\n\t\tbool enabled_i;\r\n\t\tinline static const char key[] = \"fast.glow\";\r\n\r\n\tpublic:\r\n\r\n\t\tstruct efGlow_var { // 1b2010\r\n\t\t\tint src_h;\r\n\t\t\tint src_w;\r\n\t\t\tint intensity;\r\n\t\t\tint blur;\r\n\t\t\tint diffusion_h;\r\n\t\t\tint diffusion_w;\r\n\t\t\tint diffusion_length;\r\n\t\t\tshort light_cb;\r\n\t\t\tshort light_cr;\r\n\t\t\tshort light_y;\r\n\t\t\tshort _padding;\r\n\t\t\tvoid* buf_temp;\r\n\t\t\tvoid* buf_temp2;\r\n\t\t\tint threshold; // 1b203c\r\n\t\t};\r\n\t\t\r\n\r\n\t\tvoid init() {\r\n\t\t\tenabled_i = enabled;\r\n\t\t\tif (!enabled_i)return;\r\n\r\n\t\t\t{ // クロス斜め\r\n\t\t\t\t{\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x55363, 4);\r\n\t\t\t\t\t\th.store_i32(0, &lower_right_convolution1_wrap);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x553cb, 4);\r\n\t\t\t\t\t\th.store_i32(0, &lower_right_convolution1_wrap);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t{\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x55373, 4);\r\n\t\t\t\t\t\th.store_i32(0, &lower_right_convolution2_wrap);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x553db, 4);\r\n\t\t\t\t\t\th.store_i32(0, &lower_right_convolution2_wrap);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t{\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x55383, 4);\r\n\t\t\t\t\t\th.store_i32(0, &lower_left_convolution1_wrap);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x553eb, 4);\r\n\t\t\t\t\t\th.store_i32(0, &lower_left_convolution1_wrap);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t{\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x55393, 4);\r\n\t\t\t\t\t\th.store_i32(0, &lower_left_convolution2_wrap);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x553fb, 4);\r\n\t\t\t\t\t\th.store_i32(0, &lower_left_convolution2_wrap);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t{ // クロス斜め以外\r\n\t\t\t\tauto cpucmdset = get_CPUCmdSet();\r\n\t\t\t\tif (!has_flag(cpucmdset, CPUCmdSet::F_AVX2))return;\r\n\r\n\t\t\t\t{\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x551ea, 4);\r\n\t\t\t\t\t\th.store_i32(0, &vertical_convolution);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x5528a, 4);\r\n\t\t\t\t\t\th.store_i32(0, &vertical_convolution);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x552ca, 4);\r\n\t\t\t\t\t\th.store_i32(0, &vertical_convolution);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x55309, 4);\r\n\t\t\t\t\t\th.store_i32(0, &vertical_convolution);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x55444, 4);\r\n\t\t\t\t\t\th.store_i32(0, &vertical_convolution);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x55464, 4);\r\n\t\t\t\t\t\th.store_i32(0, &vertical_convolution);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t{\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x55454, 4);\r\n\t\t\t\t\t\th.store_i32(0, &horizontal_convolution);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x55474, 4);\r\n\t\t\t\t\t\th.store_i32(0, &horizontal_convolution);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t{\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x5525a, 4);\r\n\t\t\t\t\t\th.store_i32(0, &horizontal_convolution_intensity_blur);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x552a3, 4);\r\n\t\t\t\t\t\th.store_i32(0, &horizontal_convolution_intensity_blur);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x552e5, 4);\r\n\t\t\t\t\t\th.store_i32(0, &horizontal_convolution_intensity_blur);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x55326, 4);\r\n\t\t\t\t\t\th.store_i32(0, &horizontal_convolution_intensity_blur);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t{\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x5533b, 4);\r\n\t\t\t\t\t\th.store_i32(0, &vertical_convolution_intensity3);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x553ab, 4);\r\n\t\t\t\t\t\th.store_i32(0, &vertical_convolution_intensity3);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x55422, 4);\r\n\t\t\t\t\t\th.store_i32(0, &vertical_convolution_intensity3);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t{\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x5534b, 4);\r\n\t\t\t\t\t\th.store_i32(0, &horizontal_convolution_intensity3);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x553bb, 4);\r\n\t\t\t\t\t\th.store_i32(0, &horizontal_convolution_intensity3);\r\n\t\t\t\t\t}\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x55410, 4);\r\n\t\t\t\t\t\th.store_i32(0, &horizontal_convolution_intensity3);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tvoid switching(bool flag) { enabled = flag; }\r\n\r\n\t\tbool is_enabled() { return enabled; }\r\n\t\tbool is_enabled_i() { return enabled_i; }\r\n\r\n\t\tvoid switch_load(ConfigReader& cr) {\r\n\t\t\tcr.regist(key, [this](json_value_s* value) {\r\n\t\t\t\tConfigReader::load_variable(value, enabled);\r\n\t\t\t\t});\r\n\t\t}\r\n\r\n\t\tvoid switch_store(ConfigWriter& cw) {\r\n\t\t\tcw.append(key, enabled);\r\n\t\t}\r\n\r\n\t} Glow;\r\n} // namespace patch::fast\r\n#endif // ifdef PATCH_SWITCH_FAST_GLOW\r\n"
  },
  {
    "path": "patch/patch_fast_lensblur.cpp",
    "content": "/*\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_fast_lensblur.hpp\"\n#ifdef PATCH_SWITCH_FAST_LENSBLUR\n\n#include \"debug_log.hpp\"\n#include \"patch_fast_cl.hpp\"\n\n//#define PATCH_STOPWATCH\n#include \"stopwatch.hpp\"\n\nnamespace patch::fast {\n    static stopwatch_mem sw;\n\n    BOOL LensBlur_t::media_mt_func(AviUtl::MultiThreadFunc original_func_ptr, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\n        if constexpr (true) {\n            if (256 < efpip->obj_w * efpip->obj_h) {\n                sw.start();\n                try {\n                    const auto buf_size = efpip->obj_line * efpip->obj_h * sizeof(ExEdit::PixelYCA);\n                    cl::Buffer clmem_src(cl.context, CL_MEM_READ_ONLY, buf_size);\n                    cl.queue.enqueueWriteBuffer(clmem_src, CL_TRUE, 0, buf_size, efpip->obj_edit);\n\n                    cl::Buffer clmem_dst(cl.context, CL_MEM_WRITE_ONLY, buf_size);\n                    efLensBlur_var& lensblur = *(efLensBlur_var*)uintptr_t(reinterpret_cast<efLensBlur_var*>(GLOBAL::exedit_base + OFS::ExEdit::efLensBlur_var_ptr));\n                    auto kernel = cl.readyKernel(\n                        \"LensBlur_Media\",\n                        clmem_dst,\n                        clmem_src,\n                        efpip->obj_w,\n                        efpip->obj_h,\n                        efpip->obj_line,\n                        lensblur.range,\n                        lensblur.rangep05_sqr,\n                        lensblur.range_t3m1,\n                        lensblur.rangem1_sqr\n                    );\n                    cl.queue.enqueueNDRangeKernel(kernel, { 0,0 }, { (size_t)efpip->obj_w ,(size_t)efpip->obj_h });\n\n                    cl.queue.enqueueReadBuffer(clmem_dst, CL_TRUE, 0, buf_size, efpip->obj_temp);\n                }\n                catch (const cl::Error& err) {\n                    debug_log(\"OpenCL Error\\n({}) {}\", err.err(), err.what());\n                    return efp->aviutl_exfunc->exec_multi_thread_func(original_func_ptr, efp, efpip);\n                }\n                sw.stop();\n                return TRUE;\n            } else {\n                return efp->aviutl_exfunc->exec_multi_thread_func(original_func_ptr, efp, efpip);\n            }\n        } else {\n            sw.start();\n            const auto ret = efp->aviutl_exfunc->exec_multi_thread_func(original_func_ptr, efp, efpip);\n            sw.stop();\n            return ret;\n        }\n    }\n\n    BOOL LensBlur_t::filter_mt_func(AviUtl::MultiThreadFunc original_func_ptr, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\n        if constexpr (true) {\n            sw.start();\n            try {\n                const auto buf_size = efpip->scene_line * efpip->scene_h * sizeof(ExEdit::PixelYC);\n                cl::Buffer clmem_src(cl.context, CL_MEM_READ_ONLY, buf_size);\n                cl.queue.enqueueWriteBuffer(clmem_src, CL_TRUE, 0, buf_size, efpip->frame_edit);\n\n                cl::Buffer clmem_dst(cl.context, CL_MEM_WRITE_ONLY, buf_size);\n                efLensBlur_var& lensblur = *(efLensBlur_var*)uintptr_t(reinterpret_cast<efLensBlur_var*>(GLOBAL::exedit_base + OFS::ExEdit::efLensBlur_var_ptr));\n                auto kernel = cl.readyKernel(\n                    \"LensBlur_Filter\",\n                    clmem_dst,\n                    clmem_src,\n                    efpip->scene_w,\n                    efpip->scene_h,\n                    efpip->scene_line,\n                    lensblur.range,\n                    lensblur.rangep05_sqr,\n                    lensblur.range_t3m1,\n                    lensblur.rangem1_sqr\n                );\n                cl.queue.enqueueNDRangeKernel(kernel, { 0,0 }, { (size_t)efpip->scene_w ,(size_t)efpip->scene_h });\n\n                cl.queue.enqueueReadBuffer(clmem_dst, CL_TRUE, 0, buf_size, efpip->frame_temp);\n            }\n            catch (const cl::Error& err) {\n                debug_log(\"OpenCL Error\\n({}) {}\", err.err(), err.what());\n                return efp->aviutl_exfunc->exec_multi_thread_func(original_func_ptr, efp, efpip);\n            }\n\n            sw.stop();\n            return TRUE;\n        } else {\n            sw.start();\n            const auto ret = efp->aviutl_exfunc->exec_multi_thread_func(original_func_ptr, efp, efpip);\n            sw.stop();\n            return ret;\n        }\n    }\n\n} // namespace patch::fast\n#endif // ifdef PATCH_SWITCH_FAST_LENSBLUR\n"
  },
  {
    "path": "patch/patch_fast_lensblur.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n\tit under the terms of the GNU Lesser General Public License as published by\n\tthe Free Software Foundation, either version 3 of the License, or\n\t(at your option) any later version.\n\n\tThis program is distributed in the hope that it will be useful,\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\tGNU Lesser General Public License for more details.\n\n\tYou should have received a copy of the GNU Lesser General Public License\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_FAST_LENSBLUR\n#include <exedit.hpp>\n#include \"util_magic.hpp\"\n#include \"offset_address.hpp\"\n#include \"global.hpp\"\n#include \"config_rw.hpp\"\n\nnamespace patch::fast {\n\t// init at exedit load\n\t// レンズブラーの高速化\n\tinline class LensBlur_t {\n\t\tstatic BOOL media_mt_func(AviUtl::MultiThreadFunc original_func_ptr, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\n\t\tstatic BOOL filter_mt_func(AviUtl::MultiThreadFunc original_func_ptr, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\n\n\t\tbool enabled = true;\n\t\tbool enabled_i;\n\t\tinline static const char key[] = \"fast.lensblur\";\n\tpublic:\n\t\tstruct efLensBlur_var { // 11ec5c\n\t\t\tint range; // 11ec5c\n\t\t\tint rangep05_sqr; // 11ec60\n\t\t\tint range_t3m1; // 11ec64\n\t\t\tint rangem1_sqr; // 11ec68\n\t\t};\n\n\t\tvoid init() {\n\t\t\tenabled_i = enabled;\n\t\t\tif (!enabled_i)return;\n\t\t\t{\n\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::efLensBlur_Media_mt_func_call, 6);\n\t\t\t\th.store_i16(0, '\\x90\\xe8'); // nop; call (rel32)\n\t\t\t\th.replaceNearJmp(2, &media_mt_func);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::efLensBlur_Filter_mt_func_call, 6);\n\t\t\t\th.store_i16(0, '\\x90\\xe8'); // nop; call (rel32)\n\t\t\t\th.replaceNearJmp(2, &filter_mt_func);\n\t\t\t}\n\t\t}\n\n\t\tvoid switching(bool flag) { enabled = flag; }\n\n\t\tbool is_enabled() { return enabled; }\n\t\tbool is_enabled_i() { return enabled_i; }\n\n\t\tvoid switch_load(ConfigReader& cr) {\n\t\t\tcr.regist(key, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, enabled);\n\t\t\t\t});\n\t\t}\n\n\t\tvoid switch_store(ConfigWriter& cw) {\n\t\t\tcw.append(key, enabled);\n\t\t}\n\n\t} LensBlur;\n} // namespace patch::fast\n#endif // ifdef PATCH_SWITCH_FAST_LENSBLUR\n"
  },
  {
    "path": "patch/patch_fast_polortransform.cpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"patch_fast_polortransform.hpp\"\r\n#ifdef PATCH_SWITCH_FAST_POLORTRANSFORM\r\n\r\n#include <numbers>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util_int.hpp\"\r\n#include \"patch_fast_cl.hpp\"\r\n#include \"debug_log.hpp\"\r\n\r\n//#define PATCH_STOPWATCH\r\n#include \"stopwatch.hpp\"\r\nstatic stopwatch_mem sw;\r\n\r\nnamespace patch::fast {\r\n    BOOL PolorTransform_t::mt_func(AviUtl::MultiThreadFunc original_func_ptr, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\r\n        if constexpr (true) {\r\n            if (256 < efpip->obj_w * efpip->obj_h) {\r\n                sw.start();\r\n                try {\r\n\r\n                    efPolorTransform_var& polor = *reinterpret_cast<efPolorTransform_var*>(GLOBAL::exedit_base + OFS::ExEdit::efPolorTransform_var_ptr);\r\n\r\n                    const auto src_size = efpip->obj_line * polor.src_h * sizeof(ExEdit::PixelYCA);\r\n                    cl::Buffer clmem_src(cl.context, CL_MEM_READ_ONLY, src_size);\r\n                    cl.queue.enqueueWriteBuffer(clmem_src, CL_TRUE, 0, src_size, efpip->obj_edit);\r\n\r\n                    const auto dst_size = efpip->obj_line * polor.output_size * 8;\r\n                    cl::Buffer clmem_dst(cl.context, CL_MEM_WRITE_ONLY, dst_size);\r\n\r\n                    auto kernel = cl.readyKernel(\r\n                        \"PolorTransform\",\r\n                        clmem_dst,\r\n                        clmem_src,\r\n                        polor.src_w,\r\n                        polor.src_h,\r\n                        efpip->obj_line,\r\n                        polor.center_length,\r\n                        polor.radius,\r\n                        static_cast<float>(polor.angle),\r\n                        static_cast<float>(polor.uzu),\r\n                        static_cast<float>(polor.uzu_a)\r\n                    );\r\n                    cl.queue.enqueueNDRangeKernel(kernel, { 0,0 }, { (size_t)polor.output_size ,(size_t)polor.output_size });\r\n\r\n                    cl.queue.enqueueReadBuffer(clmem_dst, CL_TRUE, 0, dst_size, efpip->obj_temp);\r\n                }\r\n                catch (const cl::Error& err) {\r\n                    debug_log(\"OpenCL Error\\n({}) {}\", err.err(), err.what());\r\n                    return efp->aviutl_exfunc->exec_multi_thread_func(original_func_ptr, efp, efpip);\r\n                }\r\n                sw.stop();\r\n                return TRUE;\r\n            } else {\r\n                return efp->aviutl_exfunc->exec_multi_thread_func(original_func_ptr, efp, efpip);\r\n            }\r\n        } else {\r\n            sw.start();\r\n            const auto ret = efp->aviutl_exfunc->exec_multi_thread_func(original_func_ptr, efp, efpip);\r\n            sw.stop();\r\n            return ret;\r\n        }\r\n    }\r\n}\r\n#endif // ifdef PATCH_SWITCH_FAST_POLORTRANSFORM\r\n"
  },
  {
    "path": "patch/patch_fast_polortransform.hpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n#ifdef PATCH_SWITCH_FAST_POLORTRANSFORM\r\n\r\n#include <aviutl.hpp>\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util.hpp\"\r\n#include \"global.hpp\"\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch::fast {\r\n\t// init at exedit load\r\n\t// 極座標変換の高速化\r\n\tinline class PolorTransform_t {\r\n\t\tstatic BOOL mt_func(AviUtl::MultiThreadFunc original_func_ptr, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\r\n\r\n\t\tbool enabled = true;\r\n\t\tbool enabled_i;\r\n\t\tinline static const char key[] = \"fast.polortransform\";\r\n\r\n\tpublic:\r\n\r\n\t\tstruct efPolorTransform_var { // 1e48c0\r\n\t\t\tint src_h;\r\n\t\t\tint radius;\r\n\t\t\tint src_w;\r\n\t\t\tint _padding;\r\n\t\t\tdouble uzu;\r\n\t\t\tdouble uzu_a;\r\n\t\t\tdouble angle;\r\n\t\t\tint center_length;\r\n\t\t\tint output_size;\r\n\t\t};\r\n\r\n\t\tvoid init() {\r\n\t\t\tenabled_i = enabled;\r\n\t\t\tif (!enabled_i)return;\r\n\r\n\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::efPolorTransform_mt_func_call, 6);\r\n\t\t\th.store_i16(0, '\\x90\\xe8'); // nop; call (rel32)\r\n\t\t\th.replaceNearJmp(2, &mt_func);\r\n\r\n\t\t}\r\n\r\n\t\tvoid switching(bool flag) { enabled = flag; }\r\n\r\n\t\tbool is_enabled() { return enabled; }\r\n\t\tbool is_enabled_i() { return enabled_i; }\r\n\r\n\t\tvoid switch_load(ConfigReader& cr) {\r\n\t\t\tcr.regist(key, [this](json_value_s* value) {\r\n\t\t\t\tConfigReader::load_variable(value, enabled);\r\n\t\t\t\t});\r\n\t\t}\r\n\r\n\t\tvoid switch_store(ConfigWriter& cw) {\r\n\t\t\tcw.append(key, enabled);\r\n\t\t}\r\n\r\n\t} PolorTransform;\r\n} // namespace patch::fast\r\n#endif // ifdef PATCH_SWITCH_FAST_POLORTRANSFORM\r\n"
  },
  {
    "path": "patch/patch_fast_radiationalblur.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_fast_radiationalblur.hpp\"\n#ifdef PATCH_SWITCH_FAST_RADIATIONALBLUR\n\n#include \"debug_log.hpp\"\n#include \"patch_fast_cl.hpp\"\n\n//#define PATCH_STOPWATCH\n#include \"stopwatch.hpp\"\n\nnamespace patch::fast {\n    static stopwatch_mem sw;\n\n    BOOL RadiationalBlur_t::media_mt_func(AviUtl::MultiThreadFunc original_func_ptr, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\n        if constexpr (true) {\n            sw.start();\n            try {\n                auto& rb = *reinterpret_cast<efRadiationalBlur_var*>(GLOBAL::exedit_base + OFS::ExEdit::efRadiationalBlur_var_ptr);\n\n                const auto src_size = efpip->obj_line * efpip->obj_h * sizeof(ExEdit::PixelYCA);\n                cl::Buffer clmem_src(cl.context, CL_MEM_READ_ONLY, src_size);\n                cl.queue.enqueueWriteBuffer(clmem_src, CL_TRUE, 0, src_size, efpip->obj_edit);\n\n                const auto dst_size = efpip->obj_line * (rb.h - rb.obj_cy) * sizeof(ExEdit::PixelYCA);\n                cl::Buffer clmem_dst(cl.context, CL_MEM_WRITE_ONLY, dst_size);\n\n                auto kernel = cl.readyKernel(\n                    \"RadiationalBlur_Media\",\n                    clmem_dst,\n                    clmem_src,\n                    efpip->obj_w,\n                    efpip->obj_h,\n                    efpip->obj_line,\n                    rb.blur_cx,\n                    rb.blur_cy,\n                    rb.obj_cx,\n                    rb.obj_cy,\n                    rb.range,\n                    rb.pixel_range\n                );\n                cl.queue.enqueueNDRangeKernel(kernel, { 0,0 }, { (size_t)rb.w - rb.obj_cx ,(size_t)rb.h - rb.obj_cy });\n\n                cl.queue.enqueueReadBuffer(clmem_dst, CL_TRUE, 0, dst_size, efpip->obj_temp);\n            }\n            catch (const cl::Error& err) {\n                debug_log(\"OpenCL Error\\n({}) {}\", err.err(), err.what());\n                return efp->aviutl_exfunc->exec_multi_thread_func(original_func_ptr, efp, efpip);\n            }\n\n            sw.stop();\n            return TRUE;\n        } else {\n            sw.start();\n            const auto ret = efp->aviutl_exfunc->exec_multi_thread_func(original_func_ptr, efp, efpip);\n            sw.stop();\n            return ret;\n        }\n    }\n\n    BOOL RadiationalBlur_t::filter_mt_func(AviUtl::MultiThreadFunc original_func_ptr, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\n        if constexpr (true) {\n            sw.start();\n            try {\n                const auto buf_size = efpip->scene_line * efpip->scene_h * sizeof(ExEdit::PixelYC);\n                cl::Buffer clmem_src(cl.context, CL_MEM_READ_ONLY, buf_size);\n                cl.queue.enqueueWriteBuffer(clmem_src, CL_TRUE, 0, buf_size, efpip->frame_edit);\n\n                cl::Buffer clmem_dst(cl.context, CL_MEM_WRITE_ONLY, buf_size);\n                auto& rb = *reinterpret_cast<efRadiationalBlur_var*>(GLOBAL::exedit_base + OFS::ExEdit::efRadiationalBlur_var_ptr);\n                auto kernel = cl.readyKernel(\n                    \"RadiationalBlur_Filter\",\n                    clmem_dst,\n                    clmem_src,\n                    efpip->scene_line,\n                    rb.blur_cx,\n                    rb.blur_cy,\n                    rb.range,\n                    rb.pixel_range\n                );\n                cl.queue.enqueueNDRangeKernel(kernel, { 0,0 }, { (size_t)efpip->scene_w ,(size_t)efpip->scene_h });\n\n                cl.queue.enqueueReadBuffer(clmem_dst, CL_TRUE, 0, buf_size, efpip->frame_temp);\n            }\n            catch (const cl::Error& err) {\n                debug_log(\"OpenCL Error\\n({}) {}\", err.err(), err.what());\n                return efp->aviutl_exfunc->exec_multi_thread_func(original_func_ptr, efp, efpip);\n            }\n\n            sw.stop();\n            return TRUE;\n        } else {\n            sw.start();\n            const auto ret = efp->aviutl_exfunc->exec_multi_thread_func(original_func_ptr, efp, efpip);\n            sw.stop();\n            return ret;\n        }\n    }\n\n    BOOL RadiationalBlur_t::filter_mt_far_func(AviUtl::MultiThreadFunc original_func_ptr, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip) {\n        if constexpr (true) {\n            sw.start();\n            try {\n                const auto buf_size = efpip->scene_line * efpip->scene_h * sizeof(ExEdit::PixelYC);\n                cl::Buffer clmem_src(cl.context, CL_MEM_READ_ONLY, buf_size);\n                cl.queue.enqueueWriteBuffer(clmem_src, CL_TRUE, 0, buf_size, efpip->frame_edit);\n\n                cl::Buffer clmem_dst(cl.context, CL_MEM_WRITE_ONLY, buf_size);\n                auto& rb = *reinterpret_cast<efRadiationalBlur_var*>(GLOBAL::exedit_base + OFS::ExEdit::efRadiationalBlur_var_ptr);\n                auto kernel = cl.readyKernel(\n                    \"RadiationalBlur_Filter_Far\",\n                    clmem_dst,\n                    clmem_src,\n                    efpip->scene_w,\n                    efpip->scene_h,\n                    efpip->scene_line,\n                    rb.blur_cx,\n                    rb.blur_cy,\n                    rb.range,\n                    rb.pixel_range\n                );\n                cl.queue.enqueueNDRangeKernel(kernel, { 0,0 }, { (size_t)efpip->scene_w ,(size_t)efpip->scene_h });\n\n                cl.queue.enqueueReadBuffer(clmem_dst, CL_TRUE, 0, buf_size, efpip->frame_temp);\n            }\n            catch (const cl::Error& err) {\n                debug_log(\"OpenCL Error\\n({}) {}\", err.err(), err.what());\n                return efp->aviutl_exfunc->exec_multi_thread_func(original_func_ptr, efp, efpip);\n            }\n\n            sw.stop();\n            return TRUE;\n        } else {\n            sw.start();\n            const auto ret = efp->aviutl_exfunc->exec_multi_thread_func(original_func_ptr, efp, efpip);\n            sw.stop();\n            return ret;\n        }\n    }\n\n} // namespace patch::fast\n#endif // ifdef PATCH_SWITCH_FAST_RADIATIONALBLUR\n"
  },
  {
    "path": "patch/patch_fast_radiationalblur.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_FAST_RADIATIONALBLUR\n#include <exedit.hpp>\n#include \"util_magic.hpp\"\n#include \"offset_address.hpp\"\n#include \"global.hpp\"\n#include \"config_rw.hpp\"\n\nnamespace patch::fast {\n\t// init at exedit load\n\t// 放射ブラーの高速化\n\tinline class RadiationalBlur_t {\n\n\t\tstatic BOOL media_mt_func(AviUtl::MultiThreadFunc original_func_ptr, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\n\t\tstatic BOOL filter_mt_func(AviUtl::MultiThreadFunc original_func_ptr, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\n\t\tstatic BOOL filter_mt_far_func(AviUtl::MultiThreadFunc original_func_ptr, ExEdit::Filter* efp, ExEdit::FilterProcInfo* efpip);\n\n\t\tbool enabled = true;\n\t\tbool enabled_i;\n\t\tinline static const char key[] = \"fast.radiationalblur\";\n\tpublic:\n\t\tstruct efRadiationalBlur_var { // d75a8\n\t\t\tint blur_cx; // ブラーの中心位置\n\t\t\tint blur_cy;\n\t\t\tint w;\n\t\t\tint h;\n\t\t\tint pixel_range;\n\t\t\tint obj_cx;\n\t\t\tint range;\n\t\t\tint obj_cy;\n\t\t};\n\n\t\tvoid init() {\n\t\t\tenabled_i = enabled;\n\t\t\tif (!enabled_i)return;\n\t\t\t{   // Media object\n\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x00b5c1, 6);\n\t\t\t\th.store_i16(0, '\\x90\\xe8'); // nop; call (rel32)\n\t\t\t\th.replaceNearJmp(2, &media_mt_func);\n\t\t\t}\n\n\t\t\t{   // Filter object\n\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x00bb39, 6);\n\t\t\t\th.store_i16(0, '\\x90\\xe8'); // nop; call (rel32)\n\t\t\t\th.replaceNearJmp(2, &filter_mt_func);\n\t\t\t}\n\t\t\t{   // Filter object\n\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x00bb4f, 6);\n\t\t\t\th.store_i16(0, '\\x90\\xe8'); // nop; call (rel32)\n\t\t\t\th.replaceNearJmp(2, &filter_mt_far_func);\n\t\t\t}\n\n\t\t\t{   // SceneChange\n\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x00c1ec, 6);\n\t\t\t\th.store_i16(0, '\\x90\\xe8'); // nop; call (rel32)\n\t\t\t\th.replaceNearJmp(2, &filter_mt_func);\n\t\t\t}\n\n\t\t}\n\n\t\tvoid switching(bool flag) { enabled = flag; }\n\n\t\tbool is_enabled() { return enabled; }\n\t\tbool is_enabled_i() { return enabled_i; }\n\t\t\n        void switch_load(ConfigReader& cr) {\n            cr.regist(key, [this](json_value_s* value) {\n                ConfigReader::load_variable(value, enabled);\n            });\n        }\n\n        void switch_store(ConfigWriter& cw) {\n            cw.append(key, enabled);\n        }\n\n\t} RadiationalBlur;\n} // namespace patch::fast\n#endif // ifdef PATCH_SWITCH_FAST_RADIATIONALBLUR\n"
  },
  {
    "path": "patch/patch_fast_setting_dialog.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_fast_setting_dialog.hpp\"\n#ifdef PATCH_SWITCH_FAST_SETTINGDIALOG\n\n#include <exedit.hpp>\n\n//#define PATCH_STOPWATCH\n#include \"stopwatch.hpp\"\n\nnamespace patch {\n\n\tstatic stopwatch_mem sw;\n\n\tvoid __cdecl fast_setting_dialog_t::FUN_10030500_Wrap() {\n\t\tsw.start();\n\t\tauto hwnd = load_i32<HWND>(GLOBAL::exedit_base + 0x1539c8);\n\t\tSendMessageA(hwnd, WM_SETREDRAW, FALSE, NULL);\n\t\treinterpret_cast<void(__cdecl*)()>(GLOBAL::exedit_base + 0x030500)();\n\t\tSendMessageA(hwnd, WM_SETREDRAW, TRUE, NULL);\n\t\tUpdateWindow(hwnd);\n\t\tsw.stop();\n\t}\n\n\tBOOL __cdecl fast_setting_dialog_t::FUN_100305e0_Wrap(int param1) {\n\t\tsw.start();\n\t\tauto hwnd = load_i32<HWND>(GLOBAL::exedit_base + 0x1539c8);\n\t\tSendMessageA(hwnd, WM_SETREDRAW, FALSE, NULL);\n\t\tauto ret = reinterpret_cast<BOOL(__cdecl*)(int)>(GLOBAL::exedit_base + 0x0305e0)(param1);\n\t\tSendMessageA(hwnd, WM_SETREDRAW, TRUE, NULL);\n\t\tUpdateWindow(hwnd);\n\t\tsw.stop();\n\t\treturn ret;\n\t}\n\n\n\tvoid __cdecl fast_setting_dialog_t::FUN_10030500_Wrap2() {\n\t\tsw.start();\n\t\tauto hwnd = load_i32<HWND>(GLOBAL::exedit_base + 0x1539c8);\n\t\tSendMessageA(hwnd, WM_SETREDRAW, FALSE, NULL);\n\t\treinterpret_cast<void(__cdecl*)()>(GLOBAL::exedit_base + 0x030500)();\n\t}\n\n\tBOOL __cdecl fast_setting_dialog_t::FUN_100305e0_Wrap2(int param1) {\n\t\tauto hwnd = load_i32<HWND>(GLOBAL::exedit_base + 0x1539c8);\n\t\tauto ret = reinterpret_cast<BOOL(__cdecl*)(int)>(GLOBAL::exedit_base + 0x0305e0)(param1);\n\t\tSendMessageA(hwnd, WM_SETREDRAW, TRUE, NULL);\n\t\tUpdateWindow(hwnd);\n\t\tsw.stop();\n\t\treturn ret;\n\t}\n\n\tvoid __cdecl fast_setting_dialog_t::FUN_10030500_Wrap3() {\n\t\treinterpret_cast<void(__cdecl*)()>(GLOBAL::exedit_base + 0x030500)();\n\t}\n\n\tvoid __cdecl fast_setting_dialog_t::FUN_1002bf10_Wrap(HDC hDC) {\n\t\tif (load_i32<ExEdit::Object*>(GLOBAL::exedit_base + 0x1e0fa4) == nullptr) return;\n\t\tif (load_i32<int>(GLOBAL::exedit_base + 0x177a10) == -1)return;\n\t\treinterpret_cast<void(__cdecl*)(HDC)>(GLOBAL::exedit_base + 0x02bf10)(hDC);\n\t}\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_FAST_SETTINGDIALOG\n"
  },
  {
    "path": "patch/patch_fast_setting_dialog.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n\n#ifdef PATCH_SWITCH_FAST_SETTINGDIALOG\n#include \"global.hpp\"\n#include \"util_magic.hpp\"\n#include \"global.hpp\"\n#include \"config_rw.hpp\"\n\nnamespace patch {\n\t// init at exedit load\n\t// 設定ダイアログの高速化\n\tinline class fast_setting_dialog_t {\n\t\tstatic void __cdecl FUN_10030500_Wrap();\n\t\tstatic BOOL __cdecl FUN_100305e0_Wrap(int param1);\n\n\t\tstatic void __cdecl FUN_10030500_Wrap2();\n\t\tstatic BOOL __cdecl FUN_100305e0_Wrap2(int param1);\n\n\t\tstatic void __cdecl FUN_10030500_Wrap3();\n\n\t\tstatic void __cdecl FUN_1002bf10_Wrap(HDC hDC);\n\n\t\tbool enabled = true;\n\t\tbool enabled_i;\n\t\tinline static const char key[] = \"fast_settingdialog\";\n\n\tpublic:\n\n\t\tvoid init() {\n\t\t\tenabled_i = enabled;\n\t\t\tif (!enabled_i) return;\n\n\t\t\t// 単体呼び出し\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x0417c8, &FUN_10030500_Wrap);\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x04194a, &FUN_10030500_Wrap);\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x0419eb, &FUN_10030500_Wrap);\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x041b4f, &FUN_10030500_Wrap);\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x041c65, &FUN_10030500_Wrap);\n\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x02cd04, &FUN_100305e0_Wrap);\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x02da5d, &FUN_100305e0_Wrap);\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x03957d, &FUN_100305e0_Wrap);\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x0417d3, &FUN_100305e0_Wrap);\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x041956, &FUN_100305e0_Wrap);\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x0419f7, &FUN_100305e0_Wrap);\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x041b5a, &FUN_100305e0_Wrap);\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x041c71, &FUN_100305e0_Wrap);\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x041f52, &FUN_100305e0_Wrap);\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x08d75b, &FUN_100305e0_Wrap);\n\t\t\t\n\t\t\t// 30500の直後に305e0を呼ぶとき\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x041ade, &FUN_10030500_Wrap2);\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x041ae9, &FUN_100305e0_Wrap2);\n\n\t\t\t// 305e0中での30500の呼び出し\n\t\t\t//ReplaceNearJmp(GLOBAL::exedit_base + 0x0306ac, &FUN_10030500_Wrap3);\n\n\t\t\t// 2bf2c 例外対策\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x02ceb7, &FUN_1002bf10_Wrap);\n\t\t\t// テキスト の行間等のコントロールの描画がおかしくなる\n\t\t\t//OverWriteOnProtectHelper(GLOBAL::exedit_base + 0x02e881, 4).store_i32(0, WS_EX_TOOLWINDOW | WS_EX_COMPOSITED);\n\t\t}\n\n\t\tvoid switching(bool flag) { enabled = flag; }\n\n\t\tbool is_enabled() { return enabled; }\n\t\tbool is_enabled_i() { return enabled_i; }\n\n\t\tvoid switch_load(ConfigReader& cr) {\n\t\t\tcr.regist(key, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, enabled);\n\t\t\t});\n\t\t}\n\n\t\tvoid switch_store(ConfigWriter& cw) {\n\t\t\tcw.append(key, enabled);\n\t\t}\n\n\t} fast_setting_dialog;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_FAST_SETTINGDIALOG\n"
  },
  {
    "path": "patch/patch_fast_text.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_fast_text.hpp\"\n\n#ifdef PATCH_SWITCH_FAST_TEXT\n\n#include \"global.hpp\"\n\nnamespace patch::fast {\n\n\tHFONT __cdecl text_t::MyCreateFont(const char* fontname, int height, int weight, BOOL italic, BOOL high_precision, BOOL vertical) {\n\t\tHFONT& currentFont = load_i32<HFONT&>(GLOBAL::exedit_base + 0x236388);\n\n\t\theight = -height;\n\t\tif (high_precision) {\n\t\t\theight *= 2;\n\t\t}\n\n\t\tchar fontname_v[LF_FACESIZE + 1];\n\t\tif (vertical) {\n\t\t\tfontname_v[0] = '@';\n\t\t\tstrncpy_s(fontname_v + 1, LF_FACESIZE + 1, fontname, LF_FACESIZE);\n\t\t\tfontname = fontname_v;\n\t\t}\n\n\t\tauto font = ::CreateFontA(height, 0, 0, 0, weight, italic, 0, 0, 1, 8, 0, 4, 0, fontname);\n\t\tif (font == NULL)return currentFont = NULL;\n\t\tLOGFONTW lfw;\n\t\t::GetObjectW(font, sizeof(LOGFONTW), &lfw);\n\n\t\tstd::lock_guard lock(text.mtx);\n\n\t\tauto [val, b] = text.map.try_emplace(lfw, font);\n\t\tif (!b) {\n\t\t\t::DeleteObject(font);\n\t\t}\n\t\treturn currentFont = val->second.font;\n\t}\n\n\tHFONT WINAPI text_t::CreateFontIndirectW(const LOGFONTW* lplf) {\n\t\tchar facename[LF_FACESIZE];\n\t\tauto const facename_size = ::WideCharToMultiByte(CP_ACP, 0U, lplf->lfFaceName, -1, nullptr, 0, nullptr, nullptr);\n\t\tif (::WideCharToMultiByte(CP_ACP, 0U, lplf->lfFaceName, -1, facename, sizeof(facename), nullptr, nullptr) == 0) {\n\t\t\treturn NULL;\n\t\t}\n\n\t\tstd::lock_guard lock(text.mtx);\n\t\tauto& map = text.map;\n\t\tif (auto itr = map.find(*lplf); itr != map.end()) {\n\t\t\treturn itr->second.font;\n\t\t}\n\n\t\treturn map.try_emplace(*lplf, ::CreateFontIndirectW(lplf)).first->second.font;\n\t}\n\n\n\tDWORD WINAPI text_t::GetGlyphOutlineW(HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm, DWORD cjBuffer, LPVOID pvBuffer, CONST MAT2* lpmat2) {\n\t\tauto font = reinterpret_cast<HFONT>(GetCurrentObject(hdc, OBJ_FONT));\n\n\t\tLOGFONTW lfw;\n\t\t::GetObjectW(font, sizeof(LOGFONTW), &lfw);\n\n\t\tstd::lock_guard lock(text.mtx);\n\n\t\tauto itr = text.map.find(lfw);\n\t\tif (itr == text.map.end()) {\n\t\t\treturn ::GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cjBuffer, pvBuffer, lpmat2);\n\t\t}\n\t\tauto& glyph = itr->second.glyph_map;\n\n\t\tGlyphKey glyphkey{ .uChar = uChar, .fuFormat = fuFormat };\n\t\tauto itr2 = glyph.find(glyphkey);\n\t\tif (itr2 != glyph.end()) {\n\t\t\tauto& val = itr2->second;\n\t\t\tmemcpy(lpgm, &val.gm, sizeof(GLYPHMETRICS));\n\t\t\tif (cjBuffer && pvBuffer) {\n\t\t\t\tif (val.size == GDI_ERROR)return GDI_ERROR;\n\t\t\t\tmemcpy_s(pvBuffer, cjBuffer, &val.data[0], val.size);\n\t\t\t}\n\t\t\tauto now = text_detail::gettime();\n\t\t\tval.last_use = now;\n\t\t\titr->second.last_use = now;\n\n\t\t\treturn val.size;\n\t\t}\n\t\tauto size = ::GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, 0, nullptr, lpmat2);\n\t\tauto& val = glyph.try_emplace(glyphkey, size, text_detail::gettime(), lpgm, nullptr).first->second;\n\t\tif (size == GDI_ERROR)return GDI_ERROR;\n\n\n\t\tval.data.reset(new byte[size]);\n\t\t::GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, size, val.data.get(), lpmat2);\n\n\t\tif (cjBuffer && pvBuffer) {\n\t\t\tif (val.size == GDI_ERROR)return GDI_ERROR;\n\t\t\tmemcpy_s(pvBuffer, cjBuffer, &val.data[0], val.size);\n\t\t}\n\n\t\treturn size;\n\t}\n\n\tBOOL WINAPI text_t::DeleteObject(HGDIOBJ ho) {\n\t\tstd::lock_guard lock(text.mtx);\n\n\t\tfor (const auto& v : text.map) {\n\t\t\tif (v.second.font == ho)return TRUE;\n\t\t}\n\t\treturn ::DeleteObject(ho);\n\t}\n\n\tvoid text_t::collect(int elapse) {\n\t\tstd::lock_guard lock(text.mtx);\n\n\t\tauto& font_map = text.map;\n\t\tauto now = text_detail::gettime();\n\n\t#ifdef _DEBUG\n\t\tsize_t count = 0;\n\t\tfor (auto fitr = font_map.begin(); fitr != font_map.end();) {\n\t\t\tif (now - fitr->second.last_use > elapse) {\n\t\t\t\tprintf(\"collected font\\n\");\n\t\t\t\tfont_map.erase(fitr++);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tauto& glyph_map = fitr->second.glyph_map;\n\t\t\t\tfor (auto gitr = glyph_map.begin(); gitr != glyph_map.end();) {\n\t\t\t\t\tif (now - gitr->second.last_use > elapse) {\n\t\t\t\t\t\t//printf(\"collected glyph\\n\");\n\t\t\t\t\t\tglyph_map.erase(gitr++);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tcount += sizeof GlyphKey;\n\t\t\t\t\t\tcount += sizeof GlyphValue;\n\t\t\t\t\t\tcount += gitr->second.size;\n\t\t\t\t\t\tgitr++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcount += sizeof LOGFONTW;\n\t\t\t\tcount += sizeof FontValue;\n\t\t\t\tfitr++;\n\t\t\t}\n\t\t}\n\t\tprintf(\"[lighttext]using memory: %dKB\\n\", count / 1000);\n\n#else\n\t\tfor (auto fitr = font_map.begin(); fitr != font_map.end();) {\n\t\t\tif (now - fitr->second.last_use > elapse) {\n\t\t\t\tfont_map.erase(fitr++);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tauto& glyph_map = fitr->second.glyph_map;\n\t\t\t\tfor (auto gitr = glyph_map.begin(); gitr != glyph_map.end();) {\n\t\t\t\t\tif (now - gitr->second.last_use > elapse) {\n\t\t\t\t\t\tglyph_map.erase(gitr++);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tgitr++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfitr++;\n\t\t\t}\n\t\t}\n#endif\n\t}\n\n}\n#endif\n"
  },
  {
    "path": "patch/patch_fast_text.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n\n#ifdef PATCH_SWITCH_FAST_TEXT\n\n#include <compare>\n#include <map>\n#include <mutex>\n#include <memory>\n#include <algorithm>\n#include <Windows.h>\n\n#include \"cryptostring.hpp\"\n#include \"util_magic.hpp\"\n#include \"timer.hpp\"\n#include \"config_rw.hpp\"\n\nnamespace patch::fast {\n\tnamespace text_detail {\n\t\tinline auto gettime() {\n\t\t\treturn std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();\n\t\t}\n\n\t\tusing FontKey = LOGFONTW;\n\n\t\tstruct GlyphKey {\n\t\t\tUINT uChar;\n\t\t\tUINT fuFormat;\n\t\t};\n\t\tinline bool operator<(const GlyphKey& l, const GlyphKey& r) {\n\t\t\treturn\n\t\t\t\tstd::tie(l.uChar, l.fuFormat) <\n\t\t\t\tstd::tie(r.uChar, r.fuFormat);\n\t\t}\n\n\t\tstruct GlyphValue {\n\t\t\tDWORD size = 0;\n\t\t\ttime_t last_use = 0;\n\t\t\tGLYPHMETRICS gm;\n\t\t\tstd::shared_ptr<byte[]> data;\n\t\t\tGlyphValue(DWORD size_, time_t time_, LPGLYPHMETRICS lpgm_, void* data_) :size(size_), last_use(time_) {\n\t\t\t\tmemcpy(&gm, lpgm_, sizeof(GLYPHMETRICS));\n\t\t\t\tif (size == GDI_ERROR)return;\n\t\t\t\tdata = std::make_unique<byte[]>(size);\n\t\t\t\tif (data_) {\n\t\t\t\t\tmemcpy(data.get(), data_, size_);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tstruct FontValue {\n\t\t\tHFONT font;\n\t\t\ttime_t last_use;\n\t\t\tstd::map<GlyphKey, GlyphValue> glyph_map;\n\n\t\t\tFontValue(HFONT font_) : font(font_), last_use(gettime()), glyph_map() {}\n\t\t\t~FontValue() {\n\t\t\t\tDeleteObject(font);\n\t\t\t}\n\t\t};\n\n\t\tinline std::strong_ordering operator<=>(const FontKey& a, const FontKey& b) {\n\t\t\t#define comp(member) if (auto cmp = a.##member <=> b.##member; cmp != 0) do { return cmp; } while(0)\n\t\t\t#define compb(member) \\\n\t\t\tif(a.##member == TRUE) { \\\n\t\t\t\tif(b.##member != TRUE) \\\n\t\t\t\t\treturn std::strong_ordering::less; /*a==TRUE b==FALSE */ \\\n\t\t\t} else { \\\n\t\t\t\tif (b.##member == TRUE) \\\n\t\t\t\t\treturn std::strong_ordering::greater; /*a==FALSE b==TRUE */ \\\n\t\t\t}\n\n\t\t\tcomp(lfHeight);\n\t\t\tcomp(lfWidth);\n\t\t\tcomp(lfEscapement);\n\t\t\tcomp(lfOrientation);\n\t\t\tcomp(lfWeight);\n\t\t\tcompb(lfItalic);\n\t\t\tcompb(lfUnderline);\n\t\t\tcompb(lfStrikeOut);\n\t\t\tcomp(lfCharSet);\n\t\t\tcomp(lfOutPrecision);\n\t\t\tcomp(lfClipPrecision);\n\t\t\tcomp(lfQuality);\n\t\t\tcomp(lfPitchAndFamily);\n\n\t\t\t#undef comp\n\t\t\t#undef compb\n\n\t\t\tauto cmp = wcscmp(a.lfFaceName, b.lfFaceName);\n\t\t\tif (cmp < 0)return std::strong_ordering::less;\n\t\t\tif (cmp > 0)return std::strong_ordering::greater;\n\t\t\treturn std::strong_ordering::equal;\n\t\t}\n\t\tstruct comp_fontkey {\n\t\t\tbool operator()(const FontKey& a, const FontKey& b) const {\n\t\t\t\treturn (a <=> b) < 0;\n\t\t\t}\n\t\t};\n\t}\n\n\tinline class text_t {\n\t\tusing FontKey = text_detail::FontKey;\n\t\tusing FontValue = text_detail::FontValue;\n\t\tusing GlyphKey = text_detail::GlyphKey;\n\t\tusing GlyphValue = text_detail::GlyphValue;\n\tpublic:\n\n\t\tstatic HFONT __cdecl MyCreateFont(const char* fontname, int height, int weight, BOOL italic, BOOL high_precision, BOOL vertical);\n\t\tstatic HFONT WINAPI CreateFontIndirectW(const LOGFONTW* lplf);\n\t\tstatic BOOL WINAPI DeleteObject(HGDIOBJ ho);\n\t\tstatic DWORD WINAPI GetGlyphOutlineW(HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm, DWORD cjBuffer, LPVOID pvBuffer, CONST MAT2* lpmat2);\n\n\t\tvoid collect(int elapse);\n\n\tprivate:\n\t\tstd::map<FontKey, FontValue, text_detail::comp_fontkey> map;\n\t\tstd::mutex mtx;\n\n\t\tbool enabled = true;\n\t\tbool enabled_i;\n\n\t\tint release_time = 120;\n\n\t\tinline static const char key[] = \"fast.text\";\n\n\t\tinline static const char key_release_time[] = \"release_time\";\n\n\tpublic:\n\t\tvoid init() {\n\t\t\tenabled_i = enabled;\n\t\t\tif (!enabled_i)return;\n\n\t\t\tExchangeFunction(GLOBAL::exedit_hmod, cstr_gdi32_dll.get(), cstr_GetGlyphOutlineW.get(), &GetGlyphOutlineW);\n\t\t\tExchangeFunction(GLOBAL::exedit_hmod, cstr_gdi32_dll.get(), cstr_DeleteObject.get(), &DeleteObject);\n\t\t\tExchangeFunction(GLOBAL::exedit_hmod, cstr_gdi32_dll.get(), cstr_CreateFontIndirectW.get(), &CreateFontIndirectW);\n\t\t\tReplaceFunction(GLOBAL::exedit_base + 0x8a720, &MyCreateFont);\n\n\t\t\ttimer.set([this]() {\n\t\t\t\tcollect(release_time);\n\t\t\t}, release_time * 1000);\n\t\t}\n\n\t\tvoid switching(bool flag) { enabled = flag; }\n\n\t\tbool is_enabled() { return enabled; }\n\t\tbool is_enabled_i() { return enabled_i; }\n\n\t\tvoid config_load(ConfigReader& cr) {\n\t\t\tcr.regist(key_release_time, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, release_time);\n\t\t\t});\n\t\t}\n\n\t\tvoid config_store(ConfigWriter& cw) {\n\t\t\tcw.append(key_release_time, release_time);\n\t\t}\n\n\t\tvoid switch_load(ConfigReader& cr) {\n\t\t\tcr.regist(key, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, enabled);\n\t\t\t});\n\t\t}\n\n\t\tvoid switch_store(ConfigWriter& cw) {\n\t\t\tcw.append(key, enabled);\n\t\t}\n\n\t} text;\n\n}\n#endif\n"
  },
  {
    "path": "patch/patch_fileinfo.hpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_FILEINFO\r\n\r\n#include <exedit.hpp>\r\n#include \"config_rw.hpp\"\r\n\r\n#include \"global.hpp\"\r\n#include \"util.hpp\"\r\n\r\nnamespace patch {\r\n\r\n    // init at patch load\r\n    // ファイルの情報を開くと落ちるのを修正\r\n    inline class fileinfo_t {\r\n        bool enabled = true;\r\n        bool enabled_i;\r\n        inline static const char key[] = \"fileinfo\";\r\n    public:\r\n        void init() {\r\n            enabled_i = enabled;\r\n\r\n            if (!enabled_i)return;\r\n\r\n\r\n            OverWriteOnProtectHelper h(GLOBAL::aviutl_base + 0x01c47a, 6);\r\n            h.store_i16(0, '\\x90\\xb8');\r\n            h.store_i32(2, GLOBAL::aviutl_base + 0x0b87b0);\r\n            /*\r\n                0041c47a 8b800c040000    mov     eax,dword ptr[eax + 0x40c] ; editp+0x40c\r\n                ↓\r\n                0041c47a 90              nop\r\n                0041c47b b8XxXxXxXx      mov     eax,aviutl + 0xb87b0\r\n\r\n                    ; eaxが本来はaviutl+0xb87b0でなければいけないのにプロジェクト保存時のアドレスを使っている\r\n            */\r\n        }\r\n\r\n        void switching(bool flag) {\r\n            enabled = flag;\r\n        }\r\n\r\n        bool is_enabled() { return enabled; }\r\n        bool is_enabled_i() { return enabled_i; }\r\n\r\n        void switch_load(ConfigReader& cr) {\r\n            cr.regist(key, [this](json_value_s* value) {\r\n                ConfigReader::load_variable(value, enabled);\r\n                });\r\n        }\r\n\r\n        void switch_store(ConfigWriter& cw) {\r\n            cw.append(key, enabled);\r\n        }\r\n    } fileinfo;\r\n} // namespace patch\r\n\r\n#endif // ifdef PATCH_SWITCH_FILEINFO\r\n"
  },
  {
    "path": "patch/patch_font_dialog.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_FONT_DIALOG\n\n#include <Windows.h>\n#include \"global.hpp\"\n\nnamespace patch {\n\t// init at exedit load\n\t// フォント選択ダイアログを表示\n\t// コンボボックスの右クリで適当なダイアログを召喚する\n\tinline class font_dialog_t {\n\n\t\t//inline static constexpr LPCWSTR class_name = L\"PATCH_FONTDLG\";\n\n\t\tbool enabled = true;\n\t\tbool enabled_i;\n\t\tinline static const char key[] = \"font_dialog\";\n\n\tpublic:\n\t\tvoid init() {\n\t\t\tenabled_i = enabled;\n\t\t\tif (!enabled_i)return;\n\t\t\t/*WNDCLASSW wc{\n\t\t\t\t.style = 0,\n\t\t\t\t.lpfnWndProc = nullptr,\n\t\t\t\t.cbClsExtra = 0,\n\t\t\t\t.cbWndExtra = 0,\n\t\t\t\t.hInstance = GLOBAL::patchaul_hinst,\n\t\t\t\t.hIcon = NULL,\n\t\t\t\t.hCursor = NULL,\n\t\t\t\t.hbrBackground = HBRUSH(COLOR_BACKGROUND + 1),\n\t\t\t\t.lpszMenuName = NULL,\n\t\t\t\t.lpszClassName = class_name,\n\t\t\t};\n\t\t\tRegisterClassW(&wc);\n\t\t\t*/\n\t\t\t\n\n\n\t\t}\n\n\t\t~font_dialog_t() {\n\t\t\t//UnregisterClassW(class_name, GLOBAL::patchaul_hinst);\n\t\t}\n\n\n\t\tvoid switching(bool flag) {\n\t\t\tenabled = flag;\n\t\t}\n\n\t\tbool is_enabled() { return enabled; }\n\t\tbool is_enabled_i() { return enabled_i; }\n\n\t\tvoid switch_load(ConfigReader& cr) {\n\t\t\tcr.regist(key, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, enabled);\n\t\t\t});\n\t\t}\n\n\t\tvoid switch_store(ConfigWriter& cw) {\n\t\t\tcw.append(key, enabled);\n\t\t}\n\t} font_dialog;\n\t\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_FONT_DIALOG\n"
  },
  {
    "path": "patch/patch_helpful_msgbox.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_helpful_msgbox.hpp\"\n\n#ifdef PATCH_SWITCH_HELPFUL_MSGBOX\nnamespace patch {\n\n\tint WINAPI helpful_msgbox_t::MessageBoxAWrap(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) {\n\t\tstd::optional<std::string> localText, localCaption;\n\t\tUINT id = 0;\n\t\tif (auto itr = strptr2rid.find(lpText); itr != strptr2rid.end()) {\n\t\t\tid = itr->second;\n\t\t\tlocalText = resource_string_a(id);\n\t\t\tif (localText) lpText = localText->c_str();\n\t\t}\n\t\tif (auto itr = strptr2rid.find(lpCaption); itr != strptr2rid.end()) {\n\t\t\tlocalCaption = resource_string_a(itr->second);\n\t\t\tif (localCaption)lpCaption = localCaption->c_str();\n\t\t}\n\t\treturn HelpedMsg(hWnd, lpText, lpCaption, uType, id);\n\t}\n\n\tint helpful_msgbox_t::HelpedMsg(HWND hwnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, UINT id) {\n\t\tMSGBOXPARAMSA param{\n\t\t\t.cbSize = sizeof(param),\n\t\t\t.hwndOwner = hwnd,\n\t\t\t.hInstance = NULL,\n\t\t\t.lpszText = lpText,\n\t\t\t.lpszCaption = lpCaption,\n\t\t\t.dwStyle = uType | (id ? MB_HELP : 0),\n\t\t\t.dwContextHelpId = id,\n\t\t\t.lpfnMsgBoxCallback = [](LPHELPINFO hip) {\n\t\t\t\tconst auto& itr = rid2md.find(hip->dwContextId);\n\t\t\t\tif (itr == rid2md.end()) {\n\t\t\t\t\tMessageBoxW(NULL, L\"ヘルプは設定されていません\", L\"patch.aul\", MB_ICONINFORMATION | MB_TASKMODAL);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst auto& data = itr->second;\n\n\t\t\t\tUrlConfirm(data.url);\n\t\t\t}\n\t\t};\n\t\treturn MessageBoxIndirectA(&param);\n\t}\n\n\tvoid helpful_msgbox_t::UrlConfirm(std::wstring_view url) {\n\t\tauto ret = MessageBoxW(NULL, L\"次のリンクを開こうとしています。同意しますか？\\n{}\"_fmt(url).c_str(), L\"patch.aul\", MB_ICONQUESTION | MB_YESNO | MB_TASKMODAL);\n\t\tswitch (ret) {\n\t\tcase IDYES:\n\t\t\tShellExecuteW(NULL, L\"open\", url.data(), NULL, NULL, SW_SHOW);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t\t}\n\t}\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_HELPFUL_MSGBOX\n"
  },
  {
    "path": "patch/patch_helpful_msgbox.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_HELPFUL_MSGBOX\n\n#include <unordered_map>\n\n#include <Windows.h>\n\n#include \"cryptostring.hpp\"\n#include \"global.hpp\"\n#include \"util_resource.hpp\"\n#include \"util_magic.hpp\"\n#include \"restorable_patch.hpp\"\n#include \"config_rw.hpp\"\n\nnamespace patch {\n\t// init at exedit load\n\t// メッセージボックスの拡張\n\t// メッセージの翻訳をしたりヘルプを表示したり\n\tinline class helpful_msgbox_t {\n\n\t\tstruct MessageData {\n\t\t\tstd::wstring url;\n\t\t};\n\n\t\t// メッセージ文字列のポインタからメッセージID(リソースID)に変換\n\t\tinline static std::unordered_map<LPCSTR, UINT> strptr2rid;\n\n\t\t// strptr2ridで拡張編集のオフセットのものだけ\n\t\tinline static std::pair<LPCSTR, UINT> strptr2rid_ofs_ee[]{\n\t\t\t{ reinterpret_cast<LPCSTR>(0x09da28), 10010 }, // \"動画ファイルの読み込みに失敗しました\\n対応していないフォーマットの可能性があります\"\n\t\t};\n\n\t\t// メッセージIDをMessageDataに変換\n\t\tinline static std::unordered_map<UINT, MessageData> rid2md{\n\t\t\t{ 10010, { L\"https://scrapbox.io/aviutl/**%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%81%BF%E3%81%AB%E5%A4%B1%E6%95%97%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F_%E5%AF%BE%E5%BF%9C%E3%81%97%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88%E3%81%AE%E5%8F%AF%E8%83%BD%E6%80%A7%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99\" }},\n\t\t};\n\n\t\tstatic void UrlConfirm(std::wstring_view url);\n\n\t\t// ヘルプを表示できるメッセージボックス関数\n\t\tstatic int HelpedMsg(HWND hwnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, UINT id);\n\n\t\tstatic int WINAPI MessageBoxAWrap(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);\n\n\t\tbool enabled = true;\n\t\tinline static const char key[] = \"helpful_msgbox\";\n\n\t\tstd::optional<restorable_patch_i32> rp;\n\n\tpublic:\n\t\tvoid init() {\n\t\t\tif (!enabled)return;\n\n\t\t\tfor (auto& p : strptr2rid_ofs_ee) {\n\t\t\t\tstrptr2rid.emplace(GLOBAL::exedit_base + p.first, p.second);\n\t\t\t}\n\n\t\t\tauto address = search_import(GLOBAL::exedit_hmod, cstr_user32_dll.get(), cstr_MessageBoxA.get());\n\t\t\trp.emplace(reinterpret_cast<uintptr_t>(address), reinterpret_cast<i32>(&MessageBoxAWrap));\n\t\t}\n\n        void switching(bool flag) {\n            rp->switching(enabled = flag);\n        }\n\n        bool is_enabled() { return enabled; }\n        bool is_enabled_i() { return enabled; }\n\n        void switch_load(ConfigReader& cr) {\n\t\t\tcr.regist(key, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, enabled);\n\t\t\t});\n        }\n\n        void switch_store(ConfigWriter& cw) {\n            cw.append(key, enabled);\n        }\n\t} helpful_msgbox;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_HELPFUL_MSGBOX\n"
  },
  {
    "path": "patch/patch_ignore_media_param_reset.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_IGNORE_MEDIA_PARAM_RESET\n#include \"global.hpp\"\n#include \"util_magic.hpp\"\n\n#include \"restorable_patch.hpp\"\n\nnamespace patch {\n\t// init at exedit load\n\t// 動画ファイル と 音声ファイル で中間点を打っていないときでもファイルを再参照しても再生位置などの情報を変更しない\n    inline class ignore_media_param_reset_t {\n\n        std::optional<restorable_patch_i16> rp1;\n        std::optional<restorable_patch_i8> rp2;\n\n        bool enabled = false;\n\n        inline static const char key[] = \"ignore_media_param_reset\";\n\n    public:\n        void init() {\n            rp1.emplace(GLOBAL::exedit_base + OFS::ExEdit::ignore_media_param_reset_mov, '\\x90\\xe9');\n            rp2.emplace(GLOBAL::exedit_base + OFS::ExEdit::ignore_media_param_reset_aud, '\\xeb');\n\n            rp1->switching(enabled);\n            rp2->switching(enabled);\n        }\n\n        void switching(bool flag) {\n            enabled = flag;\n            rp1->switching(enabled);\n            rp2->switching(enabled);\n        }\n\n        bool is_enabled() { return enabled; }\n        bool is_enabled_i() { return enabled; }\n\n        void switch_load(ConfigReader& cr) {\n            cr.regist(key, [this](json_value_s* value) {\n                ConfigReader::load_variable(value, enabled);\n           });\n        }\n\n        void switch_store(ConfigWriter& cw) {\n            cw.append(key, enabled);\n        }\n\n    } ignore_media_param_reset;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_IGNORE_MEDIA_PARAM_RESET\n"
  },
  {
    "path": "patch/patch_lua.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_lua.hpp\"\n#ifdef PATCH_SWITCH_LUA\n\n#include <format>\n\n#include \"debug_log.hpp\"\n#include \"global.hpp\"\n#include \"offset_address.hpp\"\n\n#include \"patch_lua_getvalueex.hpp\"\n#include \"patch_lua_rand.hpp\"\n#include \"patch_lua_randex.hpp\"\n\nnamespace patch {\n    \n    static void assign_to_luastate(lua_State* L) {\n        // _G, obj の順で積んでる\n\n        lua_pushstring(L, PATCH_VERSION_NAME);\n        lua_setfield(L, -3, \"_PATCH\");\n\n        #ifdef PATCH_SWITCH_LUA_RAND\n            if (lua_rand.is_enabled_i()) lua_rand_t::require(L);\n        #endif\n\n        #ifdef PATCH_SWITCH_LUA_RANDEX\n            if (lua_randex.is_enabled_i()) lua_randex_t::require(L);\n        #endif\n\n        #ifdef PATCH_SWITCH_LUA_GETVALUE\n            if (lua_getvalueex.is_enabled_i()) lua_getvalueex_t::require(L);\n        #endif\n    }\n\n    lua_State* __cdecl lua_t::luaGetOrCreateState(int idx) {\n        if (idx > 1) return nullptr;\n        auto LuaState = (lua_State**)(GLOBAL::exedit_base + 0x1baca8);\n        auto& L = LuaState[idx];\n        if (L == nullptr) {\n            auto loadLua = (BOOL(__cdecl*)())(GLOBAL::exedit_base + OFS::ExEdit::LoadLua);\n            if (loadLua() != TRUE) return nullptr;\n            auto mod = load_i32<HMODULE>(GLOBAL::exedit_base + OFS::ExEdit::hmodule_lua);\n            #define def(name) name=reinterpret_cast<decltype(name)>(GetProcAddress(mod, #name))\n                def(lua_isstring);\n                def(lua_pushcclosure);\n                def(lua_remove);\n                def(lua_setmetatable);\n                def(luaL_newmetatable);\n                def(lua_pushvalue);\n            #undef def\n\n            L = luaL_newstate();\n            if (L == nullptr)return nullptr;\n\n            luaL_openlibs(L);\n            luaL_register(L, \"_G\", (luaL_Reg*)(GLOBAL::exedit_base + OFS::ExEdit::luaL_Reg_global_table));\n            luaL_register(L, \"obj\", (luaL_Reg*)(GLOBAL::exedit_base + OFS::ExEdit::luaL_Reg_obj_table));\n\n            assign_to_luastate(L);\n\n            lua_pop(L, 2);\n        }\n        return L;\n    }\n\n    lua_State* __cdecl lua_t::luaGetOrCreateState_envpatch(int idx) {\n\n        if(lua_t::state == nullptr) {\n            auto loadLua = (BOOL(__cdecl*)())(GLOBAL::exedit_base + OFS::ExEdit::LoadLua);\n            if(loadLua() != TRUE) return nullptr;\n\n            auto mod = load_i32<HMODULE>(GLOBAL::exedit_base + OFS::ExEdit::hmodule_lua);\n            #define def(name) name=reinterpret_cast<decltype(name)>(GetProcAddress(mod, #name))\n                def(lua_isstring);\n                def(lua_pushcclosure);\n                def(lua_remove);\n                def(lua_setmetatable);\n                def(luaL_newmetatable);\n                def(lua_pushvalue);\n            #undef def\n            \n            auto state = luaL_newstate();\n            if(state == nullptr) return nullptr;\n\n            lua_t::state = state;\n            luaL_openlibs(state);\n            \n            luaL_register(state, \"_G\", (luaL_Reg*)(GLOBAL::exedit_base + OFS::ExEdit::luaL_Reg_global_table));\n            luaL_register(state, \"obj\", (luaL_Reg*)(GLOBAL::exedit_base + OFS::ExEdit::luaL_Reg_obj_table));\n            \n            assign_to_luastate(state);\n\n            lua_pop(state, 2);\n\n            //inject_viewer();\n            return state;\n        }\n        return lua_t::state;\n    }\n    \n    void __cdecl lua_t::luaUnload() {\n        if(state) {\n            lua_close(state);\n            state = nullptr;\n        }\n        auto& hmod_lua = load_i32<HMODULE&>(GLOBAL::exedit_base + OFS::ExEdit::hmodule_lua);\n        if(hmod_lua != NULL) {\n            FreeLibrary(hmod_lua);\n            hmod_lua = NULL;\n        }\n    }\n\n    BOOL __cdecl lua_t::luaUpdatePath(lua_State* L) {\n        //debug_log(\"luaUpdatePath()\");\n        lua_getglobal(L, \"package\");\n        const auto exedit_dir = load_i32<char*>(GLOBAL::exedit_base + OFS::ExEdit::exeditdir);\n        if(auto folder_name = load_i32<char*>(GLOBAL::exedit_base + OFS::ExEdit::sScriptFolderName); folder_name == nullptr || folder_name[0] == '\\0') {\n            lua_pushstring(L, \"{0}?.lua;{0}script\\\\?.lua;{0}module\\\\?.lua;{0}module\\\\?\\\\init.lua\"_fmt(exedit_dir).c_str());\n            lua_setfield(L, -2, \"path\");\n\n            lua_pushstring(L, \"{0}?.dll;{0}script\\\\?.dll;{0}module\\\\?.dll\"_fmt(exedit_dir).c_str());\n            lua_setfield(L, -2, \"cpath\");\n        }\n        else {\n            lua_pushstring(L, \"{0}?.lua;{0}script\\\\?.lua;{0}script\\\\{1}\\\\?.lua;{0}module\\\\?.lua;{0}module\\\\?\\\\init.lua\"_fmt(exedit_dir, folder_name).c_str());\n            lua_setfield(L, -2, \"path\");\n\n            lua_pushstring(L, \"{0}?.dll;{0}script\\\\?.dll;{0}script\\\\{1}\\\\?.dll;{0}module\\\\?.dll\"_fmt(exedit_dir, folder_name).c_str());\n            lua_setfield(L, -2, \"cpath\");\n        }\n        lua_pop(L, 1);\n        return TRUE;\n    }\n\n    double __cdecl lua_t::lua_tonumber_remove_stack(lua_State* L, int idx) {\n        //view_stack(L, \"hoge\");\n        auto ret = lua_tonumber(L, idx);\n        lua_remove(L, idx);\n        //view_stack(L, \"hoge\");\n        return ret;\n    }\n\n    const char* __cdecl lua_t::lua_tolstring_remove_stack(lua_State* L, int idx, size_t* len) {\n        auto ret = lua_tolstring(L, idx, len);\n        lua_remove(L, idx);\n        return ret;\n    }\n    \n    static int luastateidx_internal = 0;\n    BOOL __cdecl lua_t::DoScriptInit() {\n        env::store();\n        luastateidx_internal++;\n        store_i32(GLOBAL::exedit_base + OFS::ExEdit::luastateidx, (std::min)(luastateidx_internal, 1));\n        return TRUE;\n    }\n\n    BOOL __cdecl lua_t::DoScriptExit() {\n        env::load();\n        luastateidx_internal--;\n        store_i32(GLOBAL::exedit_base + OFS::ExEdit::luastateidx, (std::min)(luastateidx_internal, 1));\n        ((BOOL(__cdecl*)(lua_State*))(GLOBAL::exedit_base + OFS::ExEdit::SetLuaPathAndCpath))(luaGetOrCreateState_envpatch(0));\n        return TRUE;\n    }\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_LUA\n"
  },
  {
    "path": "patch/patch_lua.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_LUA\n\n#include <cstdint>\n#include <vector>\n#include <array>\n#include <Windows.h>\n\n#include \"util.hpp\"\n#include \"global.hpp\"\n#include \"offset_address.hpp\"\n#include \"mylua.hpp\"\n#include \"config_rw.hpp\"\n\nnamespace patch {\n    // init at exedit load\n    // Luaの環境を一つにまとめる\n    inline class lua_t {\n        struct env {\n            inline static constexpr std::ptrdiff_t target[] = {\n                0x1b2b4c, // sScriptFolderName\n                0x1b28d4, // obj_layer_ptr\n                0x1baca4, // script_objectp\n                0x1b2b20, // efpip_g\n                0x1b2368, // textbuffer_pointer\n                0x1b28b4, // textbuffer_max\n                0x1b2204, // textbuffer_current\n                0x1b28d0, // draw_state\n                0x1b249c, // something_drawstate1\n                0x1b24a0, // something_drawstate2\n                0x1b21e4, // draw_target\n                0x1b28dc, // some_flag\n                0x1b21f0, // obj_setanchor_called_count\n            };\n\n            inline static constexpr std::ptrdiff_t target_tmp[] = {\n                0x1b24b4, // sScriptFolderName\n                0x1bac94, // obj_layer_ptr\n                0x1b2b08, // script_objectp\n                0x1b24b8, // efpip_g\n                0x1b28bc, // textbuffer_pointer\n                0x1b29f4, // textbuffer_max\n                0x1b21e0, // textbuffer_current\n                0x1bacb8, // draw_state\n                0x1b2494, // something_drawstate1\n                0x1b2498, // something_drawstate2\n                0x1b23bc, // draw_target\n                0x1b2b40, // some_flag\n                0x1b2b2c, // obj_setanchor_called_count\n            };\n\n            std::array<DWORD, std::size(target)> tmp;\n            std::optional<std::string> folder_name;\n\n            inline static std::vector<env> vec;\n\n            static void load() {\n                auto& e = vec.back();\n                for(size_t i = 0; i < std::size(target); i++) {\n                    store_i32(GLOBAL::exedit_base + target[i], e.tmp[i]);\n                }\n                if (vec.size()) {\n                    for (size_t i = 0; i < std::size(target); i++) {\n                        store_i32(GLOBAL::exedit_base + target_tmp[i], vec.back().tmp[i]);\n                    }\n                }\n                vec.pop_back();\n\n            }\n\n            static void store() {\n                vec.push_back({});\n                auto& e = vec.back();\n                for(size_t i = 0; i < std::size(target); i++) {\n                    auto val = load_i32<DWORD>(GLOBAL::exedit_base + target[i]);\n                    e.tmp[i] = val;\n                    store_i32(GLOBAL::exedit_base + target_tmp[i], val);\n                }\n            }\n        };\n        inline static lua_State* state = nullptr;\n\n        static lua_State* __cdecl luaGetOrCreateState(int idx);\n        static lua_State* __cdecl luaGetOrCreateState_envpatch(int idx);\n\n        static void __cdecl luaUnload();\n\n        static BOOL __cdecl luaUpdatePath(lua_State* L);\n\n        static BOOL __cdecl DoScriptInit();\n        static BOOL __cdecl DoScriptExit();\n\n        static double __cdecl lua_tonumber_remove_stack(lua_State* L, int idx);\n        inline static auto lua_tonumber_remove_stack_ptr = &lua_tonumber_remove_stack;\n\n        static const char* __cdecl lua_tolstring_remove_stack(lua_State* L, int idx, size_t* len);\n        inline static auto lua_tolstring_remove_stack_ptr = &lua_tolstring_remove_stack;\n\n        bool enabled = true;\n        bool enabled_i;\n        inline static const char key[] = \"lua\";\n\n        bool env = false;\n        bool env_i;\n        inline static const char key_env[] = \"lua.env\";\n\n        bool path = false;\n        bool path_i;\n        inline static const char key_path[] = \"lua.path\";\n\n    public:\n        void init() {\n            enabled_i = enabled;\n            env_i = env;\n            path_i = path;\n\n\n            if (!enabled_i)return;\n\n            if (env_i) {\n                ReplaceFunction(GLOBAL::exedit_base + OFS::ExEdit::GetOrCreateLuaState, &luaGetOrCreateState_envpatch);\n                ReplaceFunction(GLOBAL::exedit_base + OFS::ExEdit::LuaUnload, &luaUnload);\n                ReplaceFunction(GLOBAL::exedit_base + OFS::ExEdit::DoScriptInit, &DoScriptInit);\n                ReplaceFunction(GLOBAL::exedit_base + OFS::ExEdit::DoScriptExit, &DoScriptExit);\n            }\n            else {\n                ReplaceFunction(GLOBAL::exedit_base + OFS::ExEdit::GetOrCreateLuaState, &luaGetOrCreateState);\n            }\n\n\n            if (path_i) {\n                ReplaceFunction(GLOBAL::exedit_base + OFS::ExEdit::SetLuaPathAndCpath, &luaUpdatePath);\n            }\n\n\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::lua_pop_nop, 6);\n                memset((void*)(GLOBAL::exedit_base + OFS::ExEdit::lua_pop_nop), '\\x90', 6);\n            }\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::lua_set_nop, 6);\n                memset((void*)(GLOBAL::exedit_base + OFS::ExEdit::lua_set_nop), '\\x90', 6);\n            }\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::lua_tonumber_arg, 8);\n                h.store_i8(0, 0xff); // (push) 0xff\n                h.store_i32(4, &lua_tonumber_remove_stack_ptr);\n            }\n            \n            OverWriteOnProtectHelper(GLOBAL::exedit_base + OFS::ExEdit::lua_tostring_calling1, 4).store_i32(0, &lua_tolstring_remove_stack_ptr);\n            OverWriteOnProtectHelper(GLOBAL::exedit_base + OFS::ExEdit::lua_tostring_calling2, 4).store_i32(0, &lua_tolstring_remove_stack_ptr);\n            OverWriteOnProtectHelper(GLOBAL::exedit_base + OFS::ExEdit::lua_tostring_calling3, 4).store_i32(0, &lua_tolstring_remove_stack_ptr);\n        }\n\n        void switching(bool flag) {\n            enabled = flag;\n        }\n\n        bool is_enabled() { return enabled; }\n        bool is_enabled_i() { return enabled_i; }\n\n        bool get_env() { return env; }\n        bool get_env_i() { return env_i; }\n        void set_env(bool x) { env = x; }\n\n        bool get_path() { return path; }\n        bool get_path_i() { return path_i; }\n        void set_path(bool x) { path = x; }\n\n        void switch_load(ConfigReader& cr) {\n            cr.regist(key, [this](json_value_s* value) {\n                ConfigReader::load_variable(value, enabled);\n            });\n            cr.regist(key_env, [this](json_value_s* value) {\n                ConfigReader::load_variable(value, env);\n            });\n            cr.regist(key_path, [this](json_value_s* value) {\n                ConfigReader::load_variable(value, path);\n            });\n        }\n\n        void switch_store(ConfigWriter& cw) {\n            cw.append(key, enabled);\n            cw.append(key_env, env);\n            cw.append(key_path, path);\n        }\n\n    } lua;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_LUA\n"
  },
  {
    "path": "patch/patch_lua_getvalueex.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_lua_getvalueex.hpp\"\n#ifdef PATCH_SWITCH_LUA_GETVALUE\n\n#include \"offset_address.hpp\"\n\nnamespace patch {\n\tint __cdecl lua_getvalueex_t::lua_getvalue_override(lua_State* L) {\n\t\t//lua_t::states.push_back(L);\n\t\tint layer_idx = 0;\n\t\tint target_i = 0;\n\n\t\tauto efpip = load_i32<ExEdit::FilterProcInfo*>(GLOBAL::exedit_base + OFS::ExEdit::efpip_g);\n\t\tauto ScriptProcessingFilter = load_i32<ExEdit::Filter*>(GLOBAL::exedit_base + OFS::ExEdit::ScriptProcessingFilter);\n\n\t\tint n = lua_gettop(L);\n\t\tint frame;\n\t\tint subframe;\n\t\tif (n < 2) {\n\t\t\tframe = efpip->frame_num;\n\t\t\tsubframe = efpip->subframe;\n\t\t}\n\t\telse {\n\t\t\tdouble time = luaL_checknumber(L, 2);\n\t\t\tdouble frame_before_round = time * efpip->framerate_nu / efpip->framerate_de;\n\t\t\tframe = static_cast<int>(floor(frame_before_round));\n\t\t\tsubframe = static_cast<int>(floor((frame_before_round - frame) * 100.0));\n\t\t\tif (n < 3) {\n\t\t\t\tframe += ScriptProcessingFilter->frame_start_chain;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tint section = luaL_checkinteger(L, 3);\n\t\t\t\tif (section < 0) {\n\t\t\t\t\tframe += ScriptProcessingFilter->frame_end_chain;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t//exfunc_10;\n\t\t\t\t\tauto ps = reinterpret_cast<ExEdit::ObjectFilterIndex(__cdecl*)(ExEdit::ObjectFilterIndex)>(GLOBAL::exedit_base + OFS::ExEdit::exfunc_10)(ScriptProcessingFilter->processing);\n\t\t\t\t\twhile (section) {\n\t\t\t\t\t\t//exfunc_08\n\t\t\t\t\t\tps = reinterpret_cast<ExEdit::ObjectFilterIndex(__cdecl*)(ExEdit::ObjectFilterIndex)>(GLOBAL::exedit_base + OFS::ExEdit::exfunc_08)(ps);\n\t\t\t\t\t\tsection--;\n\t\t\t\t\t}\n\t\t\t\t\tif (is_valid(ps)) {\n\t\t\t\t\t\t// func_0x047ad0\n\t\t\t\t\t\tframe += reinterpret_cast<ExEdit::Object*(__cdecl*)(ExEdit::ObjectFilterIndex, int)>(GLOBAL::exedit_base + OFS::ExEdit::func_0x047ad0)(ps, 0)->frame_begin;\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tframe += ScriptProcessingFilter->frame_end_chain;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tint track_idx;\n\t\tint result_nu, result_de;\n\t\tif (lua_isnumber(L, 1)) {\n\t\t\tint target = luaL_checkinteger(L, 1);\n\t\t\tif (target < 0)return 0;\n\t\t\tif (ScriptProcessingFilter->track_n <= target)return 0;\n\t\t\treinterpret_cast<BOOL(__cdecl*)(ExEdit::ObjectFilterIndex, int, int, int*, int)>(GLOBAL::exedit_base + OFS::ExEdit::exfunc_64)(ScriptProcessingFilter->processing, frame, subframe, &result_nu, target + 1);\n\t\t\tresult_de = 100;\n\t\t}\n\t\telse {\n\t\t\tconst char* target = luaL_checkstring(L, 1);\n\t\t\tif (lstrcmpiA(target, \"scenechange\") == 0) {\n\t\t\t\tlua_pushnumber(L, load_i32<int>(GLOBAL::exedit_base + OFS::ExEdit::scenechange_progress_times4096) / 4096.0);\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tExEdit::ObjectFilterIndex ps;\n\t\t\t\n\t\t\tif (strncmp(target, \"layer\", 5) == 0) {\n\t\t\t\ttarget += 5;\n\t\t\t\tint layer_idx = 0;\n\t\t\t\twhile (*target != '.') {\n\t\t\t\t\tuint8_t i = (uint8_t)*target - (uint8_t)'0';\n\t\t\t\t\tif (i > 9) {\n\t\t\t\t\t\tlayer_idx = -1; break;\n\t\t\t\t\t}\n\t\t\t\t\tlayer_idx = layer_idx * 10 + i;\n\t\t\t\t\ttarget++;\n\t\t\t\t}\n\t\t\t\tif (layer_idx < 1 && 100 < layer_idx) return 0;\n\t\t\t\ttarget++;\n\t\t\t\t// ef0x1c\n\t\t\t\tps = reinterpret_cast<ExEdit::ObjectFilterIndex(__cdecl*)(int, int, int, int, unsigned int)>(GLOBAL::exedit_base + OFS::ExEdit::exfunc_1c)(frame, layer_idx - 1, ScriptProcessingFilter->scene_set, 0, 0x10);\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// GetCurrentProcessing\n\t\t\t\tps = reinterpret_cast<ExEdit::ObjectFilterIndex(__cdecl*)(ExEdit::FilterProcInfo*)>(GLOBAL::exedit_base + OFS::ExEdit::GetCurrentProcessing)(efpip);\n\t\t\t}\n\t\t\tif (!is_valid(ps))return 0;\n\n\t\t\tint a;\n\t\t\t// FUN_10047ad0\n\t\t\tauto eop = reinterpret_cast<ExEdit::Object*(__cdecl*)(ExEdit::ObjectFilterIndex, int*)>(GLOBAL::exedit_base + OFS::ExEdit::func_0x047ad0)(ps, &a);\n\t\t\tauto efp = reinterpret_cast<ExEdit::Filter**>(GLOBAL::exedit_base + OFS::ExEdit::LoadedFilterTable)[eop->filter_param[a].id];\n\t\t\tif (efp->track_gui == nullptr)return 0;\n\n#if 1\n\t\t\tchar target2[7];\n\t\t\t{\n\t\t\t\tint i = 0;\n\t\t\t\tdo{\n\t\t\t\t\tif(target[i] == '\\0') {\n\t\t\t\t\t\ttarget2[i] = '\\0';\n\t\t\t\t\t\tgoto BREAK;\n\t\t\t\t\t}\n\t\t\t\t\ttarget2[i] = target[i] | 0b10'0000; // to lower\n\t\t\t\t\ti++;\n\t\t\t\t} while(i < 7);\n\t\t\t\treturn 0;\n\t\t\t\tBREAK:\n\t\t\t\t;\n\t\t\t}\n\n\t\t\tswitch(target2[0]) {\n\t\t\tcase 'a': // alpha aspect\n\t\t\t\tif(*(int*)(target2 + 1) == 'ahpl') {\n\t\t\t\t\tif(target2[5] != '\\0') return 0;\n\t\t\t\t\t// alpha\n\n\t\t\t\t\tresult_de = 100;\n\t\t\t\t\ttrack_idx = efp->track_gui->alpha;\n\t\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\t\t\t\t\t\n\t\t\t\t\t//exfunc_64\n\t\t\t\t\treinterpret_cast<BOOL(__cdecl*)(ExEdit::ObjectFilterIndex, int, int, int*, int)>(GLOBAL::exedit_base + OFS::ExEdit::exfunc_64)(ps, frame, subframe, &result_nu, track_idx + 1);\n\t\t\t\t\tlua_pushnumber(L, 1. - result_nu * 0.001);\n\t\t\t\t\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\tif(*(int*)(target2 + 1) == 'ceps') {\n\t\t\t\t\tif(*(short*)(target2 + 5) != '\\0t') return 0;\n\t\t\t\t\t// aspect\n\n\t\t\t\t\tresult_de = 1000;\n\t\t\t\t\ttrack_idx = efp->track_gui->aspect;\n\t\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn 0;\n\t\t\tcase 'c': // cx cy cz\n\t\t\t\tswitch(*(short*)(target2 + 1)) {\n\t\t\t\t\tcase '\\0x':\n\n\t\t\t\t\t\tresult_de = 10;\n\t\t\t\t\t\ttrack_idx = efp->track_gui->cx;\n\t\t\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase '\\0y':\n\n\t\t\t\t\t\tresult_de = 10;\n\t\t\t\t\t\ttrack_idx = efp->track_gui->cy;\n\t\t\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase '\\0z':\n\n\t\t\t\t\t\tresult_de = 10;\n\t\t\t\t\t\ttrack_idx = efp->track_gui->cz;\n\t\t\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 't': // time\n\t\t\t\tif(*(int*)(target2 + 1) != '\\0emi') return 0;\n\n\t\t\t\tif (auto leader = eop->index_midpt_leader; leader >= 0) {\n\t\t\t\t\teop = load_i32<ExEdit::Object*>(GLOBAL::exedit_base + OFS::ExEdit::ObjectArrayPointer) + leader;\n\t\t\t\t}\n\t\t\t\tlua_pushnumber(L, (subframe * 0.01 + (double)(frame - eop->frame_begin))* (double)efpip->framerate_de / (double)efpip->framerate_nu);\n\t\t\t\t//lua_pushnumber(L, (subframe * 0.01 + (double)(frame - ScriptProcessingFilter->frame_start_chain)) * (double)efpip->framerate_de / (double)efpip->framerate_nu);\n\t\t\t\treturn 1;\n\t\t\tcase 'r': // rx ry rz\n\t\t\t\tswitch(*(short*)(target2 + 1)) {\n\t\t\t\t\tcase '\\0x':\n\n\t\t\t\t\t\tresult_de = 100;\n\t\t\t\t\t\ttrack_idx = efp->track_gui->rx;\n\t\t\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase '\\0y':\n\n\t\t\t\t\t\tresult_de = 100;\n\t\t\t\t\t\ttrack_idx = efp->track_gui->ry;\n\t\t\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase '\\0z':\n\n\t\t\t\t\t\tresult_de = 100;\n\t\t\t\t\t\ttrack_idx = efp->track_gui->rz;\n\t\t\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'x':\n\t\t\t\tif(target2[1] != '\\0') return 0;\n\n\t\t\t\tresult_de = 10;\n\t\t\t\ttrack_idx = efp->track_gui->bx;\n\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\n\t\t\t\tbreak;\n\t\t\tcase 'y':\n\t\t\t\tif(target2[1] != '\\0') return 0;\n\n\t\t\t\tresult_de = 10;\n\t\t\t\ttrack_idx = efp->track_gui->by;\n\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\n\t\t\t\tbreak;\n\t\t\tcase 'z': // z zoom\n\t\t\t\tif(target2[1] == '\\0') {\n\t\t\t\t\t// z\n\n\t\t\t\t\tresult_de = 10;\n\t\t\t\t\ttrack_idx = efp->track_gui->bz;\n\t\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\telse if(*(int*)(target2 + 1) == '\\0moo') {\n\t\t\t\t\t//zoom\n\n\t\t\t\t\tresult_de = 100;\n\t\t\t\t\ttrack_idx = efp->track_gui->zoom;\n\t\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn 0;\n\t\t\tdefault:\n\t\t\t\treturn 0;\n\t\t\t}\n#else\n\t\t\tif (lstrcmpiA(target, \"x\") == 0) {\n\t\t\t\tresult_de = 10;\n\t\t\t\ttrack_idx = efp->track_gui->bx;\n\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\t\t\t}\n\t\t\telse if (lstrcmpiA(target, \"y\") == 0) {\n\t\t\t\tresult_de = 10;\n\t\t\t\ttrack_idx = efp->track_gui->by;\n\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\t\t\t}\n\t\t\telse if (lstrcmpiA(target, \"z\") == 0) {\n\t\t\t\tresult_de = 10;\n\t\t\t\ttrack_idx = efp->track_gui->bz;\n\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\t\t\t}\n\t\t\telse if (lstrcmpiA(target, \"zoom\") == 0) {\n\t\t\t\tresult_de = 100;\n\t\t\t\ttrack_idx = efp->track_gui->zoom;\n\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\t\t\t}\n\t\t\telse if (lstrcmpiA(target, \"rx\") == 0) {\n\t\t\t\tresult_de = 100;\n\t\t\t\ttrack_idx = efp->track_gui->rx;\n\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\t\t\t}\n\t\t\telse if (lstrcmpiA(target, \"ry\") == 0) {\n\t\t\t\tresult_de = 100;\n\t\t\t\ttrack_idx = efp->track_gui->ry;\n\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\t\t\t}\n\t\t\telse if (lstrcmpiA(target, \"rz\") == 0) {\n\t\t\t\tresult_de = 100;\n\t\t\t\ttrack_idx = efp->track_gui->rz;\n\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\t\t\t}\n\t\t\telse if (lstrcmpiA(target, \"cx\") == 0) {\n\t\t\t\tresult_de = 10;\n\t\t\t\ttrack_idx = efp->track_gui->cx;\n\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\t\t\t}\n\t\t\telse if (lstrcmpiA(target, \"cy\") == 0) {\n\t\t\t\tresult_de = 10;\n\t\t\t\ttrack_idx = efp->track_gui->cy;\n\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\t\t\t}\n\t\t\telse if (lstrcmpiA(target, \"cz\") == 0) {\n\t\t\t\tresult_de = 10;\n\t\t\t\ttrack_idx = efp->track_gui->cz;\n\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\t\t\t}\n\t\t\telse if (lstrcmpiA(target, \"alpha\") == 0) {\n\t\t\t\tresult_de = 100;\n\t\t\t\ttrack_idx = efp->track_gui->alpha;\n\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\t\t\t\t\n\t\t\t\t//exfunc_64\n\t\t\t\treinterpret_cast<BOOL(__cdecl*)(ExEdit::ObjectFilterIndex, int, int, int*, int)>(GLOBAL::exedit_base + OFS::ExEdit::exfunc_64)(ps, frame, subframe, &result_nu, track_idx + 1);\n\t\t\t\tlua_pushnumber(L, 1. - result_nu * 0.001);\n\t\t\t\t\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\telse if (lstrcmpiA(target, \"aspect\") == 0) {\n\t\t\t\tresult_de = 1000;\n\t\t\t\ttrack_idx = efp->track_gui->aspect;\n\t\t\t\tif (track_idx < 0) return lua_pushnumber(L, 0), 1;\n\t\t\t}\n\t\t\telse if (lstrcmpiA(target, \"time\") == 0) {\n\t\t\t\tlua_pushnumber(L, (subframe * 0.01 + (double)(frame - ScriptProcessingFilter->frame_start_chain)) * (double)efpip->framerate_de / (double)efpip->framerate_nu);\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\telse return 0;\n#endif\n\n\t\t\treinterpret_cast<BOOL(__cdecl*)(ExEdit::ObjectFilterIndex, int, int, int*, int)>(GLOBAL::exedit_base + OFS::ExEdit::exfunc_64)(ps, frame, subframe, &result_nu, track_idx + 1);\n\t\t}\n\t\tlua_pushnumber(L, static_cast<double>(result_nu) / static_cast<double>(result_de));\n\t\treturn 1;\n\t}\n\n\tint __cdecl lua_getvalueex_t::lua_getvalueex_main(lua_State* L) {\n\t\t\n\n\t\treturn 1;\n\t}\n} // namespace patch\n#endif // #ifdef PATCH_SWITCH_GETVALUEEX\n"
  },
  {
    "path": "patch/patch_lua_getvalueex.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_LUA_GETVALUE\n\n#include <exedit.hpp>\n\n#include \"global.hpp\"\n#include \"util.hpp\"\n#include \"config_rw.hpp\"\n\n#include \"mylua.hpp\"\n\nnamespace patch {\n\t// obj.getvalue で中心座標をもらえるようにする\n\tinline class lua_getvalueex_t {\n\t\tstatic int __cdecl lua_getvalue_override(lua_State* L);\n\n\t\t// index\n\t\tstatic int __cdecl lua_getvalueex_main(lua_State* L);\n\n\t\tbool enabled = true;\n\t\tbool enabled_i;\n\t\tinline static const char key[] = \"lua.getvalue\";\n\n\tpublic:\n\t\tvoid init() {\n\t\t\tenabled_i = enabled;\n\t\t}\n\n\t\tinline static void require(lua_State* L) {\n\t\t\tlua_pushcfunction(L, &lua_getvalue_override);\n\t\t\tlua_setfield(L, -2, \"getvalue\");\n\n\t\t\tlua_pushcfunction(L, &lua_getvalueex_main);\n\t\t\tlua_setfield(L, -2, \"getvalueex\");\n\t\t}\n\n\t\tvoid switching(bool flag) {\n\t\t\tenabled = flag;\n\t\t}\n\n\t\tbool is_enabled() { return enabled; }\n\t\tbool is_enabled_i() { return enabled_i; }\n\n\t\t\n        void switch_load(ConfigReader& cr) {\n            cr.regist(key, [this](json_value_s* value) {\n                ConfigReader::load_variable(value, enabled);\n            });\n        }\n\n        void switch_store(ConfigWriter& cw) {\n            cw.append(key, enabled);\n        }\n\n\t} lua_getvalueex;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_LUA_GETVALUE\n"
  },
  {
    "path": "patch/patch_lua_rand.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_lua_rand.hpp\"\n#ifdef PATCH_SWITCH_LUA_RAND\n\n#include <exedit/FilterProcInfo.hpp>\n\n#include \"global.hpp\"\n#include \"offset_address.hpp\"\n\nnamespace patch {\n    int lua_rand_t::l_rand_overwrite(lua_State* L) {\n        int s = luaL_checkinteger(L, 1);\n        int e = luaL_checkinteger(L, 2);\n        if (s > e) std::swap(s, e);\n\n        int seed, time;\n\n        if (auto efpip = load_i32<ExEdit::FilterProcInfo*>(GLOBAL::exedit_base + OFS::ExEdit::efpip_g); efpip != nullptr) {\n            seed = efpip->obj_layerp->layer_set * 1913 ^ efpip->obj_index * 757;\n            time = efpip->frame - efpip->object_start_frame;\n        }else {\n            seed = load_i32<int>(GLOBAL::exedit_base + OFS::ExEdit::TraScript_ProcessingObjectIndex) * 1913 ^ load_i32<int>(GLOBAL::exedit_base + OFS::ExEdit::TraScript_ProcessingTrackBarIndex) * 757;\n            time = static_cast<int>(load_i64<double>(GLOBAL::exedit_base + OFS::ExEdit::TraScript_Time));\n        }\n        auto n = lua_gettop(L);\n        if(n > 2) {\n            auto seed_a = luaL_checkinteger(L, 3);\n            if(seed_a < 0) seed = -seed_a;\n            else seed += seed_a;\n\n            if(n > 3) time = luaL_checkinteger(L, 4);\n        }\n\n        auto a = seed + (time << 7 ^ time >> 2 ^ time);\n        auto b = (a * 73 ^ 326881591) + a % 7213 + a;\n        auto c = b ^ b * 128 ^ (int)b >> 2;\n        auto d = (int)((int)c >> 0x10 ^ c);\n\n        if (s == (std::numeric_limits<int>::min)() && e == (std::numeric_limits<int>::max)()) lua_pushinteger(L, d);\n        else lua_pushinteger(L, s + d % (e - s + 1));\n\n        return 1;\n    }\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_LUA_RAND\n"
  },
  {
    "path": "patch/patch_lua_rand.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_LUA_RAND\n\n#include \"config_rw.hpp\"\n\n#include \"mylua.hpp\"\n\nnamespace patch {\n    // rand関数が0除算例外になるパターンを潰す\n    inline class lua_rand_t {\n        static int l_rand_overwrite(lua_State* L);\n\n        bool enabled = true;\n        bool enabled_i;\n        inline static const char key[] = \"lua.rand\";\n\n    public:\n        void init() {\n            enabled_i = enabled;\n        }\n\n        static void require(lua_State* L) {\n            lua_pushcfunction(L, &l_rand_overwrite);\n            lua_setfield(L, -3, \"rand\");\n            lua_pushcfunction(L, &l_rand_overwrite);\n            lua_setfield(L, -2, \"rand\");\n        }\n\n        void switching(bool flag) {\n            enabled = flag;\n        }\n\n        bool is_enabled() { return enabled; }\n        bool is_enabled_i() { return enabled_i; }\n\n        void switch_load(ConfigReader& cr) {\n            cr.regist(key, [this](json_value_s* value) {\n                ConfigReader::load_variable(value, enabled);\n            });\n        }\n\n        void switch_store(ConfigWriter& cw) {\n            cw.append(key, enabled);\n        }\n\n    } lua_rand;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_LUA_RAND\n"
  },
  {
    "path": "patch/patch_lua_randex.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_lua_randex.hpp\"\n#ifdef PATCH_SWITCH_LUA_RANDEX\n\n#include <exedit/FilterProcInfo.hpp>\n\n#include \"util_magic.hpp\"\n#include \"offset_address.hpp\"\n\nnamespace patch {\n\n    int lua_randex_t::l_randex(lua_State* L) {\n        int seed, time;\n\n        if (auto efpip = *(ExEdit::FilterProcInfo**)(GLOBAL::exedit_base + OFS::ExEdit::efpip_g); efpip != nullptr) {\n            seed = efpip->obj_layerp->layer_set * 1913 ^ efpip->obj_index * 757;\n            time = efpip->frame - efpip->object_start_frame;\n        }\n        else {\n            seed = load_i32<int>(GLOBAL::exedit_base + OFS::ExEdit::TraScript_ProcessingObjectIndex) * 1913 ^ load_i32<int>(GLOBAL::exedit_base + OFS::ExEdit::TraScript_ProcessingTrackBarIndex) * 757;\n            time = static_cast<int>(load_i64<double>(GLOBAL::exedit_base + OFS::ExEdit::TraScript_Time));\n        }\n        auto n = lua_gettop(L);\n        if (n > 0) {\n            auto seed_a = luaL_checkinteger(L, 1);\n            if (seed_a < 0) seed = -seed_a;\n            else seed += seed_a;\n\n            if (n > 1) time = luaL_checkinteger(L, 2);\n        }\n\n        create_object(L, seed, time);\n\n        return 1;\n    }\n#endif\n}"
  },
  {
    "path": "patch/patch_lua_randex.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_LUA_RANDEX\n\n#include <bit>\n\n#include \"config_rw.hpp\"\n\n#include \"mylua.hpp\"\n\nnamespace patch {\n    // 正しい乱数分布になるようなrandexクラスを追加\n    inline class lua_randex_t {\n        struct Xoshiro128pp {\n            uint32_t s[4];\n            Xoshiro128pp(unsigned int seed1, unsigned int seed2) : s{ seed1,seed2,1000000007,998244353 } {\n                for (int i = 0; i < 32; i++) calc();\n            }\n            uint32_t calc() {\n                auto ret = std::rotl(s[0] + s[3], 7) + s[0];\n                auto t = s[1] << 9;\n                s[2] ^= s[0];\n                s[3] ^= s[1];\n                s[1] ^= s[2];\n                s[0] ^= s[3];\n\n                s[2] ^= t;\n                s[3] = std::rotl(s[3], 11);\n                return ret;\n            }\n            int calc(int s, int e) {\n                auto r = calc();\n                if (s > e) std::swap(s, e);\n                if (s == (std::numeric_limits<int>::min)() && e == (std::numeric_limits<int>::max)()) return std::bit_cast<int>(r);\n                return s + r % (e - s + 1);\n            }\n        };\n\n        static int l_randex(lua_State* L);\n\n        static void setmetatable(lua_State* L, int index) {\n            luaL_getmetatable(L, \"randex\");\n            lua_setmetatable(L, index > 0 ? index : index - 1);\n        }\n\n        static Xoshiro128pp* create_object(lua_State* L, int seed, int time) {\n            auto udata = lua_newuserdata(L, sizeof(Xoshiro128pp));\n            auto rnd = new(udata) Xoshiro128pp(seed, time);\n            setmetatable(L, -1);\n            return rnd;\n        }\n\n        bool enabled = true;\n        bool enabled_i;\n        inline static const char key[] = \"lua.randex\";\n    public:\n        void init() {\n            enabled_i = enabled;\n        }\n\n        static void require(lua_State* L) {\n            luaL_newmetatable(L, \"randex\");\n            lua_pushcclosure(L, [](lua_State* L) {\n                auto rnd = static_cast<Xoshiro128pp*>(lua_touserdata(L, 1));\n                int s = luaL_checkinteger(L, 2);\n                int e = luaL_checkinteger(L, 3);\n                lua_pushinteger(L, rnd->calc(s, e));\n                return 1;\n            }, 0);\n            lua_setfield(L, -2, \"__call\");\n\n            lua_pop(L, 1);\n\n\n            lua_pushcfunction(L, l_randex);\n            lua_setfield(L, -3, \"randex\");\n            lua_pushcfunction(L, l_randex);\n            lua_setfield(L, -2, \"randex\");\n        }\n\n        void switching(bool flag) {\n            enabled = flag;\n        }\n\n        bool is_enabled() { return enabled; }\n        bool is_enabled_i() { return enabled_i; }\n        \n        void switch_load(ConfigReader& cr) {\n            cr.regist(key, [this](json_value_s* value) {\n                ConfigReader::load_variable(value, enabled);\n            });\n        }\n\n        void switch_store(ConfigWriter& cw) {\n            cw.append(key, enabled);\n        }\n    } lua_randex;\n}\n#endif\n"
  },
  {
    "path": "patch/patch_obj_colorcorrection.cpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"patch_obj_colorcorrection.hpp\"\r\n\r\n#include <numbers>\r\n\r\n#ifdef PATCH_SWITCH_OBJ_COLORCORRECTION\r\nnamespace patch {\r\n    /**/\r\n    void rgb2hsv_12(int r, int g, int b, int* h, int* s, int* v) {\r\n        int rgbmax = (std::max)({ r, g, b });\r\n        int rgbsub = rgbmax - (std::min)({ r, g, b });\r\n        if (rgbsub) {\r\n            if (rgbmax == r) {\r\n                *h = 600 * (g - b) / rgbsub;\r\n            } else if (rgbmax == g) {\r\n                *h = 600 * (b - r) / rgbsub + 1200;\r\n            } else {\r\n                *h = 600 * (r - g) / rgbsub + 2400;\r\n            }\r\n            if (rgbmax) {\r\n                *s = 4096 * rgbsub / rgbmax;\r\n            } else {\r\n                *s = 0;\r\n            }\r\n        } else {\r\n            *h = 0;\r\n            *s = 0;\r\n        }\r\n        *v = rgbmax;\r\n    }\r\n    /*/\r\n    void rgb2hsv_12(int r, int g, int b, int* h, int* s, int* v) {\r\n        constexpr auto half_sqrt3 = 0.86602540378443864676372317075294;\r\n\r\n        const auto vx = (r * 2 - (g + b)) * .5;\r\n        const auto vy = (g - b) * half_sqrt3;\r\n\r\n        const auto ht = static_cast<int>(std::round(std::atan2(vy, vx) * (3600 / (std::numbers::pi * 2))));\r\n        if (ht < 0) *h = ht + 3600;\r\n        else *h = ht;\r\n\r\n        const auto mx = (std::max)({ r,g,b });\r\n        const auto mn = (std::min)({ r,g,b });\r\n\r\n        if (mx) {\r\n            *s = (mx - mn) * 4096 / mx;\r\n        }\r\n        else {\r\n            *s = 0;\r\n        }\r\n        *v = mx;\r\n\r\n    }\r\n    //*/\r\n    void yc2rgb_12(int y, int cb, int cr, int* r, int* g, int* b) {\r\n        *r = y + (cr * 11485 >> 13);\r\n        *g = y - ((cb * 2818 + cr * 5849) >> 13);\r\n        *b = y + (cb * 14516 >> 13);\r\n    }\r\n    void yc2hsv_12(int y, int cb, int cr, int* h, int* s, int* v) {\r\n        int r, g, b;\r\n        yc2rgb_12(y, cb, cr, &r, &g, &b);\r\n        rgb2hsv_12(r, g, b, h, s, v);\r\n    }\r\n\r\n    /**/\r\n    void hsv2rgb_12(int h, int s, int v, int* r, int* g, int* b) {\r\n        h %= 3600;\r\n        if (h < 0) {\r\n            h += 3600;\r\n        }\r\n\r\n        int tmp = v * s;\r\n        int rgbmin = v - (tmp >> 12);\r\n\r\n        switch (h / 600) {\r\n        case 0:\r\n            *r = v;\r\n            *g = v - (tmp / 75 * (600 - h) >> 15);\r\n            *b = rgbmin;\r\n            break;\r\n        case 1:\r\n            *r = v - (tmp / 75 * (h - 600) >> 15);\r\n            *g = v;\r\n            *b = rgbmin;\r\n            break;\r\n        case 2:\r\n            *r = rgbmin;\r\n            *g = v;\r\n            *b = v - (tmp / 75 * (1800 - h) >> 15);\r\n            break;\r\n        case 3:\r\n            *r = rgbmin;\r\n            *g = v - (tmp / 75 * (h - 1800) >> 15);\r\n            *b = v;\r\n            break;\r\n        case 4:\r\n            *r = v - (tmp / 75 * (3000 - h) >> 15);\r\n            *g = rgbmin;\r\n            *b = v;\r\n            break;\r\n        case 5:\r\n            *r = v;\r\n            *g = rgbmin;\r\n            *b = v - (tmp / 75 * (h - 3000) >> 15);\r\n            break;\r\n        }\r\n    }\r\n    /*/\r\n    void hsv2rgb_12(int h, int s, int v, int* r, int* g, int* b) {\r\n        h %= 3600;\r\n\r\n        const auto mx = v;\r\n        const auto mn = v * (4096 - s) / 4096;\r\n\r\n        const auto mxf = mx / 4096.;\r\n        const auto mnf = mn / 4096.;\r\n\r\n        constexpr auto pi = std::numbers::pi;\r\n\r\n        const auto h_rad = h * (pi * 2 / 3600.);\r\n        const auto sinh = std::sin(h_rad);\r\n        const auto cosh = std::cos(h_rad);\r\n\r\n        constexpr auto sqrt3_d2 = .86602540378443864676372317075294;\r\n\r\n        const auto ar = sinh;\r\n        const auto ag = cosh * sqrt3_d2 + sinh * .5;\r\n        const auto ab = cosh * sqrt3_d2 - sinh * .5;\r\n\r\n        double rf, gf, bf;\r\n        if (h_rad < pi / 3) {\r\n            *r = mx;\r\n            *b = mn;\r\n            rf = mxf;\r\n            bf = mnf;\r\n            gf = (ar * rf + ab * bf) / ag;\r\n            *g = static_cast<int>(std::round(gf * 4096));\r\n        }\r\n        else if (h_rad < pi * 2 / 3) {\r\n            *g = mx;\r\n            *b = mn;\r\n            gf = mxf;\r\n            bf = mnf;\r\n            rf = (ag * gf - ab * bf) / ar;\r\n            *r = static_cast<int>(std::round(rf * 4096));\r\n        }\r\n        else if (h_rad < pi) {\r\n            *g = mx;\r\n            *r = mn;\r\n            gf = mxf;\r\n            rf = mnf;\r\n            bf = (ag * gf - ar * rf) / ab;\r\n            *b = static_cast<int>(std::round(bf * 4096));\r\n        }\r\n        else if (h_rad < pi * 4 / 3) {\r\n            *b = mx;\r\n            *r = mn;\r\n            bf = mxf;\r\n            rf = mnf;\r\n            gf = (ar * rf + ab * bf) / ag;\r\n            *g = static_cast<int>(std::round(gf * 4096));\r\n        }\r\n        else if (h_rad < pi * 5 / 3) {\r\n            *b = mx;\r\n            *g = mn;\r\n            bf = mxf;\r\n            gf = mnf;\r\n            rf = (ag * gf - ab * bf) / ar;\r\n            *r = static_cast<int>(std::round(rf * 4096));\r\n        }\r\n        else {\r\n            *r = mx;\r\n            *g = mn;\r\n            rf = mxf;\r\n            gf = mnf;\r\n            bf = (ag * gf - ar * rf) / ab;\r\n            *b = static_cast<int>(std::round(bf * 4096));\r\n        }\r\n    }\r\n    //*/\r\n\r\n    void rgb2yc_12(int r, int g, int b, int* y, int* cb, int* cr) {\r\n        *y  = (r *  4898 + g *  9617 + b *  1867) >> 14;\r\n        *cb = (r * -2768 + g * -5423 + b *  8192) >> 14;\r\n        *cr = (r *  8192 + g * -6864 + b * -1327) >> 14;\r\n    }\r\n    void hsv2yc_12(int h, int s, int v, int* y, int* cb, int* cr) {\r\n        int r, g, b;\r\n        hsv2rgb_12(h, s, v, &r, &g, &b);\r\n        rgb2yc_12(r, g, b, y, cb, cr);\r\n    }\r\n\r\n\r\n\tvoid __cdecl obj_ColorCorrection_t::rot_hue(ExEdit::PixelYC* pix, int angle10, int luminance, int brightness, int saturation) {\r\n\t\tint h, s, v;\r\n\t\tyc2hsv_12(pix->y, pix->cb, pix->cr, &h, &s, &v);\r\n\t\th += angle10;\r\n\t\tint y, cb, cr;\r\n\t\thsv2yc_12(h, s, v, &y, &cb, &cr);\r\n\r\n\t\tpix->y = (y * luminance >> 8) + brightness;\r\n\t\tpix->cb = cb * saturation >> 8;\r\n\t\tpix->cr = cr * saturation >> 8;\r\n\r\n\t}\r\n\r\n\tvoid __cdecl obj_ColorCorrection_t::rot_hue_sat(ExEdit::PixelYC* pix, int angle10, int luminance, int brightness, int saturation) {\r\n\t\trot_hue(pix, angle10, luminance, brightness, saturation);\r\n\t\tif (pix->y < 0) {\r\n\t\t\tint ysub = pix->y + 0x400;\r\n\t\t\tif (0 < ysub) {\r\n\t\t\t\tpix->cb = ysub * pix->cb >> 10;\r\n\t\t\t\tpix->cr = ysub * pix->cr >> 10;\r\n\t\t\t} else {\r\n\t\t\t\tpix->cb = pix->cr = 0;\r\n\t\t\t}\r\n\t\t\tpix->y = 0;\r\n\t\t} else if (0x2000 < pix->y) {\r\n\t\t\tint ysub = 0x3000 - pix->y;\r\n\t\t\tif (0 < ysub) {\r\n\t\t\t\tpix->cb = ysub * pix->cb >> 12;\r\n\t\t\t\tpix->cr = ysub * pix->cr >> 12;\r\n\t\t\t} else {\r\n\t\t\t\tpix->cb = pix->cr = 0;\r\n\t\t\t}\r\n\t\t\tpix->y = 0x2000;\r\n\t\t}\r\n\t}\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_OBJ_COLORCORRECTION\r\n"
  },
  {
    "path": "patch/patch_obj_colorcorrection.hpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_OBJ_COLORCORRECTION\r\n\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util.hpp\"\r\n\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch {\r\n\r\n    // init at exedit load\r\n    // 色調補正の色相計算が正しくないのを修正\r\n\r\n    inline class obj_ColorCorrection_t {\r\n\r\n        static void rot_hue(ExEdit::PixelYC* pix, int angle10, int luminance, int brightness, int saturation);\r\n        static void rot_hue_sat(ExEdit::PixelYC* pix, int angle10, int luminance, int brightness, int saturation);\r\n        bool enabled = true;\r\n        bool enabled_i;\r\n        inline static const char key[] = \"obj_colorcorrection\";\r\n    public:\r\n        void init() {\r\n            enabled_i = enabled;\r\n\r\n            if (!enabled_i)return;\r\n\r\n            { // メディアオブジェクト\r\n                char code_effect[] =\r\n                    \"\\x8b\\x44\\x24\\x2c\"         // mov     eax,dword ptr [esp+2c] ; efp\r\n                    \"\\x8b\\x48\\x44\"             // mov     ecx,dword ptr [eax+44] ; efp->track\r\n                    \"\\x8b\\x41\\x08\"             // mov     eax,dword ptr [ecx+08] ; efp->track[2]\r\n                    \"\\x53\"                     // push    ebx\r\n                    \"\\x57\"                     // push    edi\r\n                    \"\\xff\\x74\\x24\\x38\"         // push    dword ptr [esp+38]\r\n                    \"\\x50\"                     // push    eax\r\n                    \"\\x56\"                     // push    esi\r\n                    \"\\xe8XXXX\"                 // call    rot_hue()\r\n                    \"\\x83\\xc4\\x14\"             // add     esp,+14\r\n                    \"\\xe9\\x8d\\x00\\x00\\x00\"     // jmp     10014996\r\n                    ;\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x148ea, sizeof(code_effect) - 1);\r\n                memcpy(reinterpret_cast<void*>(h.address()), code_effect, sizeof(code_effect) - 1);\r\n                h.replaceNearJmp(19, rot_hue);\r\n            }\r\n\r\n\r\n            { // メディアオブジェクト // 飽和する\r\n                {\r\n                    char code_effect_sat[] =\r\n                        \"\\x8b\\x44\\x24\\x34\"         // mov     eax,dword ptr [esp+34] ; efp\r\n                        \"\\x8b\\x48\\x44\"             // mov     ecx,dword ptr [eax+44] ; efp->track\r\n                        \"\\x8b\\x41\\x08\"             // mov     eax,dword ptr [ecx+08] ; efp->track[2]\r\n                        \"\\xff\\x74\\x24\\x2c\"         // push    dword ptr [esp+2c]\r\n                        \"\\xff\\x74\\x24\\x28\"         // push    dword ptr [esp+28]\r\n                        \"\\xff\\x74\\x24\\x18\"         // push    dword ptr [esp+18]\r\n                        \"\\x50\"                     // push    eax\r\n                        \"\\x53\"                     // push    ebx\r\n                        \"\\xe8XXXX\"                 // call    rot_hue_sat()\r\n                        \"\\x83\\xc4\\x14\"             // add     esp,+14\r\n                        \"\\x8b\\x44\\x24\\x38\"         // mov     eax,dword ptr [esp+38] ; efpip\r\n                        \"\\xe9\\xea\\x00\\x00\\x00\"     // jmp     10014f8c\r\n                        ;\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x14e79, sizeof(code_effect_sat) - 1);\r\n                    memcpy(reinterpret_cast<void*>(h.address()), code_effect_sat, sizeof(code_effect_sat) - 1);\r\n                    h.replaceNearJmp(25, rot_hue_sat);\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x14e3b, 1);\r\n                    h.store_i8(0, 0x1c);\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x14fa9, 1);\r\n                    h.store_i8(0, 0x1c);\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x14fb4, 1);\r\n                    h.store_i8(0, 0x1c);\r\n                }\r\n            }\r\n\r\n\r\n            { // フィルタオブジェクト\r\n                char code_filter[] =\r\n                    \"\\x8b\\x44\\x24\\x2c\"         // mov     eax,dword ptr [esp+2c] ; efp\r\n                    \"\\x8b\\x48\\x44\"             // mov     ecx,dword ptr [eax+44] ; efp->track\r\n                    \"\\x8b\\x41\\x08\"             // mov     eax,dword ptr [ecx+08] ; efp->track[2]\r\n                    \"\\x57\"                     // push    edi\r\n                    \"\\x55\"                     // push    ebp\r\n                    \"\\xff\\x74\\x24\\x38\"         // push    dword ptr [esp+38]\r\n                    \"\\x50\"                     // push    eax\r\n                    \"\\x56\"                     // push    esi\r\n                    \"\\xe8XXXX\"                 // call    rot_hue()\r\n                    \"\\x83\\xc4\\x14\"             // add     esp,+14\r\n                    \"\\x8b\\x4c\\x24\\x18\"         // mov     ecx,dword ptr [esp+18] ; x\r\n                    \"\\x83\\xc6\\x06\"             // add     esi,+06\r\n                    \"\\xe9\\x8e\\x00\\x00\\x00\"     // jmp     10014c67\r\n                    ;\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x14bb3, sizeof(code_filter) - 1);\r\n                memcpy(reinterpret_cast<void*>(h.address()), code_filter, sizeof(code_filter) - 1);\r\n                h.replaceNearJmp(19, rot_hue);\r\n            }\r\n\r\n\r\n            { // フィルタオブジェクト 飽和する\r\n                {\r\n                    char code_filter_sat[] =\r\n                        \"\\x8b\\x44\\x24\\x34\"         // mov     eax,dword ptr [esp+34] ; efp\r\n                        \"\\x8b\\x48\\x44\"             // mov     ecx,dword ptr [eax+44] ; efp->track\r\n                        \"\\x8b\\x41\\x08\"             // mov     eax,dword ptr [ecx+08] ; efp->track[2]\r\n                        \"\\xff\\x74\\x24\\x10\"         // push    dword ptr [esp+10]\r\n                        \"\\xff\\x74\\x24\\x28\"         // push    dword ptr [esp+28]\r\n                        \"\\xff\\x74\\x24\\x34\"         // push    dword ptr [esp+34]\r\n                        \"\\x50\"                     // push    eax\r\n                        \"\\x53\"                     // push    ebx\r\n                        \"\\xe8XXXX\"                 // call    rot_hue_sat()\r\n                        \"\\x83\\xc4\\x14\"             // add     esp,+14\r\n                        \"\\x8b\\x4c\\x24\\x30\"         // mov     ecx,dword ptr [esp+30]\r\n                        \"\\x8b\\x44\\x24\\x38\"         // mov     eax,dword ptr [esp+38] ; efpip\r\n                        \"\\xe9\\xea\\x00\\x00\\x00\"     // jmp     10015354\r\n                        ;\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x1523d, sizeof(code_filter_sat) - 1);\r\n                    memcpy(reinterpret_cast<void*>(h.address()), code_filter_sat, sizeof(code_filter_sat) - 1);\r\n                    h.replaceNearJmp(25, rot_hue_sat);\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x15210, 1);\r\n                    h.store_i8(0, 0x1c);\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x1536e, 1);\r\n                    h.store_i8(0, 0x1c);\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x1537b, 1);\r\n                    h.store_i8(0, 0x1c);\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x1545e, 1);\r\n                    h.store_i8(0, 0x1c);\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x15469, 1);\r\n                    h.store_i8(0, 0x1c);\r\n                }\r\n            }\r\n\r\n        }\r\n\r\n        void switching(bool flag) {\r\n            enabled = flag;\r\n        }\r\n\r\n        bool is_enabled() { return enabled; }\r\n        bool is_enabled_i() { return enabled_i; }\r\n\r\n        void switch_load(ConfigReader& cr) {\r\n            cr.regist(key, [this](json_value_s* value) {\r\n                ConfigReader::load_variable(value, enabled);\r\n                });\r\n        }\r\n\r\n        void switch_store(ConfigWriter& cw) {\r\n            cw.append(key, enabled);\r\n        }\r\n    } ColorCorrection;\r\n} // namespace patch\r\n\r\n#endif // ifdef PATCH_SWITCH_OBJ_COLORCORRECTION\r\n"
  },
  {
    "path": "patch/patch_obj_glow.hpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_OBJ_GLOW\r\n\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util.hpp\"\r\n\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch {\r\n\r\n    // init at exedit load\r\n    // グローのバグ修正\r\n\r\n    /* オフセットアドレス exedit + 55625 の修正\r\n        曲線移動などで しきい値 が負の数になった時にエラーが出る\r\n    */\r\n\r\n    /* 小さいオブジェクトに効果が無いのを修正\r\n        スレッド数より小さいオブジェクトに効果が乗らない\r\n    */\r\n\r\n\r\n    inline class obj_Glow_t {\r\n\r\n        bool enabled = true;\r\n        bool enabled_i;\r\n        inline static const char key[] = \"obj_glow\";\r\n    public:\r\n\r\n\r\n        void init() {\r\n            enabled_i = enabled;\r\n\r\n            if (!enabled_i)return;\r\n\r\n            { // オフセットアドレス exedit + 55625 の修正\r\n\r\n                auto& cursor = GLOBAL::executable_memory_cursor;\r\n\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x054ed5, 6);\r\n                h.store_i16(0, '\\x90\\xe8');\r\n                h.replaceNearJmp(2, cursor);\r\n                /*\r\n                    10054ed5 8b4908             mov     ecx,dword ptr [ecx+08]\r\n                    10054ed8 c1e10c             shl     ecx,0c\r\n                    ↓\r\n                    10054ed5 90                 nop\r\n                    10054ed6 e8xXxXxXxX         call    &executable_memory_cursor\r\n\r\n                    ; しきい値 track[2] が0未満の時に0にする\r\n                */\r\n\r\n                static const char code_put[] =\r\n                    \"\\x8b\\x49\\x08\"             // mov     ecx,dword ptr [ecx+08]\r\n                    \"\\x85\\xc9\"                 // test    ecx,ecx\r\n                    \"\\x7c\\x04\"                 // jl      skip,4\r\n                    \"\\xc1\\xe1\\x0c\"             // shl     ecx,0c\r\n                    \"\\xc3\"                     // ret\r\n                    \"\\x33\\xc9\"                 // xor     ecx,ecx\r\n                    \"\\xc3\"                     // ret\r\n                    ;\r\n\r\n                memcpy(cursor, code_put, sizeof(code_put) - 1);\r\n                cursor += sizeof(code_put) - 1;\r\n            }\r\n\r\n            \r\n            { // 小さいオブジェクトに効果が無いのを修正\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x055572, 2);\r\n                    h.store_i16(0, '\\xeb\\x0a');\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x0556c0, 2);\r\n                    h.store_i16(0, '\\xeb\\x0a');\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x0557d0, 2);\r\n                    h.store_i16(0, '\\xeb\\x0a');\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x055910, 2);\r\n                    h.store_i16(0, '\\xeb\\x0a');\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x055a54, 1);\r\n                    h.store_i8(0, '\\xeb');\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x055cb6, 1);\r\n                    h.store_i8(0, '\\xeb');\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x055f0e, 2);\r\n                    h.store_i16(0, '\\xeb\\x0a');\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x056258, 1);\r\n                    h.store_i8(0, '\\xeb');\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x056a18, 1);\r\n                    h.store_i8(0, '\\xeb');\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x05710c, 1);\r\n                    h.store_i8(0, '\\xeb');\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x05776d, 1);\r\n                    h.store_i8(0, '\\xeb');\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x057dcc, 1);\r\n                    h.store_i8(0, '\\xeb');\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x05846c, 1);\r\n                    h.store_i8(0, '\\xeb');\r\n                }\r\n            }\r\n\r\n        }\r\n\r\n        void switching(bool flag) {\r\n            enabled = flag;\r\n        }\r\n\r\n        bool is_enabled() { return enabled; }\r\n        bool is_enabled_i() { return enabled_i; }\r\n\r\n        void switch_load(ConfigReader& cr) {\r\n            cr.regist(key, [this](json_value_s* value) {\r\n                ConfigReader::load_variable(value, enabled);\r\n                });\r\n        }\r\n\r\n        void switch_store(ConfigWriter& cw) {\r\n            cw.append(key, enabled);\r\n        }\r\n    } Glow;\r\n} // namespace patch\r\n\r\n#endif // ifdef PATCH_SWITCH_OBJ_GLOW\r\n"
  },
  {
    "path": "patch/patch_obj_lensblur.cpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"patch_obj_lensblur.hpp\"\r\n\r\n#ifdef PATCH_SWITCH_OBJ_LENSBLUR\r\nnamespace patch {\r\n\tvoid* __cdecl obj_LensBlur_t::lbResize_709a0_wrap_12809(void* pix_edit, int w0, int h0, int w1, int h1, void* pix_temp) {\r\n\t\tif (w0 && h0 && w1 && h1) {\r\n\t\t\treturn reinterpret_cast<void* (__cdecl*)(void*, int, int, int, int, void*)>(GLOBAL::exedit_base + 0x0709a0)(pix_edit, w0, h0, w1, h1, pix_temp);\r\n\t\t}\r\n\t\treturn pix_edit;\r\n\t}\r\n\r\n\tvoid* __cdecl obj_LensBlur_t::lbResize_71420_wrap_126a6(void* pix_edit, int w0, int h0, int w1, int h1, void* pix_temp) {\r\n\t\tif (w0 && h0 && w1 && h1) {\r\n\t\t\treturn reinterpret_cast<void* (__cdecl*)(void*, int, int, int, int, void*)>(GLOBAL::exedit_base + 0x071420)(pix_edit, w0, h0, w1, h1, pix_temp);\r\n\t\t}\r\n\t\treturn pix_edit;\r\n\t}\r\n\r\n\r\n\tvoid __cdecl obj_LensBlur_t::lbResize_set_w_end(void* dst, void* src, int w, int h, int back) {\r\n\t\tlbResize_wh_end = w - 1;\r\n\t}\r\n\tvoid __cdecl obj_LensBlur_t::lbResize_set_h_end(void* dst, void* src, int w, int h, int back) {\r\n\t\tlbResize_wh_end = h - 1;\r\n\t}\r\n\r\n\r\n\r\n\r\n\tstruct PixelYC_fbb {\r\n\t\tfloat y;\r\n\t\tbyte cb;\r\n\t\tbyte cr;\r\n\t};\r\n\r\n\tvoid obj_LensBlur_t::lbResize_media(int thread_id, int thread_num, int loop1, int forstep1, int loop2, int forstep2, int flag) {\r\n\t\tforstep1 *= sizeof(struct ExEdit::PixelYCA);\r\n\t\tforstep2 *= sizeof(struct ExEdit::PixelYCA);\r\n\t\tint i_end = (thread_id + 1) * loop1 / thread_num;\r\n\t\tfor (int i = thread_id * loop1 / thread_num; i < i_end; i++) {\r\n\t\t\tint ii = lbresize->resize_step * i + (lbresize->resize_step - 0x10000) / 2;\r\n\t\t\tint fraction = ii & 0xffff;\r\n\t\t\tint inv_fraction = 0x10000 - fraction;\r\n\t\t\tii >>= 16;\r\n\t\t\tauto dst = (ExEdit::PixelYCA*)((int)lbresize->resize_temp + i * forstep1);\r\n\t\t\tauto src0 = (ExEdit::PixelYCA*)((int)lbresize->resize_edit + max(0, ii) * forstep1);\r\n\t\t\tauto src1 = (ExEdit::PixelYCA*)((int)lbresize->resize_edit + min(ii + 1, lbResize_wh_end) * forstep1);\r\n\r\n\t\t\tfor (int j = 0; j < loop2; j++) {\r\n\t\t\t\tint src0_a = (src0->a * inv_fraction + 0x800) >> 12;\r\n\t\t\t\tint src1_a = (src1->a * fraction + 0x800) >> 12;\r\n\t\t\t\tint a = src0_a + src1_a;\r\n\t\t\t\tif (a <= 0) {\r\n\t\t\t\t\tdst->y = dst->cb = dst->cr = dst->a = 0;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tif (flag) {\r\n\t\t\t\t\t\t((PixelYC_fbb*)dst)->y = (((PixelYC_fbb*)src0)->y * (float)src0_a + ((PixelYC_fbb*)src1)->y * (float)src1_a) / (float)a;\r\n\t\t\t\t\t\t((PixelYC_fbb*)dst)->cb = (byte)((((PixelYC_fbb*)src0)->cb * src0_a + ((PixelYC_fbb*)src1)->cb * src1_a) / a);\r\n\t\t\t\t\t\t((PixelYC_fbb*)dst)->cr = (byte)((((PixelYC_fbb*)src0)->cr * src0_a + ((PixelYC_fbb*)src1)->cr * src1_a) / a);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tdst->y = (short)((src0->y * src0_a + src1->y * src1_a) / a);\r\n\t\t\t\t\t\tdst->cb = (short)((src0->cb * src0_a + src1->cb * src1_a) / a);\r\n\t\t\t\t\t\tdst->cr = (short)((src0->cr * src0_a + src1->cr * src1_a) / a);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tdst->a = (short)((a + 8) >> 4);\r\n\t\t\t\t}\r\n\t\t\t\tdst = (ExEdit::PixelYCA*)((int)dst + forstep2);\r\n\t\t\t\tsrc0 = (ExEdit::PixelYCA*)((int)src0 + forstep2);\r\n\t\t\t\tsrc1 = (ExEdit::PixelYCA*)((int)src1 + forstep2);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\r\n\tvoid obj_LensBlur_t::lbResize_filter(int thread_id, int thread_num, int loop1, int forstep1, int loop2, int forstep2, int flag) {\r\n\t\tforstep1 *= sizeof(struct AviUtl::PixelYC);\r\n\t\tforstep2 *= sizeof(struct AviUtl::PixelYC);\r\n\t\tint i_end = (thread_id + 1) * loop1 / thread_num;\r\n\t\tfor (int i = thread_id * loop1 / thread_num; i < i_end; i++) {\r\n\t\t\tint ii = lbresize->resize_step * i + (lbresize->resize_step - 0x10000) / 2;\r\n\t\t\tint fraction = ii & 0xffff;\r\n\t\t\tint inv_fraction = 0x10000 - fraction;\r\n\t\t\tii >>= 16;\r\n\t\t\tauto dst = (AviUtl::PixelYC*)((int)lbresize->resize_temp + i * forstep1);\r\n\t\t\tauto src0 = (AviUtl::PixelYC*)((int)lbresize->resize_edit + max(0, ii) * forstep1);\r\n\t\t\tauto src1 = (AviUtl::PixelYC*)((int)lbresize->resize_edit + min(ii + 1, lbResize_wh_end) * forstep1);\r\n\r\n\t\t\tfor (int j = 0; j < loop2; j++) {\r\n\t\t\t\tif (flag) {\r\n\t\t\t\t\t((PixelYC_fbb*)dst)->y = (((PixelYC_fbb*)src0)->y * (float)inv_fraction + ((PixelYC_fbb*)src1)->y * (float)fraction) / 65536.0f;\r\n\t\t\t\t\t((PixelYC_fbb*)dst)->cb = (byte)((((PixelYC_fbb*)src0)->cb * inv_fraction + ((PixelYC_fbb*)src1)->cb * fraction + 0x8000) >> 16);\r\n\t\t\t\t\t((PixelYC_fbb*)dst)->cr = (byte)((((PixelYC_fbb*)src0)->cr * inv_fraction + ((PixelYC_fbb*)src1)->cr * fraction + 0x8000) >> 16);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tdst->y = (short)((src0->y * inv_fraction + src1->y * fraction + 0x8000) >> 16);\r\n\t\t\t\t\tdst->cb = (short)((src0->cb * inv_fraction + src1->cb * fraction + 0x8000) >> 16);\r\n\t\t\t\t\tdst->cr = (short)((src0->cr * inv_fraction + src1->cr * fraction + 0x8000) >> 16);\r\n\t\t\t\t}\r\n\t\t\t\tdst = (AviUtl::PixelYC*)((int)dst + forstep2);\r\n\t\t\t\tsrc0 = (AviUtl::PixelYC*)((int)src0 + forstep2);\r\n\t\t\t\tsrc1 = (AviUtl::PixelYC*)((int)src1 + forstep2);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\r\n\tvoid __cdecl obj_LensBlur_t::lbResize_media_interpolation_y(int thread_id, int thread_num, void* n1, void* n2) {\r\n\t\t// exedit + 70df0 相当\r\n\t\tint exedit_buffer_line = *(int*)(GLOBAL::exedit_base + OFS::ExEdit::exedit_buffer_line);\r\n\t\tlbResize_media(thread_id, thread_num, lbresize->resize_h, exedit_buffer_line, lbresize->resize_w, 1, 0);\r\n\t}\r\n\tvoid __cdecl obj_LensBlur_t::lbResize_media_interpolation_x(int thread_id, int thread_num, void* n1, void* n2) {\r\n\t\t// exedit + 71270 相当\r\n\t\tint exedit_buffer_line = *(int*)(GLOBAL::exedit_base + OFS::ExEdit::exedit_buffer_line);\r\n\t\tlbResize_media(thread_id, thread_num, lbresize->resize_w, 1, lbresize->resize_h, exedit_buffer_line, 0);\r\n\t}\r\n\tvoid __cdecl obj_LensBlur_t::lbResize_media_interpolation_y_fbb(int thread_id, int thread_num, void* n1, void* n2) {\r\n\t\t// exedit + 71870 相当\r\n\t\tint exedit_buffer_line = *(int*)(GLOBAL::exedit_base + OFS::ExEdit::exedit_buffer_line);\r\n\t\tlbResize_media(thread_id, thread_num, lbresize->resize_h, exedit_buffer_line, lbresize->resize_w, 1, 1);\r\n\t}\r\n\tvoid __cdecl obj_LensBlur_t::lbResize_media_interpolation_x_fbb(int thread_id, int thread_num, void* n1, void* n2) {\r\n\t\t// exedit + 71ce0 相当\r\n\t\tint exedit_buffer_line = *(int*)(GLOBAL::exedit_base + OFS::ExEdit::exedit_buffer_line);\r\n\t\tlbResize_media(thread_id, thread_num, lbresize->resize_w, 1, lbresize->resize_h, exedit_buffer_line, 1);\r\n\t}\r\n\tvoid __cdecl obj_LensBlur_t::lbResize_filter_interpolation_y(int thread_id, int thread_num, void* n1, void* n2) {\r\n\t\t// exedit + 72390 相当\r\n\t\tint si_vram_w = *(int*)(GLOBAL::exedit_base + OFS::ExEdit::exedit_YC_vram_w);\r\n\t\tlbResize_filter(thread_id, thread_num, lbresize->resize_h, si_vram_w, lbresize->resize_w, 1, 0);\r\n\t}\r\n\tvoid __cdecl obj_LensBlur_t::lbResize_filter_interpolation_x(int thread_id, int thread_num, void* n1, void* n2) {\r\n\t\t// exedit + 72720 相当\r\n\t\tint si_vram_w = *(int*)(GLOBAL::exedit_base + OFS::ExEdit::exedit_YC_vram_w);\r\n\t\tlbResize_filter(thread_id, thread_num, lbresize->resize_w, 1, lbresize->resize_h, si_vram_w, 0);\r\n\t}\r\n\tvoid __cdecl obj_LensBlur_t::lbResize_filter_interpolation_y_fbb(int thread_id, int thread_num, void* n1, void* n2) {\r\n\t\t// exedit + 72c20 相当\r\n\t\tint si_vram_w = *(int*)(GLOBAL::exedit_base + OFS::ExEdit::exedit_YC_vram_w);\r\n\t\tlbResize_filter(thread_id, thread_num, lbresize->resize_h, si_vram_w, lbresize->resize_w, 1, 1);\r\n\t}\r\n\tvoid __cdecl obj_LensBlur_t::lbResize_filter_interpolation_x_fbb(int thread_id, int thread_num, void* n1, void* n2) {\r\n\t\t// exedit + 72f90 相当\r\n\t\tint si_vram_w = *(int*)(GLOBAL::exedit_base + OFS::ExEdit::exedit_YC_vram_w);\r\n\t\tlbResize_filter(thread_id, thread_num, lbresize->resize_w, 1, lbresize->resize_h, si_vram_w, 1);\r\n\t}\r\n\r\n\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_OBJ_LENSBLUR\r\n"
  },
  {
    "path": "patch/patch_obj_lensblur.hpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_OBJ_LENSBLUR\r\n\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util.hpp\"\r\n\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch {\r\n\r\n    // init at exedit load\r\n    // レンズブラーのエラー修正\r\n    \r\n    /* オフセットアドレス exedit + 71449 の修正\r\n        サイズ２～３の図形にレンズブラーを付けて\r\n        サイズ固定にチェックが入った状態でレンズブラー範囲を広げる\r\n    */\r\n\r\n    /* オフセットアドレス exedit + 71f95 の修正\r\n        フィルタオブジェクトのレンズブラー(範囲を広げたもの)をシーンオブジェクトで読み込む\r\n        シーンオブジェクト以外でエラーはあまり見られないけど他データを破壊していそうなのでそちらもまとめて修正\r\n    */\r\n\r\n    inline class obj_LensBlur_t {\r\n\r\n        static void* __cdecl lbResize_709a0_wrap_12809(void* pix_edit, int w0, int h0, int w1, int h1, void* pix_temp);\r\n        static void* __cdecl lbResize_71420_wrap_126a6(void* pix_edit, int w0, int h0, int w1, int h1, void* pix_temp);\r\n\r\n\r\n\r\n        inline static struct lbResize_var { // 1e42c0\r\n            void* resize_edit;\r\n            int _others1[8];\r\n            void* resize_temp; // 1e42e4\r\n            int _others2[14];\r\n            int resize_step; // 1e4320\r\n            int resize_h; // 1e4324\r\n            int _bufcpy_h; // 1e4328\r\n            int resize_w; // 1e432c\r\n        }*lbresize;\r\n\r\n        inline static int lbResize_wh_end;\r\n\r\n        static void __cdecl lbResize_set_w_end(void* dst, void* src, int w, int h, int back);\r\n        static void __cdecl lbResize_set_h_end(void* dst, void* src, int w, int h, int back);\r\n\r\n        static void lbResize_media(int thread_id, int thread_num, int loop1, int forstep1, int loop2, int forstep2, int flag);\r\n        static void lbResize_filter(int thread_id, int thread_num, int loop1, int forstep1, int loop2, int forstep2, int flag);\r\n\r\n        static void __cdecl lbResize_media_interpolation_y(int thread_id, int thread_num, void* n1, void* n2);\r\n        static void __cdecl lbResize_media_interpolation_x(int thread_id, int thread_num, void* n1, void* n2);\r\n        static void __cdecl lbResize_media_interpolation_y_fbb(int thread_id, int thread_num, void* n1, void* n2);\r\n        static void __cdecl lbResize_media_interpolation_x_fbb(int thread_id, int thread_num, void* n1, void* n2);\r\n        static void __cdecl lbResize_filter_interpolation_y(int thread_id, int thread_num, void* n1, void* n2);\r\n        static void __cdecl lbResize_filter_interpolation_x(int thread_id, int thread_num, void* n1, void* n2);\r\n        static void __cdecl lbResize_filter_interpolation_y_fbb(int thread_id, int thread_num, void* n1, void* n2);\r\n        static void __cdecl lbResize_filter_interpolation_x_fbb(int thread_id, int thread_num, void* n1, void* n2);\r\n\r\n\r\n        bool enabled = true;\r\n        bool enabled_i;\r\n        inline static const char key[] = \"obj_lensblur\";\r\n    public:\r\n\r\n\r\n        void init() {\r\n            enabled_i = enabled;\r\n\r\n            if (!enabled_i)return;\r\n\r\n            { // オフセットアドレス exedit + 71449 の修正\r\n                ReplaceNearJmp(GLOBAL::exedit_base + 0x01280a, &lbResize_709a0_wrap_12809);\r\n                ReplaceNearJmp(GLOBAL::exedit_base + 0x0126a7, &lbResize_71420_wrap_126a6);\r\n            }\r\n\r\n            \r\n            { // オフセットアドレス exedit + 71f95 の修正、なんかやヴぁそうなバグの修正\r\n\r\n                /* 以下の関数にて行われる危険な処理：memcpy( &ycp_edit[-line_size-1], &ycp_edit[-1], (line_size+2) * sizeof(PIXEL_YC));\r\n                    おそらく補間処理を行うための前処理として行われている\r\n                    危険なのでその前処理は全て削除し、ついでにリサイズ前のw,hを取得したいので置き換える\r\n                */\r\n                ReplaceNearJmp(GLOBAL::exedit_base + 0x070a08, &lbResize_set_h_end);\r\n                ReplaceNearJmp(GLOBAL::exedit_base + 0x070aab, &lbResize_set_w_end);\r\n                ReplaceNearJmp(GLOBAL::exedit_base + 0x071488, &lbResize_set_h_end);\r\n                ReplaceNearJmp(GLOBAL::exedit_base + 0x07152b, &lbResize_set_w_end);\r\n                ReplaceNearJmp(GLOBAL::exedit_base + 0x072068, &lbResize_set_h_end);\r\n                ReplaceNearJmp(GLOBAL::exedit_base + 0x07210b, &lbResize_set_w_end);\r\n                ReplaceNearJmp(GLOBAL::exedit_base + 0x0728d8, &lbResize_set_h_end);\r\n                ReplaceNearJmp(GLOBAL::exedit_base + 0x07297b, &lbResize_set_w_end);\r\n\r\n                lbresize = (lbResize_var*)(GLOBAL::exedit_base + 0x1e42c0);\r\n\r\n                /* 前処理が無くても同じように動くように書いたものに置き換える\r\n                    リソースのことを考えて関数はできるだけ纏めた\r\n                    x方向の処理が従来より効率が良いのでそんなに速度が落ちることは無いはず\r\n                */\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x070a3f, 4);\r\n                    h.store_i32(0, &lbResize_media_interpolation_y);\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x070ac5, 4);\r\n                    h.store_i32(0, &lbResize_media_interpolation_x);\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x0714bf, 4);\r\n                    h.store_i32(0, &lbResize_media_interpolation_y_fbb);\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x071545, 4);\r\n                    h.store_i32(0, &lbResize_media_interpolation_x_fbb);\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x07209f, 4);\r\n                    h.store_i32(0, &lbResize_filter_interpolation_y);\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x072125, 4);\r\n                    h.store_i32(0, &lbResize_filter_interpolation_x);\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x07290f, 4);\r\n                    h.store_i32(0, &lbResize_filter_interpolation_y_fbb);\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x072995, 4);\r\n                    h.store_i32(0, &lbResize_filter_interpolation_x_fbb);\r\n                }\r\n\r\n\r\n            }\r\n\r\n        }\r\n\r\n        void switching(bool flag) {\r\n            enabled = flag;\r\n        }\r\n\r\n        bool is_enabled() { return enabled; }\r\n        bool is_enabled_i() { return enabled_i; }\r\n\r\n        void switch_load(ConfigReader& cr) {\r\n            cr.regist(key, [this](json_value_s* value) {\r\n                ConfigReader::load_variable(value, enabled);\r\n            });\r\n        }\r\n\r\n        void switch_store(ConfigWriter& cw) {\r\n            cw.append(key, enabled);\r\n        }\r\n    } LensBlur;\r\n} // namespace patch\r\n\r\n#endif // ifdef PATCH_SWITCH_OBJ_LENSBLUR\r\n"
  },
  {
    "path": "patch/patch_obj_noise.hpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_OBJ_NOISE\r\n#include <memory>\r\n\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util.hpp\"\r\n\r\nnamespace patch {\r\n\r\n    // init at exedit load\r\n    // ノイズの 速度X 変化速度 を移動無し以外に設定している時、速度Y の値をもとに計算されるバグの修正\r\n    inline class obj_Noise_t {\r\n        bool enabled = true;\r\n        bool enabled_i;\r\n        inline static const char key[] = \"obj_noise\";\r\n    public:\r\n        void init() {\r\n            enabled_i = enabled;\r\n\r\n            if (!enabled_i)return;\r\n\r\n            auto& cursor = GLOBAL::executable_memory_cursor;\r\n\r\n            OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x04d8e7, 5);\r\n            h.store_i8(0, '\\xe8');\r\n            h.store_i32(1, cursor - (GLOBAL::exedit_base + 0x04d8ec));\r\n            /*\r\n                1004d8e7 2bf0          sub     esi,eax\r\n                1004d8e9 8b4a08        mov     ecx,dword ptr [edx+8]\r\n                ↓\r\n                1004d8e7 e8xXxXxXxX    call    &executable_memory_cursor\r\n\r\n                ecx,dword ptr [edx+8]を ecx,dword ptr [edx+ track_id*4]にする\r\n            */\r\n\r\n            static const char code_put[] =\r\n\r\n                \"\\x2b\\xf0\"          // sub     esi, eax\r\n                \"\\x8b\\x4c\\x24\\x4c\"  // mov     ecx, dword ptr[esp + 0x4c]\r\n                \"\\x8b\\x0c\\x8a\"      // mov     ecx, dword ptr[edx + ecx * 4]\r\n                \"\\xc3\"              // ret     exedit_base + 0x4d8ec\r\n                ;\r\n\r\n            memcpy(cursor, code_put, sizeof(code_put) - 1);\r\n            cursor += sizeof(code_put) - 1;\r\n        }\r\n\r\n        void switching(bool flag) {\r\n            enabled = flag;\r\n        }\r\n\r\n        bool is_enabled() { return enabled; }\r\n        bool is_enabled_i() { return enabled_i; }\r\n\r\n        void switch_load(ConfigReader& cr) {\r\n            cr.regist(key, [this](json_value_s* value) {\r\n                ConfigReader::load_variable(value, enabled);\r\n                });\r\n        }\r\n\r\n        void switch_store(ConfigWriter& cw) {\r\n            cw.append(key, enabled);\r\n        }\r\n    } Noise;\r\n} // namespace patch\r\n\r\n#endif // ifdef PATCH_SWITCH_OBJ_NOISE\r\n"
  },
  {
    "path": "patch/patch_obj_specialcolorconv.hpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n#ifdef PATCH_SWITCH_OBJ_SPECIALCOLORCONV\r\n\r\n#include <memory>\r\n\r\n#include \"util.hpp\"\r\n\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch {\r\n    // init at exedit load\r\n    // 特定色域変換で変換前色に黒色を指定すると0除算が起こることがあるのを修正\r\n\r\n    /*\r\n        問題のコード\r\n        if (pix_y < before_y) {\r\n            after_y = (after_y * pix_y) / before_y;\r\n        }\r\n\r\n        今回行った修正は以下を追加 (Yが負の値を取らない前提で作られていたようなので)\r\n        if (pix_y < 0) {\r\n            pix_y = 0;\r\n        }\r\n\r\n    */\r\n\r\n    inline class obj_specialcolorconv_t {\r\n\r\n        bool enabled = true;\r\n        bool enabled_i;\r\n\r\n        inline static const char key[] = \"obj_specialcolorconv\";\r\n\r\n\r\n    public:\r\n        void init() {\r\n            enabled_i = enabled;\r\n\r\n            if (!enabled_i)return;\r\n\r\n            auto& cursor = GLOBAL::executable_memory_cursor;\r\n            {\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x015cca, 7);\r\n                    h.store_i32(0, '\\x90\\x90\\xe8\\x00');\r\n                    h.replaceNearJmp(3, cursor);\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x015e25, 7);\r\n                    h.store_i32(0, '\\x90\\x90\\xe8\\x00');\r\n                    h.replaceNearJmp(3, cursor);\r\n                }\r\n                {\r\n                    OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x015f77, 7);\r\n                    h.store_i32(0, '\\x90\\x90\\xe8\\x00');\r\n                    h.replaceNearJmp(3, cursor);\r\n                }\r\n\r\n                {\r\n                    /*\r\n                        10015f77 0fbf31             movsx   esi,dword ptr [ecx]\r\n                        10015f7a 0fbf5d00           movsx   ebx,dword ptr [ebp+00]\r\n\r\n                        ↓\r\n\r\n                        10015f77 9090               nop\r\n                        10015f79 e8XxXxXxXx         call    executable_memory_cursor\r\n\r\n                            ; esi(pix->y)が0未満の場合、0にする\r\n                    */\r\n                    static const char code_put[] =\r\n                        \"\\x0f\\xbf\\x31\"             // movsx   esi,dword ptr [ecx]\r\n                        \"\\x0f\\xbf\\x5d\\x00\"         // movsx   ebx,dword ptr [ebp+00]\r\n                        \"\\x85\\xf6\"                 // test    esi,esi\r\n                        \"\\x7f\\x02\"                 // jg      skip,+02\r\n                        \"\\x33\\xf6\"                 // xor     esi,esi\r\n                        \"\\xc3\"                     // ret\r\n                        ;\r\n\r\n                    memcpy(cursor, code_put, sizeof(code_put) - 1);\r\n                    cursor += sizeof(code_put) - 1;\r\n                }\r\n            }\r\n\r\n            {\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x0156f5, 6);\r\n                h.store_i16(0, '\\x90\\xe8');\r\n                h.replaceNearJmp(2, cursor);\r\n                /*\r\n                    100156f5 0fbf1f             movsx   ebx,dword ptr [edi]\r\n                    100156f8 0fbf2e             movsx   ebp,dword ptr [esi]\r\n\r\n                    ↓\r\n\r\n                    100156f5 90                 nop\r\n                    100156f6 e8XxXxXxXx         call    executable_memory_cursor\r\n\r\n                        ; ebx(pix->y)が0未満の場合、0にする\r\n                */\r\n                static const char code_put[] =\r\n                    \"\\x0f\\xbf\\x1f\"             // movsx   ebx,dword ptr [edi]\r\n                    \"\\x0f\\xbf\\x2e\"             // movsx   ebp,dword ptr [esi]\r\n                    \"\\x85\\xdb\"                 // test    ebx,ebx\r\n                    \"\\x7f\\x02\"                 // jg      skip,+02\r\n                    \"\\x33\\xdb\"                 // xor     ebx,ebx\r\n                    \"\\xc3\"                     // ret\r\n                    ;\r\n\r\n                memcpy(cursor, code_put, sizeof(code_put) - 1);\r\n                cursor += sizeof(code_put) - 1;\r\n            }\r\n\r\n        }\r\n\r\n        void switching(bool flag) {\r\n            enabled = flag;\r\n        }\r\n\r\n        bool is_enabled() { return enabled; }\r\n        bool is_enabled_i() { return enabled_i; }\r\n\r\n        void switch_load(ConfigReader& cr) {\r\n            cr.regist(key, [this](json_value_s* value) {\r\n                ConfigReader::load_variable(value, enabled);\r\n                });\r\n        }\r\n\r\n        void switch_store(ConfigWriter& cw) {\r\n            cw.append(key, enabled);\r\n        }\r\n    } obj_specialcolorconv;\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_OBJ_SPECIALCOLORCONV\r\n"
  },
  {
    "path": "patch/patch_playback_speed.hpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_PLAYBACK_SPEED\r\n\r\n#include <exedit.hpp>\r\n#include \"config_rw.hpp\"\r\n\r\n#include \"global.hpp\"\r\n\r\nnamespace patch {\r\n\r\n    // init at exedit load\r\n    // n番目の中間点で再生速度を変化させるとnフレーム遅れて反映されるのを修正\r\n    inline class playback_speed_t {\r\n        bool enabled = true;\r\n        bool enabled_i;\r\n        inline static const char key[] = \"playback_speed\";\r\n    public:\r\n        void init() {\r\n            enabled_i = enabled;\r\n\r\n            if (!enabled_i)return;\r\n\r\n            { // movie_file\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x005fd9, 1);\r\n                h.store_i8(0, '\\x90');\r\n            }\r\n            { // audio_file\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x08faab, 1);\r\n                h.store_i8(0, '\\x90');\r\n            }\r\n\r\n            { // scene\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x0836b3, 1);\r\n                h.store_i8(0, '\\x90');\r\n            }\r\n            { // scene_audio\r\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x084297, 1);\r\n                h.store_i8(0, '\\x90');\r\n            }\r\n        }\r\n\r\n        void switching(bool flag) {\r\n            enabled = flag;\r\n        }\r\n\r\n        bool is_enabled() { return enabled; }\r\n        bool is_enabled_i() { return enabled_i; }\r\n\r\n        void switch_load(ConfigReader& cr) {\r\n            cr.regist(key, [this](json_value_s* value) {\r\n                ConfigReader::load_variable(value, enabled);\r\n                });\r\n        }\r\n\r\n        void switch_store(ConfigWriter& cw) {\r\n            cw.append(key, enabled);\r\n        }\r\n    } playback_speed;\r\n} // namespace patch\r\n\r\n#endif // ifdef PATCH_SWITCH_PLAYBACK_SPEED\r\n"
  },
  {
    "path": "patch/patch_rclickmenu_delete.cpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"patch_rclickmenu_delete.hpp\"\r\n\r\n#ifdef PATCH_SWITCH_RCLICKMENU_DELETE\r\nnamespace patch {\r\n\r\n\tvoid __cdecl rclickmenu_delete_t::disp_near_settingdialog_wrap3fef6() {\r\n\t\tif (0 <= *settingdialog_object_idx_ptr) {\r\n\t\t\tint object_idx = *settingdialog_object_idx_ptr;\r\n\t\t\tif (*selecting_obj_num_ptr) {\r\n\t\t\t\tobject_idx = selecting_obj_list[0];\r\n\t\t\t}\r\n\t\t\tlast_id = reinterpret_cast<int(__cdecl*)(int, int)>(GLOBAL::exedit_base + OFS::ExEdit::get_near_object_idx)(object_idx, 1);\r\n\t\t}\r\n\t}\r\n\tvoid __cdecl rclickmenu_delete_t::DrawTimelineMask_wrap3ff68(int* to_draw) {\r\n\t\tif (0 <= last_id) {\r\n\t\t\treinterpret_cast<void(__cdecl*)(int)>(GLOBAL::exedit_base + OFS::ExEdit::disp_settingdialog)(last_id);\r\n\t\t\tlast_id = -1;\r\n\t\t}\r\n\t\treinterpret_cast<void(__cdecl*)(int*)>(GLOBAL::exedit_base + OFS::ExEdit::DrawTimelineMask)(to_draw);\r\n\t}\r\n\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_RCLICKMENU_DELETE\r\n"
  },
  {
    "path": "patch/patch_rclickmenu_delete.hpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_RCLICKMENU_DELETE\r\n\r\n#include <memory>\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util.hpp\"\r\n#include \"restorable_patch.hpp\"\r\n\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch {\r\n\t// init at exedit load\r\n\t// 右クリックメニューの削除でテキストの字間・行間が変わることがあるのを修正\r\n\t// 設定ダイアログの更新タイミングを変えることで修正\r\n\tinline class rclickmenu_delete_t {\r\n\t\tstatic void __cdecl disp_near_settingdialog_wrap3fef6();\r\n\t\tstatic void __cdecl DrawTimelineMask_wrap3ff68(int* to_draw);\r\n\r\n\t\tbool enabled = true;\r\n\t\tbool enabled_i;\r\n\r\n\t\tinline static const char key[] = \"r_click_menu_delete\";\r\n\r\n\t\tinline static int last_id = -1;\r\n\r\n\tpublic:\r\n\r\n\t\tinline static int* settingdialog_object_idx_ptr;\r\n\t\tinline static int* selecting_obj_num_ptr;\r\n\t\tinline static int* selecting_obj_list;\r\n\r\n\r\n\t\tvoid init() {\r\n\t\t\tenabled_i = enabled;\r\n\r\n\t\t\tif (!enabled_i)return;\r\n\r\n\t\t\tsettingdialog_object_idx_ptr = reinterpret_cast<decltype(settingdialog_object_idx_ptr)>(GLOBAL::exedit_base + 0x177a10);\r\n\t\t\tselecting_obj_num_ptr = reinterpret_cast<decltype(selecting_obj_num_ptr)>(GLOBAL::exedit_base + 0x167d88);\r\n\t\t\tselecting_obj_list = reinterpret_cast<decltype(selecting_obj_list)>(GLOBAL::exedit_base + 0x179230);\r\n\r\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x03fef6, &disp_near_settingdialog_wrap3fef6);\r\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x03ff68, &DrawTimelineMask_wrap3ff68);\r\n\r\n\t\t}\r\n\t\tvoid switching(bool flag) {\r\n\t\t\tenabled = flag;\r\n\t\t}\r\n\r\n\t\tbool is_enabled() { return enabled; }\r\n\t\tbool is_enabled_i() { return enabled_i; }\r\n\r\n\t\tvoid switch_load(ConfigReader& cr) {\r\n\t\t\tcr.regist(key, [this](json_value_s* value) {\r\n\t\t\t\tConfigReader::load_variable(value, enabled);\r\n\t\t\t\t});\r\n\t\t}\r\n\r\n\t\tvoid switch_store(ConfigWriter& cw) {\r\n\t\t\tcw.append(key, enabled);\r\n\t\t}\r\n\r\n\t} rclickmenu_delete;\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_RCLICKMENU_DELETE\r\n"
  },
  {
    "path": "patch/patch_rclickmenu_split.cpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"patch_rclickmenu_split.hpp\"\r\n\r\n#ifdef PATCH_SWITCH_RCLICKMENU_SPLIT\r\nnamespace patch {\r\n\r\n\tint __cdecl rclickmenu_split_t::filter_sendmessage_wrap3fd46(int object_idx, int wparam, int flag) {\r\n\t\tif (last_id < 0) {\r\n\t\t\tlast_id = object_idx;\r\n\t\t}\r\n\t\treturn reinterpret_cast<int(__cdecl*)(int,int,int)>(GLOBAL::exedit_base + OFS::ExEdit::filter_sendmessage)(object_idx, wparam, flag);\r\n\t}\r\n\r\n\tvoid __cdecl rclickmenu_split_t::splitted_object_new_group_belong_wrap3fd5c() {\r\n\t\tif (0 <= last_id) {\r\n\t\t\treinterpret_cast<void(__cdecl*)(int)>(GLOBAL::exedit_base + OFS::ExEdit::disp_settingdialog)(last_id);\r\n\t\t\tlast_id = -1;\r\n\t\t}\r\n\t\treinterpret_cast<void(__cdecl*)(void)>(GLOBAL::exedit_base + OFS::ExEdit::splitted_object_new_group_belong)();\r\n\r\n\t}\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_RCLICKMENU_SPLIT\r\n"
  },
  {
    "path": "patch/patch_rclickmenu_split.hpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_RCLICKMENU_SPLIT\r\n\r\n#include <memory>\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util.hpp\"\r\n#include \"restorable_patch.hpp\"\r\n\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch {\r\n\t// init at exedit load\r\n\t// 右クリックメニューの分割で設定ダイアログの更新が行われないのを修正\r\n\tinline class rclickmenu_split_t {\r\n\t\tstatic int __cdecl filter_sendmessage_wrap3fd46(int object_idx, int wparam, int flag);\r\n\t\tstatic void __cdecl splitted_object_new_group_belong_wrap3fd5c();\r\n\r\n\t\tbool enabled = true;\r\n\t\tbool enabled_i;\r\n\r\n\t\tinline static const char key[] = \"r_click_menu_split\";\r\n\r\n\t\tinline static int last_id = -1;\r\n\r\n\tpublic:\r\n\r\n\t\tvoid init() {\r\n\t\t\tenabled_i = enabled;\r\n\r\n\t\t\tif (!enabled_i)return;\r\n\r\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x03fd46, &filter_sendmessage_wrap3fd46);\r\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x03fd5c, &splitted_object_new_group_belong_wrap3fd5c);\r\n\r\n\t\t}\r\n\t\tvoid switching(bool flag) {\r\n\t\t\tenabled = flag;\r\n\t\t}\r\n\r\n\t\tbool is_enabled() { return enabled; }\r\n\t\tbool is_enabled_i() { return enabled_i; }\r\n\r\n\t\tvoid switch_load(ConfigReader& cr) {\r\n\t\t\tcr.regist(key, [this](json_value_s* value) {\r\n\t\t\t\tConfigReader::load_variable(value, enabled);\r\n\t\t\t\t});\r\n\t\t}\r\n\r\n\t\tvoid switch_store(ConfigWriter& cw) {\r\n\t\t\tcw.append(key, enabled);\r\n\t\t}\r\n\r\n\t} rclickmenu_split;\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_RCLICKMENU_SPLIT\r\n"
  },
  {
    "path": "patch/patch_redo.cpp",
    "content": "/*\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_redo.hpp\"\n\n#ifdef PATCH_SWITCH_UNDO_REDO\n\nnamespace patch {\n\nvoid __cdecl redo_t::init_undo_patch() {\n    *UndoInfo_object_num_ptr = -1;\n    *UndoInfo_write_offset_ptr = -1;\n    *UndoInfo_current_id_ptr = 0;\n\n    UndoInfo_max_id = 0;\n    UndoInfo_object_new = 0;\n    UndoInfo_pre_id = 0;\n    new_object = true;\n    running_undo = false;\n\n    pre_scene_idx = *SceneDisplaying_ptr;\n}\n\nint __cdecl redo_t::f8d290(void* ret, int object_idx, int flag) {\n    int& UndoInfo_object_num = *UndoInfo_object_num_ptr;\n    int& UndoInfo_write_offset = *UndoInfo_write_offset_ptr;\n    int& UndoInfo_limit_mode = *UndoInfo_limit_mode_ptr;\n\n    // データが生成されない条件をそのまま追加\n    if ((UndoInfo_limit_mode && (flag & 2) == 0) || UndoInfo_write_offset < 0 || UndoInfo_object_num < 0) {\n        return UndoInfo_limit_mode;\n    }\n    if ((flag & 0x10) == 0) {\n        auto ObjectArrayPointer = *ObjectArrayPointer_ptr;\n        if (!has_flag(ObjectArrayPointer[object_idx].flag, ExEdit::Object::Flag::Exist) && ((flag & 2) == 0)) {\n            return UndoInfo_limit_mode;\n        }\n        if ((flag & 1) && 0 <= ObjectArrayPointer[object_idx].index_midpt_leader) {\n            return UndoInfo_limit_mode;\n        }\n    }\n    // ----------------------------------\n\n    if (running_undo) {\n        move_redo_data();\n    }\n    else {\n        optimize_undo_data();\n    }\n\n    return UndoInfo_limit_mode;\n}\n\nint __cdecl redo_t::pre_run_undo() {\n\n    // shift + ctrl + zでredoを実行させるためのコード(元に戻せない状態からでも使えます)\n\n\n#ifdef PATCH_SWITCH_UNDO_REDO_SHIFT\n    if (redo.enabled_i && redo.c_shift) {\n        if (!running_undo) {\n            if (GetKeyState(VK_SHIFT) < 0) {\n                run_redo();\n                return 0;\n            }\n        }\n    }\n#endif\n\n\n    int& UndoInfo_write_offset = *UndoInfo_write_offset_ptr;\n    int& UndoInfo_current_id = *UndoInfo_current_id_ptr;\n    int& UndoInfo_object_num = *UndoInfo_object_num_ptr;\n    int& selecting_obj_num = *selecting_obj_num_ptr;\n\n    // optimize_undo_data()で処理していない最新のデータを処理する(元に戻す操作をしているため状態は確定しているはず)\n    optimize_newer_undo_data();\n\n\n    if (UndoInfo_current_id <= 0 || UndoInfo_write_offset <= 0 || UndoInfo_object_num <= 0)return 0;\n\n    // Ctrlを押しながら複数選択した状態で元に戻すをしてオブジェクトが消えると幽霊オブジェクトが出現するのを修正 (選択状態を強制解除)\n    selecting_obj_num = 0;\n\n    running_undo = true;\n\n    int i;\n    // 元々はobject_numを返す。redoデータが残ることでobject_numではなくdata_id > current_idとなるタイミングのnumを返すことでrun_undo内の処理との辻褄が合う\n    for (i = 1; i < UndoInfo_object_num; i++) {\n        if (UndoDataPtrArray[i]->data_id > UndoInfo_current_id) {\n            break;\n        }\n    }\n\n    // 必要であればシーン切り替えを行う\n    if (UndoDataPtrArray[i - 1]->data_id == UndoInfo_current_id) {\n        int scene_idx = get_scene_idx_UndoData(i - 1);\n        if (scene_idx != *SceneDisplaying_ptr) {\n            //void*& editpm = *(void**)uintptr_t(gp_editp);\n            change_disp_scene(scene_idx, *fp_g_ptr, *editp_ptr);\n        }\n    }\n\n    return i;\n}\n\nvoid __cdecl redo_t::end_run_undo() {\n    int& UndoInfo_current_id = *UndoInfo_current_id_ptr;\n    move_redo_data();\n    running_undo = false;\n    UndoInfo_current_id--;\n    UndoInfo_pre_id = UndoInfo_current_id;\n}\n\nvoid __cdecl redo_t::undo_change_disp_scene() {\n    optimize_newer_undo_data();\n    pre_scene_idx = *SceneDisplaying_ptr;\n}\n\n} // namespace patch\n\n#endif\n"
  },
  {
    "path": "patch/patch_redo.hpp",
    "content": "/*\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_UNDO_REDO\n\n#include <exedit.hpp>\n\n#include \"patch_undo.hpp\"\n\nnamespace patch {\n    inline class redo_t {\n        inline static ExEdit::Object** ObjectArrayPointer_ptr;\n        inline static ExEdit::LayerSetting** layer_setting_ofsptr_ptr;\n        inline static void** exdata_buffer_ptr;\n\n        struct UndoData {\n            int data_id;\n            int object_id; // layer | 0x1000000;\n            int data_size;\n            DWORD object_flag;\n            int object_layer_disp;\n            int object_frame_begin;\n            int object_frame_end;\n            DWORD* data;\n        };\n\n        inline static int* UndoInfo_object_num_ptr;\n        inline static int* UndoInfo_write_offset_ptr;\n        inline static int* UndoInfo_current_id_ptr;\n        inline static int* SceneDisplaying_ptr;\n        inline static DWORD* UndoInfo_buffer_ptr_ptr;\n        inline static int* UndoInfo_buffer_size_ptr;\n        inline static int* UndoInfo_limit_mode_ptr;\n        inline static int* selecting_obj_num_ptr;\n        inline static AviUtl::EditHandle** editp_ptr;\n        inline static AviUtl::FilterPlugin** fp_g_ptr;\n\n        inline static UndoData** UndoDataPtrArray;\n\n        inline static void* (__cdecl* exedit_memmove)(void*, void*, size_t);\n        inline static void(__cdecl* run_undo)();\n        inline static void(__cdecl* change_disp_scene)(int, AviUtl::FilterPlugin*, AviUtl::EditHandle*);\n\n        inline static int pre_scene_idx = 0;\n        inline static int UndoInfo_max_id = 0;\n        inline static int UndoInfo_object_new = 0;\n        inline static int UndoInfo_pre_id = 0;\n        inline static bool new_object = true;\n        inline static bool running_undo = false;\n\n\n        static void __cdecl init_undo_patch();\n\n\n        // レイヤーUndo情報そのままではシーンが分からないため、UndoData.object_layer_dispにscene_idxを入れておくようにする\n        static void add_scene_idx() {\n            for (int i = UndoInfo_object_new; i < *UndoInfo_object_num_ptr; i++) {\n                UndoData* undodata = UndoDataPtrArray[i];\n                if (undodata->object_id & 0x1000000) { // レイヤー\n                    undodata->object_layer_disp = pre_scene_idx;\n                }\n            }\n        }\n\n        static int get_scene_idx_UndoData(int undo_id) {\n            UndoData* undodata = UndoDataPtrArray[undo_id];\n            if (undodata->object_id & 0x1000000) {\n                return undodata->object_layer_disp;\n            }\n            else {\n                return (*ObjectArrayPointer_ptr)[undodata->object_id].scene_set;\n            }\n        }\n\n        // undo_bufferから指定idのデータを削除（空白が出来ないようにずらす）\n        static void shift_undo_buffer(int id) {\n            DWORD UndoInfo_buffer_ptr = *UndoInfo_buffer_ptr_ptr;\n            int& UndoInfo_object_num = *UndoInfo_object_num_ptr;\n            int& UndoInfo_write_offset = *UndoInfo_write_offset_ptr;\n\n            int size = UndoDataPtrArray[id]->data_size;\n            DWORD delptr = (DWORD)UndoDataPtrArray[id];\n\n            DWORD nextptr = delptr + size;\n            if (UndoInfo_buffer_ptr + (DWORD)UndoInfo_write_offset > nextptr) {\n                exedit_memmove((void*)delptr, (void*)nextptr, UndoInfo_buffer_ptr + (DWORD)UndoInfo_write_offset - nextptr);\n            }\n            UndoInfo_write_offset -= size;\n\n            for (int i = 0; i < UndoInfo_object_num; i++) {\n                if (delptr < (DWORD)UndoDataPtrArray[i]) {\n                    UndoDataPtrArray[i] = (UndoData*)((DWORD)UndoDataPtrArray[i] - size);\n                }\n            }\n            UndoInfo_object_num--;\n        }\n\n        // 指定idのデータを削除・整理\n        static void remove_UndoData(int id) {\n            shift_undo_buffer(id);\n            for (int i = id; i < *UndoInfo_object_num_ptr; i++) {\n                UndoDataPtrArray[i] = UndoDataPtrArray[i + 1];\n            }\n        }\n\n        // 指定id以上のデータを削除(新しく追加されるデータを除く) \n        static void remove_old_UndoData(int id) {\n            for (int i = UndoInfo_object_new - 1; i >= 0; i--) {\n                if (id <= UndoDataPtrArray[i]->data_id) {\n                    remove_UndoData(i);\n                }\n            }\n        }\n\n        // id1のデータを削除し、id2のデータを置き換える\n        static void move_UndoData(int id1, int id2) {\n            shift_undo_buffer(id1);\n            UndoDataPtrArray[id1] = UndoDataPtrArray[id2];\n        }\n\n        // id1とid2の統合(重複部分はid1が優先)\n        static void integrate_undodata(int id1, int id2) {\n            int& UndoInfo_write_offset = *UndoInfo_write_offset_ptr;\n\n            UndoData* undodata1 = UndoDataPtrArray[id1];\n            UndoData* undodata2 = UndoDataPtrArray[id2];\n\n            if (undodata1->object_flag == 0) {\n                remove_UndoData(id2);\n                return;\n            }\n            if (undodata2->object_flag == 0) {\n                remove_UndoData(id1);\n                return;\n            }\n\n            if (undodata1->data_size < undodata2->data_size) {\n\n                memcpy((void*)((DWORD)undodata2 + 0xc), (void*)((DWORD)undodata1 + 0xc), undodata1->data_size - 0xc);\n\n                if (undodata1->data_size == 0x1c) {\n                    auto undoobj = reinterpret_cast<ExEdit::Object*>(&undodata2->data);\n                    undoobj->flag = static_cast<ExEdit::Object::Flag>(undodata1->object_flag);\n                    if (undodata1->object_flag) {\n                        undoobj->layer_set = undoobj->layer_disp = undodata1->object_layer_disp;\n                        undoobj->frame_begin = undodata1->object_frame_begin;\n                        undoobj->frame_end = undodata1->object_frame_end;\n                    }\n                }\n                remove_UndoData(id1);\n            }\n            else {\n                remove_UndoData(id2);\n            }\n        }\n\n        // 新しく追加されたデータに対して、重複があれば統合する\n        static void optimize_new_undo_buffer() {\n            int& UndoInfo_object_num = *UndoInfo_object_num_ptr;\n            UndoData* newdata = UndoDataPtrArray[UndoInfo_object_num - 1];\n            UndoData* undodata;\n            for (int i = UndoInfo_object_new; i < UndoInfo_object_num - 1; i++) {\n                undodata = UndoDataPtrArray[i];\n                if (undodata->object_id == newdata->object_id && undodata->data_id == newdata->data_id) {\n                    integrate_undodata(i, UndoInfo_object_num - 1);\n                    break;\n                }\n            }\n        }\n\n        // 現在のオブジェクトデータと比べて変更が無ければ削除する\n        static void remove_emptiness_UndoData() {\n            // 指定idのデータと現在のオブジェクト状態を比較 (TRUE:相違点あり FALSE:同じ)\n            auto cmp_obj_undo = [](int id) {\n                auto& ObjectArrayPointer = *ObjectArrayPointer_ptr;\n                auto& layer_setting_ofsptr = *layer_setting_ofsptr_ptr;\n                auto& exdata_buffer = *exdata_buffer_ptr;\n                auto& UndoInfo_object_num = *UndoInfo_object_num_ptr;\n                auto& UndoInfo_write_offset = *UndoInfo_write_offset_ptr;\n\n                UndoData* undodata = UndoDataPtrArray[id];\n\n                void* ptr1;\n                void* ptr2;\n                int cmpsize;\n\n                if (undodata->object_id & 0x1000000) { // レイヤー\n                    ptr1 = (void*)&layer_setting_ofsptr[undodata->object_id & 0xffffff];\n                    ptr2 = &undodata->data;\n                    cmpsize = 8;\n                }\n                else {\n                    ptr1 = (void*)&ObjectArrayPointer[undodata->object_id];\n                    if (undodata->data_size > 0x1c) {\n                        ptr2 = &undodata->data;\n                        cmpsize = sizeof(ExEdit::Object);\n\n                        auto fix_track_right = [](ExEdit::Object* obj) {\n                            int track_num = obj->track_n;\n                            for (int i = 0; i < track_num; i++) {\n                                if (obj->track_mode[i].num == 0) {\n                                    obj->track_value_right[i] = obj->track_value_left[i];\n                                }\n                            }\n                        };\n\n                        fix_track_right(static_cast<ExEdit::Object*>(ptr1)); // 処理順の関係かトラック右の値が変わってしまっていることがあるので直す\n                        fix_track_right(static_cast<ExEdit::Object*>(ptr2));\n\n                        void* ptr3 = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(exdata_buffer) + ObjectArrayPointer[undodata->object_id].exdata_offset + 4);\n                        void* ptr4 = reinterpret_cast<void*>(reinterpret_cast<DWORD>(&undodata->data) + cmpsize);\n                        int excmpsize = undodata->data_size - 0x1c - cmpsize;\n                        if (memcmp(ptr3, ptr4, excmpsize))return true;\n                    }\n                    else {\n                        ptr2 = &undodata->object_flag;\n                        if (undodata->object_flag == 0) {\n                            cmpsize = 4;\n                        }\n                        else {\n                            cmpsize = 0x10;\n                        }\n                    }\n                }\n\n                if (memcmp(ptr1, ptr2, cmpsize))return true;\n\n                return false;\n            };\n\n            for (int i = UndoInfo_object_new; i < *UndoInfo_object_num_ptr; i++) {\n                if (!cmp_obj_undo(i)) { // 変更なし\n                    remove_UndoData(i);\n                    i--;\n                }\n            }\n        }\n\n        // run_undo内で生成されたredo用データを置き換える\n        static void move_redo_data() {\n            int& UndoInfo_object_num = *UndoInfo_object_num_ptr;\n\n            if (UndoInfo_object_new < UndoInfo_object_num) {\n                int dataid = UndoDataPtrArray[UndoInfo_object_new]->data_id;\n                int objid = UndoDataPtrArray[UndoInfo_object_new]->object_id;\n\n                // 元のUndoデータを削除、UndoDataPtrArrayの置換\n                BOOL movef = FALSE;\n                for (int i = 0; i < UndoInfo_object_new; i++) {\n                    if (UndoDataPtrArray[i]->object_id == objid && UndoDataPtrArray[i]->data_id == dataid) {\n                        add_scene_idx();\n                        move_UndoData(i, UndoInfo_object_new);\n                        movef = TRUE;\n                        break;\n                    }\n                }\n                if (!movef) {\n                    remove_UndoData(UndoInfo_object_new);\n                }\n            }\n            UndoInfo_object_new = UndoInfo_object_num;\n        }\n\n        static void __stdcall AllocUndoBuffer_patch(int num) {\n            for (int i = num - 1; i >= 0; i--) {\n                UndoInfo_object_new--;\n                remove_UndoData(i);\n            }\n        }\n\n        // 一つ前の操作で作られたundoデータの最適化(状態が確定してから最適化を行う必要があるため一つ前のデータに対して行う)\n        static void optimize_undo_data() {\n            int& UndoInfo_current_id = *UndoInfo_current_id_ptr;\n            int& UndoInfo_object_num = *UndoInfo_object_num_ptr;\n            int& UndoInfo_write_offset = *UndoInfo_write_offset_ptr;\n\n            if (new_object) {\n                new_object = FALSE;\n                UndoInfo_pre_id = UndoInfo_current_id;\n                UndoInfo_object_new = UndoInfo_object_num;\n            }\n\n            if (UndoInfo_object_new < UndoInfo_object_num) {\n                optimize_new_undo_buffer();\n\n                if (UndoInfo_pre_id < UndoInfo_current_id) {\n                    remove_emptiness_UndoData();\n\n                    if (UndoInfo_object_new < UndoInfo_object_num) { // 変更があった\n                        add_scene_idx();\n                        remove_old_UndoData(UndoInfo_pre_id);\n                        UndoInfo_pre_id = UndoInfo_current_id;\n                        UndoInfo_max_id = UndoInfo_current_id - 1;\n                        UndoInfo_object_new = UndoInfo_object_num;\n                    }\n                    else {\n                        UndoInfo_current_id--;\n                    }\n                }\n            }\n\n        }\n\n        // 最新のundoデータの最適化(undo処理を行う直前に、まだの部分の最適化を行う)\n        static void optimize_newer_undo_data() {\n            int& UndoInfo_current_id = *UndoInfo_current_id_ptr;\n            int& UndoInfo_object_num = *UndoInfo_object_num_ptr;\n\n            if (!new_object) {\n                if (UndoInfo_object_new < UndoInfo_object_num) {\n                    optimize_new_undo_buffer();\n\n                    remove_emptiness_UndoData();\n                    if (UndoInfo_object_new < UndoInfo_object_num) { // 変更があった\n                        add_scene_idx();\n                        remove_old_UndoData(UndoInfo_current_id);\n                        UndoInfo_max_id = UndoInfo_current_id;\n                    }\n                    else {\n                        UndoInfo_current_id--;\n                    }\n                }\n            }\n            UndoInfo_pre_id = UndoInfo_current_id;\n            UndoInfo_object_new = UndoInfo_object_num;\n            new_object = TRUE;\n        }\n\n        // set_undoの先頭に追加する処理\n        static int __cdecl f8d290(void* ret, int object_idx, int flag);\n\n        // run_undoの始めの方に追加する処理\n        static int __cdecl pre_run_undo();\n\n        // run_undoの後処理\n        static void __cdecl end_run_undo();\n\n        static void __cdecl undo_change_disp_scene();\n\n        // undoと同じ処理でredoをするためには並び順を逆にする必要がある\n        static void reverse_UndoDataPtrArray() {\n            int& UndoInfo_current_id = *UndoInfo_current_id_ptr;\n            int& UndoInfo_object_num = *UndoInfo_object_num_ptr;\n\n            int begin = 0;\n            int end = 0;\n            for (int i = 0; i < UndoInfo_object_num; i++) {\n                if (UndoDataPtrArray[i]->data_id == UndoInfo_current_id) {\n                    begin = i;\n                    break;\n                }\n            }\n            for (int i = begin; i < UndoInfo_object_num; i++) {\n                if (UndoDataPtrArray[i]->data_id == UndoInfo_current_id) {\n                    end = i;\n                }\n            }\n\n            UndoData* tmp;\n            while (begin < end) {\n                tmp = UndoDataPtrArray[begin];\n                UndoDataPtrArray[begin] = UndoDataPtrArray[end];\n                UndoDataPtrArray[end] = tmp;\n                begin++; end--;\n            }\n        }\n\n        bool enabled = true;\n        bool enabled_i;\n\n        inline static const char key[] = \"undo.redo\";\n\n        inline static const char c_shift_name[] = \"shift\";\n        bool c_shift = true;\n\n    public:\n\n        void init() {\n            enabled_i = enabled;\n            if (!enabled_i)return;\n\n            ObjectArrayPointer_ptr = reinterpret_cast<decltype(ObjectArrayPointer_ptr)>(GLOBAL::exedit_base + OFS::ExEdit::ObjectArrayPointer);\n            layer_setting_ofsptr_ptr = reinterpret_cast<decltype(layer_setting_ofsptr_ptr)>(GLOBAL::exedit_base + 0x0a4058);\n            exdata_buffer_ptr = reinterpret_cast<void**>(GLOBAL::exedit_base + 0x1e0fa8);\n\n            UndoInfo_object_num_ptr = reinterpret_cast<decltype(UndoInfo_object_num_ptr)>(GLOBAL::exedit_base + 0x244e08);\n            UndoInfo_write_offset_ptr = reinterpret_cast<decltype(UndoInfo_write_offset_ptr)>(GLOBAL::exedit_base + 0x244e10);\n            UndoInfo_current_id_ptr = reinterpret_cast<decltype(UndoInfo_current_id_ptr)>(GLOBAL::exedit_base + 0x244e14);\n            SceneDisplaying_ptr = reinterpret_cast<decltype(SceneDisplaying_ptr)>(GLOBAL::exedit_base + 0x1a5310);\n            UndoInfo_buffer_ptr_ptr = reinterpret_cast<decltype(UndoInfo_buffer_ptr_ptr)>(GLOBAL::exedit_base + 0x244e0c);\n            UndoInfo_buffer_size_ptr = reinterpret_cast<decltype(UndoInfo_buffer_size_ptr)>(GLOBAL::exedit_base + 0x244e18);\n            UndoInfo_limit_mode_ptr = reinterpret_cast<decltype(UndoInfo_limit_mode_ptr)>(GLOBAL::exedit_base + 0x244e1c);\n            selecting_obj_num_ptr = reinterpret_cast<decltype(selecting_obj_num_ptr)>(GLOBAL::exedit_base + 0x167d88);\n            editp_ptr = reinterpret_cast<decltype(editp_ptr)>(GLOBAL::exedit_base + 0x1a532c);\n            fp_g_ptr = reinterpret_cast<decltype(fp_g_ptr)>(GLOBAL::exedit_base + 0x14d4b4);\n\n            UndoDataPtrArray = reinterpret_cast<decltype(UndoDataPtrArray)>(GLOBAL::exedit_base + 0x2363a8);\n\n            exedit_memmove = reinterpret_cast<decltype(exedit_memmove)>(GLOBAL::exedit_base + 0x091f60);\n            run_undo = reinterpret_cast<decltype(run_undo)>(GLOBAL::exedit_base + 0x08d490);\n            change_disp_scene = reinterpret_cast<decltype(change_disp_scene)>(GLOBAL::exedit_base + 0x02ba60);\n\n\n            /*  initに内容を追加する\n                void __cdecl InitUndo(void) { // 8d140\n                    UndoInfo_object_num = -1;\n                    UndoInfo_write_offset = -1;\n                }\n            */\n            ReplaceFunction(GLOBAL::exedit_base + 0x08d140, &init_undo_patch);\n\n            /*  AddUndoCount 8d150 の処理を少し変更した方が良いように見えるけど、今回の実装では変えなくても影響なさそう\n                if ((UndoInfo_write_offset <= 0) || (UndoInfo_object_num <= 0)) {\n                    UndoInfo_write_offset = 0;\n                    UndoInfo_object_num = 0;\n                }\n                ↓\n                if ((UndoInfo_write_offset <= 0) || (UndoInfo_object_num < 0)) {\n                    UndoInfo_write_offset = 0;\n                    UndoInfo_object_num = 0;\n                }\n\n                1008d15a 7e 08           JLE\n                1008d162 7f 0a           JG\n\n            byte jle2jl[1] = { 0x7c };\n            exedit_ReplaceData(0x8d15a, jle2jl, 1);\n\n            byte jg2jge[1] = { 0x7d };\n            exedit_ReplaceData(0x8d162, jg2jge, 1);\n            */\n\n\n            /*  bufferの最適化処理を行う\n                1008d290 a11c4e2410   MOV        EAX, [UndoInfo_limit_mode]\n                →       e8--------   CALL       f8d290\n            */\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x08d290, 5);\n                h.store_i8(0, '\\xe8'); // call (rel32)\n                h.replaceNearJmp(1, &f8d290);\n            }\n\n            /*  undoの前処理\n                1008d4a9 a1084e2410     EAX = UndoInfo_object_num\n                →       e8--------     pre_run_undo();\n\n            */\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x08d4a9, 5);\n                h.store_i8(0, '\\xe8'); // call (rel32)\n                h.replaceNearJmp(1, &pre_run_undo);\n            }\n\n\n            /*  redoデータ生成を無効にする処理を消す\n                1008d4c5 89151c4e2410   Undoinfo_limit_mode = 1\n                1008d4cb\n                ↓\n                1008d4c5 660f1f440000   nop word ptr [eax+eax+00H]\n                1008d4cb\n            */\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x08d4c5, 6);\n                char patch[] = {\n                    0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00\n                };\n                memcpy(reinterpret_cast<void*>(h.address()), patch, 6);\n            }\n\n\n            /*  後処理\n            1008d723 8b0d144e2410       mov     ecx,UndoInfo_current_id\n            1008d729 40                 inc     eax++\n            1008d72a a3084e2410         mov     UndoInfo_object_num = eax\n            1008d72f 8b442428           mov     eax = pre_limit_mode\n            1008d733 49                 dec     ecx--\n            1008d734 a31c4e2410         mov     UndoInfo_limit_mode = eax\n            1008d739 890d144e2410       mov     UndoInfo_current_id = ecx\n            ↓\n            1008d723 eb15               jmp     1008d73a\n            1008d725 144e2410           err\n            1008d729 40                 inc     eax++\n            1008d72a a3084e2410         mov     UndoInfo_object_num = eax\n            1008d72f 8b442428           mov     eax = pre_limit_mode\n            1008d733 49                 dec     ecx--\n            1008d734 a31c4e2410         mov     UndoInfo_limit_mode = eax\n            1008d739 89                 err\n            1008d73a e8--------         call    end_run_undo()\n\n            */\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x08d723, 2);\n                h.store_i16(0, '\\xeb\\x15');\n            }\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x08d73a, 5);\n                h.store_i8(0, '\\xe8'); // call (rel32)\n                h.replaceNearJmp(1, &end_run_undo);\n            }\n\n            /*  AllocUndoBufferにて削除が行われる場合にUndoInfo_object_newを再計算する必要あり\n            1008d22a e8 31 4d 00 00     CALL    exedit_memmove()\n\n            exedit_ReplaceCall(0x8d22b, &redo_8d22b_patch);\n            */\n\n            /*  AllocUndoBufferで行われる削除処理がそのままではまずそうなので書きかえ\n                while (true) {\n                    if (object_num < 15000 && write_offset + data_size < UndoInfo_buffer_size) {\n                        return TRUE;\n                    }\n\n                    if (object_num < 1) break;\n\n                    for (i = 1; i < object_num; i++) {\n                        if (UndoDataPtrArray[i]->data_id != UndoDataPtrArray[0]->data_id) break;\n                    }\n                    if (i == object_num) break;\n\n                    // -------------- ここから下を関数に置き換える ---------------------\n\n                    buffer_size = (DWORD)UndoDataPtrArray[i] - (DWORD)buffer_ptr;\n                    FUN_10091f60(buffer_ptr, (void)UndoDataPtrArray[i], write_offset - buffer_size); // memmove相当の関数\n\n                    buffer_ptr = UndoInfo_buffer_ptr;\n                    object_num = UndoInfo_object_num - i;\n                    write_offset = UndoInfo_write_offset - buffer_size;\n                    UndoInfo_object_num = object_num;\n                    UndoInfo_write_offset = write_offset;\n\n                    offset = 0;\n                    for (i = 0; i < object_num; i++) { //\n                        UndoDataPtrArray[i] = (UndoData*)((DWORD)buffer_ptr + offset);\n                        offset += ((UndoData*)((DWORD)buffer_ptr + offset))->data_size;\n                    }\n                }\n\n\n                1008d21a 8b04bda8632310  MOV   EAX,dword ptr [EDI*0x4 + 0x102363a8]\n                1008d221\n                ..\n                1008d22f 8b15084e2410    MOV   EDX,dword ptr [UndoInfo_object_num]\n                1008d235 8b2d104e2410    MOV   EBP,dword ptr [UndoInfo_write_offset]\n                ..\n                1008d274 e95dffffff      JMP   1008d1d6\n\n\n                ↓\n                1008d21a 57              PUSH  EDI ; == i\n                1008d21b e8--------      CALL  AllocUndoBuffer_patch(i)\n                1008d220 eb0d            JMP   1008d22f\n                1008d222\n                ..\n                1008d22f 8b15084e2410    MOV   EDX,dword ptr [UndoInfo_object_num]\n                1008d235 8b2d104e2410    MOV   EBP,dword ptr [UndoInfo_write_offset]\n                1008d23b eb99            JMP   1008d1d6\n                1008d23d\n\n            */\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x08d21a, 6);\n                h.store_i16(0, '\\x57\\xe8');\n                h.replaceNearJmp(2, &AllocUndoBuffer_patch);\n            }\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x08d220, 2);\n                h.store_i16(0, '\\xeb\\x0d'); // jmp +0dh\n            }\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x08d23b, 2);\n                h.store_i16(0, '\\xeb\\x99'); // jmp +99h\n            }\n\n            // シーン切り替えてもUndoが継続できるようにする\n            /*  change_disp_scene内のundo初期化を削除し、別の処理を入れる\n                1002ba84 e8b7160600       CALL   InitUndo()\n                ↓\n                1002ba84 e8--------       CALL   new_function()\n            */\n            ReplaceNearJmp(GLOBAL::exedit_base + 0x02ba85, &undo_change_disp_scene);\n\n        }\n\n\n        static void run_redo() {\n            int& UndoInfo_current_id = *UndoInfo_current_id_ptr;\n\n            // この後呼ばれるrun_undo()でも同じ処理が行われることになるが、ここで先に処理してredoが可能かどうかを判定する必要がある\n            optimize_newer_undo_data();\n\n            // 上記処理にて新しい操作が行われていたとしたら、現在が最新状態という事になるのでredoはできない\n            if (UndoInfo_current_id >= UndoInfo_max_id)return;\n\n\n            // idを増やしてUndoDataPtrArrayの並びを逆にしてrun_undoを動かせばredoになる\n            UndoInfo_current_id++;\n            reverse_UndoDataPtrArray();\n\n            running_undo = true;\n            run_undo();\n\n            UndoInfo_current_id++;\n            UndoInfo_pre_id = UndoInfo_current_id;\n            reverse_UndoDataPtrArray();\n        }\n\n        void switching(bool flag) {\n            enabled = flag;\n        }\n\n        bool is_enabled() { return enabled; }\n        bool is_enabled_i() { return enabled_i; }\n\n        void switch_load(ConfigReader& cr) {\n            cr.regist(key, [this](json_value_s* value) {\n                ConfigReader::load_variable(value, enabled);\n            });\n            cr.regist(key, [this](json_value_s* value) {\n                ConfigReader::load_variable(value, enabled);\n            });\n        }\n\n        void switch_store(ConfigWriter& cw) {\n            cw.append(key, enabled);\n        }\n        \n\t\tvoid config_load(ConfigReader& cr) {\n            cr.regist(c_shift_name, [this](json_value_s* value) {\n                ConfigReader::load_variable(value, c_shift);\n            });\n\t\t}\n\n\t\tvoid config_store(ConfigWriter& cw) {\n\t\t\tcw.append(c_shift_name, c_shift);\n\t\t}\n\n    } redo;\n}\n\n#endif\n"
  },
  {
    "path": "patch/patch_scroll_objdlg.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_SCROLL_OBJDLG\n\n#include <WIndows.h>\n\n#include \"offset_address.hpp\"\n#include \"util.hpp\"\n\nnamespace patch {\n    // init at exedit load\n    // 設定ダイアログサイズ固定化\n    inline class scroll_objdlg_t {\n\n        static void movewindow(HWND hwnd, int x, int y) {\n            \n            SetWindowPos(hwnd, NULL, x, y, NULL, NULL, SWP_NOZORDER | SWP_NOSIZE);\n        }\n\n\n        static LRESULT CALLBACK a(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {\n            switch(message) {\n            case WM_CREATE: {\n                RECT rc;\n                GetClientRect(hwnd, &rc);\n                SCROLLINFO si = {\n                    .cbSize = sizeof(SCROLLINFO),\n                    .fMask = SIF_DISABLENOSCROLL | SIF_ALL,\n                    .nMin = 0,\n                    .nMax = rc.bottom - rc.top,\n                    .nPage = 12,\n                    .nPos = 0\n                };\n                SetScrollInfo(hwnd, SB_VERT, &si, TRUE);\n\n\n                break;\n            }\n            case WM_SIZE: {\n                RECT rc;\n                GetClientRect(hwnd, &rc);\n                SCROLLINFO si = { .cbSize = sizeof(SCROLLINFO) };\n                GetScrollInfo(hwnd, SB_VERT, &si);\n                \n                \n                SetScrollInfo(hwnd, SB_VERT, &si, TRUE);\n\n\n                break;\n            }\n            case WM_SIZING: {\n                auto& rect = *(RECT*)lparam;\n                \n                switch(wparam) {\n                    case WMSZ_RIGHT: {\n                        rect.right = rect.left + 0x1f0;\n                    }\n                }\n                break;\n            }\n            case WM_VSCROLL:{\n                switch(LOWORD(wparam)) {\n                    case SB_TOP:\n                    case SB_BOTTOM:\n                    case SB_LINEUP:\n                    case SB_LINEDOWN:\n                    case SB_PAGEUP:\n                    case SB_PAGEDOWN:\n                    case SB_THUMBPOSITION:\n                    break;\n                }\n\n                break;\n            }\n            }\n\n            return 0;\n        }\n\n        bool enabled = true;\n        bool enabled_i;\n        inline static const char key[] = \"scroll_objdlg\";\n\n    public:\n        void init() {\n            enabled_i = enabled;\n            if (!enabled_i)return;\n\n            OverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::ExtendedFilter_wndcls, 4);\n            store_i32(GLOBAL::exedit_base + OFS::ExEdit::ExtendedFilter_wndcls, WS_SYSMENU | WS_VSCROLL);\n        }\n\n        void switching(bool flag) {\n            enabled = flag;\n        }\n\n        bool is_enabled() { return enabled; }\n        bool is_enabled_i() { return enabled_i; }\n\n\t\tvoid switch_load(ConfigReader& cr) {\n\t\t\tcr.regist(key, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, enabled);\n\t\t\t});\n\t\t}\n\n        void switch_store(ConfigWriter& cw) {\n            cw.append(key, enabled);\n        }\n\n    }scroll_objdlg;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_SCROLL_OBJDLG\n"
  },
  {
    "path": "patch/patch_setting_dialog_excolorconfig.cpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"patch_setting_dialog_excolorconfig.hpp\"\r\n#ifdef PATCH_SWITCH_SETTINGDIALOG_EXCOLORCONFIG\r\n\r\n\r\n\r\nnamespace patch {\r\n\r\n\tvoid __cdecl excolorconfig_t::efExColorConfig_setButtonStr_wrap_17083(ExEdit::Filter* efp) {\r\n\r\n\t\tHWND ctrl_hwnd = efp->exfunc->get_hwnd(efp->processing, 7, 2);\r\n\t\tif (ctrl_hwnd) {\r\n\t\t\tSetWindowPos(ctrl_hwnd, (HWND)0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW);\r\n\t\t}\r\n\t\tctrl_hwnd = efp->exfunc->get_hwnd(efp->processing, 7, 1);\r\n\t\tif (ctrl_hwnd) {\r\n\t\t\tSetWindowPos(ctrl_hwnd, (HWND)0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW);\r\n\t\t}\r\n\r\n\t\tefExColorConfig_setButtonStr(efp);\r\n\t}\r\n\r\n\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_SETTINGDIALOG_EXCOLORCONFIG\r\n"
  },
  {
    "path": "patch/patch_setting_dialog_excolorconfig.hpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_SETTINGDIALOG_EXCOLORCONFIG\r\n#include <exedit.hpp>\r\n#include \"global.hpp\"\r\n#include \"util_magic.hpp\"\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch {\r\n\t// init at exedit load\r\n\t// 設定ダイアログで拡張色設定の下のフィルタにウィンドウが被る\r\n\tinline class excolorconfig_t {\r\n\r\n\t\tstatic void __cdecl efExColorConfig_setButtonStr_wrap_17083(ExEdit::Filter* efp);\r\n\r\n\t\tbool enabled = true;\r\n\t\tbool enabled_i;\r\n\t\tinline static const char key[] = \"settingdialog_excolorconfig\";\r\n\r\n\tpublic:\r\n\t\tinline static void(__cdecl* efExColorConfig_setButtonStr)(ExEdit::Filter* efp);\r\n\r\n\t\tvoid init() {\r\n\t\t\tenabled_i = enabled;\r\n\t\t\tif (!enabled_i) return;\r\n\r\n\t\t\tefExColorConfig_setButtonStr = reinterpret_cast<decltype(efExColorConfig_setButtonStr)>(GLOBAL::exedit_base + 0x016e90);\r\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x017084, &efExColorConfig_setButtonStr_wrap_17083);\r\n\r\n\t\t}\r\n\r\n\t\tvoid switching(bool flag) { enabled = flag; }\r\n\r\n\t\tbool is_enabled() { return enabled; }\r\n\t\tbool is_enabled_i() { return enabled_i; }\r\n\r\n\t\tvoid switch_load(ConfigReader& cr) {\r\n\t\t\tcr.regist(key, [this](json_value_s* value) {\r\n\t\t\t\tConfigReader::load_variable(value, enabled);\r\n\t\t\t\t});\r\n\t\t}\r\n\r\n\t\tvoid switch_store(ConfigWriter& cw) {\r\n\t\t\tcw.append(key, enabled);\r\n\t\t}\r\n\r\n\t} excolorconfig;\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_SETTINGDIALOG_EXCOLORCONFIG\r\n"
  },
  {
    "path": "patch/patch_setting_dialog_move.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n\n#ifdef PATCH_SWITCH_SETTINGDIALOG_MOVE\n#include <atomic>\n#include <thread>\n#include <Windows.h>\n\n#include \"config_rw.hpp\"\n\nnamespace patch {\n\tinline class setting_dialog_move_t {\n\t\tinline static std::jthread th;\n\t\tinline static std::atomic_bool waiting;\n\n\t\tbool enabled = true;\n        inline static const char key[] = \"settingdialog_move\";\npublic:\n\t\tvoid operator()(HWND hwnd) {\n\t\t\tif (!enabled)return;\n\t\t\tstd::this_thread::sleep_for(std::chrono::milliseconds{ 10 });\n\t\t}\n\t\t\n        void switching(bool flag) {\n            enabled = flag;\n        }\n\n        bool is_enabled() { return enabled; }\n        bool is_enabled_i() { return enabled; }\n\n        void switch_load(ConfigReader& cr) {\n            cr.regist(key, [this](json_value_s* value) {\n                ConfigReader::load_variable(value, enabled);\n            });\n        }\n\n        void switch_store(ConfigWriter& cw) {\n            cw.append(key, enabled);\n        }\n\t} setting_dialog_move;\n}\n#endif\n"
  },
  {
    "path": "patch/patch_setting_dialog_wndproc_override.cpp",
    "content": "/*\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_setting_dialog_wndproc_override.hpp\"\n\n#include \"patch_setting_dialog_move.hpp\"\n\nnamespace patch {\n\tLRESULT CALLBACK setting_dialog_t::wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {\n\t\tswitch (message) {\n\t\tcase WM_MOVE:\n\t\t\t#ifdef PATCH_SWITCH_SETTINGDIALOG_MOVE\n\t\t\t\tsetting_dialog_move(hwnd);\n\t\t\t#endif\n\t\t\tbreak;\n\t\t}\n\t\treturn wndproc_orig(hwnd, message, wparam, lparam);\n\t}\n}\n"
  },
  {
    "path": "patch/patch_setting_dialog_wndproc_override.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n\n#include \"global.hpp\"\n#include \"util_magic.hpp\"\n\nnamespace patch {\n\n\tinline class setting_dialog_t {\n\t\tinline static WNDPROC wndproc_orig;\n\t\tstatic LRESULT CALLBACK wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);\n\n\tpublic:\n\t\tvoid operator()() {\n\t\t\twndproc_orig = reinterpret_cast<decltype(wndproc_orig)>(GLOBAL::exedit_base + 0x02cde0);\n\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x02e804, 4);\n\t\t\th.store_i32(0, &wndproc);\n\t\t}\n\t} setting_dialog;\n}\n"
  },
  {
    "path": "patch/patch_setting_gui.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"macro.h\"\n\n#ifdef PATCH_SWITCH_SETTING_GUI\nnamespace patch {\n\t// patch.aul の設定用ダイアログ\n\tinline class setting_gui_t {\n\n\tpublic:\n\t\tvoid operator()() {\n\n\t\t}\n\t} setting_gui;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_SETTING_GUI\n"
  },
  {
    "path": "patch/patch_setting_new_project.cpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"patch_setting_new_project.hpp\"\r\n\r\n#ifdef PATCH_SWITCH_SETTING_NEW_PROJECT\r\nnamespace patch {\r\n\r\n\tBOOL __cdecl setting_new_project_t::exedit_edit_open_wrap(int w, int h, int video_rate, int video_scale, int audio_rate, HWND hwnd, AviUtl::EditHandle* editp, AviUtl::FilterPlugin* fp) {\r\n\t\tif (reinterpret_cast<BOOL(__cdecl*)(int, int, int, int, int, HWND, AviUtl::EditHandle*, AviUtl::FilterPlugin*)>(GLOBAL::exedit_base + OFS::ExEdit::exedit_edit_open)(w, h, video_rate, video_scale, audio_rate, hwnd, editp, fp)) {\r\n\t\t\tHWND* aviutl_hwnd = (HWND*)(GLOBAL::exedit_base + OFS::ExEdit::aviutl_hwnd);\r\n\t\t\tif (*(byte*)(GLOBAL::aviutl_base + 0x7ad58) & 1) { // クリッピング&リサイズが有効\r\n\t\t\t\tSendMessageA(*aviutl_hwnd, WM_COMMAND, 10008, 0); // フィルタ>クリッピング&リサイズ\r\n\t\t\t}\r\n\t\t\tSendMessageA(*aviutl_hwnd, WM_COMMAND, 12100, 0); // 設定>サイズの変更>なし\r\n\t\t\tSendMessageA(*aviutl_hwnd, WM_COMMAND, 12107, 0); // 設定>フレームレートの変更>なし\r\n\t\t\treturn TRUE;\r\n\t\t}\r\n\t\treturn FALSE;\r\n\t}\r\n\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_SETTING_NEW_PROJECT"
  },
  {
    "path": "patch/patch_setting_new_project.hpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_SETTING_NEW_PROJECT\r\n#include <exedit.hpp>\r\n#include \"global.hpp\"\r\n#include \"util.hpp\"\r\n#include \"restorable_patch.hpp\"\r\n\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch {\r\n    // init at exedit load\r\n    // プロジェクト作成時、サイズの変更＞なし　フレームレートの変更＞なし　クリッピング＆リサイズOFF にする\r\n\r\n    inline class setting_new_project_t {\r\n\r\n        static BOOL __cdecl exedit_edit_open_wrap(int w, int h, int video_rate, int video_scale, int audio_rate, HWND hwnd, AviUtl::EditHandle* editp, AviUtl::FilterPlugin* fp);\r\n        bool enabled = true;\r\n        bool enabled_i;\r\n\r\n        inline static const char key[] = \"setting_new_project\";\r\n\r\n    public:\r\n        void init() {\r\n            enabled_i = enabled;\r\n\r\n            if (!enabled_i)return;\r\n\r\n            {\r\n                // ReplaceNearJmp(GLOBAL::exedit_base + 0x004d4a, &exedit_edit_open_wrap); // バックアップファイルから新規作成\r\n                ReplaceNearJmp(GLOBAL::exedit_base + 0x03c0d0, &exedit_edit_open_wrap); // プロジェクト作成前のD&D\r\n                ReplaceNearJmp(GLOBAL::exedit_base + 0x04392f, &exedit_edit_open_wrap); // オブジェクトファイルから新規作成\r\n                ReplaceNearJmp(GLOBAL::exedit_base + 0x043aea, &exedit_edit_open_wrap); // 新規プロジェクトの作成\r\n            }\r\n\r\n\r\n        }\r\n        void switching(bool flag) {\r\n            enabled = flag;\r\n        }\r\n\r\n        bool is_enabled() { return enabled; }\r\n        bool is_enabled_i() { return enabled_i; }\r\n\r\n        void switch_load(ConfigReader& cr) {\r\n            cr.regist(key, [this](json_value_s* value) {\r\n                ConfigReader::load_variable(value, enabled);\r\n                });\r\n        }\r\n\r\n        void switch_store(ConfigWriter& cw) {\r\n            cw.append(key, enabled);\r\n        }\r\n\r\n    } setting_new_project;\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_SETTING_NEW_PROJECT\r\n"
  },
  {
    "path": "patch/patch_splash.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_splash.hpp\"\n\n#ifdef PATCH_SWITCH_SPLASH\nnamespace patch {\n    LRESULT CALLBACK splash_t::SplashWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {\n        using namespace Gdiplus;\n\n        static GdiplusStartupInput gdi_input;\n        static ULONG_PTR gdi_token;\n\n        static HDC image_dc;\n        static int w, h;\n\n        switch (message) {\n        case WM_CREATE: {\n            Gdiplus::GdiplusStartup(&gdi_token, &gdi_input, NULL);\n\n            auto hmod = GLOBAL::patchaul_hinst;\n            auto resource_splash = FindResourceA(hmod, \"SPLASH\", RT_RCDATA);\n            auto resource_splash_size = SizeofResource(hmod, resource_splash);\n            auto resource_splash_data = LoadResource(hmod, resource_splash);\n            auto resource_splash_ptr = LockResource(resource_splash_data);\n\n            auto hglobal = GlobalAlloc(0, resource_splash_size);\n            if (hglobal == NULL) return -1;\n            auto ptr = GlobalLock(hglobal);\n            if (ptr == nullptr) {\n                GlobalFree(hglobal);\n                return -1;\n            }\n\n            memcpy(ptr, resource_splash_ptr, resource_splash_size);\n\n            GlobalUnlock(ptr);\n            UnlockResource(resource_splash_ptr);\n\n            IStream* is;\n            CreateStreamOnHGlobal(hglobal, FALSE, &is);\n            \n            Gdiplus::Image image_plus(is);\n\n            is->Release();\n            GlobalFree(hglobal);\n            \n            w = image_plus.GetWidth();\n            h = image_plus.GetHeight();\n\n            auto hdc = GetDC(hwnd);\n            image_dc = CreateCompatibleDC(hdc);\n            auto image_bmp = CreateCompatibleBitmap(hdc, w, h);\n            SelectObject(image_dc, image_bmp);\n            Graphics graphics(image_dc);\n            graphics.DrawImage(&image_plus, 0, 0);\n            ReleaseDC(hwnd, hdc);\n\n            RECT window_rect;\n            GetWindowRect(GetDesktopWindow(), &window_rect);\n            SetWindowLongA(hwnd, GWL_STYLE, 0);\n            SetWindowPos(hwnd, HWND_TOPMOST, (window_rect.right - w) / 2, (window_rect.bottom - h) / 2, w, h, SWP_FRAMECHANGED);\n            return 0;\n        }\n        case WM_DESTROY:\n            DeleteDC(image_dc);\n            GdiplusShutdown(gdi_token);\n            PostQuitMessage(0);\n            return 0;\n        case WM_CLOSE:\n            DestroyWindow(hwnd);\n            return DefWindowProcA(hwnd, message, wparam, lparam);\n        case WM_PAINT: {\n            PAINTSTRUCT ps;\n            HDC hdc = BeginPaint(hwnd, &ps);\n            \n            BitBlt(hdc, 0, 0, w, h, image_dc, 0, 0, SRCCOPY);\n            //SetTextAlign(hdc, TA_CENTER | TA_BOTTOM);\n            {\n                std::lock_guard lock(mutex);\n                TextOutW(hdc, 2, h - 40, state.phase.c_str(), state.phase.length());\n                TextOutW(hdc, 2, h - 20, state.detail.c_str(), state.detail.length());\n            }\n            \n            EndPaint(hwnd, &ps);\n            return 0;\n        }\n        case WM_ERASEBKGND:\n            return 1;\n\n        default:\n            return DefWindowProcA(hwnd, message, wparam, lparam);\n        }\n    }\n    \n    void __cdecl InitEnd() {\n        patch::splash.finish();\n    }\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_SPLASH\n"
  },
  {
    "path": "patch/patch_splash.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_SPLASH\n\n#include <memory>\n#include <atomic>\n#include <string>\n#include <thread>\n#include <mutex>\n#include <condition_variable>\n\n#include <Windows.h>\n\n#include <Shlwapi.h>\n#pragma comment(lib, \"Shlwapi.lib\")\n\n#include <gdiplus.h>\n#pragma comment(lib, \"gdiplus.lib\")\n\n#include \"global.hpp\"\n#include \"util.hpp\"\n#include \"debug_log.hpp\"\n#include \"config_rw.hpp\"\n\nnamespace patch {\n\n\tvoid __cdecl InitEnd();\n\n\t// init at dllload\n\t// スプラッシュウィンドウ\n\tinline class splash_t {\n\t\t\n\t\tinline static std::thread thread;\n\t\tinline static std::mutex mutex;\n\n\t\tinline static struct {\n\t\t\tstd::wstring phase;\n\t\t\tstd::wstring detail;\n\t\t} state;\n\n\t\t__declspec(align(4)) inline static std::atomic<bool> load_finished{false};\n\t\t__declspec(align(4)) inline static std::atomic<bool> update_state{false};\n\n\t\tinline static const char classname[] = \"patchaul_splash\";\n\n\t\tstatic LRESULT CALLBACK SplashWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);\n\n\t\tinline static const char key[] = \"splash\";\n\n\t\tbool enabled = false;\n\t\tbool enabled_i;\n\n\tpublic:\n\t\tvoid init() {\n\t\t\tenabled_i = enabled;\n\n\t\t\tWNDCLASSA winc{\n\t\t\t\t.style = 0,\n\t\t\t\t.lpfnWndProc = SplashWndProc,\n\t\t\t\t.cbClsExtra = 0,\n\t\t\t\t.cbWndExtra = 0,\n\t\t\t\t.hInstance = GLOBAL::patchaul_hinst,\n\t\t\t\t.hIcon = LoadIconA(NULL, IDI_APPLICATION),\n\t\t\t\t.hCursor = LoadCursorA(NULL, IDC_ARROW),\n\t\t\t\t.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH),\n\t\t\t\t.lpszMenuName = NULL,\n\t\t\t\t.lpszClassName = classname\n\t\t\t};\n\t\t\tRegisterClassA(&winc);\n\n\t\t\t{\n\t\t\t\t// 0x02e70 の Init の ret にスプラッシュウィンドウを閉じる処理を仕込む\n\n\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::aviutl_base + 0x041af, 0x21);\n\t\t\t\tstore_i16(GLOBAL::aviutl_base + 0x041af, '\\xeb\\x11'); // jmp near +0x11\n\n\t\t\t\tstore_i16(GLOBAL::aviutl_base + 0x041c2, '\\x50\\xb9'); // push eax | mov ecx, (i32)\n\t\t\t\tstore_i32(GLOBAL::aviutl_base + 0x041c4, &InitEnd);\n\n\t\t\t\tstore_i16(GLOBAL::aviutl_base + 0x041c8, '\\xff\\xd1'); // call ecx\n\n\t\t\t\tstore_i32(GLOBAL::aviutl_base + 0x041ca, '\\x58\\x8b\\xe5\\x5d'); // pop eax | mov esp, ebp | pop ebp\n\t\t\t\tstore_i8(GLOBAL::aviutl_base + 0x041ce, '\\xc3'); // ret\n\t\t\t}\n\t\t}\n\t\t~splash_t() {\n\t\t\tfinish();\n\t\t\t\n\t\t\tUnregisterClassA(classname, GLOBAL::patchaul_hinst);\n\t\t}\n\n\n\t\tvoid switching(bool flag) {\n\t\t\tenabled = flag;\n\t\t}\n\n\t\tbool is_enabled() { return enabled; }\n\t\tbool is_enabled_i() { return enabled; }\n\t\t\n\t\tvoid switch_load(ConfigReader& cr) {\n\t\t\tcr.regist(key, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, enabled);\n\t\t\t});\n\t\t}\n\n\t\tvoid switch_store(ConfigWriter& cw) {\n\t\t\tcw.append(key, enabled);\n\t\t}\n\n\t\tvoid start() {\n\t\t\tfinish();\n\n\t\t\tthread = std::thread([] {\n\t\t\t\t//WS_EX_LAYERED\n\t\t\t\tauto hwnd = CreateWindowExA(0, classname, \"\", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, NULL, NULL);\n\n\t\t\t\tMSG message;\n\t\t\t\twhile (true) {\n\t\t\t\t\tif (PeekMessageA(&message, NULL, 0, 0, PM_NOREMOVE)) {\n\t\t\t\t\t\tif (message.message == WM_QUIT)break;\n\t\t\t\t\t\tLRESULT result = GetMessageA(&message, NULL, 0, 0);\n\t\t\t\t\t\tif (result <= 0)break;\n\t\t\t\t\t\tDispatchMessageA(&message);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tSleep(50);\n\t\t\t\t\t}\n\t\t\t\t\tif (update_state.load()) {\n\t\t\t\t\t\tupdate_state.store(false);\n\t\t\t\t\t\tInvalidateRect(hwnd, NULL, FALSE);\n\t\t\t\t\t\tauto updated = UpdateWindow(hwnd);\n\t\t\t\t\t\t//debug_log(updated);\n\t\t\t\t\t}\n\t\t\t\t\tif (load_finished.load())\n\t\t\t\t\t\tDestroyWindow(hwnd);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tvoid finish() {\n\t\t\tif (thread.joinable()) {\n\t\t\t\tload_finished.store(true);\n\t\t\t\tthread.join();\n\t\t\t\tload_finished.store(false);\n\t\t\t}\n\t\t}\n\t\tvoid set_phase(std::wstring_view phase, std::wstring_view detail) {\n\t\t\t{\n\t\t\t\tstd::lock_guard lock(mutex);\n\t\t\t\tstate.phase = phase;\n\t\t\t\tstate.detail = detail;\n\t\t\t}\n\t\t\tupdate_state.store(true);\n\t\t}\n\t\tvoid set_detail(std::wstring_view detail) {\n\t\t\t{\n\t\t\t\tstd::lock_guard lock(mutex);\n\t\t\t\tstate.detail = detail;\n\t\t\t}\n\t\t\tupdate_state.store(true);\n\t\t}\n\n\t} splash;\n\t\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_SPLASH\n"
  },
  {
    "path": "patch/patch_susie_load.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_susie_load.hpp\"\n#ifdef PATCH_SWITCH_SUSIE_LOAD\n\nnamespace patch {\n\n\tvoid __cdecl susie_load_t::LoadSpi(LPCSTR dir) {\n\t\tauto loaded_spi_array = reinterpret_cast<ExEdit::structSPI*>(GLOBAL::exedit_base + OFS::ExEdit::loaded_spi_array);\n\n\t\tZeroMemory(loaded_spi_array, sizeof(ExEdit::structSPI) * 32);\n\t\t//MyFindFirstFile\n\t\treinterpret_cast<BOOL(*)(LPCSTR)>(GLOBAL::exedit_base + OFS::ExEdit::MyFindFirstFile)(dir);\n\n\t\tfor (int i = 0; i < 32;) {\n\t\t\tchar path[260];\n\t\t\t// MyFindNextFile\n\t\t\tif (reinterpret_cast<BOOL(*)(LPSTR)>(GLOBAL::exedit_base + OFS::ExEdit::MyFindNextFile)(path) != TRUE)return;\n\n\t\t\tif (auto hMod = LoadLibraryA(path); hMod != NULL) {\n\t\t\t\tauto spi_GetPluginInfo = reinterpret_cast<ExEdit::SpiGetPluginInfo>(GetProcAddress(hMod, \"GetPluginInfo\"));\n\t\t\t\tif (!spi_GetPluginInfo) continue;\n\n\t\t\t\tloaded_spi_array[i].GetPicture = reinterpret_cast<ExEdit::SpiGetPicture>(GetProcAddress(hMod, \"GetPicture\"));\n\t\t\t\tloaded_spi_array[i].hmodule = hMod;\n\n\t\t\t\tspi_GetPluginInfo(1, loaded_spi_array[i].information, 256);\n\n\n\t\t\t\tint j = 2;\n\t\t\t\tauto ext = loaded_spi_array[i].extension;\n\t\t\t\tauto ext_pos = 0;\n\t\t\t\tauto ext_size = std::size(loaded_spi_array[i].extension);\n\n\t\t\t\twhile (true) {\n\t\t\t\t\tchar buf[256];\n\t\t\t\t\tauto ret = spi_GetPluginInfo(j, buf, sizeof(buf));\n\t\t\t\t\tif (ret == 0)break;\n\n\t\t\t\t\tconst std::string_view view(buf);\n\n\t\t\t\t\tsize_t pos_a = 0;\n\t\t\t\t\tsize_t pos_b;\n\t\t\t\t\twhile ((pos_b = view.find_first_of(';', pos_a)) != std::string_view::npos) {\n\t\t\t\t\t\tauto ext_pos_new = ext_pos + (pos_b - pos_a) + 1;\n\t\t\t\t\t\tif (ext_pos_new >= ext_size) {\n\t\t\t\t\t\t\tif (i == 31) goto BREAK_EXT;\n\t\t\t\t\t\t\text[ext_pos - 1] = '\\0';\n\n\t\t\t\t\t\t\tLoadLibraryA(path);\n\n\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\text = loaded_spi_array[i].extension;\n\t\t\t\t\t\t\text_pos = 0;\n\t\t\t\t\t\t\text_pos_new = (pos_b - pos_a) + 1;\n\n\t\t\t\t\t\t\tloaded_spi_array[i].GetPicture = loaded_spi_array[i - 1].GetPicture;\n\t\t\t\t\t\t\tloaded_spi_array[i].hmodule = hMod;\n\n\t\t\t\t\t\t\tstrcpy_s(loaded_spi_array[i].information, loaded_spi_array[i - 1].information);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstrncpy_s(ext + ext_pos, ext_size - ext_pos, buf + pos_a, pos_b - pos_a);\n\n\t\t\t\t\t\text_pos = ext_pos_new;\n\t\t\t\t\t\text[ext_pos - 1] = ';';\n\n\t\t\t\t\t\tpos_a = pos_b + 1;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (ret - pos_a > 0) {\n\t\t\t\t\t\tauto ext_pos_new = ext_pos + (ret - pos_a) + 1;\n\t\t\t\t\t\tif (ext_pos_new >= ext_size) {\n\t\t\t\t\t\t\tif (i == 31) goto BREAK_EXT;\n\t\t\t\t\t\t\text[ext_pos - 1] = '\\0';\n\n\t\t\t\t\t\t\tLoadLibraryA(path);\n\n\t\t\t\t\t\t\ti++;\n\t\t\t\t\t\t\text = loaded_spi_array[i].extension;\n\t\t\t\t\t\t\text_pos = 0;\n\t\t\t\t\t\t\text_pos_new = (pos_b - pos_a) + 1;\n\n\t\t\t\t\t\t\tloaded_spi_array[i].GetPicture = loaded_spi_array[i - 1].GetPicture;\n\t\t\t\t\t\t\tloaded_spi_array[i].hmodule = hMod;\n\n\t\t\t\t\t\t\tstrcpy_s(loaded_spi_array[i].information, loaded_spi_array[i - 1].information);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tstrncpy_s(ext + ext_pos, ext_size - ext_pos, buf + pos_a, ret - pos_a);\n\t\t\t\t\t\text_pos = ext_pos_new;\n\t\t\t\t\t\text[ext_pos - 1] = ';';\n\t\t\t\t\t}\n\n\t\t\t\t\tif (j >= (std::numeric_limits<int>::max)() - 1)break;\n\t\t\t\t\tj += 2;\n\t\t\t\t}\n\t\t\tBREAK_EXT:\n\n\t\t\t\tif (ext_pos != 0) ext[ext_pos - 1] = '\\0';\n\n\t\t\t\t//spi_GetPluginInfo(2, loaded_spi_array[i].extension, 256);\n\n\t\t\t\ti++;\n\t\t\t}\n\t\t}\n\n\t}\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_SUSIE_LOAD\n"
  },
  {
    "path": "patch/patch_susie_load.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_SUSIE_LOAD\n\n#include <exedit.hpp>\n\n#include \"util.hpp\"\n#include \"global.hpp\"\n#include \"offset_address.hpp\"\n\n#include \"restorable_patch.hpp\"\n#include \"config_rw.hpp\"\n\nnamespace patch {\n\t// init at exedit load\n\t// Susieのプラグインで正しく対応拡張子情報を取得できない\n\tinline class susie_load_t {\n\t\tstatic void __cdecl LoadSpi(LPCSTR dir);\n\n\t\tinline static const char key[] = \"susie_load\";\n\n\t\tbool enabled = true;\n\n\t\tstd::optional<restorable_patch_function> rpf;\n\n\tpublic:\n\n\t\tbool init() {\n\t\t\trpf.emplace(GLOBAL::exedit_base + OFS::ExEdit::LoadSpi, &LoadSpi);\n\t\t\trpf->switching(enabled);\n\t\t}\n\n\t\tvoid switching(bool flag) {\n\t\t\trpf->switching(enabled = flag);\n\t\t}\n\n\t\tbool is_enabled() { return enabled; }\n\t\tbool is_enabled_i() { return enabled; }\n\n\t\tvoid switch_load(ConfigReader& cr) {\n\t\t\tcr.regist(key, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, enabled);\n\t\t\t});\n\t\t}\n\n\t\tvoid switch_store(ConfigWriter& cw) {\n\t\t\tcw.append(key, enabled);\n\t\t}\n\n\t}susie_load;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_SUSIE_LOAD\n"
  },
  {
    "path": "patch/patch_sysinfo_write.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_SYSINFO_MODIFY\n\n#include \"global.hpp\"\n#include \"offset_address.hpp\"\n#include \"util.hpp\"\n#include \"version.hpp\"\n\nnamespace patch {\n\t// init at dllload\n\t// Sysinfo::versionの書き換え\n\tinline class sysinfo_info_write_t {\n\tprivate:\n\t\tinline static const char str[] = \"1.10 (patched \" PATCH_VERSION_STR \")\";\n\tpublic:\n\t\tvoid operator()() {\n\t\t\tOverWriteOnProtectHelper(GLOBAL::aviutl_base + OFS::AviUtl::getsys_versionstr_arg, 4).store_i32(0, &str);\n\t\t}\n\t} sysinfo_info_write;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_SYSINFO_MODIFY\n"
  },
  {
    "path": "patch/patch_text_op_size.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_TEXT_OP_SIZE\n\n#include \"global.hpp\"\n#include \"offset_address.hpp\"\n#include \"util.hpp\"\n\nnamespace patch {\n\t// init at exedit load\n\t// 制御文字のサイズのみを変えるとフォントの情報が壊れる\n    inline class text_op_size_t {\n        std::optional<restorable_patch_i8> rp;\n\n        bool enabled = true;\n        inline static const char key[] = \"text_op_size\";\n    public:\n        void init() {\n            rp.emplace(GLOBAL::exedit_base + OFS::ExEdit::text_op_logfont_size, sizeof(LOGFONTW));\n\n            rp->switching(enabled);\n        }\n\n        void switching(bool flag) {\n            rp->switching(enabled = flag);\n        }\n\n        bool is_enabled() { return enabled; }\n        bool is_enabled_i() { return enabled; }\n\n        void switch_load(ConfigReader& cr) {\n            cr.regist(key, [this](json_value_s* value) {\n                ConfigReader::load_variable(value, enabled);\n            });\n        }\n\n        void switch_store(ConfigWriter& cw) {\n            cw.append(key, enabled);\n        }\n    } text_op_size;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_TEXT_OP_SIZE\n"
  },
  {
    "path": "patch/patch_theme_cc.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_THEME_CC\n\n#include \"global.hpp\"\n#include \"util.hpp\"\n#include \"config_rw.hpp\"\n\nnamespace patch {\n\t// init at exedit load\n\t// ConstChanger相当のテーマ機能\n\tinline class theme_cc_t {\n\t\tinline static void* LayerLockBorder_mod_jmp_adr;\n\t\tinline static void* LayerLockBorder_mod_jmp_ret_adr;\n\n\t\tinline static uint32_t* LayerLockBorder_ptr;\n\n\t\tusing ColorBGR = config_type::ColorBGR;\n\t\tusing ColorBGR2 = config_type::ColorBGR2;\n\t\tusing ColorBGR2_Opt = config_type::ColorBGR2_Opt;\n\t\tusing ColorBGR3 = config_type::ColorBGR3;\n\n\t\tbool enabled = true;\n\t\tbool enabled_i;\n\n\t\tinline static const char key[] = \"theme_cc\";\n\n\t\tstruct {\n\t\t\tinline static const char name[] = \"layer\";\n\n\t\t\tstd::optional<int> height_large;\n\t\t\tstd::optional<int> height_medium;\n\t\t\tstd::optional<int> height_small;\n\t\t\tColorBGR2_Opt link_col;\n\t\t\tColorBGR2_Opt clipping_col;\n\t\t\tColorBGR2_Opt lock_col;\n\t\t\tstd::optional<double> hide_alpha;\n\t\t\t//std::optional<int> name_height;\n\n\t\t\tinline static const char key_large[] = \"height_large\";\n\t\t\tinline static const char key_medium[] = \"height_medium\";\n\t\t\tinline static const char key_small[] = \"height_small\";\n\t\t\tinline static const char key_link_col[] = \"link_col\";\n\t\t\tinline static const char key_clipping_col[] = \"clipping_col\";\n\t\t\tinline static const char key_lock_col[] = \"lock_col\";\n\t\t\tinline static const char key_hide_alpha[] = \"hide_alpha\";\n\t\t\t//inline static const char key_name_height[] = \"name_height\";\n\n\t\t\tvoid load(ConfigReader& cr) {\n\t\t\t\tcr.regist(key_large, [this](json_value_s* value) {\n\t\t\t\t\tConfigReader::load_variable(value, height_large);\n\t\t\t\t});\n\t\t\t\tcr.regist(key_medium, [this](json_value_s* value) {\n\t\t\t\t\tConfigReader::load_variable(value, height_medium);\n\t\t\t\t});\n\t\t\t\tcr.regist(key_small, [this](json_value_s* value) {\n\t\t\t\t\tConfigReader::load_variable(value, height_small);\n\t\t\t\t});\n\t\t\t\tcr.regist(key_link_col, [this](json_value_s* value) {\n\t\t\t\t\tConfigReader::load_variable(value, link_col);\n\t\t\t\t});\n\t\t\t\tcr.regist(key_clipping_col, [this](json_value_s* value) {\n\t\t\t\t\tConfigReader::load_variable(value, clipping_col);\n\t\t\t\t});\n\t\t\t\tcr.regist(key_lock_col, [this](json_value_s* value) {\n\t\t\t\t\tConfigReader::load_variable(value, lock_col);\n\t\t\t\t});\n\t\t\t\tcr.regist(key_hide_alpha, [this](json_value_s* value) {\n\t\t\t\t\tConfigReader::load_variable(value, hide_alpha);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tvoid store(ConfigWriter& cw) {\n\t\t\t\tcw.append(key_large, height_large);\n\t\t\t\tcw.append(key_medium, height_medium);\n\t\t\t\tcw.append(key_small, height_small);\n\t\t\t\tcw.append(key_link_col, link_col);\n\t\t\t\tcw.append(key_clipping_col, clipping_col);\n\t\t\t\tcw.append(key_lock_col, lock_col);\n\t\t\t\tcw.append(key_hide_alpha, hide_alpha);\n\t\t\t}\n\n\t\t} layer;\n\n\t\tstruct {\n\t\t\tinline static const char name[] = \"object\";\n\n\t\t\tColorBGR3 media_col;\n\t\t\tColorBGR3 mfilter_col;\n\t\t\tColorBGR3 audio_col;\n\t\t\tColorBGR3 afilter_col;\n\t\t\tColorBGR3 control_col;\n\t\t\tColorBGR3 inactive_col;\n\t\t\tColorBGR clipping_col;\n\t\t\tstd::optional<int> clipping_height;\n\t\t\tstd::optional<std::array<int, 3>> midpt_size;\n\t\t\tColorBGR2 name_col;\n\n\t\t\tinline static const char key_media_col[] = \"media_col\";\n\t\t\tinline static const char key_mfilter_col[] = \"mfilter_col\";\n\t\t\tinline static const char key_audio_col[] = \"audio_col\";\n\t\t\tinline static const char key_afilter_col[] = \"afilter_col\";\n\t\t\tinline static const char key_control_col[] = \"control_col\";\n\t\t\tinline static const char key_inactive_col[] = \"inactive_col\";\n\t\t\tinline static const char key_clipping_col[] = \"clipping_col\";\n\t\t\tinline static const char key_clipping_height[] = \"clipping_height\";\n\t\t\tinline static const char key_midpt_size[] = \"midpt_size\";\n\t\t\tinline static const char key_name_col[] = \"name_col\";\n\n\t\t\tvoid load(ConfigReader& cr) {\n\t\t\t\tcr.regist(key_media_col, [this](json_value_s* jv) {\n\t\t\t\t\tConfigReader::load_variable(jv, media_col);\n\t\t\t\t});\n\t\t\t\tcr.regist(key_mfilter_col, [this](json_value_s* jv) {\n\t\t\t\t\tConfigReader::load_variable(jv, mfilter_col);\n\t\t\t\t});\n\t\t\t\tcr.regist(key_audio_col, [this](json_value_s* jv) {\n\t\t\t\t\tConfigReader::load_variable(jv, audio_col);\n\t\t\t\t});\n\t\t\t\tcr.regist(key_afilter_col, [this](json_value_s* jv) {\n\t\t\t\t\tConfigReader::load_variable(jv, afilter_col);\n\t\t\t\t});\n\t\t\t\tcr.regist(key_control_col, [this](json_value_s* jv) {\n\t\t\t\t\tConfigReader::load_variable(jv, control_col);\n\t\t\t\t});\n\t\t\t\tcr.regist(key_inactive_col, [this](json_value_s* jv) {\n\t\t\t\t\tConfigReader::load_variable(jv, inactive_col);\n\t\t\t\t});\n\t\t\t\tcr.regist(key_clipping_col, [this](json_value_s* jv) {\n\t\t\t\t\tConfigReader::load_variable(jv, clipping_col);\n\t\t\t\t});\n\t\t\t\tcr.regist(key_clipping_height, [this](json_value_s* jv) {\n\t\t\t\t\tConfigReader::load_variable(jv, clipping_height);\n\t\t\t\t});\n\t\t\t\tcr.regist(key_midpt_size, [this](json_value_s* jv) {\n\t\t\t\t\tConfigReader::load_variable(jv, midpt_size);\n\t\t\t\t});\n\t\t\t\tcr.regist(key_name_col, [this](json_value_s* jv) {\n\t\t\t\t\tConfigReader::load_variable(jv, name_col);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tvoid store(ConfigWriter& cw) {\n\t\t\t\tcw.append(key_media_col, media_col);\n\t\t\t\tcw.append(key_mfilter_col, mfilter_col);\n\t\t\t\tcw.append(key_audio_col, audio_col);\n\t\t\t\tcw.append(key_afilter_col, afilter_col);\n\t\t\t\tcw.append(key_control_col, control_col);\n\t\t\t\tcw.append(key_inactive_col, inactive_col);\n\t\t\t\tcw.append(key_clipping_col, clipping_col);\n\t\t\t\tcw.append(key_clipping_height, clipping_height);\n\t\t\t\tcw.append(key_midpt_size, midpt_size);\n\t\t\t\tcw.append(key_name_col, name_col);\n\t\t\t}\n\n\t\t} object;\n\n\t\tstruct {\n\t\t\tinline static const char name[] = \"timeline\";\n\n\t\t\tColorBGR2 scale_col;\n\t\t\tColorBGR2 bpm_grid_col;\n\n\t\t\tinline static const char key_scale_col[] = \"scale_col\";\n\t\t\tinline static const char key_bpm_grid_col[] = \"bpm_grid_col\";\n\n\n\t\t\tvoid load(ConfigReader& cr) {\n\t\t\t\tcr.regist(key_scale_col, [this](json_value_s* jv) {\n\t\t\t\t\tConfigReader::load_variable(jv, scale_col);\n\t\t\t\t});\n\t\t\t\tcr.regist(key_bpm_grid_col, [this](json_value_s* jv) {\n\t\t\t\t\tConfigReader::load_variable(jv, bpm_grid_col);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tvoid store(ConfigWriter& cw) {\n\t\t\t\tcw.append(key_scale_col, scale_col);\n\t\t\t\tcw.append(key_bpm_grid_col, bpm_grid_col);\n\t\t\t}\n\t\t} timeline;\n\tpublic:\n\t\tvoid init() {\n\t\t\tenabled_i = enabled;\n\t\t\tif (!enabled_i) return;\n\n\t\t\t{\n\t\t\t\tauto ptr = GLOBAL::executable_memory_cursor;\n\t\t\t\tGLOBAL::executable_memory_cursor += 17;\n\t\t\t\tconst auto adr = GLOBAL::exedit_base + OFS::ExEdit::LayerLockBorder_mod;\n\n\t\t\t\tLayerLockBorder_mod_jmp_ret_adr = reinterpret_cast<void*>(adr + 8);\n\t\t\t\tLayerLockBorder_mod_jmp_adr = ptr;\n\n\t\t\t\tstore_i32(ptr, load_i32(adr)); // CALL SelectObject\n\t\t\t\tstore_i32(ptr + 4, load_i32(adr + 4));\n\t\t\t\tstore_i16(ptr + 6, '\\x68'); // PUSH (i32)\n\t\t\t\tstore_i32(ptr + 7, 0); LayerLockBorder_ptr = reinterpret_cast<decltype(LayerLockBorder_ptr)>(ptr + 7);\n\t\t\t\tstore_i16(ptr + 11, '\\xff\\x25'); // jmp [i32]\n\t\t\t\tstore_i32(ptr + 13, &LayerLockBorder_mod_jmp_ret_adr);\n\t\t\t\t\n\t\t\t\tOverWriteOnProtectHelper h(adr, 6);\n\t\t\t\t\n\t\t\t\th.store_i16(0, '\\xff\\x25'); // jmp [i32]\n\t\t\t\th.store_i32(2, &LayerLockBorder_mod_jmp_adr);\n\t\t\t}\n\n\t\t\t{\n\t\t\t\t{\n\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::layer_height_array, 12);\n\t\t\t\t\tauto store = [&h](size_t adr_ofs, std::optional<int>& val) {\n\t\t\t\t\t\tauto in_range = [](size_t x) { return 6 <= x && x <= 60; };\n\t\t\t\t\t\tif (val && in_range(*val)) {\n\t\t\t\t\t\t\th.store_i32(adr_ofs, *val);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tval = h.load_i32<int>(adr_ofs);\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\tstore(0, layer.height_large);\n\t\t\t\t\tstore(4, layer.height_medium);\n\t\t\t\t\tstore(8, layer.height_small);\n\t\t\t\t}\n\t\t\t\t{\n\t\t\t\t\tauto store = [](i32 adr_border, i32 adr_center, config_type::ColorBGR2_Opt& val) {\n\t\t\t\t\t\tOverWriteOnProtectHelper hb(adr_border, 4);\n\t\t\t\t\t\tOverWriteOnProtectHelper hc(adr_center, 4);\n\t\t\t\t\t\tif (val.has_value()) {\n\t\t\t\t\t\t\thb.store_i32(0, val.ary[0].to_col_rgb());\n\t\t\t\t\t\t\tif(val.ary[1].is_valid())\n\t\t\t\t\t\t\t\thc.store_i32(0, val.ary[1].to_col_rgb());\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\thc.store_i32(0, val.ary[0].to_col_rgb());\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tconst auto cb = config_type::ColorBGR::from_rgb(hb.load_i32<uint32_t>(0));\n\t\t\t\t\t\t\tconst auto cc = config_type::ColorBGR::from_rgb(hc.load_i32<uint32_t>(0));\n\t\t\t\t\t\t\tif (cb == cc)\n\t\t\t\t\t\t\t\tval = { cb, {} };\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tval = { cb,cc };\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\t\n\t\t\t\t\tstore(\n\t\t\t\t\t\tGLOBAL::exedit_base + OFS::ExEdit::LayerClippingBorder,\n\t\t\t\t\t\tGLOBAL::exedit_base + OFS::ExEdit::LayerClippingCenter,\n\t\t\t\t\t\tlayer.clipping_col\n\t\t\t\t\t);\n\t\t\t\t\tstore(\n\t\t\t\t\t\tGLOBAL::exedit_base + OFS::ExEdit::LayerLinkBorder,\n\t\t\t\t\t\tGLOBAL::exedit_base + OFS::ExEdit::LayerLinkCenter,\n\t\t\t\t\t\tlayer.link_col\n\t\t\t\t\t);\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t{\n\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::LayerLockCenter, 4);\n\t\t\t\t\tif (auto& o = layer.lock_col; o.has_value()) {\n\t\t\t\t\t\t*LayerLockBorder_ptr = o.ary[0].to_col_rgb();\n\t\t\t\t\t\th.store_i32(0, o.ary[1].to_col_rgb());\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\to = {\n\t\t\t\t\t\t\tconfig_type::ColorBGR::from_rgb(0),\n\t\t\t\t\t\t\tconfig_type::ColorBGR::from_rgb(h.load_i32<uint32_t>(0))\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t{\n\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::LayerHideAlpha, 8);\n\t\t\t\t\tif (auto& o = layer.hide_alpha) {\n\t\t\t\t\t\th.store_i64(0, std::bit_cast<uint64_t>(*o));\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\to = h.load_i64<double>(0);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t/*\n\t\t\t\t{\n\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::LayerNameRectWidth, 1);\n\t\t\t\t\tif (auto& o = layer.name_height) {\n\t\t\t\t\t\th.store_i8(0, static_cast<int8_t>(*o));\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\to = h.load_i8<uint8_t>(0);\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t\t*/\n\t\t\t}\n\n\t\t\t{\n\t\t\t\t{\n\t\t\t\t\tauto store = [](uint32_t adr, config_type::ColorBGR3& col) {\n\t\t\t\t\t\tOverWriteOnProtectHelper h(adr, 36);\n\t\t\t\t\t\tif (col.has_value()) {\n\t\t\t\t\t\t\th.store_i32(0 , col.ary[0].r);\n\t\t\t\t\t\t\th.store_i32(4 , col.ary[0].g);\n\t\t\t\t\t\t\th.store_i32(8 , col.ary[0].b);\n\t\t\t\t\t\t\th.store_i32(12, col.ary[1].r);\n\t\t\t\t\t\t\th.store_i32(16, col.ary[1].g);\n\t\t\t\t\t\t\th.store_i32(20, col.ary[1].b);\n\t\t\t\t\t\t\th.store_i32(24, col.ary[2].r);\n\t\t\t\t\t\t\th.store_i32(28, col.ary[2].g);\n\t\t\t\t\t\t\th.store_i32(32, col.ary[2].b);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tcol = {\n\t\t\t\t\t\t\t\tconfig_type::ColorBGR{\n\t\t\t\t\t\t\t\t\th.load_i32<int>(8),\n\t\t\t\t\t\t\t\t\th.load_i32<int>(4),\n\t\t\t\t\t\t\t\t\th.load_i32<int>(0)\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tconfig_type::ColorBGR{\n\t\t\t\t\t\t\t\t\th.load_i32<int>(20),\n\t\t\t\t\t\t\t\t\th.load_i32<int>(16),\n\t\t\t\t\t\t\t\t\th.load_i32<int>(12)\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tconfig_type::ColorBGR{\n\t\t\t\t\t\t\t\t\th.load_i32<int>(32),\n\t\t\t\t\t\t\t\t\th.load_i32<int>(28),\n\t\t\t\t\t\t\t\t\th.load_i32<int>(24)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tstore(GLOBAL::exedit_base + OFS::ExEdit::ObjectColorControl, object.control_col);\n\t\t\t\t\tstore(GLOBAL::exedit_base + OFS::ExEdit::ObjectColorMedia, object.media_col);\n\t\t\t\t\tstore(GLOBAL::exedit_base + OFS::ExEdit::ObjectColorMFilter, object.mfilter_col);\n\t\t\t\t\tstore(GLOBAL::exedit_base + OFS::ExEdit::ObjectColorSound, object.audio_col);\n\t\t\t\t\tstore(GLOBAL::exedit_base + OFS::ExEdit::ObjectColorSFilter, object.afilter_col);\n\t\t\t\t\tstore(GLOBAL::exedit_base + OFS::ExEdit::ObjectColorInactive, object.inactive_col);\n\t\t\t\t}\n\t\t\t\t{\n\t\t\t\t\tOverWriteOnProtectHelper hb(GLOBAL::exedit_base + OFS::ExEdit::ObjectClippingColorB, 5);\n\t\t\t\t\t//OverWriteOnProtectHelper hg(GLOBAL::exedit_base + OFS::ExEdit::ObjectClippingColorG, 1);\n\t\t\t\t\t//OverWriteOnProtectHelper hr(GLOBAL::exedit_base + OFS::ExEdit::ObjectClippingColorR, 1);\n\n\t\t\t\t\tif (auto& o = object.clipping_col; o.is_valid()) {\n\t\t\t\t\t\thb.store_i8(0, o.b);\n\t\t\t\t\t\thb.store_i8(2, o.g);\n\t\t\t\t\t\thb.store_i8(4, o.r);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\to = {\n\t\t\t\t\t\t\thb.load_i8<uint8_t>(0),\n\t\t\t\t\t\t\thb.load_i8<uint8_t>(2),\n\t\t\t\t\t\t\thb.load_i8<uint8_t>(4)\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t{\n\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::ObjectClippingHeight, 1);\n\t\t\t\t\tif (auto& o = object.clipping_height) \n\t\t\t\t\t\th.store_i8(0, static_cast<int8_t>(*o));\n\t\t\t\t\telse\n\t\t\t\t\t\to = h.load_i8<int8_t>(0);\n\t\t\t\t}\n\n\t\t\t\t{\n\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::MidPointSize, 12);\n\t\t\t\t\tif (auto& o = object.midpt_size; o) {\n\t\t\t\t\t\th.store_i32(0, static_cast<int>(o.value()[0]));\n\t\t\t\t\t\th.store_i32(4, static_cast<int>(o.value()[1]));\n\t\t\t\t\t\th.store_i32(8, static_cast<int>(o.value()[2]));\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\to.emplace();\n\t\t\t\t\t\to.value()[0] = h.load_i32(0);\n\t\t\t\t\t\to.value()[1] = h.load_i32(4);\n\t\t\t\t\t\to.value()[2] = h.load_i32(8);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t{\n\t\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + OFS::ExEdit::ObjectNameColor, 8 );\n\t\t\t\t\tif (auto& o = object.name_col; o.has_value()) {\n\t\t\t\t\t\th.store_i32(0, o.ary[0].to_col());\n\t\t\t\t\t\th.store_i32(4, o.ary[1].to_col());\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\to.ary[0] = h.load_i32<uint32_t>(0);\n\t\t\t\t\t\to.ary[1] = h.load_i32<uint32_t>(4);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t{\n\t\t\t\t{\n\t\t\t\t\tOverWriteOnProtectHelper hf(GLOBAL::exedit_base + OFS::ExEdit::ScaleColorForeGround, 4);\n\t\t\t\t\tOverWriteOnProtectHelper hb(GLOBAL::exedit_base + OFS::ExEdit::ScaleColorBackGround, 4);\n\t\t\t\t\t\n\t\t\t\t\tif (auto& val = timeline.scale_col; val.has_value()) {\n\t\t\t\t\t\thf.store_i32(0, val.ary[0].to_col_rgb());\n\t\t\t\t\t\thb.store_i32(0, val.ary[1].to_col_rgb());\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tval = {\n\t\t\t\t\t\t\tconfig_type::ColorBGR::from_rgb(hf.load_i32<uint32_t>(0)),\n\t\t\t\t\t\t\tconfig_type::ColorBGR::from_rgb(hb.load_i32<uint32_t>(0))\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\t{\n\t\t\t\t\tOverWriteOnProtectHelper hm(GLOBAL::exedit_base + OFS::ExEdit::BPMGridColorMeasure, 4);\n\t\t\t\t\tOverWriteOnProtectHelper hb(GLOBAL::exedit_base + OFS::ExEdit::BPMGridColorBeat, 4);\n\n\t\t\t\t\tif (auto& val = timeline.bpm_grid_col; val.has_value()) {\n\t\t\t\t\t\thm.store_i32(0, val.ary[0].to_col());\n\t\t\t\t\t\thb.store_i32(0, val.ary[1].to_col());\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tval = { hm.load_i32<uint32_t>(0),hb.load_i32<uint32_t>(0) };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tvoid switching(bool flag) {\n\t\t\tenabled = flag;\n\t\t}\n\n\t\tbool is_enabled() { return enabled; }\n\t\tbool is_enabled_i() { return enabled_i; }\n\n\t\tvoid switch_load(ConfigReader& cr) {\n\t\t\tcr.regist(key, [this](json_value_s* value) {\n\t\t\t\tConfigReader::load_variable(value, enabled);\n\t\t\t});\n\t\t}\n\n\t\tvoid switch_store(ConfigWriter& cw) {\n\t\t\tcw.append(key, enabled);\n\t\t}\n\n\t\tvoid config_load(ConfigReader& cr) {\n\t\t\tcr.regist(layer.name, [this](json_value_s* value) {\n\t\t\t\tConfigReader cr(value);\n\t\t\t\tlayer.load(cr);\n\t\t\t\tcr.load();\n\t\t\t});\n\t\t\tcr.regist(object.name, [this](json_value_s* value) {\n\t\t\t\tConfigReader cr(value);\n\t\t\t\tobject.load(cr);\n\t\t\t\tcr.load();\n\t\t\t});\n\t\t\tcr.regist(timeline.name, [this](json_value_s* value) {\n\t\t\t\tConfigReader cr(value);\n\t\t\t\ttimeline.load(cr);\n\t\t\t\tcr.load();\n\t\t\t});\n\t\t}\n\n\t\tvoid config_store(ConfigWriter& cw) {\n\t\t\t{\n\t\t\t\tConfigWriter cw_layer(cw.get_level() + 1);\n\t\t\t\tlayer.store(cw_layer);\n\t\t\t\tstd::stringstream ss;\n\t\t\t\tcw_layer.write(ss);\n\t\t\t\tcw.append(layer.name, ss.str());\n\t\t\t}\n\t\t\t{\n\t\t\t\tConfigWriter cw_object(cw.get_level() + 1);\n\t\t\t\tobject.store(cw_object);\n\t\t\t\tstd::stringstream ss;\n\t\t\t\tcw_object.write(ss);\n\t\t\t\tcw.append(object.name, ss.str());\n\t\t\t}\n\t\t\t{\n\t\t\t\tConfigWriter cw_timeline(cw.get_level() + 1);\n\t\t\t\ttimeline.store(cw_timeline);\n\t\t\t\tstd::stringstream ss;\n\t\t\t\tcw_timeline.write(ss);\n\t\t\t\tcw.append(timeline.name, ss.str());\n\t\t\t}\n\t\t}\n\t} theme_cc;\n} // namespace patch\n#endif // ifdef PATCH_SWITCH_THEME_CC\n"
  },
  {
    "path": "patch/patch_tra_aviutlfilter.hpp",
    "content": "/*\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU Lesser General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU Lesser General Public License for more details.\r\n    You should have received a copy of the GNU Lesser General Public License\r\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_TRA_AVIUTL_FILTER\r\n#include <memory>\r\n\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util.hpp\"\r\n\r\nnamespace patch {\r\n\r\n\t// init at exedit load\r\n\t// 拡張編集以外のフィルタのトラックバーにトラックバー変化方法スクリプトを適用していると例外になる\r\n\tinline class tra_aviutlfilter_t {\r\n        bool enabled = true;\r\n        bool enabled_i;\r\n        inline static const char key[] = \"tra_aviutlfilter\";\r\n\tpublic:\r\n\t\tvoid init() {\r\n            enabled_i = enabled;\r\n\r\n\t\t\tif (!enabled_i)return;\r\n\r\n\t\t\tauto& cursor = GLOBAL::executable_memory_cursor;\r\n\r\n            OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x06577a, 6);\r\n            h.store_i16(0, '\\x90\\xe9');\r\n            h.store_i32(2, cursor - (GLOBAL::exedit_base + 0x065780));\r\n            /*\r\n                1006577a 8b91d0000000  mov     edx,dword ptr [ecx+000000d0] ; filter_param_ptr->track_link\r\n                10065780 8b89cc000000  mov     ecx,dword ptr [ecx+000000cc] ; filter_param_ptr->track_scale\r\n                10065786 03c3          add     eax,ebx\r\n                10065788 50            push    eax\r\n                10065789 52            push    edx\r\n                1006578a 8b1481        mov     edx,dword ptr [ecx+eax*4]\r\n                1006578d 8b4514        mov     eax,dword ptr [ebp+14]\r\n\r\n\r\n                1006577a 8b91d0000000  mov     edx,dword ptr [ecx+000000d0]\r\n                ↓\r\n                1006577a 90e9XXXXXXXX  jmp     executable_memory_cursor\r\n\r\n                    ; 拡張編集以外のフィルタの場合は\r\n                    ; filter_param_ptr->track_link の部分を 0 に\r\n                    ; filter_param_ptr->track_scale[eax] の部分を 1 に\r\n            */\r\n\r\n            static const char code_put[] =\r\n                \"\\x03\\xc3\"          // add     eax, ebx\r\n                \"\\x50\"              // push    eax\r\n                \"\\x8a\\x51\\x03\"      // mov     dl,[ecx + 03]\r\n                \"\\xf6\\xc2\\x04\"      // test    dl,04\r\n                \"\\x74\\x14\"          // jz      +20byte\r\n                \"\\x8b\\x91\\xd0\"\r\n                \"\\x00\\x00\\x00\"      // mov     edx, dword ptr[ecx + 000000d0]\r\n                \"\\x8b\\x89\\xcc\"\r\n                \"\\x00\\x00\\x00\"      // mov     ecx, dword ptr[ecx + 000000cc]\r\n                \"\\x85\\xc9\"          // test    ecx\r\n                \"\\x0f\\x85XXXX\"      // jnz     exedit_base + 65789\r\n                \"\\x33\\xd2\"          // xor     edx\r\n                \"\\x52\"              // push    edx\r\n                \"\\x42\"              // inc     edx\r\n                \"\\xe9XXXX\"          // jmp     exedit_base + 6578d\r\n                ;\r\n\r\n            memcpy(cursor, code_put, sizeof(code_put) - 1);\r\n\r\n            store_i32(cursor + 27, GLOBAL::exedit_base + 0x065789 - (uint32_t)(cursor + 31));\r\n\r\n            cursor += sizeof(code_put) - 1;\r\n            store_i32(cursor - 4, GLOBAL::exedit_base + 0x06578d - (uint32_t)cursor);\r\n\t\t}\r\n        \r\n        void switching(bool flag) {\r\n            enabled = flag;\r\n        }\r\n\r\n        bool is_enabled() { return enabled; }\r\n        bool is_enabled_i() { return enabled_i; }\r\n\r\n        void switch_load(ConfigReader& cr) {\r\n            cr.regist(key, [this](json_value_s* value) {\r\n                ConfigReader::load_variable(value, enabled);\r\n            });\r\n        }\r\n\r\n        void switch_store(ConfigWriter& cw) {\r\n            cw.append(key, enabled);\r\n        }\r\n\t} tra_aviutlfilter;\r\n} // namespace patch\r\n\r\n#endif // ifdef PATCH_SWITCH_TRA_AVIUTL_FILTER\r\n"
  },
  {
    "path": "patch/patch_tra_change_drawfilter.cpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#include \"patch_tra_change_drawfilter.hpp\"\r\n\r\n#ifdef PATCH_SWITCH_TRA_CHANGE_DRAWFILTER\r\nnamespace patch {\r\n\r\n\tint __cdecl tra_change_drawfilter_t::switch_drawfilter_trackdata_to_mem(int* data, int object_idx, int track_begin, int track_id) {\r\n\t\tif (0 <= track_id) {\r\n\t\t\tauto& eop = (*ObjectArrayPointer_ptr)[object_idx];\r\n\t\t\tint tr = track_begin + track_id;\r\n\t\t\tdata[0] = eop.track_value_left[tr];\r\n\t\t\tdata[1] = eop.track_value_right[tr];\r\n\t\t\tdata[2] = *(int*)&eop.track_mode[tr];\r\n\t\t\tdata[3] = eop.track_param[tr];\r\n\t\t\treturn 4;\r\n\t\t}\r\n\t\treturn 0;\r\n\t}\r\n\r\n\tint __cdecl tra_change_drawfilter_t::switch_drawfilter_mem_to_trackdata(int* data, int object_idx, int track_begin, int pre_track_exists, int track_id) {\r\n\t\tif (0 <= pre_track_exists) {\r\n\t\t\tif (0 <= track_id) {\r\n\t\t\t\tauto& eop = (*ObjectArrayPointer_ptr)[object_idx];\r\n\t\t\t\tint tr = track_begin + track_id;\r\n\t\t\t\teop.track_value_left[tr] = data[0];\r\n\t\t\t\teop.track_value_right[tr] = data[1];\r\n\t\t\t\t*(int*)&eop.track_mode[tr] = data[2];\r\n\t\t\t\teop.track_param[tr] = data[3];\r\n\t\t\t}\r\n\t\t\treturn 4;\r\n\t\t}\r\n\t\treturn 0;\r\n\t}\r\n\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_TRA_CHANGE_DRAWFILTER"
  },
  {
    "path": "patch/patch_tra_change_drawfilter.hpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_TRA_CHANGE_DRAWFILTER\r\n\r\n#include <memory>\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util.hpp\"\r\n#include \"restorable_patch.hpp\"\r\n\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch {\r\n\t// init at exedit load\r\n\t// 標準描画-拡張描画-パーティクル出力 を切り替えた際にトラックの設定値(移動フレーム間隔)が0になるのを修正\r\n\t// 値を引き継ぐための関数に足りていなかったので追加した関数を置き換える\r\n\tinline class tra_change_drawfilter_t {\r\n\t\tstatic int __cdecl switch_drawfilter_trackdata_to_mem(int* data, int object_idx, int track_begin, int track_id);\r\n\t\tstatic int __cdecl switch_drawfilter_mem_to_trackdata(int* data, int object_idx, int track_begin, int pre_track_exists, int track_id);\r\n\r\n\t\tbool enabled = true;\r\n\t\tbool enabled_i;\r\n\r\n\t\tinline static const char key[] = \"tra_change_drawfilter\";\r\n\r\n\t\tinline static ExEdit::Object** ObjectArrayPointer_ptr;\r\n\r\n\tpublic:\r\n\r\n\t\tvoid init() {\r\n\t\t\tenabled_i = enabled;\r\n\r\n\t\t\tif (!enabled_i)return;\r\n\r\n\t\t\tObjectArrayPointer_ptr = reinterpret_cast<decltype(ObjectArrayPointer_ptr)>(GLOBAL::exedit_base + OFS::ExEdit::ObjectArrayPointer);\r\n\r\n\t\t\t{\r\n\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x44280, 5);\r\n\t\t\t\th.store_i8(0, '\\xe9'); // jmp\r\n\t\t\t\th.replaceNearJmp(1, &switch_drawfilter_trackdata_to_mem);\r\n\t\t\t}\r\n\t\t\t{\r\n\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x44530, 5);\r\n\t\t\t\th.store_i8(0, '\\xe9'); // jmp\r\n\t\t\t\th.replaceNearJmp(1, &switch_drawfilter_mem_to_trackdata);\r\n\t\t\t}\r\n\r\n\r\n\t\t}\r\n\t\tvoid switching(bool flag) {\r\n\t\t\tenabled = flag;\r\n\t\t}\r\n\r\n\t\tbool is_enabled() { return enabled; }\r\n\t\tbool is_enabled_i() { return enabled_i; }\r\n\r\n\t\tvoid switch_load(ConfigReader& cr) {\r\n\t\t\tcr.regist(key, [this](json_value_s* value) {\r\n\t\t\t\tConfigReader::load_variable(value, enabled);\r\n\t\t\t\t});\r\n\t\t}\r\n\r\n\t\tvoid switch_store(ConfigWriter& cw) {\r\n\t\t\tcw.append(key, enabled);\r\n\t\t}\r\n\r\n\t} tra_change_drawfilter;\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_TRA_CHANGE_DRAWFILTER\r\n"
  },
  {
    "path": "patch/patch_tra_specified_speed.hpp",
    "content": "/*\r\n\tThis program is free software: you can redistribute it and/or modify\r\n\tit under the terms of the GNU Lesser General Public License as published by\r\n\tthe Free Software Foundation, either version 3 of the License, or\r\n\t(at your option) any later version.\r\n\r\n\tThis program is distributed in the hope that it will be useful,\r\n\tbut WITHOUT ANY WARRANTY; without even the implied warranty of\r\n\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n\tGNU Lesser General Public License for more details.\r\n\r\n\tYou should have received a copy of the GNU Lesser General Public License\r\n\talong with this program.  If not, see <https://www.gnu.org/licenses/>.\r\n*/\r\n\r\n#pragma once\r\n#include \"macro.h\"\r\n\r\n#ifdef PATCH_SWITCH_TRA_SPECIFIED_SPEED\r\n\r\n#include <memory>\r\n#include <exedit.hpp>\r\n\r\n#include \"global.hpp\"\r\n#include \"offset_address.hpp\"\r\n#include \"util.hpp\"\r\n#include \"restorable_patch.hpp\"\r\n\r\n#include \"config_rw.hpp\"\r\n\r\nnamespace patch {\r\n\t// init at exedit load\r\n\t// トラック変化方式の「移動量指定」で計算が足りていなかった（主に時間制御との組み合わせでバグる）のを修正\r\n\tinline class tra_specified_speed_t {\r\n\r\n\t\tbool enabled = true;\r\n\t\tbool enabled_i;\r\n\r\n\t\tinline static const char key[] = \"tra_specified_speed\";\r\n\r\n\tpublic:\r\n\r\n        void init() {\r\n            enabled_i = enabled;\r\n\r\n            if (!enabled_i)return;\r\n\r\n            auto& cursor = GLOBAL::executable_memory_cursor;\r\n\r\n            /*\r\n\t\t\t\t1006821c 8b8cb7f8000000     mov     ecx,dword ptr [edi+esi*4+000000f8] ;ecx = obj[object_idx].track_value_left[track_begin]\r\n\t\t\t\t10068223 0faf442458         imul    eax,dword ptr [esp+58] ;eax *= obj_frame\r\n\t\t\t\t↓\r\n\t\t\t\t1006821c e8XxXxXxXx         call    bin_data\r\n\t\t\t\t10068221 8b8cb7f8000000     mov     ecx,dword ptr [edi+esi*4+000000f8] ;ecx = obj[object_idx].track_value_left[track_begin]\r\n\r\n\r\n\t\t\t\t; arg3_subframeが0以外の時はobj_frameが100倍されてarg3_subframeが加算されている\r\n\t\t\t\t; 移動量指定では100で割るコードを忘れている\r\n            */\r\n\r\n\r\n\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x06821c, 12);\r\n\t\t\th.store_i8(0, '\\xe8');\r\n\t\t\th.replaceNearJmp(1, cursor);\r\n\t\t\th.store_i32(5, '\\x8b\\x8c\\xb7\\xf8');\r\n\t\t\th.store_i32(8, '\\xf8\\x00\\x00\\x00'); // \\xf8は範囲ダブらせてstore_i32 * 2 で行っています\r\n\r\n\t\t\tstatic const char code_put[] =\r\n\t\t\t\t\"\\x0f\\xaf\\x44\\x24\\x5c\"     // imul    eax,dword ptr [esp+5c] ;eax *= obj_frame\r\n\t\t\t\t\"\\x8b\\x4d\\x10\"             // mov     ecx,dword ptr [ebp+10] ;ecx = arg3_subframe\r\n\t\t\t\t\"\\x85\\xc9\"                 // test    ecx,ecx\r\n\t\t\t\t\"\\x74\\x08\"                 // jz      skip 8 byte ;if(ecx == 0)return\r\n\t\t\t\t\"\\xb9\\x64\\x00\\x00\\x00\"     // mov     ecx,00000064 ;ecx = 100\r\n\t\t\t\t\"\\x99\"                     // cdq\r\n\t\t\t\t\"\\xf7\\xf9\"                 // idiv    ecx ;edx = eax % ecx, eax /= ecx\r\n\t\t\t\t\"\\xc3\"                     // ret      ;return\r\n\t\t\t\t;\r\n\r\n            memcpy(cursor, code_put, sizeof(code_put) - 1);\r\n\r\n            cursor += sizeof(code_put) - 1;\r\n        }\r\n\r\n\t\tvoid switching(bool flag) {\r\n\t\t\tenabled = flag;\r\n\t\t}\r\n\r\n\t\tbool is_enabled() { return enabled; }\r\n\t\tbool is_enabled_i() { return enabled_i; }\r\n\r\n\t\tvoid switch_load(ConfigReader& cr) {\r\n\t\t\tcr.regist(key, [this](json_value_s* value) {\r\n\t\t\t\tConfigReader::load_variable(value, enabled);\r\n\t\t\t\t});\r\n\t\t}\r\n\r\n\t\tvoid switch_store(ConfigWriter& cw) {\r\n\t\t\tcw.append(key, enabled);\r\n\t\t}\r\n\r\n\t} tra_specified_speed;\r\n} // namespace patch\r\n#endif // ifdef PATCH_SWITCH_TRA_SPECIFIED_SPEED\r\n"
  },
  {
    "path": "patch/patch_undo.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"patch_undo.hpp\"\n\nnamespace patch {\n#ifdef PATCH_SWITCH_UNDO\n\n    void __cdecl undo_t::set_undo_wrap_3e037(unsigned int object_idx, unsigned int flag) {\n        auto exists_movable_playback_pos = [](unsigned int object_idx) {\n            auto& exdata_buffer = *exdata_buffer_ptr;\n            auto eop = &(*ObjectArrayPointer_ptr)[object_idx];\n            for (int i = 0; i < 12; i++) {\n                auto fparam = &eop->filter_param[i];\n                switch (fparam->id) {\n                case FILTER_ID_MOVIE:\n                    if (eop->track_mode[fparam->track_begin].num == 0) {\n                        if (eop->check_value[fparam->check_begin] == 0) {\n                            auto exdata = reinterpret_cast<ExEdit::Exdata::efMovieFile*>(reinterpret_cast<uintptr_t>(exdata_buffer) + 4 + eop->exdata_offset + fparam->exdata_offset);\n                            if (exdata->frame_n > 0) {\n                                return true;\n                            }\n                        }\n                    }\n                    break;\n                case FILTER_ID_MOVIE_MIX:\n                    if (eop->track_mode[fparam->track_begin].num == 0) {\n                        if (eop->check_value[fparam->check_begin] == 0) {\n                            auto exdata = reinterpret_cast<ExEdit::Exdata::efMovieSynthesis*>(reinterpret_cast<uintptr_t>(exdata_buffer) + 4 + eop->exdata_offset + fparam->exdata_offset);\n                            if (exdata->frame_n > 0) {\n                                return true;\n                            }\n                        }\n                    }\n                    break;\n                case FILTER_ID_AUDIO:\n                    if (eop->track_mode[fparam->track_begin].num == 0) {\n                        if (eop->check_value[fparam->check_begin] == 0 && eop->check_value[fparam->check_begin + 1] == 0) {\n                            auto exdata = reinterpret_cast<ExEdit::Exdata::efAudioFile*>(reinterpret_cast<uintptr_t>(exdata_buffer) + 4 + eop->exdata_offset + fparam->exdata_offset);\n                            if (exdata->frame_n > 0) {\n                                return true;\n                            }\n                        }\n                    }\n                    break;\n                case FILTER_ID_WAVEFORM:\n                    if (eop->track_mode[fparam->track_begin].num == 0) {\n                        if (eop->check_value[fparam->check_begin + 3] == 0) {\n                            auto exdata = reinterpret_cast<ExEdit::Exdata::efWaveForm*>(reinterpret_cast<uintptr_t>(exdata_buffer) + 4 + eop->exdata_offset + fparam->exdata_offset);\n                            if (exdata->frame_n > 0) {\n                                return true;\n                            }\n                        }\n                    }\n                    break;\n                case FILTER_ID_SCENE:\n                    if (eop->track_mode[fparam->track_begin].num == 0) {\n                        if (eop->check_value[fparam->check_begin] == 0) {\n                            auto exdata = reinterpret_cast<ExEdit::Exdata::efScene*>(reinterpret_cast<uintptr_t>(exdata_buffer) + 4 + eop->exdata_offset + fparam->exdata_offset);\n                            if (scene_setting[exdata->scene].max_frame > 0) {\n                                return true;\n                            }\n                        }\n                    }\n                    break;\n                case FILTER_ID_SCENE_AUDIO:\n                    if (eop->track_mode[fparam->track_begin].num == 0) {\n                        if (eop->check_value[fparam->check_begin] == 0 && eop->check_value[fparam->check_begin + 1] == 0) {\n                            auto exdata = reinterpret_cast<ExEdit::Exdata::efSceneAudio*>(reinterpret_cast<uintptr_t>(exdata_buffer) + 4 + eop->exdata_offset + fparam->exdata_offset);\n                            if (scene_setting[exdata->scene].max_frame > 0) {\n                                return true;\n                            }\n                        }\n                    }\n                    break;\n                case -1:\n                    return false;\n                }\n            }\n            return false;\n        };\n\n        if (*timeline_obj_click_mode_ptr == 2 || (*timeline_obj_click_mode_ptr == 3 && (*timeline_edit_both_adjacent_ptr & 1))) { // 左端 || (右端 && 環境設定の隣接するオブジェクトも選択がON )\n            auto eop = &(*ObjectArrayPointer_ptr)[object_idx];\n            int obj_idx = eop->index_midpt_leader;\n            if (obj_idx == -1) {\n                if (exists_movable_playback_pos(object_idx)) {\n                    set_undo(object_idx, 0);\n                    return;\n                }\n            } else if (obj_idx == object_idx) {\n                if (exists_movable_playback_pos(obj_idx)) {\n                    while (0 <= obj_idx) {\n                        set_undo(obj_idx, 0);\n                        obj_idx = NextObjectIdxArray[obj_idx];\n                    }\n                    return;\n                }\n            }\n        }\n        set_undo(object_idx, flag);\n    }\n\n    int __cdecl undo_t::efDraw_func_WndProc_wrap_06e2b4(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, AviUtl::EditHandle* editp, ExEdit::Filter* efp) {\n        auto ret = efDraw_func_WndProc(hwnd, message, wparam, lparam, editp, efp);\n        if (ret) return ret;\n        if (LOWORD(wparam) == 7708) {\n            AddUndoCount();\n            set_undo(object(efp->processing) - 1, 1);\n        }\n        return ret;\n    }\n\n    int __stdcall undo_t::f8b97f(HWND hwnd, ExEdit::Filter* efp, WPARAM wparam, LPARAM lparam) {\n        interval_set_undo(object(efp->processing) - 1, 1);\n        return SendMessageA(hwnd, CB_GETLBTEXT, wparam, lparam);\n    }\n\n    int __stdcall undo_t::f8ba87_8bad5(ExEdit::Filter* efp, HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {\n        int ret = SendMessageA(hwnd, message, wparam, lparam);\n        if (ret != -1) {\n            AddUndoCount();\n            set_undo(object(efp->processing) - 1, 1);\n        }\n        return ret;\n    }\n\n    int __stdcall undo_t::f8bb4d_8bbcc(int value, int8_t* exdata, int offset, ExEdit::Filter* efp) {\n        if (value < -100) value = -100;\n        else if (100 < value) value = 100;\n        if (exdata[offset] != value) {\n            AddUndoCount();\n            set_undo(object(efp->processing) - 1, 1);\n        }\n        return value;\n    }\n\n    int* __stdcall undo_t::f59e27(WPARAM wparam, LPARAM lparam, ExEdit::Filter* efp, UINT message) {\n        if ((message != 0x702) || (wparam != 0x651e24)) return 0;\n\n        int* exdata_layer_num = (int*)efp->exdata_ptr;\n        int new_layer_num = *exdata_layer_num - *(int*)(lparam + 0x10);\n\n        if (new_layer_num < 0) new_layer_num = 0;\n        else if (99 < new_layer_num) new_layer_num = 99;\n\n        if (new_layer_num != *exdata_layer_num) {\n            AddUndoCount();\n            set_undo(object(efp->processing) - 1, 1);\n        }\n\n        return exdata_layer_num;\n    }\n\n    int __stdcall undo_t::f8b9f0(ExEdit::Filter* efp, HWND hWnd, LPWSTR lpString, int nMaxCount) {\n        interval_set_undo(object(efp->processing) - 1, 1);\n        return GetWindowTextW(hWnd, lpString, nMaxCount);\n    }\n\n    int __stdcall undo_t::f875ef(ExEdit::Filter* efp, HWND hWnd, LPWSTR lpString) {\n        return f8b9f0(efp, hWnd, lpString, 0x400);\n    }\n\n    int __cdecl undo_t::NormalizeExeditTimelineY_wrap_3c8fa_42629_42662_42924_42a0a(int timeline_y) {\n        timeline_y = NormalizeExeditTimelineY(timeline_y);\n        AddUndoCount();\n        set_undo(timeline_y, 0x10);\n        return timeline_y;\n    }\n\n    int __cdecl undo_t::NormalizeExeditTimelineY_wrap_4253e(int timeline_y) {\n        timeline_y = NormalizeExeditTimelineY(timeline_y);\n\n        AddUndoCount();\n        BOOL other_flag = FALSE;\n        for (int i = 0; i < 100; i++) {\n            if (timeline_y != i) {\n                if (has_flag((*layer_setting_ofsptr_ptr)[i].flag, ExEdit::LayerSetting::Flag::UnDisp)) {\n                    other_flag = TRUE;\n                    break;\n                }\n            }\n        }\n\n        if (has_flag((*layer_setting_ofsptr_ptr)[timeline_y].flag, ExEdit::LayerSetting::Flag::UnDisp)) {\n            set_undo(timeline_y, 0x10);\n        }\n\n        if (other_flag) {\n            for (int i = 0; i < 100; i++) {\n                if (timeline_y != i) {\n                    if (has_flag((*layer_setting_ofsptr_ptr)[i].flag, ExEdit::LayerSetting::Flag::UnDisp)) {\n                        set_undo(i, 0x10);\n                    }\n                }\n            }\n        }\n        else {\n            for (int i = 0; i < 100; i++) {\n                if (timeline_y != i) {\n                    if (!has_flag((*layer_setting_ofsptr_ptr)[i].flag, ExEdit::LayerSetting::Flag::UnDisp)) {\n                        set_undo(i, 0x10);\n                    }\n                }\n            }\n        }\n\n        return timeline_y;\n    }\n\n    ExEdit::Object* __stdcall undo_t::f42617() {\n        AddUndoCount();\n        set_undo((*ObjectArrayPointer_ptr)[*ObjDlg_ObjectIndex_ptr].layer_disp, 0x10);\n        return *ObjectArrayPointer_ptr;\n    }\n\n    void __stdcall undo_t::f4355c(ExEdit::Object* obj) {\n        AddUndoCount();\n        set_undo(obj - *ObjectArrayPointer_ptr, 0);\n        *(int*)&obj->flag ^= 0x200;\n    }\n\n    void __stdcall undo_t::f435bd(ExEdit::Object* obj) {\n        AddUndoCount();\n        set_undo(obj - *ObjectArrayPointer_ptr, 0);\n        *(int*)&obj->flag ^= 0x100;\n    }\n\n    void __cdecl undo_t::add_track_value_wrap(ExEdit::Filter* efp, int track_id, int add_value) {\n        interval_set_undo(object(efp->processing) - 1, 1);\n        add_track_value(efp, track_id, add_value);\n    }\n\n#endif\n}\n"
  },
  {
    "path": "patch/patch_undo.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"macro.h\"\n#ifdef PATCH_SWITCH_UNDO\n\n#include <exedit.hpp>\n#include \"util_magic.hpp\"\n#include \"global.hpp\"\n#include \"offset_address.hpp\"\n#include \"config_rw.hpp\"\n\n// ty saunazo\n\nnamespace patch {\n\n    // init at exedit load\n    inline class undo_t {\n\n        inline static ExEdit::Object** ObjectArrayPointer_ptr;\n        inline static int* NextObjectIdxArray;\n        inline static ExEdit::LayerSetting** layer_setting_ofsptr_ptr;\n        inline static void** exdata_buffer_ptr;\n        inline static int* timeline_obj_click_mode_ptr;\n        inline static int* ObjDlg_ObjectIndex_ptr;\n        inline static int* timeline_edit_both_adjacent_ptr;\n        inline static int* UndoInfo_current_id_ptr;\n\n        inline static ExEdit::SceneSetting* scene_setting;\n\n        inline static void(__cdecl*set_undo)(unsigned int, unsigned int);\n        inline static void(__cdecl*AddUndoCount)();\n        inline static int(__cdecl*efDraw_func_WndProc)(HWND, UINT, WPARAM, LPARAM, AviUtl::EditHandle*, ExEdit::Filter*);\n        inline static int(__cdecl*NormalizeExeditTimelineY)(int);\n        inline static void(__cdecl *add_track_value)(ExEdit::Filter*, int, int);\n        \n        inline constexpr static int UNDO_INTERVAL = 1000;\n\n\t\tstatic void __cdecl set_undo_wrap_42878(unsigned int object_idx, int layer_id) {\n\t\t\tif (layer_id < (*ObjectArrayPointer_ptr)[object_idx].layer_disp) {\n\t\t\t\tset_undo(object_idx, 8);\n\t\t\t}\n\t\t}\n\n\t\tstatic void __cdecl set_undo_wrap_40e5c(unsigned int object_idx, unsigned int flag) {\n\t\t\t// select_idx_list\n\t\t\tset_undo(reinterpret_cast<int*>(GLOBAL::exedit_base + 0x179230)[object_idx], flag);\n\t\t}\n\n\n        inline constexpr static int FILTER_ID_MOVIE = 0; // track 0 check 0 exdata 268 = maxframe\n        inline constexpr static int FILTER_ID_AUDIO = 2; // track 0 check 0,1 exdata 268 = maxframe\n        inline constexpr static int FILTER_ID_WAVEFORM = 6; // track 0 check 3 exdata 268 = maxframe\n        inline constexpr static int FILTER_ID_SCENE = 7; // track 0 check 0 exdata 0 = sceneid\n        inline constexpr static int FILTER_ID_SCENE_AUDIO = 8; // track 0 check 0,1 exdata 0 = sceneid\n        inline constexpr static int FILTER_ID_MOVIE_MIX = 82; // track 0 check 0 exdata 268 = maxframe\n\n        static void __cdecl set_undo_wrap_3e037(unsigned int object_idx, unsigned int flag);\n\n        static int __cdecl efDraw_func_WndProc_wrap_06e2b4(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, AviUtl::EditHandle* editp, ExEdit::Filter* efp);\n\n        static int __stdcall f8b97f(HWND hwnd, ExEdit::Filter* efp, WPARAM wparam, LPARAM lparam);\n\n        static int __stdcall f8ba87_8bad5(ExEdit::Filter* efp, HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);\n\n        static int __stdcall f8bb4d_8bbcc(int value, int8_t* exdata, int offset, ExEdit::Filter* efp);\n\n        static int* __stdcall f59e27(WPARAM wparam, LPARAM lparam, ExEdit::Filter* efp, UINT message);\n\n        static int __stdcall f8b9f0(ExEdit::Filter* efp, HWND hWnd, LPWSTR lpString, int nMaxCount);\n        \n        static int __stdcall f875ef(ExEdit::Filter* efp, HWND hWnd, LPWSTR lpString);\n\n        static int __cdecl NormalizeExeditTimelineY_wrap_3c8fa_42629_42662_42924_42a0a(int timeline_y);\n\n        static int __cdecl NormalizeExeditTimelineY_wrap_4253e(int timeline_y);\n\n        static ExEdit::Object* __stdcall f42617();\n\n        static void __stdcall f4355c(ExEdit::Object* obj);\n\n        static void __stdcall f435bd(ExEdit::Object* obj);\n\n        static void __cdecl add_track_value_wrap(ExEdit::Filter* efp, int track_id, int add_value);\n\n        static void interval_set_undo(int object_idx, int flag) {\n            static ULONGLONG pretime = 0;\n            static int pre_undo_id = 0;\n            int& UndoInfo_current_id = *UndoInfo_current_id_ptr;\n            ULONGLONG time = GetTickCount64();\n            if (pretime < time - UNDO_INTERVAL || pre_undo_id != UndoInfo_current_id) {\n                AddUndoCount();\n                set_undo(object_idx, flag);\n            }\n            pretime = time;\n            pre_undo_id = UndoInfo_current_id;\n        }\n\n        bool enabled = true;\n        bool enabled_i;\n\n        inline static const char key[] = \"undo\";\n\n    public:\n\n\t\tvoid init() {\n            enabled_i = enabled;\n            if (!enabled_i) return;\n\n            ObjectArrayPointer_ptr = reinterpret_cast<decltype(ObjectArrayPointer_ptr)>(GLOBAL::exedit_base + OFS::ExEdit::ObjectArrayPointer);\n            NextObjectIdxArray = reinterpret_cast<int*>(GLOBAL::exedit_base + OFS::ExEdit::NextObjectIdxArray);\n            layer_setting_ofsptr_ptr = reinterpret_cast<decltype(layer_setting_ofsptr_ptr)>(GLOBAL::exedit_base + 0x0a4058);\n            exdata_buffer_ptr = reinterpret_cast<void**>(GLOBAL::exedit_base + 0x1e0fa8);\n            timeline_obj_click_mode_ptr = reinterpret_cast<int*>(GLOBAL::exedit_base + 0x177a24);\n            ObjDlg_ObjectIndex_ptr = reinterpret_cast<int*>(GLOBAL::exedit_base + 0x177a10);\n            timeline_edit_both_adjacent_ptr = reinterpret_cast<int*>(GLOBAL::exedit_base + 0x14ea00);\n            scene_setting = reinterpret_cast<decltype(scene_setting)>(GLOBAL::exedit_base + 0x177a50);\n            UndoInfo_current_id_ptr = reinterpret_cast<decltype(UndoInfo_current_id_ptr)>(GLOBAL::exedit_base + 0x244e14);\n\t\t\t\n            set_undo = reinterpret_cast<decltype(set_undo)>(GLOBAL::exedit_base + 0x08d290);\n            AddUndoCount = reinterpret_cast<decltype(AddUndoCount)>(GLOBAL::exedit_base + 0x08d150);\n            efDraw_func_WndProc = reinterpret_cast<decltype(efDraw_func_WndProc)>(GLOBAL::exedit_base + 0x01b550);\n            NormalizeExeditTimelineY = reinterpret_cast<decltype(NormalizeExeditTimelineY)>(GLOBAL::exedit_base + 0x032c10);\n            add_track_value = reinterpret_cast<decltype(add_track_value)>(GLOBAL::exedit_base + 0x01c0f0);\n\n\n\t\t\t// レイヤー削除→元に戻すで他シーンのオブジェクトが消える\n\t\t\t{\n\t\t\t\tOverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x042875, 2);\n\t\t\t\th.store_i8(0, '\\x56'); // push esi=layer_id\n\t\t\t\th.store_i8(1, '\\x90'); // nop\n\t\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x042879, &set_undo_wrap_42878);\n\t\t\t}\n\n\t\t\t// Ctrlで複数オブジェクトを選択しながら設定ダイアログのトラックバーを動かすと一部オブジェクトが正常に戻らない\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x040e5d, &set_undo_wrap_40e5c);\n\n\t\t\t// オブジェクトの左端をつまんで動かすと再生位置パラメータが変わるが、それが元に戻らない\n\t\t\tReplaceNearJmp(GLOBAL::exedit_base + 0x03e038, &set_undo_wrap_3e037);\n\t\t\t\n\t\t\t// 一部フィルタのファイル参照を変更→元に戻すで設定ダイアログが更新されない(音声波形など)\n\t\t\tOverWriteOnProtectHelper(GLOBAL::exedit_base + 0x08d50e, 4).store_i32(0, '\\x0f\\x1f\\x40\\x00'); // nop\n\n            // 部分フィルタのマスクの種類を変更してもUndoデータが生成されない\n            ReplaceNearJmp(GLOBAL::exedit_base + 0x06e2b5, &efDraw_func_WndProc_wrap_06e2b4);\n\n            // テキストオブジェクトのフォントを変更してもUndoデータが生成されない\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x08b97c, 8);\n                h.store_i32(0, '\\x90\\x57\\x51\\xe8'); // nop; push edi=efp; push ecx; call (rel32)\n                h.replaceNearJmp(4, &f8b97f);\n            }\n\n            // テキストオブジェクトの影付き・縁付きを変更してもUndoデータが生成されない\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x08ba86, 2);\n                h.store_i16(0, '\\x57\\xe8'); // push edi=efp; call (rel32)\n                ReplaceNearJmp(GLOBAL::exedit_base + 0x08ba88, &f8ba87_8bad5);\n            }\n\n            // テキストオブジェクトの文字配置(左寄せ[上]など)を変更してもUndoデータが生成されない\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x08bad4, 6);\n                h.store_i16(0, '\\x57\\xe8'); // push edi=efp; call (rel32)\n                h.replaceNearJmp(2, &f8ba87_8bad5);\n            }\n\n            // テキストオブジェクトの字間を変更してもUndoデータが生成されない\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x08bb48, 10);\n                h.store_i32(0, '\\x57\\x6a\\x05\\x56'); // push edi=efp; push 5; push esi=exdata\n                h.store_i16(4, '\\x50\\xe8'); //  push eax=value; call rel32\n                h.replaceNearJmp(6, &f8bb4d_8bbcc);\n            }\n\n            // テキストオブジェクトの行間を変更してもUndoデータが生成されない\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x08bbc7, 10);\n                h.store_i32(0, '\\x57\\x6a\\x06\\x56'); // push edi=efp; push 6; push esi=exdata\n                h.store_i16(4, '\\x50\\xe8'); //  push eax=value; call rel32\n                h.replaceNearJmp(6, &f8bb4d_8bbcc);\n            }\n\n            // グループ制御とかの対象レイヤー数を変更してもUndoデータが生成されない\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x059e1b, 20);\n                const char patch[] = {\n                    \"\\x51\" // push ecx=message\n                    \"\\x50\" // push eax=efp\n                    \"\\x8b\\x4c\\x24\\x28\" // mov ecx, dword ptr[esp + 0x28]=lparam\n                    \"\\x51\" // push ecx\n                    \"\\x8b\\x4c\\x24\\x28\" // mov ecx, dword ptr[esp + 0x28]=wparam\n                    \"\\x51\" // push ecx\n                    \"\\xe8XXXX\" // call rel32\n                    \"\\x85\\xc0\" // test eax, eax\n                    \"\\x74\" /* 0x6e */ // JZ +0x6e\n                };\n                memcpy(reinterpret_cast<void*>(h.address()), patch, sizeof(patch) - 1);\n                h.replaceNearJmp(13, &f59e27);\n            }\n\n            // テキストを変更してもUndoデータが生成されない\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x08b9ef, 6);\n                h.store_i16(0, '\\x57\\xe8'); // push edi; call (rel32)\n                h.replaceNearJmp(2, &f8b9f0);\n            }\n\n            // スクリプト制御・カメラスクリプトを変更してもUndoデータが生成されない\n            {\n                // 100875e7 68 00 04 00 00    PUSH       0x400\n                // 100875ec 56                PUSH       ESI\n                // 100875ed 51                PUSH       ECX\n                // 100875ee ff 15 54 a2 09 10 CALL       dword ptr [->USER32.DLL::GetWindowTextW] = 0009bc30\n                // ↓\n                // 100875e7 8b 54 24 38       MOV EDX, DWORD PTR [ESP+38H]\n                // 100875eb 90                NOP\n                // 100875ec 56                PUSH ESI\n                // 100875ed 51                PUSH ECX\n                // 100875ee 52                PUSH EDX\n                // 100875ef e8 XXXX           CALL rel32\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x0875e7, 13);\n                h.store_i32(0, '\\x8b\\x54\\x24\\x38');\n                h.store_i32(4, '\\x90\\x56\\x51\\x52');\n                h.store_i8(8, '\\xe8');\n                h.replaceNearJmp(9, &f875ef);\n            }\n\n\n            // 左クリックよりレイヤーの表示状態を変更してもUndoデータが生成されない\n            ReplaceNearJmp(GLOBAL::exedit_base + 0x03c8fb, &NormalizeExeditTimelineY_wrap_3c8fa_42629_42662_42924_42a0a);\n\n            // 右クリックメニューよりレイヤーの表示状態を変更してもUndoデータが生成されない\n            ReplaceNearJmp(GLOBAL::exedit_base + 0x04262a, &NormalizeExeditTimelineY_wrap_3c8fa_42629_42662_42924_42a0a);\n\n            // 右クリックメニューよりレイヤーのロック状態を変更してもUndoデータが生成されない\n            ReplaceNearJmp(GLOBAL::exedit_base + 0x042663, &NormalizeExeditTimelineY_wrap_3c8fa_42629_42662_42924_42a0a);\n\n            // 右クリックメニューよりレイヤーの座標のリンク状態を変更してもUndoデータが生成されない\n            ReplaceNearJmp(GLOBAL::exedit_base + 0x042925, &NormalizeExeditTimelineY_wrap_3c8fa_42629_42662_42924_42a0a);\n\n            // 右クリックメニューより上クリッピング状態を変更してもUndoデータが生成されない\n            ReplaceNearJmp(GLOBAL::exedit_base + 0x042a0b, &NormalizeExeditTimelineY_wrap_3c8fa_42629_42662_42924_42a0a);\n\n            // 右クリックメニューより他のレイヤーを全表示/非表示を押してもUndoデータが生成されない\n            ReplaceNearJmp(GLOBAL::exedit_base + 0x04253f, &NormalizeExeditTimelineY_wrap_4253e);\n\n            // ショートカットよりレイヤーの表示状態を変更してもUndoデータが生成されない\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x042617, 5);\n                h.store_i8(0, '\\xe8');\n                h.replaceNearJmp(1, &f42617);\n            }\n\n            // カメラ制御の対象 を切り替えてもUndoデータが生成されない\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x04355b, 6);\n                h.store_i16(0, '\\x51\\xe8'); // push ecx, call (rel32)\n                h.replaceNearJmp(2, &f4355c);\n            }\n            // 上のオブジェクトでクリッピング を切り替えてもUndoデータが生成されない\n            {\n                OverWriteOnProtectHelper h(GLOBAL::exedit_base + 0x0435ba, 8);\n                h.store_i32(0, '\\x90\\x90\\x50\\xe8'); // nop, push eax, call (rel32)\n                h.replaceNearJmp(4, &f435bd);\n            }\n\n            // テンキー2468+-*/ Ctrl+テンキー2468 で(座標XY 回転 拡大率 中心XY)トラックバーを変えてもUndoデータが生成されない\n            ReplaceNearJmp(GLOBAL::exedit_base + 0x01b611, &add_track_value_wrap); // テンキー4座標X-\n            ReplaceNearJmp(GLOBAL::exedit_base + 0x01b646, &add_track_value_wrap); // Ctrl+テンキー6中心X+\n            ReplaceNearJmp(GLOBAL::exedit_base + 0x01b674, &add_track_value_wrap); // テンキー6座標X+\n            ReplaceNearJmp(GLOBAL::exedit_base + 0x01b6ab, &add_track_value_wrap); // Ctrl+テンキー8中心Y-\n            ReplaceNearJmp(GLOBAL::exedit_base + 0x01b6db, &add_track_value_wrap); // テンキー8座標Y-\n            ReplaceNearJmp(GLOBAL::exedit_base + 0x01b710, &add_track_value_wrap); // Ctrl+テンキー2中心Y+, Ctrl+テンキー4中心X-\n            ReplaceNearJmp(GLOBAL::exedit_base + 0x01b73e, &add_track_value_wrap); // テンキー2座標Y+\n            ReplaceNearJmp(GLOBAL::exedit_base + 0x01b765, &add_track_value_wrap); // テンキー-拡大率-\n            ReplaceNearJmp(GLOBAL::exedit_base + 0x01b78c, &add_track_value_wrap); // テンキー+拡大率+\n            ReplaceNearJmp(GLOBAL::exedit_base + 0x01b7b0, &add_track_value_wrap); // テンキー/回転-\n            ReplaceNearJmp(GLOBAL::exedit_base + 0x01b7d4, &add_track_value_wrap); // テンキー*回転+\n\n\n\t\t}\n\n        \n        void switching(bool flag) {\n            enabled = flag;\n        }\n\n        bool is_enabled() { return enabled; }\n        bool is_enabled_i() { return enabled_i; }\n\n        void switch_load(ConfigReader& cr) {\n            cr.regist(key, [this](json_value_s* value) {\n                ConfigReader::load_variable(value, enabled);\n            });\n        }\n\n        void switch_store(ConfigWriter& cw) {\n            cw.append(key, enabled);\n        }\n\t} undo;\n}\n\n\n#endif\n"
  },
  {
    "path": "patch/resource.h",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#define PATCH_MENU_INFO 20001\n#define PATCH_MENU_CONSOLE 20002\n\n#define PATCH_EXEDITMENU_REDO 2000\n\n#define PATCH_RS_PATCH_FAILED_TO_SAVE_SETTING 9000\n#define PATCH_RS_PATCH_FAILED_TO_LOAD_SETTING 9001\n#define PATCH_RS_PATCH_FAILED_TO_INIT_CONSOLE 9002\n#define PATCH_RS_PATCH_CONSOLE_IS_DIABLED 9003\n#define PATCH_RS_PATCH_INVALID_SETTING_JSON 9004\n#define PATCH_RS_PATCH_FAILED_TO_CREATE_EXCEPTION_DIALOG 9005\n#define PATCH_RS_PATCH_CONFLICT_PLUGIN 9006\n#define PATCH_RS_PATCH_OLD_LSW 9007\n#define PATCH_RS_PATCH_CANT_USE_CL 9010\n#define PATCH_RS_PATCH_WEB_CONFIRM 9011\n#define PATCH_RS_PATCH_WEB_CONFIRM_BUTTON_OPEN 9012\n#define PATCH_RS_PATCH_WEB_CONFIRM_BUTTON_COPY 9013\n#define PATCH_RS_PATCH_WEB_CONFIRM_BUTTON_CANCEL 9014\n\n#define PATCH_RS_EXEDIT_INFORMATION 10000\n\n#define PATCH_ID_EXCEPTION_OK 101\n#define PATCH_ID_EXCEPTION_DETAIL_BUTTON 102\n#define PATCH_ID_EXCEPTION_SAVE_PROJECT 103\n#define PATCH_ID_EXCEPTION_DETAIL_TEXT 111\n#define PATCH_ID_EXCEPTION_LABEL1 121\n#define PATCH_ID_EXCEPTION_LABEL2 122\n#define PATCH_ID_EXCEPTION_LINK 131\n#define PATCH_ID_EXCEPTION_STOPMES 141\n#define PATCH_ID_EXCEPTION_THREADID_COMBO 151\n"
  },
  {
    "path": "patch/restorable_patch.hpp",
    "content": "#pragma once\n#include <vector>\n#include <bit>\n\n#include \"util_magic.hpp\"\n\nclass restorable_patch {\nprotected:\n\tstd::vector<std::byte> data;\n\tstd::uintptr_t address;\n\n\tbool state;\n\n\trestorable_patch(std::uintptr_t address, std::vector<std::byte>&& data) : data(std::move(data)), address(address), state(false) {}\n\npublic:\n\trestorable_patch(std::uintptr_t address, void* data, size_t length) : data(static_cast<std::byte*>(data), static_cast<std::byte*>(data) + length), address(address), state(false) {}\n\n\tvoid swap_data() {\n\t\tOverWriteOnProtectHelper h(address, data.size());\n\t\tfor (size_t i = 0; i < data.size(); i++) {\n\t\t\tauto tmp = load_i8<std::byte>(address + i);\n\t\t\tstore_i8(address + i, data[i]);\n\t\t\tdata[i] = tmp;\n\t\t}\n\t}\n\n\tvoid switch_true_to_false() {\n\t\tswap_data();\n\t}\n\n\tvoid switch_false_to_true() {\n\t\tswap_data();\n\t}\n\n\tvoid switching(bool flag) {\n\t\tif (flag) {\n\t\t\tif (!state) {\n\t\t\t\tswitch_false_to_true();\n\t\t\t\tstate = flag;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif (state) {\n\t\t\t\tswitch_true_to_false();\n\t\t\t\tstate = flag;\n\t\t\t}\n\t\t}\n\t}\n};\n\nclass restorable_patch_function : public restorable_patch {\n\tstatic std::vector<std::byte> make_data(std::uintptr_t address, void* newfunc) {\n\t\tstatic std::vector<std::byte> ret;\n\t\tret.resize(5);\n\t\tret[0] = std::byte{ 0xe9 };\n\t\tstore_i32(&ret[1], CalcNearJmp(address + 1, reinterpret_cast<i32>(newfunc)));\n\t\treturn ret;\n\t}\npublic:\n\trestorable_patch_function(std::uintptr_t address, void* newfunc) : restorable_patch(address, std::move(make_data(address, newfunc))) {}\n};\n\nclass restorable_patch_i8 : public restorable_patch {\n\tstatic std::vector<std::byte> make_data(i8 value) {\n\t\tstatic std::vector<std::byte> ret;\n\t\tret.resize(1);\n\t\tstore_i8(&ret[0], value);\n\t\treturn ret;\n\t}\npublic:\n\ttemplate<class T>\n\trestorable_patch_i8(std::uintptr_t address, T value) : restorable_patch(address, std::move(make_data((i8)value))) {}\n};\n\nclass restorable_patch_i16 : public restorable_patch {\n\tstatic std::vector<std::byte> make_data(i16 value) {\n\t\tstatic std::vector<std::byte> ret;\n\t\tret.resize(2);\n\t\tstore_i16(&ret[0], value);\n\t\treturn ret;\n\t}\npublic:\n\ttemplate<class T>\n\trestorable_patch_i16(std::uintptr_t address, T value) : restorable_patch(address, std::move(make_data((i16)value))) {}\n};\n\nclass restorable_patch_i32 : public restorable_patch {\n\tstatic std::vector<std::byte> make_data(i32 value) {\n\t\tstatic std::vector<std::byte> ret;\n\t\tret.resize(4);\n\t\tstore_i32(&ret[0], value);\n\t\treturn ret;\n\t}\npublic:\n\ttemplate<class T>\n\trestorable_patch_i32(std::uintptr_t address, T value) : restorable_patch(address, std::move(make_data((i32)value))) {}\n};\n"
  },
  {
    "path": "patch/stopwatch.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include <chrono>\n#include <iostream>\n\n#include \"debug_log.hpp\"\n\nclass stopwatch {\n#ifdef PATCH_STOPWATCH\n\tstd::chrono::system_clock::time_point start;\npublic:\n\tstopwatch() noexcept : start(std::chrono::system_clock::now()) {}\n\t~stopwatch() {\n\t\tprint();\n\t}\n\tlong long now() const noexcept {\n\t\tauto end = std::chrono::system_clock::now();\n\t\treturn std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();\n\t}\n\tvoid print() const noexcept {\n\t\tdebug_log(\"{} us\", now());\n\t}\n#else\npublic:\n\tlong long now() const noexcept { return 0; }\n\tvoid print() const noexcept {}\n#endif\n};\n\nclass stopwatch_mem {\n#ifdef PATCH_STOPWATCH\n\tstd::chrono::system_clock::time_point start_tp;\n\tlong long sum;\n\tlong long cnt;\n\n\tlong long now() const noexcept {\n\t\tauto end = std::chrono::system_clock::now();\n\t\treturn std::chrono::duration_cast<std::chrono::microseconds>(end - start_tp).count();\n\t}\npublic:\n\tstopwatch_mem() noexcept : start_tp{}, sum{}, cnt{} {}\n\t~stopwatch_mem() {}\n\tvoid start() noexcept {\n\t\tstart_tp = std::chrono::system_clock::now();\n\t}\n\tvoid stop() noexcept {\n\t\tauto time = now();\n\t\tcnt++;\n\t\tsum += time;\n\t\tdebug_log(\"{} us  ave : {} us\", time, sum / cnt);\n\t}\n#else\npublic:\n\tvoid start() noexcept {}\n\tvoid stop() noexcept {}\n#endif\n};\n"
  },
  {
    "path": "patch/timer.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include <functional>\n#include <chrono>\n#include <vector>\n#include <thread>\n#include <atomic>\n#include <unordered_map>\n\n#include <Windows.h>\n\nclass Timer;\nextern Timer timer;\n\ninline class Timer {\n\tusing timer_func = std::function<void()>;\n\n\tstd::unordered_map<UINT_PTR, timer_func> list;\n\n\tstatic VOID CALLBACK timerproc(HWND, UINT, UINT_PTR nIDEvent, DWORD) {\n\t\tconst auto& list = timer.list;\n\t\tif (auto func = list.find(nIDEvent); func != list.end())\n\t\t\tfunc->second();\n\t}\n\npublic:\n\t~Timer() {\n\t\tfor (auto [id, _] : list) {\n\t\t\tKillTimer(NULL, id);\n\t\t}\n\t}\n\n\tvoid set(timer_func f, UINT elapse) {\n\t\tUINT_PTR try_id = 1;\n\t\tUINT_PTR timer_id;\n\t\twhile ((timer_id = SetTimer(NULL, try_id, elapse, timerproc)) == 0) {\n\t\t\ttry_id++;\n\t\t}\n\t\tlist.try_emplace(timer_id, f);\n\t}\n} timer;\n"
  },
  {
    "path": "patch/util.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"util_int.hpp\"\n#include \"util_pe.hpp\"\n#include \"util_magic.hpp\"\n#include \"util_others.hpp\"\n#include \"util_resource.hpp\"\n"
  },
  {
    "path": "patch/util_int.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include <cstdint>\n#include <type_traits>\n#include <utility>\n\nusing i8 = uint8_t;\nusing i16 = uint16_t;\nusing i32 = uint32_t;\nusing i64 = uint64_t;\n\ninline void store_i8(auto address, auto value) {\n\t*std::bit_cast<i8*>(address) = (i8)value;\n}\ninline void store_i16(auto address, auto value) {\n\t*std::bit_cast<i16*>(address) = (i16)value;\n}\ninline void store_i32(auto address, auto value) {\n\t*std::bit_cast<i32*>(address) = (i32)value;\n}\ninline void store_i64(auto address, auto value) {\n\t*std::bit_cast<i64*>(address) = (i64)value;\n}\n\ntemplate<class T0 = uint8_t, class T1>\ninline T0 load_i8(T1 address) {\n\tstatic_assert(sizeof(T0) == sizeof(i8));\n\treturn *std::bit_cast<std::add_pointer_t<T0>>(address);\n}\ntemplate<class T0 = uint16_t, class T1>\ninline T0 load_i16(T1 address) {\n\tstatic_assert(sizeof(T0) == sizeof(i16));\n\treturn *std::bit_cast<std::add_pointer_t<T0>>(address);\n}\ntemplate<class T0 = uint32_t, class T1>\ninline T0 load_i32(T1 address) {\n\tstatic_assert(sizeof(T0) == sizeof(i32));\n\treturn *std::bit_cast<std::add_pointer_t<T0>>(address);\n}\ntemplate<class T0 = uint64_t, class T1>\ninline T0 load_i64(T1 address) {\n\tstatic_assert(sizeof(T0) == sizeof(i64));\n\treturn *std::bit_cast<std::add_pointer_t<T0>>(address);\n}\n\ntemplate<class T0, class T1>\ninline T1 exchange_i8(T0 address, T1&& value) {\n\treturn (T1)std::exchange(*std::bit_cast<i8*>(address), (i8)value);\n}\ntemplate<class T0, class T1>\ninline T1 exchange_i16(T0 address, T1&& value) {\n\treturn (T1)std::exchange(*std::bit_cast<i16*>(address), (i16)value);\n}\ntemplate<class T0, class T1>\ninline T1 exchange_i32(T0 address, T1&& value) {\n\treturn (T1)std::exchange(*std::bit_cast<i32*>(address), (i32)value);\n}\ntemplate<class T0, class T1>\ninline T1 exchange_i64(T0 address, T1&& value) {\n\treturn (T1)std::exchange(*std::bit_cast<i64*>(address), (i64)value);\n}\n"
  },
  {
    "path": "patch/util_magic.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include <cstdint>\n#include <bit>\n#include <algorithm>\n\n#include <Windows.h>\n\n#include \"global.hpp\"\n\n#include \"util_int.hpp\"\n#include \"util_pe.hpp\"\n\ninline i32 CalcNearJmp(i32 address, i32 jmp_address) {\n\treturn jmp_address - (address + 4);\n}\n\nclass OverWriteOnProtectHelper {\n\tuintptr_t m_address, m_size;\n\tDWORD m_oldProtect;\npublic:\n\ttemplate<class T>\n\tOverWriteOnProtectHelper(T address, uintptr_t size) noexcept : m_address((uintptr_t)address), m_size(size) {\n\t\tVirtualProtect(reinterpret_cast<LPVOID>(m_address), m_size, PAGE_EXECUTE_READWRITE, &m_oldProtect);\n\t}\n\t~OverWriteOnProtectHelper() noexcept {\n\t\tVirtualProtect(reinterpret_cast<LPVOID>(m_address), m_size, m_oldProtect, &m_oldProtect);\n\t}\n\n\ttemplate<class T1, class T2>\n\tvoid store_i8(T1 address, T2 value) const {\n\t\t::store_i8(m_address + address, value);\n\t}\n\ttemplate<class T1, class T2>\n\tvoid store_i16(T1 address, T2 value) const {\n\t\t::store_i16(m_address + address, value);\n\t}\n\ttemplate<class T1, class T2>\n\tvoid store_i32(T1 address, T2 value) const {\n\t\t::store_i32(m_address + address, value);\n\t}\n\ttemplate<class T1, class T2>\n\tvoid store_i64(T1 address, T2 value) const {\n\t\t::store_i64(m_address + address, value);\n\t}\n\n\ttemplate<class T0 = uint8_t, class T1>\n\tT0 load_i8(T1 address) const {\n\t\treturn ::load_i8<T0>(m_address + address);\n\t}\n\ttemplate<class T0 = uint16_t, class T1>\n\tT0 load_i16(T1 address) const {\n\t\treturn ::load_i16<T0>(m_address + address);\n\t}\n\ttemplate<class T0 = uint32_t, class T1>\n\tT0 load_i32(T1 address) const {\n\t\treturn ::load_i32<T0>(m_address + address);\n\t}\n\ttemplate<class T0 = uint64_t, class T1>\n\tT0 load_i64(T1 address) const {\n\t\treturn ::load_i64<T0>(m_address + address);\n\t}\n\n\tvoid replaceNearJmp(i32 offset, void* jmp_address) {\n\t\tstore_i32(offset, CalcNearJmp(m_address + offset, reinterpret_cast<i32>(jmp_address)));\n\t}\n\n\tauto address() const {\n\t\treturn m_address;\n\t}\n\tauto address(uintptr_t ofs) const {\n\t\treturn m_address + ofs;\n\t}\n};\n\n/// <summary>\n/// ニアージャンプ・コールを書き換える\n/// </summary>\n/// <param name=\"address\">書き換える対象のアドレス</param>\n/// <param name=\"jmp_address\">代わりに飛ばして欲しいアドレス</param>\ninline void ReplaceNearJmp(i32 address, void* jmp_address) {\n\tOverWriteOnProtectHelper(address, 4).replaceNearJmp(0, jmp_address);\n}\n\n// 既存の関数を破壊して，自分の関数を実行する\ninline class ReplaceFunction_t {\n\tstatic const int asm_size = 5;\n\npublic:\n\t// 乗っ取りたい関数があるアドレス,ジャンプさせる関数のポインタ,元の関数の内容が返る場所\n\ttemplate<class T, size_t N = asm_size, std::enable_if_t<N >= asm_size, std::nullptr_t> = nullptr>\n\tvoid operator()(T address, const void* function, std::byte(&original)[N]) noexcept {\n\t\tauto adr = std::bit_cast<i32>(address);\n\t\tOverWriteOnProtectHelper h(adr, asm_size);\n\t\tstd::copy(adr, adr + N, original);\n\t\tstore_i8(adr, '\\xe9'); // jmp rel32\n\t\tstore_i32(adr + 1, CalcNearJmp(address + 1, (i32)function));\n\t}\n\n\ttemplate<class T>\n\tvoid operator()(T address, const void* function) noexcept {\n\t\tauto adr = std::bit_cast<i32>(address);\n\t\tOverWriteOnProtectHelper h(adr, asm_size);\n\t\tstore_i8(adr, '\\xe9'); // jmp rel32\n\t\tstore_i32(adr + 1, CalcNearJmp(adr + 1, (i32)function));\n\t}\n} ReplaceFunction;\n\n\n// 乗っ取りたいモジュール, 乗っ取る関数があるDLLのファイル名, 乗っ取る関数の名前, 新しい関数へのポインタ\ninline BOOL ExchangeFunction(HMODULE hModule, std::string_view modname, std::string_view funcname, void* function) noexcept {\n\tauto ptr = search_import(hModule, modname, funcname);\n\tif (!ptr)return FALSE;\n\tDWORD flOldProtect;\n\tif (VirtualProtect(ptr, 4, PAGE_EXECUTE_READWRITE, &flOldProtect) == FALSE) return FALSE;\n\tstore_i32(ptr, function);\n\treturn VirtualProtect(ptr, 4, flOldProtect, &flOldProtect);\n}\n\n/// <summary>\n/// 指定したアドレスの関数の直前に、自分の関数を実行する\n/// 実行後元の関数に戻る\n/// __stdcall,__cdecl専用\n/// </summary>\n/// <param name=\"address\"> 中断したい関数のアドレス </param>\n/// <param name=\"function\"> 挿入する関数 </param>\n/// <param name=\"asm_word_n\"> 命令単位に合った数(7以上) </param>\n/// <returns> TRUE </returns>\ninline bool InjectFunction_stdcall(uint32_t address, const void* function, size_t asm_word_n) noexcept {\n\tstd::byte* cursor = GLOBAL::executable_memory_cursor;\n\n\tstore_i8(cursor, '\\xb8'); // mov eax, (i32)\n\tstore_i32(cursor + 1, function);\n\tstore_i16(cursor + 5, '\\xff\\xd0'); // call eax\n\t\n\tstd::copy((std::byte*)address, (std::byte*)address + asm_word_n, cursor + 7);\n\tstore_i16(cursor + asm_word_n + 7, '\\xff\\x25'); // jmp [(i32)]\n\tstore_i32(cursor + asm_word_n + 9, cursor + asm_word_n + 13);\n\tstore_i32(cursor + asm_word_n + 13, address + asm_word_n);\n\tGLOBAL::executable_memory_cursor += asm_word_n + 17;\n\n\t{\n\t\tOverWriteOnProtectHelper protect(address, 7);\n\t\tstore_i8(address, '\\xb8'); // mov eax, (i32)\n\t\tstore_i32(address + 1, cursor);\n\t\tstore_i16(address + 5, '\\xff\\xe0'); // call eax\n\t}\n\treturn TRUE;\n}\n\n/// <summary>\n/// 指定したアドレスの関数の直前に、自分の関数を実行する\n/// 実行後元の関数に戻る\n/// __cdecl専用 (__stdcallと一緒だけど)\n/// </summary>\n/// <param name=\"address\"> 中断したい関数のアドレス </param>\n/// <param name=\"function\"> 挿入する関数 </param>\n/// <param name=\"asm_word_n\"> 命令単位に合った数(7以上) </param>\n/// <returns> TRUE </returns>\ninline bool InjectFunction_cdecl(uint32_t address, const void* function, size_t asm_word_n) noexcept {\n\tInjectFunction_stdcall(address, function, asm_word_n);\n}\n\n/// <summary>\n/// 指定したアドレスの関数の直前に、自分の関数を実行する\n/// 実行後元の関数に戻る\n/// __fastcall専用\n/// </summary>\n/// <param name=\"address\"> 中断したい関数のアドレス </param>\n/// <param name=\"function\"> 挿入する関数 </param>\n/// <param name=\"asm_word_n\"> 命令単位に合った数(7以上) </param>\n/// <returns> TRUE </returns>\ninline bool InjectFunction_fastcall(uint32_t address, void(*func)(), size_t asm_word_n) {\n\tif (asm_word_n < 7)return false;\n\tOverWriteOnProtectHelper helper(address, asm_word_n);\n\n\tauto bridge = GLOBAL::executable_memory_cursor;\n\n\tstore_i16(bridge, '\\x51\\x52'); // PUSH ECX; PUSH EDX\n\tstore_i8(bridge + 2, '\\xb8'); // MOV EAX, (i32)\n\tstore_i32(bridge + 3, func);\n\tstore_i16(bridge + 7, '\\xff\\xd0'); // CALL EAX\n\tstore_i16(bridge + 9, '\\x5a\\x59'); // POP EDX; POP ECX\n\tstd::copy((std::byte*)address, (std::byte*)address + asm_word_n, bridge + 11);\n\tstore_i16(bridge + asm_word_n + 11, '\\xff\\x25'); // JMP (i32)\n\tstore_i32(bridge + asm_word_n + 13, bridge + asm_word_n + 17);\n\tstore_i32(bridge + asm_word_n + 17, address + asm_word_n);\n\tGLOBAL::executable_memory_cursor += asm_word_n + 21;\n\n\tstore_i8(address, '\\xb8'); // MOV EAX,\n\tstore_i32(address + 1, bridge);\n\tstore_i16(address + 5, '\\xff\\xe0'); // JMP EAX\n\n\treturn true;\n}\n"
  },
  {
    "path": "patch/util_others.cpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#include \"util_others.hpp\"\n\n#include <Shlwapi.h>\n#pragma comment(lib, \"shlwapi.lib\")\n\n#include <aviutl.hpp>\n\n#include \"global.hpp\"\n\nvoid save_project(HWND hwnd_owner) {\n\tstd::string path;\n\tpath.resize(512);\n\tOPENFILENAMEA ofna{\n\t\t.lStructSize = sizeof(OPENFILENAMEA),\n\t\t.hwndOwner = hwnd_owner,\n\t\t.hInstance = GLOBAL::patchaul_hinst,\n\t\t.lpstrFilter = \"ProjectFile (*.aup)\\0*.aup\\0AllFile (*.*)\\0*.*\\0\",\n\t\t.lpstrCustomFilter = NULL,\n\t\t.nMaxCustFilter = 0,\n\t\t.nFilterIndex = 0,\n\t\t.lpstrFile = path.data(),\n\t\t.nMaxFile = path.size(),\n\t\t.lpstrFileTitle = NULL,\n\t\t.nMaxFileTitle = NULL,\n\t\t.lpstrInitialDir = NULL,\n\t\t.lpstrTitle = NULL,\n\t\t.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_PATHMUSTEXIST | OFN_ENABLESIZING,\n\t\t.lpstrDefExt = \"aup\",\n\t\t.lCustData = 0,\n\t\t.lpfnHook = NULL,\n\t\t.lpTemplateName = NULL,\n\t\t.pvReserved = NULL,\n\t\t.dwReserved = NULL,\n\t\t.FlagsEx = NULL\n\t};\n\n\tauto editp = load_i32<AviUtl::EditHandle*>(GLOBAL::aviutl_base + OFS::AviUtl::edit_handle_ptr);\n\tstd::string dir(editp->project_filename);\n\tif (dir.size() > 0) {\n\t\tdir.erase(PathFindFileNameA(dir.data()) - dir.data());\n\t\tofna.lpstrInitialDir = dir.c_str();\n\t}\n\n\tif (GetSaveFileNameA(&ofna)) {\n\t\t((BOOL(__fastcall*)(AviUtl::EditHandle*, LPCSTR))(GLOBAL::aviutl_base + OFS::AviUtl::saveProjectFile))(\n\t\t\teditp,\n\t\t\tpath.c_str()\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "patch/util_others.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include <cstdint>\n#include <iterator>\n#include <type_traits>\n#include <format>\n#include <concepts>\n\n#include <Windows.h>\n#include <CommCtrl.h>\n\n#include <intrin.h>\n\n#include <aviutl/flag.hpp>\n\n#include \"global.hpp\"\n#include \"resource.h\"\n#include \"offset_address.hpp\"\n\ninline HWND pid2hwnd(DWORD pid) {\n\tauto hwnd = FindWindow(NULL, NULL);\n\twhile (hwnd) {\n\t\tif (!GetParent(hwnd) /*&& IsWindowVisible(hwnd)*/) {\n\t\t\tDWORD pid_tmp;\n\t\t\tGetWindowThreadProcessId(hwnd, &pid_tmp);\n\t\t\tif (pid == pid_tmp) return hwnd;\n\t\t}\n\t\thwnd = GetWindow(hwnd, GW_HWNDNEXT);\n\t}\n\treturn hwnd;\n}\n\ntemplate<class Func>\nconcept modify_menuitem_check_callback = requires(Func func) {\n\t{ func(std::declval<bool>()) } -> std::convertible_to<bool>;\n};\n\ntemplate<modify_menuitem_check_callback Func>\nvoid modify_menuitem_check(HMENU menu, UINT item, BOOL position, Func func) {\n\tMENUITEMINFOA info = { .cbSize = sizeof(MENUITEMINFO), .fMask = MIIM_STATE };\n\tGetMenuItemInfoA(menu, item, position, &info);\n\tinfo.fState = info.fState & ~MFS_CHECKED | (func(info.fState & MFS_CHECKED) ? MFS_CHECKED : 0);\n\tSetMenuItemInfoA(menu, item, position, &info);\n}\n\nstruct format_literal_detail_a : private std::string_view {\n\tformat_literal_detail_a(const char* str, std::size_t size) : std::string_view(str, size) {}\n\n\ttemplate<class... Args>\n\tauto operator()(Args&& ...args) { return std::vformat(*this, std::make_format_args(args...)); }\n};\n\nstruct format_literal_detail_w : private std::wstring_view {\n    format_literal_detail_w(const wchar_t* str, std::size_t size) : std::wstring_view(str, size) {}\n\n    template<class... Args>\n    auto operator()(Args&& ...args) { return std::vformat(*this, std::make_wformat_args(args...)); }\n};\n\ninline auto operator\"\"_fmt(const char* str, std::size_t size) {\n\treturn format_literal_detail_a(str, size);\n}\n\ninline auto operator\"\"_fmt(const wchar_t* str, std::size_t size) {\n\treturn format_literal_detail_w(str, size);\n}\n\ntemplate<class OStream, class... Args> requires std::is_same_v<typename OStream::char_type, char>\ninline auto format_to_os(OStream& ss, const std::string_view fmt, Args&& ...args) {\n\treturn std::vformat_to(std::ostreambuf_iterator<typename OStream::char_type>(ss), fmt, std::make_format_args(args...));\n}\n\ntemplate<class OStream, class... Args> requires std::is_same_v<typename OStream::char_type, wchar_t>\ninline auto format_to_os(OStream& ss, const std::wstring_view fmt, Args&& ...args) {\n    return std::vformat_to(std::ostreambuf_iterator<typename OStream::char_type>(ss), fmt, std::make_wformat_args(args...));\n}\n\ninline auto get_local_time() {\n\tTIME_ZONE_INFORMATION tzi;\n\tGetTimeZoneInformation(&tzi);\n\n\tSYSTEMTIME st_u;\n\tGetSystemTime(&st_u);\n\n\tSYSTEMTIME st_l;\n\tSystemTimeToTzSpecificLocalTime(&tzi, &st_u, &st_l);\n\n\treturn st_l;\n}\n\n// hh:mm:ss 形式のローカル時刻をもらう\ninline auto get_local_time_string() {\n\tauto st_l = get_local_time();\n\treturn \"{:02}:{:02}:{:02}\"_fmt(st_l.wHour, st_l.wMinute, st_l.wSecond);\n}\n\n// 編集プロジェクトの保存 を行う\nvoid save_project(HWND hwnd_owner);\n\n// ANSI -> UTF-16 LE\ninline std::wstring string_convert_A2W(std::string_view str) {\n\tauto size = MultiByteToWideChar(CP_ACP, 0, str.data(), str.size(), nullptr, 0);\n\tstd::wstring ret(size, '\\0');\n\tMultiByteToWideChar(CP_ACP, 0, str.data(), str.size(), ret.data(), size);\n\treturn ret;\n}\n\n// UTF-16 LE -> ANSI\ninline std::string string_convert_W2A(std::wstring_view str) {\n\tauto size = WideCharToMultiByte(CP_ACP, 0, str.data(), str.size(), nullptr, 0, nullptr, nullptr);\n\tstd::string ret(size, '\\0');\n\tWideCharToMultiByte(CP_ACP, 0, str.data(), str.size(), ret.data(), size, nullptr, nullptr);\n\treturn ret;\n}\n\n// UTF-8 -> UTF-16 LE\ninline std::wstring string_convert_U2W(std::u8string_view str) {\n\tauto size = MultiByteToWideChar(CP_UTF8, 0, reinterpret_cast<LPCCH>(str.data()), str.size(), nullptr, 0);\n\tstd::wstring ret(size, '\\0');\n\tMultiByteToWideChar(CP_UTF8, 0, reinterpret_cast<LPCCH>(str.data()), str.size(), ret.data(), size);\n\treturn ret;\n}\n\n// UTF-16 LE -> UTF-8\ninline std::u8string string_convert_W2U(std::wstring_view str) {\n\tauto size = WideCharToMultiByte(CP_UTF8, 0, str.data(), str.size(), nullptr, 0, nullptr, nullptr);\n\tstd::u8string ret(size, '\\0');\n\tWideCharToMultiByte(CP_UTF8, 0, str.data(), str.size(), reinterpret_cast<LPSTR>(ret.data()), size, nullptr, nullptr);\n\treturn ret;\n}\n\nenum class CPUCmdSet : uint32_t {\n    F_TSC              = 1 << 0,\n    F_MMX              = 1 << 1,\n    F_SSE              = 1 << 2,\n    F_SSE2             = 1 << 3,\n    F_3DNOW            = 1 << 4,\n    F_3DNOWEXT         = 1 << 5,\n    F_SMT              = 1 << 6,\n    F_64BIT            = 1 << 7,\n    F_SSE3             = 1 << 8,\n    F_SSSE3            = 1 << 9,\n    F_SSE4A            = 1 << 10,\n    F_SSE41            = 1 << 12,\n    F_SSE42            = 1 << 13,\n    F_AESNI            = 1 << 14,\n    F_AVX              = 1 << 15,\n    F_AVX2             = 1 << 16,\n    F_FMA4             = 1 << 11,\n    F_AVX512F          = 1 << 17,\n    F_AVX512DQ         = 1 << 18,\n    F_AVX512_IFMA      = 1 << 19,\n    F_AVX512PF         = 1 << 20,\n    F_AVX512ER         = 1 << 21,\n    F_AVX512CD         = 1 << 22,\n    F_AVX512BW         = 1 << 23,\n    F_AVX512VL         = 1 << 24,\n    F_AVX512_VBMI      = 1 << 25,\n    F_AVX512_VPOPCNTDQ = 1 << 26,\n    F_AVX512_4VNNIW    = 1 << 27,\n    F_AVX512_4FMAPS    = 1 << 28,\n};\ntemplate<>struct AviUtl::detail::flag::ops_def<CPUCmdSet>:std::true_type{};\n\n/*\n    参考: https://www.timbreofprogram.info/blog/archives/951\n*/\ninline CPUCmdSet get_CPUCmdSet() {\n    static CPUCmdSet ret = {};\n    static bool inited = false;\n\n    if (inited) return ret;\n\n    int cpuinfo[4];\n\n    __cpuid(cpuinfo, 0x00000000);\n    auto basicmax = cpuinfo[0];\n\n    __cpuid(cpuinfo, 0x80000000);\n    auto extendmax = cpuinfo[0];\n\n    __cpuid(cpuinfo, 0x00000001);\n    if (cpuinfo[3] & (1u << 4)) ret |= CPUCmdSet::F_TSC;\n    if (cpuinfo[3] & (1u << 23)) ret |= CPUCmdSet::F_MMX;\n    if (cpuinfo[3] & (1u << 25)) ret |= CPUCmdSet::F_SSE;\n    if (cpuinfo[3] & (1u << 26)) ret |= CPUCmdSet::F_SSE2;\n    if (cpuinfo[3] & (1u << 28)) ret |= CPUCmdSet::F_SMT;\n\n    if (cpuinfo[2] & (1u << 0)) ret |= CPUCmdSet::F_SSE3;\n    if (cpuinfo[2] & (1u << 9)) ret |= CPUCmdSet::F_SSSE3;\n    if (cpuinfo[2] & (1u << 19)) ret |= CPUCmdSet::F_SSE41;\n    if (cpuinfo[2] & (1u << 20)) ret |= CPUCmdSet::F_SSE42;\n    if (cpuinfo[2] & (1u << 25)) ret |= CPUCmdSet::F_AESNI;\n    if (cpuinfo[2] & (1u << 28)) ret |= CPUCmdSet::F_AVX;\n\n    if (static_cast<unsigned int>(extendmax) < 0x80000000u) return ret;\n\n\n    __cpuid(cpuinfo, 0x80000001);\n    if (cpuinfo[3] & (1u << 31)) ret |= CPUCmdSet::F_3DNOW;\n    if (cpuinfo[3] & (1u << 30)) ret |= CPUCmdSet::F_3DNOWEXT;\n    if (cpuinfo[3] & (1u << 29)) ret |= CPUCmdSet::F_64BIT;\n\n    if (cpuinfo[2] & (1u << 6)) ret |= CPUCmdSet::F_SSE4A;\n    if (cpuinfo[2] & (1u << 16)) ret |= CPUCmdSet::F_FMA4;\n\n\n    if (basicmax < 7) return ret;\n\n    __cpuidex(cpuinfo, 7, 0);\n    if (cpuinfo[1] & (1u << 5)) ret |= CPUCmdSet::F_AVX2;\n    if (cpuinfo[1] & (1u << 16)) ret |= CPUCmdSet::F_AVX512F;\n    if (cpuinfo[1] & (1u << 17)) ret |= CPUCmdSet::F_AVX512DQ;\n    if (cpuinfo[1] & (1u << 21)) ret |= CPUCmdSet::F_AVX512_IFMA;\n    if (cpuinfo[1] & (1u << 26)) ret |= CPUCmdSet::F_AVX512PF;\n    if (cpuinfo[1] & (1u << 27)) ret |= CPUCmdSet::F_AVX512ER;\n    if (cpuinfo[1] & (1u << 28)) ret |= CPUCmdSet::F_AVX512CD;\n    if (cpuinfo[1] & (1u << 30)) ret |= CPUCmdSet::F_AVX512BW;\n    if (cpuinfo[1] & (1u << 31)) ret |= CPUCmdSet::F_AVX512VL;\n\n    if (cpuinfo[2] & (1u << 1)) ret |= CPUCmdSet::F_AVX512_VBMI;\n    if (cpuinfo[2] & (1u << 14)) ret |= CPUCmdSet::F_AVX512_VPOPCNTDQ;\n\n    if (cpuinfo[3] & (1u << 2)) ret |= CPUCmdSet::F_AVX512_4VNNIW;\n    if (cpuinfo[3] & (1u << 3)) ret |= CPUCmdSet::F_AVX512_4FMAPS;\n\n    inited = true;\n    return ret;\n}\n"
  },
  {
    "path": "patch/util_pe.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include <vector>\n#include <set>\n#include <unordered_map>\n#include <optional>\n#include <string>\n\n#include <Windows.h>\n#include <DbgHelp.h>\n#pragma comment(lib, \"Dbghelp.lib\")\n\n#include \"util_int.hpp\"\n\n/// <summary>\n/// reloc領域から指定アドレスが使われているアドレスを探す\n/// </summary>\n/// <param name=\"hModule\">モジュール</param>\n/// <param name=\"target_ofs\">探すアドレスのオフセット</param>\n/// <returns>アドレスが入った配列 順序の保証は特にない</returns>\ninline auto search_reloc(HMODULE hModule, i32 target_ofs) noexcept {\n\tstd::vector<void*> ret;\n\n\tauto base = reinterpret_cast<DWORD>(hModule);\n\n\tauto target = base + target_ofs;\n\n\tULONG size;\n\tauto reloc = static_cast<PIMAGE_BASE_RELOCATION>(ImageDirectoryEntryToData(hModule, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &size));\n\tif (!reloc) return ret;\n\n\tauto end_of_directory = reinterpret_cast<void*>(reinterpret_cast<ULONG_PTR>(reloc) + size);\n\n\twhile (reloc < end_of_directory && reloc->SizeOfBlock) {\n\t\tauto end_of_block = reinterpret_cast<void*>(reinterpret_cast<ULONG_PTR>(reloc) + reloc->SizeOfBlock);\n\t\tauto TypeOffset = reinterpret_cast<WORD*>(reinterpret_cast<ULONG_PTR>(reloc) + sizeof(IMAGE_BASE_RELOCATION));\n\n\t\twhile (TypeOffset < end_of_block) {\n\t\t\tauto type = (*TypeOffset >> 12) & 0xf;\n\t\t\tauto offset = *TypeOffset & 0xfff;\n\n\t\t\tif (type == IMAGE_REL_BASED_HIGHLOW) {\n\t\t\t\tauto adr = reinterpret_cast<PULONG_PTR>(base + reloc->VirtualAddress + offset);\n\t\t\t\tif (*adr == target) {\n\t\t\t\t\tret.push_back(adr);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tTypeOffset++;\n\t\t}\n\n\t\treloc = reinterpret_cast<PIMAGE_BASE_RELOCATION>(end_of_block);\n\t}\n\n\treturn ret;\n}\n\n/// <summary>\n/// search_reloc(HMODULE, i32) を複数オフセットアドレスで同時に行う\n/// </summary>\n/// <param name=\"hModule\">モジュール</param>\n/// <param name=\"target_ofs\">探すオフセットアドレスのset</param>\n/// <returns> unordered_map[オフセットアドレス] = オフセットアドレスが使われているアドレスの配列 </returns>\ninline auto search_reloc(HMODULE hModule, const std::set<i32>& target_ofs) {\n\tstd::unordered_map<i32, std::vector<void*>> ret;\n\n\tauto base = reinterpret_cast<DWORD>(hModule);\n\n\tULONG size;\n\tauto reloc = static_cast<PIMAGE_BASE_RELOCATION>(ImageDirectoryEntryToData(hModule, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &size));\n\tif (!reloc) return ret;\n\n\tauto end_of_directory = reinterpret_cast<void*>(reinterpret_cast<ULONG_PTR>(reloc) + size);\n\n\twhile (reloc < end_of_directory && reloc->SizeOfBlock) {\n\t\tauto end_of_block = reinterpret_cast<void*>(reinterpret_cast<ULONG_PTR>(reloc) + reloc->SizeOfBlock);\n\t\tauto TypeOffset = reinterpret_cast<WORD*>(reinterpret_cast<ULONG_PTR>(reloc) + sizeof(IMAGE_BASE_RELOCATION));\n\n\t\twhile (TypeOffset < end_of_block) {\n\t\t\tauto type = (*TypeOffset >> 12) & 0xf;\n\t\t\tauto offset = *TypeOffset & 0xfff;\n\n\t\t\tif (type == IMAGE_REL_BASED_HIGHLOW) {\n\t\t\t\tauto adr = reinterpret_cast<PULONG_PTR>(base + reloc->VirtualAddress + offset);\n\t\t\t\ti32 ofs = *adr - base;\n\n\t\t\t\tif (target_ofs.contains(ofs)) {\n\t\t\t\t\tif (auto itr = ret.find(ofs); itr != ret.end()) {\n\t\t\t\t\t\titr->second.push_back(adr);\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tret.try_emplace(ofs, std::vector<void*>{ adr });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tTypeOffset++;\n\t\t}\n\n\t\treloc = reinterpret_cast<PIMAGE_BASE_RELOCATION>(end_of_block);\n\t}\n\n\treturn ret;\n}\n\n/// <summary>\n/// 序数を関数名に変換する\n/// </summary>\n/// <param name=\"hMod\">モジュール</param>\n/// <param name=\"ordinal\">序数</param>\n/// <returns>関数の名前 見つからなければstd::nullopt</returns>\ninline std::optional<std::string> ordinal_to_name(HMODULE hMod, DWORD ordinal) noexcept {\n\tauto base = reinterpret_cast<DWORD>(hMod);\n\tif (!base)return std::nullopt;\n\n\tULONG size;\n\tauto iedp = static_cast<PIMAGE_EXPORT_DIRECTORY>(ImageDirectoryEntryToData(hMod, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size));\n\tauto names = reinterpret_cast<DWORD*>(base + iedp->AddressOfNames);\n\tauto ordinals = reinterpret_cast<WORD*>(base + iedp->AddressOfNameOrdinals);\n\tfor (DWORD i = 0; i < iedp->NumberOfFunctions; i++) {\n\t\tfor (DWORD j = 0; j < iedp->NumberOfNames; j++) {\n\t\t\tif (ordinals[j] != i)continue;\n\t\t\tif (ordinals[j] == ordinal) {\n\t\t\t\treturn reinterpret_cast<char*>(base + names[j]);\n\t\t\t}\n\t\t}\n\t}\n\treturn std::nullopt;\n}\n\n/// <summary>\n/// 関数名を序数に変換する\n/// </summary>\n/// <param name=\"hMod\">モジュール</param>\n/// <param name=\"name\">関数の名前</param>\n/// <returns>序数 関数が無ければ-1</returns>\ninline DWORD name_to_ordinal(HMODULE hMod, std::string_view name) noexcept {\n\tif (!hMod)return -1;\n\tauto base = reinterpret_cast<DWORD>(hMod);\n\n\tULONG size;\n\tauto iedp = static_cast<PIMAGE_EXPORT_DIRECTORY>(ImageDirectoryEntryToData(hMod, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size));\n\tauto names = reinterpret_cast<DWORD*>(base + iedp->AddressOfNames);\n\tauto ordinals = reinterpret_cast<WORD*>(base + iedp->AddressOfNameOrdinals);\n\tfor (DWORD i = 0; i < iedp->NumberOfFunctions; i++) {\n\t\tfor (DWORD j = 0; j < iedp->NumberOfNames; j++) {\n\t\t\tif (ordinals[j] != i)continue;\n\t\t\tif (lstrcmpiA(reinterpret_cast<char*>(base + names[j]), name.data()) == 0) {\n\t\t\t\treturn ordinals[j];\n\t\t\t}\n\t\t}\n\t}\n\treturn -1;\n}\n\n/// <summary>\n/// 指定モジュールのIATから関数のあるポインタを探し出す\n/// </summary>\n/// <param name=\"target\">モジュール</param>\n/// <param name=\"mod_name\">探す関数のあるDLLの名前</param>\n/// <param name=\"func_name\">探す関数の名前</param>\n/// <returns>見つけたポインタ 見つからなければnullptr</returns>\ninline void* search_import(HMODULE target, std::string_view mod_name, std::string_view func_name) noexcept {\n\tauto base = reinterpret_cast<DWORD>(target);\n\tULONG size;\n\tauto iidp = static_cast<PIMAGE_IMPORT_DESCRIPTOR>(ImageDirectoryEntryToData(target, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size));\n\tif (!iidp)return nullptr;\n\n\tauto funcidx = name_to_ordinal(GetModuleHandleA(mod_name.data()), func_name);\n\n\tfor (; iidp->Name; iidp++) {\n\t\tif (lstrcmpiA(reinterpret_cast<char*>(base + iidp->Name), mod_name.data()) != 0) continue;\n\n\t\tauto itdp = reinterpret_cast<PIMAGE_THUNK_DATA>(base + iidp->FirstThunk);\n\t\tauto oitdp = reinterpret_cast<PIMAGE_THUNK_DATA>(base + iidp->OriginalFirstThunk);\n\t\tfor (; itdp->u1.Function; itdp++, oitdp++) {\n\t\t\tif (IMAGE_SNAP_BY_ORDINAL(oitdp->u1.Ordinal)) {\n\t\t\t\tif (IMAGE_ORDINAL(oitdp->u1.Ordinal) == funcidx)\n\t\t\t\t\treturn &itdp->u1.Function;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tauto iibnp = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(base + oitdp->u1.AddressOfData);\n\t\t\t\tif (lstrcmpiA(iibnp->Name, func_name.data()) == 0) {\n\t\t\t\t\treturn &itdp->u1.Function;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nullptr;\n}\n/// <summary>\n/// 指定モジュールのIATから関数のあるポインタを探し出す\n/// </summary>\n/// <param name=\"target\">モジュール</param>\n/// <param name=\"mod_name\">探す関数のあるDLLの名前</param>\n/// <param name=\"func_name\">探す関数の名前</param>\n/// <param name=\"func_ordinal\">探す関数の序数</param>\n/// <returns>見つけたポインタ 見つからなければnullptr</returns>\ninline void* search_import(HMODULE hModule, std::string_view mod_name, std::string_view func_name, unsigned int func_ordinal) noexcept {\n\tauto base = reinterpret_cast<DWORD>(hModule);\n\tULONG size;\n\tauto iidp = static_cast<PIMAGE_IMPORT_DESCRIPTOR>(ImageDirectoryEntryToData(hModule, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size));\n\tif (!iidp)return nullptr;\n\tfor (; iidp->Name; iidp++) {\n\t\tif (lstrcmpiA(reinterpret_cast<char*>(base + iidp->Name), mod_name.data()) != 0) continue;\n\n\t\tauto itdp = reinterpret_cast<PIMAGE_THUNK_DATA>(base + iidp->FirstThunk);\n\t\tauto oitdp = reinterpret_cast<PIMAGE_THUNK_DATA>(base + iidp->OriginalFirstThunk);\n\t\tfor (; itdp->u1.Function; itdp++, oitdp++) {\n\t\t\tif (IMAGE_SNAP_BY_ORDINAL(oitdp->u1.Ordinal)) {\n\t\t\t\tif (IMAGE_ORDINAL(oitdp->u1.Ordinal) == func_ordinal)\n\t\t\t\t\treturn static_cast<void*>(&itdp->u1.Function);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tauto iibnp = reinterpret_cast<PIMAGE_IMPORT_BY_NAME>(base + oitdp->u1.AddressOfData);\n\t\t\t\tif (lstrcmpiA(iibnp->Name, func_name.data()) == 0) {\n\t\t\t\t\treturn static_cast<void*>(&itdp->u1.Function);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn nullptr;\n}\n"
  },
  {
    "path": "patch/util_resource.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include <string>\n#include <optional>\n#include <format>\n\n#include <Windows.h>\n\n#include \"global_minimum.hpp\"\n#include \"offset_address.hpp\"\n\n#include \"util_others.hpp\"\n\ninline std::optional<std::wstring> resource_string_w(UINT rs_id) {\n\tauto hmod = load_i32<HMODULE>(GLOBAL::aviutl_base + OFS::AviUtl::current_resource_hmod);\n\tstruct {\n\t\tconst wchar_t* ptr;\n\t\tuint32_t padding = 0;\n\t}value;\n\tauto size = LoadStringW(hmod, rs_id, (LPWSTR)&value, 0);\n\tif (size <= 0) {\n\t\thmod = GLOBAL::patchaul_hinst;\n\t\tsize = LoadStringW(hmod, rs_id, (LPWSTR)&value, 0);\n\t\tif (size <= 0) {\n\t\t\treturn std::nullopt;\n\t\t}\n\t}\n\treturn std::wstring(value.ptr, size);\n}\n\ninline std::optional<std::string> resource_string_a(UINT rs_id) {\n\tauto hmod = load_i32<HMODULE>(GLOBAL::aviutl_base + OFS::AviUtl::current_resource_hmod);\n\tstruct {\n\t\tconst wchar_t* ptr;\n\t\tuint32_t padding;\n\t}value;\n\tauto size = LoadStringW(hmod, rs_id, (LPWSTR)&value, 0);\n\tif (size <= 0) {\n\t\thmod = GLOBAL::patchaul_hinst;\n\t\tsize = LoadStringW(hmod, rs_id, (LPWSTR)&value, 0);\n\t\tif (size <= 0) {\n\t\t\treturn std::nullopt;\n\t\t}\n\t}\n\n\tauto asize = WideCharToMultiByte(CP_ACP, 0, value.ptr, size, nullptr, 0, nullptr, nullptr);\n\tstd::string ret(asize, '\\0');\n\tWideCharToMultiByte(CP_ACP, 0, value.ptr, size, ret.data(), asize, nullptr, nullptr);\n\treturn ret;\n}\n\n\ntemplate<class... Args>\ninline std::optional<std::string> resource_format_a(UINT rs_id, Args&& ...args) {\n\tauto format_str = resource_string_a(rs_id);\n\tif (!format_str.has_value()) return std::nullopt;\n\n\ttry {\n\t\tauto ret = std::vformat(format_str.value(), std::make_format_args(args...));\n\t\treturn ret;\n\t}\n\tcatch (const std::format_error&) {\n\t\treturn std::nullopt;\n\t}\n}\n\ntemplate<class... Args>\ninline std::optional<std::wstring> resource_format_w(UINT rs_id, Args&& ...args) {\n\tauto format_str = resource_string_w(rs_id);\n\tif (!format_str.has_value()) return std::nullopt;\n\n\ttry {\n\t\tauto ret = std::vformat(format_str.value(), std::make_format_args(args...));\n\t\treturn ret;\n\t}\n\tcatch (const std::format_error&) {\n\t\treturn std::nullopt;\n\t}\n}\n\ninline std::optional<int> patch_resource_message_a(UINT rs_id, UINT uType) {\n\tauto str = resource_string_a(rs_id);\n\tif (str.has_value()) {\n\t\treturn MessageBoxA(NULL, str.value().c_str(), \"patch.aul\", uType);\n\t}\n\telse {\n\t\tMessageBoxW(NULL, L\"resource error ({})\"_fmt(rs_id).c_str(), L\"patch.aul\", MB_TOPMOST | MB_TASKMODAL | MB_ICONERROR);\n\t\treturn std::nullopt;\n\t}\n}\n\ninline std::optional<int> patch_resource_message_w(UINT rs_id, UINT uType) {\n\tauto str = resource_string_w(rs_id);\n\tif (str.has_value()) {\n\t\treturn MessageBoxW(NULL, str.value().c_str(), L\"patch.aul\", uType);\n\t}\n\telse {\n\t\tMessageBoxW(NULL, L\"resource error ({})\"_fmt(rs_id).c_str(), L\"patch.aul\", MB_TOPMOST | MB_TASKMODAL | MB_ICONERROR);\n\t\treturn std::nullopt;\n\t}\n}\n\ntemplate<class... Args>\ninline std::optional<int> patch_resource_message_a(UINT rs_id, UINT uType, Args&& ...args) {\n\tauto str = resource_string_a(rs_id);\n\tif (str.has_value()) {\n\t\ttry {\n\t\t\treturn MessageBoxA(NULL, std::vformat(str.value(), std::make_format_args(args...)).c_str(), \"patch.aul\", uType);\n\t\t}\n\t\tcatch (const std::format_error&) {\n\t\t\tMessageBoxW(NULL, L\"format error ({})\"_fmt(rs_id).c_str(), L\"patch.aul\", MB_TOPMOST | MB_TASKMODAL | MB_ICONERROR);\n\t\t\treturn std::nullopt;\n\t\t}\n\t}\n\telse {\n\t\tMessageBoxW(NULL, L\"resource error ({})\"_fmt(rs_id).c_str(), L\"patch.aul\", MB_TOPMOST | MB_TASKMODAL | MB_ICONERROR);\n\t\treturn std::nullopt;\n\t}\n}\n\ntemplate<class... Args>\ninline std::optional<int> patch_resource_message_w(UINT rs_id, UINT uType, Args&& ...args) {\n\tauto str = resource_string_w(rs_id);\n\tif (str.has_value()) {\n\t\ttry {\n\t\t\treturn MessageBoxW(NULL, std::vformat(str.value(), std::make_wformat_args(args...)).c_str(), L\"patch.aul\", uType);\n\t\t}\n\t\tcatch (const std::format_error&) {\n\t\t\tMessageBoxW(NULL, L\"format error ({})\"_fmt(rs_id).c_str(), L\"patch.aul\", MB_TOPMOST | MB_TASKMODAL | MB_ICONERROR);\n\t\t\treturn std::nullopt;\n\t\t}\n\t}\n\telse {\n\t\tMessageBoxW(NULL, L\"resource error ({})\"_fmt(rs_id).c_str(), L\"patch.aul\", MB_TOPMOST | MB_TASKMODAL | MB_ICONERROR);\n\t\treturn std::nullopt;\n\t}\n}\n\nclass patch_resource_message_class_base {\npublic:\n\tvirtual void fire() = 0;\n\tvirtual ~patch_resource_message_class_base() {}\n};\n\ntemplate<class... Args>\nclass patch_resource_message_format_class_w : public patch_resource_message_class_base {\n\tUINT rs_id, uType;\n\tstd::tuple<Args...> args;\n\npublic:\n\tpatch_resource_message_format_class_w(UINT rs_id, UINT uType, Args&& ...args) : rs_id(rs_id), uType(uType), args(std::forward(args)...) {}\n\n\tvoid fire() {\n\t\tauto str = resource_string_w(rs_id);\n\t\tif (str.has_value()) {\n\t\t\ttry {\n\t\t\t\tMessageBoxW(NULL, std::vformat(str.value(), std::apply(std::make_format_args, args)).c_str(), L\"patch.aul\", uType);\n\t\t\t}\n\t\t\tcatch (const std::format_error&) {\n\t\t\t\tMessageBoxW(NULL, L\"format error ({})\"_fmt(rs_id).c_str(), L\"patch.aul\", MB_TOPMOST | MB_TASKMODAL | MB_ICONERROR);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tMessageBoxW(NULL, L\"resource error ({})\"_fmt(rs_id).c_str(), L\"patch.aul\", MB_TOPMOST | MB_TASKMODAL | MB_ICONERROR);\n\t\t}\n\t}\n};\n\nclass patch_resource_message_class_w : public patch_resource_message_class_base {\n\tUINT rs_id, uType;\n\npublic:\n\tpatch_resource_message_class_w(UINT rs_id, UINT uType) : rs_id(rs_id), uType(uType) {}\n\n\tvoid fire() {\n\t\tauto str = resource_string_w(rs_id);\n\t\tif (str.has_value()) {\n\t\t\ttry {\n\t\t\t\tMessageBoxW(NULL, str.value().c_str(), L\"patch.aul\", uType);\n\t\t\t}\n\t\t\tcatch (const std::format_error&) {\n\t\t\t\tMessageBoxW(NULL, L\"format error ({})\"_fmt(rs_id).c_str(), L\"patch.aul\", MB_TOPMOST | MB_TASKMODAL | MB_ICONERROR);\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tMessageBoxW(NULL, L\"resource error ({})\"_fmt(rs_id).c_str(), L\"patch.aul\", MB_TOPMOST | MB_TASKMODAL | MB_ICONERROR);\n\t\t}\n\t}\n};\n\ninline std::vector<std::unique_ptr<patch_resource_message_class_base>> patch_resource_message_stack;\n\ninline void web_confirm(std::wstring_view url) {\n\tenum ID : int {\n\t\tOpen,\n\t\tCopy,\n\t\tCancel\n\t};\n\n\tauto r_main = resource_string_w(PATCH_RS_PATCH_WEB_CONFIRM);\n\tauto r_open = resource_string_w(PATCH_RS_PATCH_WEB_CONFIRM_BUTTON_OPEN);\n\tauto r_copy = resource_string_w(PATCH_RS_PATCH_WEB_CONFIRM_BUTTON_COPY);\n\tauto r_cancel = resource_string_w(PATCH_RS_PATCH_WEB_CONFIRM_BUTTON_CANCEL);\n\n\tTASKDIALOG_BUTTON vtdb[] = {\n\t\t{ static_cast<int>(ID::Open), r_open->c_str() },\n\t\t{ static_cast<int>(ID::Copy), r_copy->c_str() },\n\t\t{ static_cast<int>(ID::Cancel), r_cancel->c_str() }\n\t};\n\n\tTASKDIALOGCONFIG tdc{\n\t\t.cbSize = sizeof(TASKDIALOGCONFIG),\n\t\t.hwndParent = NULL,\n\t\t.hInstance = GLOBAL::patchaul_hinst,\n\t\t.dwFlags = TDF_SIZE_TO_CONTENT,\n\t\t.dwCommonButtons = 0,\n\t\t.pszWindowTitle = L\"patch.aul\",\n\t\t.pszMainIcon = TD_INFORMATION_ICON,\n\t\t.pszMainInstruction = r_main->c_str(),\n\t\t.pszContent = url.data(),\n\t\t.cButtons = std::size(vtdb),\n\t\t.pButtons = vtdb,\n\t\t.nDefaultButton = static_cast<int>(ID::Open),\n\t\t.cRadioButtons = 0,\n\t\t.pRadioButtons = nullptr,\n\t\t.nDefaultRadioButton = NULL,\n\t\t.pszVerificationText = nullptr,\n\t\t.pszExpandedInformation = nullptr,\n\t\t.pszExpandedControlText = nullptr,\n\t\t.pszCollapsedControlText = nullptr,\n\t\t.pszFooterIcon = NULL,\n\t\t.pszFooter = nullptr,\n\t\t.pfCallback = nullptr,\n\t\t.lpCallbackData = NULL,\n\t\t.cxWidth = 0\n\t};\n\tint nButton;\n\tTaskDialogIndirect(&tdc, &nButton, nullptr, nullptr);\n\tswitch (nButton) {\n\t\tcase ID::Open:\n\t\t\tShellExecuteW(NULL, L\"open\", url.data(), nullptr, nullptr, SW_SHOW);\n\t\t\tbreak;\n\t\tcase ID::Copy: {\n\t\t\tauto urla = string_convert_W2A(url);\n\n\t\t\tHGLOBAL handle = GlobalAlloc(GHND | GMEM_SHARE, urla.size() + 1);\n\t\t\tauto mem = static_cast<LPSTR>(GlobalLock(handle));\n\t\t\turla.copy(mem, urla.size());\n\t\t\tGlobalUnlock(handle);\n\n\t\t\tOpenClipboard(NULL);\n\t\t\tEmptyClipboard();\n\t\t\tSetClipboardData(CF_TEXT, handle);\n\t\t\tCloseClipboard();\n\t\t\tbreak;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "patch/version.hpp",
    "content": "/*\n\tThis program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU Lesser General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU Lesser General Public License for more details.\n\n    You should have received a copy of the GNU Lesser General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n*/\n\n#pragma once\n#include \"cryptostring.hpp\"\n#include \"macro.h\"\n\ninline cryptostring patchaul_info(\n\tPATCH_VERSION_NAME \"\\n\"\n\t\"developed by ePi\"\n);\n"
  },
  {
    "path": "patch.aul.txt",
    "content": "patch.aul r43 beta1\n© 2021-2023 ePi\nhttps://scrapbox.io/ePi5131/patch.aul\n\n概要\n    AviUtlや拡張編集のバグを直したり高速化をしたり新機能を追加したりするプラグインです。\n\n要求環境\n    AviUtl version 1.10\n    拡張編集 version 0.92\n    Visual C++ 再頒布可能パッケージ 2015-2022 X86\n\n推奨環境\n    OpenCLを使用可能なデバイス\n    AVX2命令を使用可能なCPU\n\n導入\n    patch.aul は aviutl.exe と同じディレクトリに配置します。\n    \n機能\n    修正\n    ・オブジェクトファイルの入力で、トラックバーの -1 超 0 未満の値が正になってしまう\n    ・オブジェクトファイルの入力で、トラックバー変化方法スクリプトの名前にASCII以外の文字が含まれているとパラメータを読み込めない\n    ・オブジェクトファイルの入出力で、シーン番号を正しく扱えない\n    ・テキストオブジェクトでUTF-16で34バイト以上のフォント名を指定している時、制御文字<s>でサイズのみを指定していると正しい動作をしない\n    ・クリッピング＆リサイズの設定のラベルの脱字\n    ・メニュー文字列を実態に即したものに変更\n    ・動画ファイル と 音声ファイル で中間点を打っていないときでもファイルを再参照しても再生位置などの情報を変更しない\n    ・拡張編集以外のフィルタ(例:拡張色調補正)を使ったプロジェクトをオブジェクトファイルに出力できないことがある\n    ・極座標変換/ディスプレイスメントマップ/放射ブラー/閃光/縁取り/方向ブラー/レンズブラー/グローの高速化\n        OpenCL/AVX2を使用します\n        わずかにオリジナルと結果が変わってしまいます (floatとdoubleの差です)\n        また、アーティファクトなどのバグを解消することもあります\n    ・図形の高速化\n        円/三角形/五角形/六角形/星形の計算を僅かに最適化\n        マスクやディスプレイスメントマップのソースとしての図形にも効果がある\n    ・テキストの軽量化\n        キャッシュをとります\n    ・Luaの環境が分かれてしまうことがある\n    ・package.path,package.cpathはどんなときでもscriptフォルダを含めるように\n    ・obj.randでs=-2^31,e=2^31-1とすると例外になる\n    ・obj.getvalueで中心座標(cx,cy,cz)の情報を取得できるように\n    ・obj.getvalue(\"layerX.time\")が正しい値を取得できるように\n    ・拡張編集ウィンドウと設定ダイアログの描画の最適化\n    ・拡張編集ウィンドウの上部をドラッグしても正常にリサイズができるように\n    ・元に戻す の多数のバグ修正\n        ・レイヤー削除→元に戻すで他シーンのオブジェクトが消える\n        ・Ctrlで複数オブジェクトを選択しながら設定ダイアログのトラックバーを動かすと一部オブジェクトが正常に戻らない\n        ・オブジェクトの左端をつまんで動かすと再生位置パラメータが変わるが、それが元に戻らない\n        ・一部フィルタのファイル参照を変更→元に戻すで設定ダイアログが更新されない(音声波形など)\n        ・部分フィルタのマスクの種類を変更してもUndoデータが生成されない\n        ・テキストオブジェクトのフォントを変更してもUndoデータが生成されない\n        ・テキストオブジェクトの影付き・縁付きを変更してもUndoデータが生成されない\n        ・テキストオブジェクトの文字配置(左寄せ[上]など)を変更してもUndoデータが生成されない\n        ・テキストオブジェクトの字間/行間を変更してもUndoデータが生成されない\n        ・グループ制御とかの対象レイヤー数を変更してもUndoデータが生成されない\n        ・テキストを変更してもUndoデータが生成されない\n        ・スクリプト制御・カメラスクリプトを変更してもUndoデータが生成されない\n        ・左クリックよりレイヤーの表示状態を変更してもUndoデータが生成されない\n        ・右クリックメニューよりレイヤーの表示状態を変更してもUndoデータが生成されない\n        ・右クリックメニューよりレイヤーのロック状態を変更してもUndoデータが生成されない\n        ・右クリックメニューよりレイヤーの座標のリンク状態を変更してもUndoデータが生成されない\n        ・右クリックメニューより上クリッピング状態を変更してもUndoデータが生成されない\n        ・右クリックメニューより他のレイヤーを全表示/非表示を押してもUndoデータが生成されない\n        ・ショートカットよりレイヤーの表示状態を変更してもUndoデータが生成されない\n        ・カメラ制御の対象にするかどうかの変更でUndoデータが生成されない\n        ・上のオブジェクトでクリッピングの変更でUndoデータが生成されない\n        ・テンキーによるオブジェクトへの操作でUndoデータが生成されない\n    ・拡張編集以外のフィルタのトラックバーにトラックバー変化方法スクリプトを適用していると例外になる問題\n    ・小さい画像に対してサイズ固定で範囲の大きいレンズブラーを掛けると例外になるのを修正\n    ・拡張色変換のウィンドウが下のフィルタに被るのを修正\n    ・ノイズの速度X、変化速度のトラック変化方法が移動無し以外の時に速度Yの値をもとに計算が行われてしまうのを修正\n    ・右クリック分割で設定ダイアログが更新されないのを修正\n    ・右クリック削除でテキストの字間行間が変わることがあるのを修正\n    ・標準描画-拡張描画-パーティクル出力の切り替え時にトラック変化の設定値(移動フレーム間隔)が0になるのを修正\n    ・トラックバー変化方法の移動量指定と時間制御の組み合わせでバグるのを修正\n    ・アルファチャンネル有りシーンで合成モード「通常」以外を使用すると、他シーンで表示した時の結果が正しくないのを修正\n    ・ファイルパスに使用できない文字が含まれている時に出すエラーメッセージを変更する\n    ・色調補正の色相計算を修正\n    ・プロジェクトの保存/読み込み時にシーン設定の一部情報（グリッド設定など）が欠けるのを修正\n    ・exa,exo生成時、設定ダイアログの▼（折り畳み）とマウスマーク（GUI表示）の情報を追加する\n    ・BMP File Readerを使うと、正しくない画像データをキャッシュしてしまうことがあるのを修正\n    ・動画、音声ファイル参照の時、exedit.iniにある拡張子を追加する\n    ・特定色域変換で変換前色に黒色を指定すると0除算が起こることがあるのを修正\n    ・範囲の大きいレンズブラーを掛けると危険な処理が行われるのを修正\n    ・新規プロジェクト作成ダイアログの画像サイズ入力欄の幅を広げる\n    ・パラメータを持つトラックバー変化方法スクリプトを含んだオブジェクトファイルの読み込みが正常に行えないことがあるのを修正\n    ・ファイルの情報を開くと落ちる/ファイル制御情報が正しくないことがあるのを修正\n    ・中間点で再生速度を変更した時、そこまでの中間点の数だけ速度変化が遅れて反映されるバグの修正\n    ・グローのしきい値が負の値になった時にエラーとなる・スレッド数より小さいサイズに正常に効果が反映されないバグの修正\n    ・新規プロジェクト作成時にサイズ・フレームレートが変わるフィルタをオフにする\n    ・レイヤー情報を保存するかどうかの判定方法を変える(従来:オブジェクトが存在する→変更:レイヤー情報が初期値でない)\n    ・読み込もうとしたファイルパスが長くて失敗するときにメッセージを出す/エラーが発生するのを修正\n    ・ドロップ処理で最終的に何も行われなかったときにメッセージを出力する\n\n    追加\n    ・コンソールの表示\n        標準入出力・エラー出力を流します。\n        「表示」メニューに「コンソールの表示」が追加されています。\n        Ctrlを押しながら選択すると、表示中でも最前面に表示し直します。\n\n    ・拡張編集のOutputDebugStringの内容の表示\n        console,console.debugstringが有効になっていなければ使えません。コンソールに表示します。\n        Luaのエラー内容なら赤い文字、debug_printの内容は青い文字で出力します。\n\n    ・例外メッセージのリニューアル\n        間違いが起こらないようにしました。\n        はいを押して、別のファイルに編集プロジェクトを保存して、それを開いてみるのが正しい作法でしたが、\n        patch.aulが追加する例外ダイアログからプロジェクトの保存を試みられるようになりました。\n        正しくプロジェクトの保存ができなければ、自動バックアップから復元します。\n\n    ・デバッグ情報出力\n        より報告/調査を楽にします。\n        デバッグ情報は <aviutl.exeがあるディレクトリ>\\log に出力されます。\n        これを発生したときの状況と一緒に有識者に投げると、原因がわかったり、patch.aulで直されたりするかもしれません。\n\n    ・メニューにアクセスキーを追加\n        ファイル(F) みたいになるやつです。\n        Alt+括弧内のキー を押すと飛べます。\n\n    ・テーマ機能\n        ConstChangerでできるのと同じようなことができます。逆に言えばそれ以上はできません。\n\n    ・Lua関連の仕様変更/追加関数\n        ・randexクラスを追加 標準のrand関数の分布がおかしいので\n        ・package.path,package.cpathに新たなディレクトリを追加\n            ・pathには<exedit.auf dir>\\module\\?.lua;<exedit.auf dir>\\module\\?\\init.lua\n            ・cpathには<exedit.auf dir>\\module\\?.dll\n\n    ・やり直し 機能\n        元に戻すの逆\n\n設定\n    patch.aulと同じパスにpatch.aul.jsonが生成されて、これが設定ファイルになります。\n    設定ファイルはAviUtlの起動時に1度だけ読み込まれて、終了時に1度だけ保存されるため、注意してください。\n\n    各キーの説明\n    ※説明用の型\n        color : stringで、書式が[0-9a-fA-F]{6}であるもの RRGGBBの順\n\n    \"console\" : { ; コンソール関連\n        \"visible\" : boolean, ; コンソールの表示 (既定値: false)\n        \"rect\" : [number, number, number, number], ; コンソールの位置(left,top,right,bottom)\n    },\n    \"theme_cc\" : { ; ConstChangerでできる設定\n        \"layer\" : {\n            \"height_large\" : number,  ; レイヤーの高さ (大 既定値: 31)\n            \"height_medium\" : number, ; レイヤーの高さ (中 既定値: 26)\n            \"height_small\" : number,  ; レイヤーの高さ (小 既定値: 22)\n            \"link_col\" : [color, color] or color, ; 座標のリンク ([縁色, 塗りつぶし色] または 色 既定値: \"4040c0\")\n            \"clipping_col\" : [color, color] or color, ; クリッピング ([縁色, 塗りつぶし色] または 色 既定値: \"c04040\")\n            \"lock_col\" : [color, color], ; レイヤーのロックの色 ([縁色, 塗りつぶし色] 既定値: [ \"000000\", \"c04040\" ])\n            \"hide_alpha\" : number, ; 非表示レイヤーの不透明度 ([0,1] 既定値: 0.85)\n        },\n        \"object\" : {\n            \"media_col\" : [color, color, color], ; 図形 などの青系のオブジェクトの色 ([グラデーション始点, 終点, 選択中] 既定値: [ \"10206c\", \"1830c0\", \"4080ff\" ])\n            \"mfilter_col\" : [color, color, color], ; シーンチェンジ などの緑系のオブジェクトの色 (既定値: [ \"106c10\", \"18c018\", \"40f040\" ])\n            \"audio_col\" : [color, color, color], ; 音声ファイル などの赤系のオブジェクトの色 (既定値: [ \"6c1018\", \"c01820\", \"f83040\" ])\n            \"afilter_col\" : [color, color, color], ; 音量の調整 などの黄系のオブジェクトの色 (既定値: [ \"6c6c10\", \"c0c020\", \"d8d840\" ])\n            \"control_col\" : [color, color, color], ; カメラ制御 などの青緑系のオブジェクトの色 (既定値: [ \"106c6c\", \"18c0c0\", \"40d8d8\" ])\n            \"inactive_col\" : [color, color, color], ; アルファチャンネル付きシーン中のフィルタオブジェクト などの灰系のオブジェクトの色 (既定値: [ \"606060\", \"808080\", \"909090\" ])\n            \"clipping_col\" : color, ; 上のオブジェクトでクリッピング(オブジェクト)の色 (既定値: \"c04040\")\n            \"clipping_height\" : number, ; 上のオブジェクトでクリッピング(オブジェクト)の印の高さ (既定値: -3)\n            \"midpt_size\" : [number, number, number], ; 中間点の大きさ(レイヤーの高さ大,中,小) (既定値: [4, 3, 3])\n            \"name_col\" : [color, color], ; オブジェクト名の色 ([有効時,無効時] 既定値: [ \"ffffff\", \"a0a0a0\" ])\n        },\n        \"timeline\" : {\n            \"scale_col\" : [fore, back], ; 拡大率の色 (既定値: [ \"60a0ff\", \"204080\" ])\n            \"bpm_grid_col\" : [measure, beat], ; BPMグリッドの色 (既定値: [ \"646464\", \"a0a0a0\" ])\n        }\n    },\n    \"redo\" : { ; やり直し 機能について\n        \"shift\" : true ; Ctrl+Shift+Z によるやり直し操作を有効化するか (既定値: true)\n    },\n    \"fast_exeditwindow\" : { ; 拡張編集ウィンドウの描画の最適化 について\n        \"step\" : 0 ; グラデーション描画の方法 (負数でパッチ無効,0でグラデーションのパッチ,正数でその分割数の単色矩形 既定値: 0),\n    },\n    \"fast_text\" : { ; テキストの軽量化について\n        \"release_time\" : 120 ; キャッシュデータの寿命[秒]\n    },\n\t\"switch\" : { ; どのパッチを有効にするかを選択するものです trueなら有効、falseなら無効\n\t\t\"access_key\" : boolean, ; アクセスキーを付加するか (既定値: false)\n\t\t\"aup_scene_setting\" : boolean, ; プロジェクトの保存/読み込み時にシーン設定の一部情報（グリッド設定など）が欠けるのを修正 (既定値: true)\n\t\t\"colorpalette_cache\" : boolean, ; bmpのキャッシュが作られる際に、カラーパレット分のデータ容量を取り忘れているのを修正 (既定値: true)\n\t\t\"fileinfo\" : boolean, ; ファイルの情報を開くと落ちる/ファイル制御情報が正しくないことがあるのを修正 (既定値: true)\n\t\t\"aup_layer_setting\" : boolean, ; プロジェクトの保存時、レイヤー情報を保存する基準を変える (既定値: true)\n\t\t\"exo_aviutl_filter\" : boolean, ; 拡張編集以外のフィルタ(例:拡張色調補正)を使ったプロジェクトをオブジェクトファイルに出力できないことがある (既定値: true)\n\t\t\"exo_sceneidx\" : boolean, ; オブジェクトファイルの入出力で、シーン番号を正しく扱えない (既定値: true)\n\t\t\"exo_trackparam\" : boolean, ; オブジェクトファイルの入力で、トラックバー変化方法スクリプトの名前にASCII以外の文字が含まれているとパラメータを読み込めない (既定値: true)\n\t\t\"exa_fold_gui\" : boolean, ; exa,exo生成時、設定ダイアログの▼（折り畳み）とマウスマーク（GUI表示）の情報を追加する (既定値: true)\n        \"exo_track_minusval\" : boolean, ; オブジェクトファイルの入力で、トラックバーの -1 超 0 未満の値が正になってしまう (既定値: true)\n\t\t\"exo_midpt_and_tra\" : boolean, ; 中間点有りで.traスクリプト変化方式のあるオブジェクトがあるexoが正常に読み込めないことがあるのを修正 (既定値: true)\n        \"exo_specialcolorconv\" : boolean, ; オブジェクトファイルの入出力で、特定色域変換のstatusが2つあって正しく入出力できない (既定値: true)\n        \"tra_aviutlfilter\" : boolean, ; 拡張編集以外のフィルタのトラックバーにトラックバー変化方法スクリプトを適用していると例外になる問題 (既定値: true)\n\t\t\"tra_change_drawfilter\" : boolean, ; 標準描画-拡張描画-パーティクルの切り替え時にトラックバーの設定値(移動フレーム間隔)が0になるのを修正 (既定値: true)\n\t\t\"tra_specified_speed\" : boolean, ; トラックバー変化方法の移動量指定と時間制御の組み合わせでバグるのを修正 (既定値: true)\n\t\t\"setting_new_project\" : boolean, ; 新規プロジェクト作成時にサイズ・フレームレートの変わるフィルタをオフにする (既定値: true)\n\t\t\"text_op_size\" : boolean, ; テキストオブジェクトでUTF-16で34バイト以上のフォント名を指定している時、制御文字<s>でサイズのみを指定していると正しい動作をしない (既定値: true)\n        \"ignore_media_param_reset\" : boolean, ; 動画ファイル と 音声ファイル で中間点を打っていないときでもファイルを再参照しても再生位置などの情報を変更しない (既定値: false)\n        \"failed_sjis_msgbox\" : boolean, ; ファイルパスに使用できない文字が含まれている時に出すエラーメッセージを変更する (既定値: true)\n\t\t\"failed_longer_path\" : boolean, ; 読み込もうとしたファイルパスが長くて失敗するときにメッセージを出す/エラーが発生するのを修正 (既定値: true)\n\t\t\"failed_file_drop\" : boolean, ; ドロップ処理で最終的に何も行われなかったときにメッセージを出力する (既定値: true)\n\t\t\"theme_cc\" : boolean, ; テーマ機能 (既定値: true)\n\t\t\"exeditwindow_sizing\" : boolean, ; 拡張編集ウィンドウの上部をドラッグして正常にリサイズできるようにする (既定値: true)\n        \"settingdialog_move\" : boolean, ; 設定ダイアログを高ポーリングレートマウス環境で移動すると重たい の解消 (既定値: true)\n\t\t\"obj_colorcorrection\" : boolean, ; 色調補正の色相計算を修正 (既定値: true)\n\t\t\"obj_lensblur\" : boolean, ; レンズブラーのバグ修正 (既定値: true)\n\t\t\"obj_glow\" : boolean, ; グローのしきい値が負の値になった時にエラーとなる・スレッド数より小さいサイズに正常に効果が反映されないバグを修正 (既定値: true)\n\t\t\"obj_lensblur\" : boolean, ; 小さい画像に対してサイズ固定で範囲の大きいレンズブラーを掛けると例外になるのを修正 (既定値: true)\n\t\t\"obj_noise\" : boolean, ; ノイズの速度X、変化速度のトラック変化方法が移動無し以外の時に速度Yの値をもとに計算が行われてしまうのを修正 (既定値: true)\n\t\t\"obj_specialcolorconv\" : boolean, ; 特定色域変換で変換前色に黒色を指定すると0除算が起こることがあるのを修正 (既定値: true)\n\t\t\"settingdialog_excolorconfig\" : boolean, ; 拡張色変換のウィンドウが下のフィルタに被るのを修正 (既定値: true)\n\t\t\"r_click_menu_split\" : boolean, ; 右クリック分割で設定ダイアログが更新されないのを修正 (既定値: true)\n\t\t\"r_click_menu_delete\" : boolean, ; 右クリック削除でテキストの字間行間が変わることがあるのを修正 (既定値: true)\n\t\t\"blend\" : boolean, ; アルファチャンネルのあるフレームバッファで合成モード「通常」以外を使用すると誤った結果になるのを修正 (既定値: true)\n\t\t\"add_extension\" : boolean, ; 動画、音声ファイル参照の時、exedit.iniにある拡張子を追加する (既定値: true)\n\t\t\"new_project_editbox\" : boolean, ; 新規プロジェクト作成ダイアログの画像サイズ入力欄の幅を広げる (既定値: true)\n\t\t\"playback_speed\" : boolean, ; 中間点で再生速度を変更した時、そこまでの中間点の数だけ速度変化が遅れて反映されるバグの修正 (既定値: true)\n        \"undo\" : boolean, ; 元に戻す 関連のバグ修正 (既定値: true)\n        \"undo.redo\" : boolean, ; やり直す を追加 (既定値: true)\n\t\t\"console\" : boolean, ; コンソール (既定値: true)\n\t\t\"console.escape\" : boolean, ; エスケープシーケンス (既定値: true)\n\t\t\"console.input\" : boolean, ; 標準入力を受け取るか (既定値: false)\n\t\t\"console.debug_string\" : boolean, ; 拡張編集のOutputDebugStringの内容を表示する (既定値: true)\n\t\t\"console.debug_string.time\" : boolean, ; 拡張編集のOutputDebugStringの内容の先頭に時刻を表示する (既定値: true)\n\t\t\"lua\" : boolean, ; lua.*配下のスイッチの主電源 (既定値: true)\n        \"lua.env\" : boolean, ; Luaの環境を統一する (既定値: false)\n        \"lua.path\" : boolean, ; package.path,cpathにパスを追加 (既定値: false)\n\t\t\"lua.getvalue\" : boolean, ; getvalueで中心座標を取得できるように (既定値: true)\n\t\t\"lua.rand\" : boolean, ; rand関数で例外になるパターンを潰す (既定値: true)\n\t\t\"lua.randex\" : boolean, ; 正確な乱数を提供するrandexクラスの追加 (既定値: true)\n\t\t\"fast\" : boolean, ; fast.*配下のスイッチの主電源 (既定値: true)\n\t\t\"fast.exeditwindow\" : boolean, ; 拡張編集ウィンドウの描画の最適化 (既定値: true)\n\t\t\"fast.settingdialog\" : boolean, ; 設定ダイアログの描画の最適化 (既定値: true)\n        \"fast.text\" : boolean, ; テキストの軽量化 (既定値: true)\n\t\t\"fast.create_figure\" : boolean, ; 図形の高速化 (既定値: true)\n        \"fast.border\" : boolean, ; 縁取りの高速化/バグ修正 (既定値: true)\n\t\t\"fast.glow\" : boolean, ; グローの高速化 (既定値: true)\n\t\t\"fast.cl\" : boolean, ; fast.*でOpenCLが必要なオプションに必要なオプション (既定値: true)\n\t\t\"fast.radiationalblur\" : boolean, ; fast.clが前提 放射ブラーの高速化 (既定値: true)\n\t\t\"fast.polortransform\" : boolean, ; fast.clが前提 極座標変換の高速化 (既定値: true)\n\t\t\"fast.displacementmap\" : boolean, ; fast.clが前提 ディスプレイスメントマップの高速化 (既定値: true)\n        \"fast.flash\" : true : boolean, ; fast.clが前提 閃光の高速化 (既定値: true)\n\t\t\"fast.directionalblur\" : boolean,  ; fast.clが前提 方向ブラーの高速化 (既定値: true)\n\t\t\"fast.lensblur\" : boolean  ; fast.clが前提 レンズブラーの高速化 (既定値: true)\n\t}\n\nLua追加要素詳細\n    _PATCH\n        patch.aulのバージョン情報\n        現在は \"patch.aul r43 beta1\" という文字列が格納されている\n\n    obj.randex(seed,frame)\n        seed : integer\n        frame : integer\n            obj.randのseed,frameと同じ使い方をする\n\n        return : userdata\n            乱数生成オブジェクト\n            userdata(start,end)の形式で呼び出せて、呼び出しの毎に返されるintegerは変わる\n\nライセンス\n    LGPLv3 詳細はLICENSEファイルを見よ\n\nその他の注意\n    デバッグ情報ファイルには、個人情報が含まれる可能性があります。例えば個人情報を扱っているところで例外が発生した場合、レジスタやスタックにその情報が載っているかもしれません。\n    ファイルを第三者に送信する際には気をつけて下さい。\n\n更新履歴\n    r2\n        バージョンが異なっていたときの処理/メッセージ修正\n        けしからんフックをするプラグインへの対策\n\n    r3\n        デバッグ情報のstackの目盛りがズレてた\n        ConstChanger相当の機能を追加\n        コンソールのエスケープシーケンスを有効にする設定を追加(デフォルトでは有効)\n        debug_print,Luaのエラーの時に先頭に時刻を付加する設定を追加(デフォルトでは有効)\n        例外ダイアログをモーダルにした\n        例外ダイアログの生成に失敗するパターンを潰した\n        例外ダイアログのXボタンでアプリケーションが終了するのは意図していない挙動だったので修正\n        その他内部の整理\n\n    r4\n        未成の処理が紛れ込んでいたので削除\n\n    r5\n        SysInfo::info に誤ったポインタを代入していた問題(r3から)を修正\n\n    r6\n        どのパッチを適用するかユーザーが指定できるようにした\n        例外ダイアログ表示時に音が出るようにした\n        例外ダイアログが言語拡張リソースに対応した\n        \n    r7\n        動画ファイル と 音声ファイル で中間点を打っていないときでもファイルを再参照しても再生位置などの情報を変更しない を追加\n\n    r8\n        例外ダイアログから編集プロジェクトの保存を試みられるようにした\n        コンソールウィンドウの位置をAviUtlが再起動しても保持するようにした\n        コンソールウィンドウが標準入力を受け取るかを選択できるようにして、受け取らないときはコンソールの表示がSW_SHOW/SW_HIDEになるようにした\n        Luaで error() としてpatch.aulの例外になるケースを修正\n        拡張編集以外のフィルタ(例:拡張色調補正)を使ったプロジェクトをオブジェクトファイルに出力できないことがある の修正を追加\n        不正な設定ファイルであったとき、初期設定で上書きしないようにした\n        patch.aulの出すメッセージが言語拡張リソースに一部対応\n        中間点のサイズがレイヤー幅中のときのものしか変更できなかった問題を修正\n        オブジェクトファイルの入出力で、特定色域変換のstatusが2つあって正しく入出力できない の修正を追加\n        [表示][拡大表示][ウィンドウサイズを自動変更]が欠落していた問題を修正\n\n    r9\n        patch.aulの出すメッセージが言語拡張リソースに全て対応\n        例外情報のC++ exceptionの詳細情報を追加\n        極座標変換と放射ブラーの高速化を追加\n\n    r10\n        v_func_WndProcをフックするプログラムにやさしくない書き方をしていたのを修正\n\n    r11\n        Luaの環境を統一\n        obj.randで例外になるものの修正\n        randexクラスを追加\n        obj.getvalueで中心座標の情報を取得できるようにした\n        obj.getvalue(\"layerX.time\")が正しい値を取得できるようにした\n        スクリプトがscriptフォルダの子フォルダにあった時にpackage.path,cpathにscriptを追加\n        package.path,cpathにmoduleフォルダを追加\n        OpenCLの要求バージョンを1系に下げた\n        OpenCLのdouble拡張を要求しないようにした\n\n    r12\n        Luaに _PATCH 変数を追加\n\n    r13\n        拡張編集ウィンドウと設定ダイアログの描画の最適化\n        拡張編集ウィンドウの上部をドラッグしても正常にリサイズができるように\n        switch\\lua.pathの既定値をfalseに\n\n    r14\n        スクリプト並び替えプラグインとの競合を解消\n\n    r15\n        Luaの環境統合をlua.envスイッチに切り出し\n        起動時に設定ファイルを生成するように\n        その他内部の整理\n\n    r17\n        OSS化\n        設定ダイアログを高ポーリングレートマウス環境で移動すると重たい の解消\n        拡張編集の元に戻すのバグ修正\n        拡張編集にやり直すを追加\n\n    r18\n        設定ダイアログへの操作の修正\n\n    r19\n        競合プラグインがあったら無効化した上で消すか訊くことにした\n\n    r20\n        設定ダイアログのサイズが変更されたときの画面外の領域が正しく描画されないのを修正\n\n    r21\n        再修正 というかやり方を変えた\n        settingdialog_moveスイッチが機能してなかったのを修正\n        \n    r22\n        閃光の高速化を追加\n        カメラ制御の対象にするかどうかの変更を元に戻せない問題の修正\n        上のオブジェクトでクリッピングの変更を元に戻せない問題の修正\n        テンキーによるオブジェクトへの操作を元に戻せない問題の修正\n        拡張編集以外のフィルタのトラックバーにトラックバー変化方法スクリプトを適用していると例外になる問題の修正\n\n    r23\n        redoの既定値がfalseになっていたのを修正\n\n    r24\n        アクセスキーの設定を有効にしても機能が有効化されないのを修正\n\n    r25\n        console\\visible,lua.getvalue,rand,randex,pathの既定値が逆になってたのを修正\n\n    r26\n        lua.env,pathの設定を正しく扱えなかったのを修正\n        exo_aviutlfilterが動作しなかったのを修正\n        switch\\redoをfalseにしているときに元に戻すのショートカットを行うと死ぬのを修正\n\n    r27\n        コンソールへのLua関連の出力が動作していなかったのを修正\n        ランタイムライブラリを不要にした\n\n    r28\n        テキストの軽量化を追加\n        ランタイムライブラリを不要にしたのを取り消し\n\n    r29\n        一部条件でテキスト軽量化がエラーになるのを修正\n\n    r30\n        lua.rand,randex,getvalueが機能していなかったのを修正\n\n    r31\n        RePOPnビルドL-SMASH Works r940を導入していると警告を表示する機能を追加\n\n    r32\n        LSWの警告で遷移するサイトをScrapboxに変更\n\n    r33\n        縁取りの高速化/バグ修正を追加\n\n    r34\n        fast.borderのバグを修正\n\n    r35\n        fast.borderのバグを修正2\n        放射ブラー(フィルタオブジェクト)/方向ブラー(両方)/レンズブラー(両方)の高速化を追加\n        小さい画像に対してサイズ固定で範囲の大きいレンズブラーを掛けると例外になるのを修正\n        拡張色変換のウィンドウが下のフィルタに被るのを修正\n        ビルド環境の変更(submoduleやNuGetを使うように)\n\n    r36\n        方向ブラー/放射ブラーの高速化のバグを修正\n\n    r37\n        OpenCLの要求バージョンが上がっていたのを修正\n\n    r38\n        OpenCLの要求バージョンが上がっていたのを修正2\n\n    r39\n        方向ブラーの高速化のバグを修正\n\n    r40\n        レンズブラーの高速化のバグを修正\n        タイムラインのアイテムが長すぎるときに描画色がおかしくなるのを修正\n\n    r41\n        タイムラインのアイテムが長すぎるときに描画色がおかしくなるのを再修正\n\n    r42\n        ディスプレイスメントマップの高速化を追加\n        図形の高速化を追加\n        色調補正の色相の修正を追加\n        ファイルパスが原因の「対応していないフォーマット～」エラーのメッセージを変更する を追加\n        極座標変換/放射ブラーの高速化を修正\n        右クリックの分割で設定ダイアログが更新されないのを修正\n        右クリックの削除でテキストの字間行間情報が失われるのを修正\n        標準描画-拡張描画-パーティクルの切り替え時にトラックバーの設定値(移動フレーム間隔)が0になるのを修正\n        トラックバー変化方法の移動量指定が時間制御で壊れるのを修正\n        アルファチャンネルのあるフレームバッファで合成モード「通常」以外を使用すると誤った結果になるのを修正\n        jsonの数値変換がロケール依存だったので修正\n        theme_ccがない状態でswitch\\themc_ccがfalseの時壊れたjsonが生成されていたのを修正\n\n    r43\n        グローの高速化を追加\n        ファイルパスに使用できない文字が含まれている時に出すエラーメッセージの変更\n        色調補正の色相計算を修正\n        プロジェクトの保存/読み込み時にシーン設定の一部情報（グリッド設定など）が欠けるのを修正\n        exa,exo生成時、設定ダイアログの▼（折り畳み）とマウスマーク（GUI表示）の情報を追加する\n        BMP File Readerを使うと、正しくない画像データをキャッシュしてしまうことがあるのを修正\n        動画、音声ファイル参照の時、exedit.iniにある拡張子を追加する\n        特定色域変換で変換前色に黒色を指定すると0除算が起こることがあるのを修正\n        範囲の大きいレンズブラーを掛けると危険な処理が行われるのを修正\n        新規プロジェクト作成ダイアログの画像サイズ入力欄の幅を広げる\n        パラメータを持つトラックバー変化方法スクリプトを含んだオブジェクトファイルの読み込みが正常に行えないことがあるのを修正\n        ファイルの情報を開くと落ちる/ファイル制御情報が正しくないことがあるのを修正\n        中間点で再生速度を変更した時、そこまでの中間点の数だけ速度変化が遅れて反映されるバグの修正\n        グローのしきい値が負の値になった時にエラーとなる・スレッド数より小さいサイズに正常に効果が反映されないバグの修正\n        新規プロジェクト作成時にサイズ・フレームレートが変わるフィルタをオフにする\n        レイヤー情報を保存するかどうかの判定方法を変える(従来:オブジェクトが存在する→変更:レイヤー情報が初期値でない)\n        読み込もうとしたファイルパスが長くて失敗するときにメッセージを出す/エラーが発生するのを修正\n        ドロップ処理で最終的に何も行われなかったときにメッセージを出力する\n"
  },
  {
    "path": "patch.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.0.32112.339\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"patch\", \"patch\\patch.vcxproj\", \"{20C4ED31-B17F-445A-90FE-77F8119F831B}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|x86 = Debug|x86\n\t\tRelease_PDB|x86 = Release_PDB|x86\n\t\tRelease|x86 = Release|x86\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{20C4ED31-B17F-445A-90FE-77F8119F831B}.Debug|x86.ActiveCfg = Debug|Win32\n\t\t{20C4ED31-B17F-445A-90FE-77F8119F831B}.Debug|x86.Build.0 = Debug|Win32\n\t\t{20C4ED31-B17F-445A-90FE-77F8119F831B}.Release_PDB|x86.ActiveCfg = Release_PDB|Win32\n\t\t{20C4ED31-B17F-445A-90FE-77F8119F831B}.Release_PDB|x86.Build.0 = Release_PDB|Win32\n\t\t{20C4ED31-B17F-445A-90FE-77F8119F831B}.Release|x86.ActiveCfg = Release|Win32\n\t\t{20C4ED31-B17F-445A-90FE-77F8119F831B}.Release|x86.Build.0 = Release|Win32\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {8ECF7614-0562-458B-825B-AADA74AAACDB}\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "readme.md",
    "content": "# patch.aul\n## これはなに\nAviUtlや拡張編集のバグを直したり機能を追加するプラグイン\n黒魔術を一手に引き受けるのが目的\n\n詳細はpatch.aul.txtを読むこと\n\n## ビルドについて\n\n- [CUDA TOOLKIT](https://developer.nvidia.com/cuda-toolkit)を用意してください\n これのOpenCLライブラリを使います 環境変数`CUDA_PATH`を使います\n\n-  `test`フォルダを用意してください\n これは`aviutl.exe`などを置くフォルダで、デバッグ実行するとこのディレクトリの`aviutl.exe`が実行されます\n\n- ビルドすると、`pack`フォルダにリリース用のファイルが集まります\n"
  }
]