修訂 | 8d6e8f0f1dcaa7bd55ec2d9aa8498b996fe227a1 (tree) |
---|---|
時間 | 2021-04-27 10:15:19 |
作者 | majiponi <majiponi@yaho...> |
Commiter | majiponi |
Ver0.02 - The engin ignores needless [aviutl path] in .aus files correctly.
@@ -10,68 +10,65 @@ namespace | ||
10 | 10 | } |
11 | 11 | |
12 | 12 | |
13 | -IATModifier::IATModifier(const char* dll, const char* name, const void* hook, HMODULE mod) | |
14 | - : dll(dll), name(name), hook(hook), oldproc(GetProcAddress(GetModuleHandleA(dll), name)), mod(mod) | |
13 | +IATModifier::IATModifier(const char* exporter, const char* apiname, const void* newproc, HMODULE importer) | |
14 | + : exporter{exporter}, apiname{apiname}, newproc{newproc}, oldproc{ GetProcAddress(GetModuleHandleA(exporter), apiname) }, importer{importer} | |
15 | 15 | { |
16 | - if(mod){ | |
17 | - modifyIAT(dll, oldproc, hook, mod); | |
16 | + if(importer){ | |
17 | + modifyIAT(exporter, oldproc, newproc, importer); | |
18 | 18 | } |
19 | 19 | else{ |
20 | - modifyIAT(dll, oldproc, hook); | |
20 | + modifyIAT(exporter, oldproc, newproc); | |
21 | 21 | } |
22 | 22 | } |
23 | 23 | |
24 | 24 | IATModifier::~IATModifier() |
25 | 25 | { |
26 | - if(mod){ | |
27 | - modifyIAT(dll, hook, oldproc, mod); | |
26 | + if(importer){ | |
27 | + modifyIAT(exporter, newproc, oldproc, importer); | |
28 | 28 | } |
29 | 29 | else{ |
30 | - modifyIAT(dll, hook, oldproc); | |
30 | + modifyIAT(exporter, newproc, oldproc); | |
31 | 31 | } |
32 | 32 | } |
33 | 33 | |
34 | 34 | namespace |
35 | 35 | { |
36 | - void modifyIAT(const char* apidll, const void* origaddr, const void* newaddr, HMODULE target) | |
36 | + void modifyIAT(const char* exporter, const void* oldproc, const void* newproc) | |
37 | + { | |
38 | + MODULEENTRY32 entry{ sizeof(entry) }; | |
39 | + | |
40 | + const HANDLE hSnap{ CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()) }; | |
41 | + | |
42 | + if(Module32First(hSnap, &entry)){ | |
43 | + do{ | |
44 | + modifyIAT(exporter, oldproc, newproc, entry.hModule); | |
45 | + }while(Module32Next(hSnap, &entry)); | |
46 | + } | |
47 | + | |
48 | + CloseHandle(hSnap); | |
49 | + } | |
50 | + | |
51 | + void modifyIAT(const char* exporter, const void* oldproc, const void* newproc, HMODULE importer) | |
37 | 52 | { |
38 | 53 | ULONG size; |
39 | - const IMAGE_IMPORT_DESCRIPTOR* pDesc = static_cast<const IMAGE_IMPORT_DESCRIPTOR*>(ImageDirectoryEntryToData(target, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size)); | |
54 | + auto pDesc{ static_cast<const IMAGE_IMPORT_DESCRIPTOR*>(ImageDirectoryEntryToData(importer, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size)) }; | |
40 | 55 | if(!pDesc) return; |
41 | 56 | |
42 | 57 | for(; pDesc->Name; pDesc++){ |
43 | - const char* name = reinterpret_cast<const char*>(target) + pDesc->Name; | |
44 | - if(!_strcmpi(name, apidll)) break; | |
58 | + const char* name{ reinterpret_cast<const char*>(importer) + pDesc->Name }; | |
59 | + if(!_strcmpi(name, exporter)) break; | |
45 | 60 | } |
46 | 61 | if(!pDesc->Name) return; |
47 | 62 | |
48 | - IMAGE_THUNK_DATA* pThunk = reinterpret_cast<IMAGE_THUNK_DATA*>(reinterpret_cast<char*>(target) + pDesc->FirstThunk); | |
63 | + auto pThunk{ reinterpret_cast<IMAGE_THUNK_DATA*>(reinterpret_cast<char*>(importer) + pDesc->FirstThunk) }; | |
49 | 64 | for(; pThunk->u1.Function; pThunk++){ |
50 | - const void* addr = reinterpret_cast<const void*>(pThunk->u1.Function); | |
51 | - if(addr == origaddr) break; | |
65 | + if(pThunk->u1.Function == reinterpret_cast<DWORD>(oldproc)) break; | |
52 | 66 | } |
53 | 67 | if(!pThunk->u1.Function) return; |
54 | 68 | |
55 | - const void*& proc = reinterpret_cast<const void*&>(pThunk->u1.Function); | |
56 | - | |
57 | 69 | DWORD protect; |
58 | - VirtualProtect(&proc, sizeof(proc), PAGE_EXECUTE_READWRITE, &protect); | |
59 | - proc = newaddr; | |
60 | - VirtualProtect(&proc, sizeof(proc), protect, &protect); | |
61 | - } | |
62 | - | |
63 | - void modifyIAT(const char* apidll, const void* origaddr, const void* newaddr) | |
64 | - { | |
65 | - MODULEENTRY32 entry { sizeof(entry) }; | |
66 | - | |
67 | - HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); | |
68 | - | |
69 | - if(Module32First(hSnap, &entry)){ | |
70 | - do{ | |
71 | - modifyIAT(apidll, origaddr, newaddr, entry.hModule); | |
72 | - }while(Module32Next(hSnap, &entry)); | |
73 | - } | |
74 | - | |
75 | - CloseHandle(hSnap); | |
70 | + VirtualProtect(&pThunk->u1.Function, sizeof(pThunk->u1.Function), PAGE_EXECUTE_READWRITE, &protect); | |
71 | + pThunk->u1.Function = reinterpret_cast<DWORD>(newproc); | |
72 | + VirtualProtect(&pThunk->u1.Function, sizeof(pThunk->u1.Function), protect, &protect); | |
76 | 73 | } |
77 | 74 | } |
@@ -5,13 +5,14 @@ | ||
5 | 5 | class IATModifier |
6 | 6 | { |
7 | 7 | private: |
8 | - const char* dll; | |
9 | - const char* name; | |
10 | - const void* hook; | |
8 | + const char* exporter; | |
9 | + const char* apiname; | |
10 | + const void* newproc; | |
11 | 11 | const void* oldproc; |
12 | - HMODULE mod; | |
12 | + HMODULE importer; | |
13 | + | |
13 | 14 | public: |
14 | - IATModifier(const char* dll, const char* name, const void* hook, HMODULE mod = nullptr); | |
15 | + IATModifier(const char* exporter, const char* apiname, const void* newproc, HMODULE importer = nullptr); | |
15 | 16 | IATModifier(const IATModifier&) = delete; |
16 | 17 | ~IATModifier(); |
17 | 18 | }; |
@@ -95,6 +95,7 @@ | ||
95 | 95 | <ConformanceMode>true</ConformanceMode> |
96 | 96 | <AssemblerOutput>NoListing</AssemblerOutput> |
97 | 97 | <AdditionalOptions>/source-charset:utf-8 %(AdditionalOptions)</AdditionalOptions> |
98 | + <LanguageStandard>stdcpp17</LanguageStandard> | |
98 | 99 | </ClCompile> |
99 | 100 | <Link> |
100 | 101 | <SubSystem>Windows</SubSystem> |
@@ -130,6 +131,7 @@ | ||
130 | 131 | <ConformanceMode>true</ConformanceMode> |
131 | 132 | <AssemblerOutput>NoListing</AssemblerOutput> |
132 | 133 | <AdditionalOptions>/source-charset:utf-8 %(AdditionalOptions)</AdditionalOptions> |
134 | + <LanguageStandard>stdcpp17</LanguageStandard> | |
133 | 135 | </ClCompile> |
134 | 136 | <Link> |
135 | 137 | <SubSystem>Windows</SubSystem> |
@@ -163,6 +165,7 @@ | ||
163 | 165 | <ClInclude Include="apihook.h" /> |
164 | 166 | <ClInclude Include="command.h" /> |
165 | 167 | <ClInclude Include="core.h" /> |
168 | + <ClInclude Include="coreimp.h" /> | |
166 | 169 | <ClInclude Include="parser.h" /> |
167 | 170 | <ClInclude Include="filter.h" /> |
168 | 171 | <ClInclude Include="stdafx.h" /> |
@@ -181,6 +184,8 @@ | ||
181 | 184 | <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader> |
182 | 185 | </ClCompile> |
183 | 186 | <ClCompile Include="ui.cpp" /> |
187 | + <ClCompile Include="v1patch.cpp" /> | |
188 | + <ClCompile Include="v2patch.cpp" /> | |
184 | 189 | </ItemGroup> |
185 | 190 | <ItemGroup> |
186 | 191 | <None Include="aus.def" /> |
@@ -39,6 +39,9 @@ | ||
39 | 39 | <ClInclude Include="command.h"> |
40 | 40 | <Filter>ヘッダー ファイル</Filter> |
41 | 41 | </ClInclude> |
42 | + <ClInclude Include="coreimp.h"> | |
43 | + <Filter>ヘッダー ファイル</Filter> | |
44 | + </ClInclude> | |
42 | 45 | </ItemGroup> |
43 | 46 | <ItemGroup> |
44 | 47 | <ClCompile Include="stdafx.cpp"> |
@@ -59,6 +62,12 @@ | ||
59 | 62 | <ClCompile Include="command.cpp"> |
60 | 63 | <Filter>ソース ファイル</Filter> |
61 | 64 | </ClCompile> |
65 | + <ClCompile Include="v1patch.cpp"> | |
66 | + <Filter>ソース ファイル</Filter> | |
67 | + </ClCompile> | |
68 | + <ClCompile Include="v2patch.cpp"> | |
69 | + <Filter>ソース ファイル</Filter> | |
70 | + </ClCompile> | |
62 | 71 | </ItemGroup> |
63 | 72 | <ItemGroup> |
64 | 73 | <None Include="aus.def"> |
@@ -1,6 +1,7 @@ | ||
1 | 1 | #include "stdafx.h" |
2 | 2 | #include <commdlg.h> |
3 | -#include <algorithm> | |
3 | +#include <cstdio> | |
4 | +#include <memory> | |
4 | 5 | #include <typeinfo> |
5 | 6 | |
6 | 7 | #include "apihook.h" |
@@ -8,115 +9,126 @@ | ||
8 | 9 | |
9 | 10 | namespace |
10 | 11 | { |
11 | - HWND getExeditWindow(); | |
12 | - | |
13 | 12 | union{ |
14 | 13 | int scene_no; |
15 | 14 | struct{ unsigned int cx, cy, fps, freq; }* videoinfo; |
16 | 15 | const char* path; |
17 | - bool transparent; | |
16 | + bool transparency; | |
18 | 17 | } dlgdata; |
18 | + | |
19 | + HWND getExeditWindow(); | |
19 | 20 | } |
20 | 21 | |
21 | 22 | namespace AviUtlCommand |
22 | 23 | { |
23 | - void CreateProject(size_t cx, size_t cy, size_t fps, size_t freq) | |
24 | - { | |
25 | - HMODULE ex = GetModuleHandleA("exedit.auf"); | |
26 | - if(!ex) return; | |
27 | - | |
28 | - std::remove_pointer<decltype(dlgdata.videoinfo)>::type data{ cx, cy, fps, freq }; | |
29 | - dlgdata.videoinfo = &data; | |
30 | - | |
31 | - IATModifier hook1{ "user32.dll", "DialogBoxParamA", static_cast<decltype(DialogBoxParamA)*>([](HINSTANCE, LPCSTR, HWND, DLGPROC proc, LPARAM) -> INT_PTR { | |
32 | - proc(nullptr, WM_COMMAND, IDOK, 0); | |
33 | - return IDOK; | |
34 | - }), ex }; | |
35 | - IATModifier hook2{ "user32.dll", "GetDlgItemInt", static_cast<decltype(GetDlgItemInt)*>([](HWND, int id, BOOL*, BOOL) -> UINT { | |
36 | - if(id == 171) return dlgdata.videoinfo->cx; | |
37 | - if(id == 172) return dlgdata.videoinfo->cy; | |
38 | - return dlgdata.videoinfo->freq; | |
39 | - }), ex }; | |
40 | - IATModifier hook3{ "user32.dll", "GetDlgItemTextA", static_cast<decltype(GetDlgItemTextA)*>([](HWND, int, char* buf, int nmax) -> UINT { | |
41 | - return sprintf_s(buf, nmax, "%d", dlgdata.videoinfo->fps); | |
42 | - }), ex }; | |
43 | - | |
44 | - SendMessageA(getExeditWindow(), WM_COMMAND, 1030, 0xFFFFFFFF); | |
45 | - } | |
46 | - | |
47 | - void OpenExoFile(const char* path) | |
24 | + void SaveProject(const char* path) | |
48 | 25 | { |
49 | - dlgdata.path = path; | |
50 | - IATModifier hook3{ "comdlg32.dll", "GetOpenFileNameA", static_cast<decltype(GetOpenFileNameA)*>([](LPOPENFILENAMEA pofn) -> BOOL { | |
26 | + const IATModifier hook{ "comdlg32.dll", "GetSaveFileNameA", static_cast<decltype(GetSaveFileNameA)*>( | |
27 | + [](LPOPENFILENAMEA pofn) -> BOOL { | |
51 | 28 | strcpy_s(pofn->lpstrFile, pofn->nMaxFile, dlgdata.path); |
52 | 29 | return TRUE; |
53 | 30 | }), GetModuleHandleA(nullptr) }; |
54 | 31 | |
55 | - SendMessageA(getExeditWindow(), WM_COMMAND, 1037, 0xFFFFFFFF); | |
32 | + dlgdata.path = path; | |
33 | + SendMessageA(AviUtlUI::GetMainWindow(), WM_COMMAND, 1023, -1); | |
56 | 34 | } |
35 | +} | |
57 | 36 | |
58 | - void Quit() | |
37 | +namespace ExeditCommand | |
38 | +{ | |
39 | + void CreateProject(size_t cx, size_t cy, size_t fps, size_t freq) | |
59 | 40 | { |
60 | - PostMessageA(AviUtlUI::GetMainWindow(), WM_CLOSE, 0, 0); | |
41 | + const HMODULE ex{ GetModuleHandleA("exedit.auf") }; | |
42 | + const IATModifier hook[]{ | |
43 | + { "user32.dll", "DialogBoxParamA", static_cast<decltype(DialogBoxParamA)*>( | |
44 | + [](HINSTANCE, LPCSTR, HWND, DLGPROC proc, LPARAM) -> INT_PTR { | |
45 | + proc(nullptr, WM_COMMAND, IDOK, 0); | |
46 | + return IDOK; | |
47 | + }), ex }, | |
48 | + { "user32.dll", "GetDlgItemInt", static_cast<decltype(GetDlgItemInt)*>( | |
49 | + [](HWND, int id, BOOL*, BOOL) -> UINT { | |
50 | + if(id == 171) return dlgdata.videoinfo->cx; | |
51 | + if(id == 172) return dlgdata.videoinfo->cy; | |
52 | + return dlgdata.videoinfo->freq; | |
53 | + }), ex }, | |
54 | + { "user32.dll", "GetDlgItemTextA", static_cast<decltype(GetDlgItemTextA)*>( | |
55 | + [](HWND, int, char* buf, int nmax) -> UINT { | |
56 | + return sprintf_s(buf, nmax, "%d", dlgdata.videoinfo->fps); | |
57 | + }), ex } | |
58 | + }; | |
59 | + | |
60 | + std::remove_pointer<decltype(dlgdata.videoinfo)>::type data{ cx, cy, fps, freq }; | |
61 | + dlgdata.videoinfo = &data; | |
62 | + SendMessageA(getExeditWindow(), WM_COMMAND, 1030, -1); | |
61 | 63 | } |
62 | 64 | |
63 | - void SaveProject(const char* path) | |
65 | + void OpenExoFile(const char* path) | |
64 | 66 | { |
65 | - dlgdata.path = path; | |
66 | - IATModifier hook3{ "comdlg32.dll", "GetSaveFileNameA", static_cast<decltype(GetSaveFileNameA)*>([](LPOPENFILENAMEA pofn) -> BOOL { | |
67 | + const IATModifier hook{ "comdlg32.dll", "GetOpenFileNameA", static_cast<decltype(GetOpenFileNameA)*>( | |
68 | + [](LPOPENFILENAMEA pofn) -> BOOL { | |
67 | 69 | strcpy_s(pofn->lpstrFile, pofn->nMaxFile, dlgdata.path); |
68 | 70 | return TRUE; |
69 | 71 | }), GetModuleHandleA(nullptr) }; |
70 | 72 | |
71 | - SendMessageA(AviUtlUI::GetMainWindow(), WM_COMMAND, 1023, 0xFFFFFFFF); | |
73 | + dlgdata.path = path; | |
74 | + SendMessageA(getExeditWindow(), WM_COMMAND, 1037, -1); | |
72 | 75 | } |
73 | 76 | |
74 | - void SwitchScene(size_t n) | |
77 | + void SwitchScene(size_t scene_no) | |
75 | 78 | { |
76 | - HMODULE ex = GetModuleHandleA("exedit.auf"); | |
77 | - if(!ex || n < 0 || n >= 50) return; | |
78 | - | |
79 | - dlgdata.scene_no = n; | |
80 | - IATModifier hook1{ "user32.dll", "DialogBoxParamA", static_cast<decltype(DialogBoxParamA)*>([](HINSTANCE, LPCSTR, HWND, DLGPROC proc, LPARAM) -> INT_PTR { | |
81 | - proc(nullptr, WM_COMMAND, MAKEWPARAM(190, LBN_SELCHANGE), 0); | |
82 | - return dlgdata.scene_no; | |
83 | - }), ex }; | |
84 | - IATModifier hook2{ "user32.dll", "SendDlgItemMessageA", static_cast<decltype(SendDlgItemMessageA)*>([](HWND, int, UINT, WPARAM, LPARAM) -> LRESULT { | |
85 | - return dlgdata.scene_no; | |
86 | - }), ex }; | |
87 | - | |
79 | + if(scene_no < 0 || scene_no >= 50) return; | |
80 | + | |
81 | + const HMODULE ex{ GetModuleHandleA("exedit.auf") }; | |
82 | + const IATModifier hook[]{ | |
83 | + { "user32.dll", "DialogBoxParamA", static_cast<decltype(DialogBoxParamA)*>( | |
84 | + [](HINSTANCE, LPCSTR, HWND, DLGPROC proc, LPARAM) -> INT_PTR { | |
85 | + proc(nullptr, WM_COMMAND, MAKEWPARAM(190, LBN_SELCHANGE), 0); | |
86 | + return dlgdata.scene_no; | |
87 | + }), ex }, | |
88 | + { "user32.dll", "SendDlgItemMessageA", static_cast<decltype(SendDlgItemMessageA)*>( | |
89 | + [](HWND, int, UINT, WPARAM, LPARAM) -> LRESULT { | |
90 | + return dlgdata.scene_no; | |
91 | + }), ex } | |
92 | + }; | |
93 | + | |
94 | + dlgdata.scene_no = scene_no; | |
88 | 95 | SendMessageA(getExeditWindow(), WM_LBUTTONDOWN, MK_LBUTTON, 0); |
89 | 96 | } |
90 | 97 | |
91 | - void TransparentScene(bool b) | |
98 | + void TransparentScene(bool transparency) | |
92 | 99 | { |
93 | - HMODULE ex = GetModuleHandleA("exedit.auf"); | |
94 | - if(!ex) return; | |
95 | - | |
96 | - dlgdata.transparent = b; | |
97 | - IATModifier hook1{ "user32.dll", "DialogBoxParamA", static_cast<decltype(DialogBoxParamA)*>([](HINSTANCE, LPCSTR, HWND, DLGPROC proc, LPARAM) -> INT_PTR { | |
98 | - proc(nullptr, WM_COMMAND, IDOK, 0); | |
99 | - return IDOK; | |
100 | - }), ex }; | |
101 | - IATModifier hook2{ "user32.dll", "IsDlgButtonChecked", static_cast<decltype(IsDlgButtonChecked)*>([](HWND, int) -> UINT { | |
102 | - return dlgdata.transparent ? BST_CHECKED : BST_UNCHECKED; | |
103 | - }), ex }; | |
104 | - | |
105 | - SendMessageA(getExeditWindow(), WM_COMMAND, 1096, 0xFFFFFFFF); | |
100 | + const HMODULE ex{ GetModuleHandleA("exedit.auf") }; | |
101 | + const IATModifier hook[]{ | |
102 | + { "user32.dll", "DialogBoxParamA", static_cast<decltype(DialogBoxParamA)*>( | |
103 | + [](HINSTANCE, LPCSTR, HWND, DLGPROC proc, LPARAM) -> INT_PTR { | |
104 | + proc(nullptr, WM_COMMAND, IDOK, 0); | |
105 | + return IDOK; | |
106 | + }), ex }, | |
107 | + { "user32.dll", "IsDlgButtonChecked", static_cast<decltype(IsDlgButtonChecked)*>( | |
108 | + [](HWND, int) -> UINT { | |
109 | + return dlgdata.transparency ? BST_CHECKED : BST_UNCHECKED; | |
110 | + }), ex } | |
111 | + }; | |
112 | + | |
113 | + dlgdata.transparency = transparency; | |
114 | + SendMessageA(getExeditWindow(), WM_COMMAND, 1096, -1); | |
106 | 115 | } |
107 | - | |
108 | 116 | } |
109 | 117 | |
110 | 118 | namespace |
111 | 119 | { |
112 | 120 | HWND getExeditWindow() |
113 | 121 | { |
114 | - HWND ret = nullptr; | |
115 | - EnumThreadWindows(GetCurrentThreadId(), static_cast<WNDENUMPROC>([](HWND hwnd, LPARAM data) -> BOOL { | |
116 | - static constexpr char head[] = "拡張編集"; | |
122 | + HWND ret{}; | |
123 | + EnumThreadWindows(GetCurrentThreadId(), static_cast<WNDENUMPROC>( | |
124 | + [](HWND hwnd, LPARAM data) -> BOOL { | |
125 | + static constexpr char head[]{"拡張編集"}; | |
126 | + static constexpr size_t size{ sizeof(head) - sizeof(head[0]) }; | |
127 | + | |
117 | 128 | char buf[16]; |
118 | 129 | GetWindowTextA(hwnd, buf, std::size(buf)); |
119 | - if(std::memcmp(buf, head, sizeof(head)-1)) return TRUE; | |
130 | + if(std::memcmp(buf, head, size)) return TRUE; | |
131 | + | |
120 | 132 | *reinterpret_cast<HWND*>(data) = hwnd; |
121 | 133 | return FALSE; |
122 | 134 | }), reinterpret_cast<LPARAM>(&ret)); |
@@ -2,10 +2,13 @@ | ||
2 | 2 | |
3 | 3 | namespace AviUtlCommand |
4 | 4 | { |
5 | + void SaveProject(const char* path); | |
6 | +} | |
7 | + | |
8 | +namespace ExeditCommand | |
9 | +{ | |
5 | 10 | void CreateProject(size_t cx, size_t cy, size_t fps, size_t freq); |
6 | 11 | void OpenExoFile(const char* path); |
7 | - void Quit(); | |
8 | - void SaveProject(const char* path); | |
9 | - void SwitchScene(size_t n); | |
10 | - void TransparentScene(bool b); | |
12 | + void SwitchScene(size_t scene_no); | |
13 | + void TransparentScene(bool transparency); | |
11 | 14 | } |
@@ -1,64 +1,26 @@ | ||
1 | 1 | #include "stdafx.h" |
2 | +#include <memory> | |
2 | 3 | #include <utility> |
3 | 4 | #include "command.h" |
4 | 5 | #include "core.h" |
5 | -#include "parser.h" | |
6 | +#include "coreimp.h" | |
6 | 7 | #include "ui.h" |
7 | 8 | |
8 | 9 | namespace |
9 | 10 | { |
10 | - struct patchdata{ | |
11 | - size_t offset_buf; | |
12 | - size_t offset_loaded; | |
13 | - struct{ | |
14 | - size_t offset; | |
15 | - void (*socketproc)(void*, const char*); | |
16 | - } engine; | |
17 | - struct{ | |
18 | - size_t offset; | |
19 | - void* proc; | |
20 | - size_t bytes; | |
21 | - } patch[5]; | |
22 | - }; | |
23 | - | |
24 | 11 | BOOL init(FILTER*); |
25 | - void applypatch(const patchdata*); | |
26 | - constexpr patchdata makeVer1Patch(size_t, size_t); | |
27 | - void ClearBuffer1(); | |
28 | - void Reload1(); | |
29 | - void Reset1(); | |
30 | - void Loader1(); | |
31 | - void Save1(); | |
32 | - constexpr patchdata makeVer2Patch(size_t, size_t, size_t); | |
33 | - void Socket(void*, const char*); | |
34 | - void ClearBuffer2(); | |
35 | - void Reload2(); | |
36 | - void Reset2(); | |
37 | - void Loader2(); | |
38 | - void Save2(); | |
39 | - size_t recalc(size_t, size_t, const char*); | |
40 | - bool is_aup_path(const char*); | |
12 | + const ScriptEngineCoreImplement::patchdata* getpatch(); | |
41 | 13 | inline const IMAGE_NT_HEADERS32* getNtHeaders(HMODULE); |
42 | 14 | inline DWORD getTimeStamp(HMODULE); |
43 | 15 | inline size_t getTextSectionSize(HMODULE); |
44 | - const patchdata* getpatch(); | |
45 | 16 | void writecaller(void*, const void*, size_t); |
46 | 17 | inline void writeptr(void*, const void*); |
47 | 18 | void modifycode(void*, const void*, size_t); |
48 | - | |
49 | - char* scriptbuf; | |
50 | - size_t* ploaded; | |
51 | - size_t oldoffset; | |
52 | - void (*engineproc)(); | |
53 | - void (*socketproc)(void*, const char*); | |
54 | - | |
55 | - constexpr size_t bufsize = 0x1000; | |
56 | 19 | } |
57 | 20 | |
58 | - | |
59 | 21 | extern "C" const FILTER_DLL* CALLBACK GetFilterTable() |
60 | 22 | { |
61 | - static constexpr FILTER_DLL filter = { | |
23 | + static constexpr FILTER_DLL filter{ | |
62 | 24 | FILTER_FLAG_ALWAYS_ACTIVE | FILTER_FLAG_NO_CONFIG | FILTER_FLAG_IMPORT, |
63 | 25 | 0, 0, const_cast<char*>("Script Engine"), 0, nullptr, nullptr, 0, 0, 0, nullptr, nullptr, nullptr, |
64 | 26 | init, nullptr, nullptr, AviUtlUI::WndProc, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr |
@@ -66,238 +28,76 @@ extern "C" const FILTER_DLL* CALLBACK GetFilterTable() | ||
66 | 28 | return &filter; |
67 | 29 | } |
68 | 30 | |
69 | -namespace | |
31 | +void LoadScript(const char* path, void *editp) | |
70 | 32 | { |
71 | - BOOL init(FILTER*) | |
72 | - { | |
73 | - const patchdata* p = getpatch(); | |
74 | - if(!p) return FALSE; | |
75 | - | |
76 | - AviUtlUI::AddMenu(); | |
77 | - applypatch(p); | |
78 | - return TRUE; | |
79 | - } | |
80 | - | |
81 | - constexpr patchdata makeVer1Patch(size_t offset_engine, size_t offset_saver, size_t offset_parser) | |
82 | - { | |
83 | - return { offset_parser + 0x48, offset_parser + 0x40, | |
84 | - { offset_engine, nullptr }, | |
85 | - { | |
86 | - { offset_engine + 0x2D, ClearBuffer1, 5 }, | |
87 | - { offset_parser + 0x07, Reload1, 6 }, | |
88 | - { offset_parser + 0x2E, Reset1, 5 }, | |
89 | - { offset_engine + 0x47, Loader1, 5 }, | |
90 | - { offset_saver + 0x8E8, Save1, 6 } | |
91 | - } | |
92 | - }; | |
93 | - } | |
94 | - | |
95 | - __declspec(naked) void ClearBuffer1() | |
96 | - { | |
97 | - __asm{ | |
98 | - xor edx, edx | |
99 | - lea ecx, [esp+8] | |
100 | - mov [ecx], dl | |
101 | - pop edx | |
102 | - push ecx | |
103 | - push edx | |
104 | - ret | |
105 | - } | |
106 | - } | |
107 | - | |
108 | - __declspec(naked) void Reload1() | |
109 | - { | |
110 | - __asm{ | |
111 | - push eax | |
112 | - push edx | |
113 | - mov eax, ploaded | |
114 | - push scriptbuf | |
115 | - push oldoffset | |
116 | - push [eax] | |
117 | - call recalc | |
118 | - add esp, 12 | |
119 | - mov edi, ploaded | |
120 | - pop edx | |
121 | - mov [edi], eax | |
122 | - mov oldoffset, eax | |
123 | - pop eax | |
124 | - mov edi, [esp+0x14] | |
125 | - mov esi, ebp | |
126 | - ret | |
127 | - } | |
128 | - } | |
33 | + ScriptEngineCoreImplement::core.loadscript(path, editp); | |
34 | +} | |
129 | 35 | |
130 | - __declspec(naked) void Reset1() | |
131 | - { | |
132 | - __asm{ | |
133 | - xor ecx, ecx | |
134 | - mov oldoffset, ecx | |
135 | - cmp eax, bufsize | |
136 | - ret | |
137 | - } | |
138 | - } | |
36 | +namespace ScriptEngineCoreImplement | |
37 | +{ | |
38 | + coredata core; | |
139 | 39 | |
140 | - __declspec(naked) void Loader1() | |
40 | + size_t recalc(size_t offset, size_t oldoffset, const char* buf) | |
141 | 41 | { |
142 | - __asm{ | |
143 | - lea edx, [esp+12] | |
144 | - push edx | |
145 | - push edx | |
146 | - call SubParser | |
147 | - add esp, 4 | |
148 | - xor ecx, ecx | |
149 | - pop edx | |
150 | - test eax, eax | |
151 | - cmove edx, ecx | |
152 | - pop ecx | |
153 | - push edx | |
154 | - push ecx | |
155 | - ret | |
156 | - } | |
157 | - } | |
42 | + if(!buf[0]) return offset; | |
43 | + if(offset < bufsize) return offset; | |
158 | 44 | |
159 | - __declspec(naked) void Save1() | |
160 | - { | |
161 | - __asm{ | |
162 | - cmp [ebp+0x4BC498], 0 | |
163 | - jne SAVE_WAV | |
164 | - lea eax, [ebp+0x108] | |
165 | - push eax | |
166 | - call is_aup_path | |
167 | - add esp, 4 | |
168 | - test eax, eax | |
169 | - jne SAVE_AUP | |
170 | - SAVE_WAV: | |
171 | - mov dl, [ebp+0x4BC198] | |
172 | - ret | |
173 | - SAVE_AUP: | |
174 | - lea eax, [ebp+0x108] | |
175 | - push eax | |
176 | - call AviUtlCommand::SaveProject | |
177 | - mov eax, [esp+4] | |
178 | - add esp, 4 | |
179 | - add eax, 0x97 | |
180 | - mov [esp], eax | |
181 | - ret | |
182 | - } | |
45 | + offset = oldoffset; | |
46 | + for(; offset < bufsize && buf[offset] && buf[offset] != '\n' && buf[offset] != '\r'; offset++); | |
47 | + for(; offset < bufsize && (buf[offset] == '\n' || buf[offset] == '\r'); offset++); | |
48 | + return offset; | |
183 | 49 | } |
184 | 50 | |
185 | - constexpr patchdata makeVer2Patch(size_t offset_engine, size_t offset_saver, size_t offset_parser) | |
51 | + bool is_aup_path(const char* path) | |
186 | 52 | { |
187 | - return { offset_parser + 0x64, offset_parser + 0x5E, | |
188 | - { offset_engine, Socket }, | |
189 | - { | |
190 | - { offset_engine + 0x42D, ClearBuffer2, 7 }, | |
191 | - { offset_parser + 0x20, Reload2, 5 }, | |
192 | - { offset_parser + 0x48, Reset2, 8 }, | |
193 | - { offset_engine + 0x450, Loader2, 7 }, | |
194 | - { offset_saver + 0xC8D, Save2, 7 } | |
195 | - } | |
196 | - }; | |
197 | - } | |
53 | + static constexpr char ext[]{".aup"}; | |
54 | + static constexpr size_t extlen{ std::size(ext) - 1 }; | |
198 | 55 | |
199 | - void Socket(void* editp, const char* path) | |
200 | - { | |
201 | - __asm{ | |
202 | - mov edx, path | |
203 | - mov ecx, editp | |
204 | - call engineproc | |
205 | - } | |
56 | + size_t len = std::strlen(path); | |
57 | + return len > extlen && !_strcmpi(path + len - extlen, ext); | |
206 | 58 | } |
207 | 59 | |
208 | - __declspec(naked) void ClearBuffer2() | |
60 | + char* erase_exe_name(char* cmdline) | |
209 | 61 | { |
210 | - __asm{ | |
211 | - xor ecx, ecx | |
212 | - lea edx, [esp+0x44C] | |
213 | - mov [edx], cl | |
214 | - ret | |
215 | - } | |
216 | - } | |
62 | + static constexpr char ext[]{".exe"}; | |
63 | + static constexpr size_t extlen{ std::size(ext) - 1 }; | |
217 | 64 | |
218 | - __declspec(naked) void Reload2() | |
219 | - { | |
220 | - __asm{ | |
221 | - mov eax, ploaded | |
222 | - push ecx | |
223 | - push edx | |
224 | - push scriptbuf | |
225 | - push oldoffset | |
226 | - push [eax] | |
227 | - call recalc | |
228 | - add esp, 12 | |
229 | - mov oldoffset, eax | |
230 | - pop edx | |
231 | - pop ecx | |
232 | - ret | |
233 | - } | |
234 | - } | |
65 | + char* p = cmdline; | |
66 | + while(*p == ' ') p++; | |
67 | + if(!*p) return nullptr; | |
235 | 68 | |
236 | - __declspec(naked) void Reset2() | |
237 | - { | |
238 | - __asm{ | |
239 | - xor eax, eax | |
240 | - mov oldoffset, eax | |
241 | - mov eax, dword ptr [ebp-8] | |
242 | - cmp eax, bufsize | |
243 | - ret | |
69 | + char del = ' '; | |
70 | + if(*p++ == '\"') del = '\"'; | |
71 | + while(*p){ | |
72 | + if(*p++ == del) break; | |
244 | 73 | } |
245 | - } | |
246 | - | |
247 | - __declspec(naked) void Loader2() | |
248 | - { | |
249 | - __asm{ | |
250 | - lea edx, [esp+0x44C] | |
251 | - push edx | |
252 | - push edx | |
253 | - call SubParser | |
254 | - add esp, 4 | |
255 | - xor ecx, ecx | |
256 | - pop edx | |
257 | - test eax, eax | |
258 | - cmove edx, ecx | |
259 | - ret | |
74 | + char* q = cmdline; | |
75 | + if(p - q >= extlen + 1){ | |
76 | + if(!_memicmp(p - (extlen + 1), ext, extlen) || !memrchr(q, '.', p - q)){ | |
77 | + std::memset(q, ' ', p - q); | |
78 | + } | |
260 | 79 | } |
80 | + return cmdline; | |
261 | 81 | } |
262 | 82 | |
263 | - __declspec(naked) void Save2() | |
83 | + const void* memrchr(const void *s, int c, size_t n) | |
264 | 84 | { |
265 | - __asm{ | |
266 | - cmp [ebx+0x4BC498], 0 | |
267 | - jne SAVE_WAV | |
268 | - lea eax, [ebx+0x108] | |
269 | - push eax | |
270 | - call is_aup_path | |
271 | - add esp, 4 | |
272 | - test eax, eax | |
273 | - jne SAVE_AUP | |
274 | - SAVE_WAV: | |
275 | - cmp byte ptr [ebx+0x4BC198], 0 | |
276 | - ret | |
277 | - SAVE_AUP: | |
278 | - lea eax, [ebx+0x108] | |
279 | - push eax | |
280 | - call AviUtlCommand::SaveProject | |
281 | - mov eax, [esp+4] | |
282 | - add esp, 4 | |
283 | - add eax, 0xC01 | |
284 | - mov [esp], eax | |
285 | - ret | |
85 | + const char* p{ static_cast<const char*>(s) }; | |
86 | + while(n-- > 0){ | |
87 | + if(p[n] == c) return p + n; | |
286 | 88 | } |
89 | + return nullptr; | |
287 | 90 | } |
288 | 91 | |
289 | - void applypatch(const patchdata* p) | |
92 | + void coredata::apply(const patchdata* p) | |
290 | 93 | { |
291 | - HMODULE base = GetModuleHandleA(nullptr); | |
94 | + HMODULE base{ GetModuleHandleA(nullptr) }; | |
292 | 95 | |
293 | 96 | ploaded = *reinterpret_cast<size_t* const*>(reinterpret_cast<const char*>(base) + p->offset_loaded); |
294 | 97 | scriptbuf = *reinterpret_cast<char* const*>(reinterpret_cast<const char*>(base) + p->offset_buf); |
295 | 98 | |
296 | - engineproc = reinterpret_cast<void(*)()>(reinterpret_cast<const char*>(base) + p->engine.offset); | |
99 | + engineproc = reinterpret_cast<const char*>(base) + p->engine.offset; | |
297 | 100 | socketproc = p->engine.socketproc; |
298 | - if(!socketproc){ | |
299 | - socketproc = reinterpret_cast<void(*)(void*, const char*)>(engineproc); | |
300 | - } | |
301 | 101 | |
302 | 102 | for(const auto& e : p->patch){ |
303 | 103 | writecaller(reinterpret_cast<char*>(base) + e.offset, e.proc, e.bytes); |
@@ -305,53 +105,38 @@ namespace | ||
305 | 105 | FlushInstructionCache(GetCurrentProcess(), base, getTextSectionSize(base)); |
306 | 106 | } |
307 | 107 | |
308 | - size_t recalc(size_t offset, size_t oldoffset, const char* buf) | |
108 | + void coredata::loadscript(const char* path, void *editp) | |
309 | 109 | { |
310 | - if(!buf[0]) return offset; | |
311 | - if(offset < bufsize) return offset; | |
312 | - | |
313 | - offset = oldoffset; | |
314 | - for(; offset < bufsize && buf[offset] && buf[offset] != '\n' && buf[offset] != '\r'; offset++); | |
315 | - for(; offset < bufsize && (buf[offset] == '\n' || buf[offset] == '\r'); offset++); | |
316 | - return offset; | |
317 | - } | |
318 | - | |
319 | - bool is_aup_path(const char* path) | |
320 | - { | |
321 | - static constexpr char ext[] = ".aup"; | |
322 | - static constexpr size_t extlen = sizeof(ext) - 1; | |
323 | - | |
324 | - size_t len = std::strlen(path); | |
325 | - return len > extlen && !_strcmpi(path + len - extlen, ext); | |
326 | - } | |
327 | - | |
328 | - inline const IMAGE_NT_HEADERS32* getNtHeaders(HMODULE base) | |
329 | - { | |
330 | - const IMAGE_DOS_HEADER* dos = reinterpret_cast<const IMAGE_DOS_HEADER*>(base); | |
331 | - return reinterpret_cast<const IMAGE_NT_HEADERS32*>(reinterpret_cast<const char*>(base) + dos->e_lfanew); | |
110 | + oldoffset = 0; | |
111 | + *ploaded = 0; | |
112 | + scriptbuf[0] = '\0'; | |
113 | + socketproc(engineproc, path, editp); | |
332 | 114 | } |
115 | +} | |
333 | 116 | |
334 | - inline DWORD getTimeStamp(HMODULE base) | |
117 | +namespace | |
118 | +{ | |
119 | + BOOL init(FILTER*) | |
335 | 120 | { |
336 | - return getNtHeaders(base)->FileHeader.TimeDateStamp; | |
337 | - } | |
121 | + const ScriptEngineCoreImplement::patchdata* p{getpatch()}; | |
122 | + if(!p) return FALSE; | |
338 | 123 | |
339 | - inline size_t getTextSectionSize(HMODULE base) | |
340 | - { | |
341 | - return getNtHeaders(base)->OptionalHeader.SizeOfCode; | |
124 | + AviUtlUI::AddMenu(); | |
125 | + ScriptEngineCoreImplement::core.apply(p); | |
126 | + return TRUE; | |
342 | 127 | } |
343 | 128 | |
344 | - const patchdata* getpatch() | |
129 | + const ScriptEngineCoreImplement::patchdata* getpatch() | |
345 | 130 | { |
346 | - static constexpr patchdata VER_0_99_k = makeVer1Patch(0xC7F0, 0x14F60, 0x22A80); | |
347 | - static constexpr patchdata VER_0_99_k2 = makeVer1Patch(0xC830, 0x14F90, 0x22BF0); | |
348 | - static constexpr patchdata VER_0_99_l = makeVer1Patch(0xC8F0, 0x15120, 0x22DC0); | |
349 | - static constexpr patchdata VER_0_99_m = makeVer1Patch(0xC950, 0x151B0, 0x22EA0); | |
350 | - static constexpr patchdata VER_1_00 = makeVer1Patch(0xC990, 0x15260, 0x22F70); | |
131 | + static auto VER_0_99_k = ScriptEngineCoreImplement::makeVer1Patch(0xC7F0, 0x14F60, 0x22A80); | |
132 | + static auto VER_0_99_k2 = ScriptEngineCoreImplement::makeVer1Patch(0xC830, 0x14F90, 0x22BF0); | |
133 | + static auto VER_0_99_l = ScriptEngineCoreImplement::makeVer1Patch(0xC8F0, 0x15120, 0x22DC0); | |
134 | + static auto VER_0_99_m = ScriptEngineCoreImplement::makeVer1Patch(0xC950, 0x151B0, 0x22EA0); | |
135 | + static auto VER_1_00 = ScriptEngineCoreImplement::makeVer1Patch(0xC990, 0x15260, 0x22F70); | |
351 | 136 | |
352 | - static constexpr patchdata VER_1_10_rc1 = makeVer2Patch(0xF910, 0x1A0A0, 0x2C010); | |
353 | - static constexpr patchdata VER_1_10_rc2 = makeVer2Patch(0xFAE0, 0x1A270, 0x2C1E0); | |
354 | - static constexpr patchdata VER_1_10 = makeVer2Patch(0xFA20, 0x1A1A0, 0x2C0F0); | |
137 | + static auto VER_1_10_rc1 = ScriptEngineCoreImplement::makeVer2Patch(0xF910, 0x1A0A0, 0x2C010); | |
138 | + static auto VER_1_10_rc2 = ScriptEngineCoreImplement::makeVer2Patch(0xFAE0, 0x1A270, 0x2C1E0); | |
139 | + static auto VER_1_10 = ScriptEngineCoreImplement::makeVer2Patch(0xFA20, 0x1A1A0, 0x2C0F0); | |
355 | 140 | |
356 | 141 | switch(getTimeStamp(GetModuleHandleA(nullptr))){ |
357 | 142 | case 0x4F01F831: return &VER_0_99_k; |
@@ -366,11 +151,28 @@ namespace | ||
366 | 151 | return nullptr; |
367 | 152 | } |
368 | 153 | |
154 | + inline const IMAGE_NT_HEADERS32* getNtHeaders(HMODULE base) | |
155 | + { | |
156 | + const auto dos{ reinterpret_cast<const IMAGE_DOS_HEADER*>(base) }; | |
157 | + return reinterpret_cast<const IMAGE_NT_HEADERS32*>(reinterpret_cast<const char*>(base) + dos->e_lfanew); | |
158 | + } | |
159 | + | |
160 | + inline DWORD getTimeStamp(HMODULE base) | |
161 | + { | |
162 | + return getNtHeaders(base)->FileHeader.TimeDateStamp; | |
163 | + } | |
164 | + | |
165 | + inline size_t getTextSectionSize(HMODULE base) | |
166 | + { | |
167 | + return getNtHeaders(base)->OptionalHeader.SizeOfCode; | |
168 | + } | |
169 | + | |
369 | 170 | void writecaller(void* dest, const void* proc, size_t opsize) |
370 | 171 | { |
371 | - BYTE opcodes[] = { | |
372 | - 0xE8, '\0', '\0', '\0', '\0', 0x90, 0x90, 0x90, | |
373 | - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 | |
172 | + constexpr std::byte call{0xE8}, nop{0x90}, XXX{}; | |
173 | + std::byte opcodes[]{ | |
174 | + call, XXX, XXX, XXX, XXX, nop, nop, nop, | |
175 | + nop , nop, nop, nop, nop, nop, nop, nop | |
374 | 176 | }; |
375 | 177 | writeptr(&opcodes[1], static_cast<const char*>(proc) - (reinterpret_cast<size_t>(dest) + 5)); |
376 | 178 | modifycode(dest, opcodes, opsize); |
@@ -389,11 +191,3 @@ namespace | ||
389 | 191 | VirtualProtect(dest, size, protect, &protect); |
390 | 192 | } |
391 | 193 | } |
392 | - | |
393 | -void LoadScript(const char* path, void *editp) | |
394 | -{ | |
395 | - oldoffset = 0; | |
396 | - *ploaded = 0; | |
397 | - scriptbuf[0] = '\0'; | |
398 | - socketproc(editp, path); | |
399 | -} |
@@ -0,0 +1,43 @@ | ||
1 | +#pragma once | |
2 | + | |
3 | +namespace ScriptEngineCoreImplement | |
4 | +{ | |
5 | + class coredata{ | |
6 | + private: | |
7 | + char* scriptbuf; | |
8 | + size_t* ploaded; | |
9 | + size_t oldoffset; | |
10 | + const void* engineproc; | |
11 | + void (*socketproc)(const void*, const char*, void*); | |
12 | + | |
13 | + public: | |
14 | + void apply(const struct patchdata*); | |
15 | + void loadscript(const char*, void*); | |
16 | + }; | |
17 | + | |
18 | + struct patchdata{ | |
19 | + size_t offset_buf; | |
20 | + size_t offset_loaded; | |
21 | + struct{ | |
22 | + size_t offset; | |
23 | + void (*socketproc)(const void*, const char*, void*); | |
24 | + } engine; | |
25 | + struct{ | |
26 | + size_t offset; | |
27 | + const void* proc; | |
28 | + size_t bytes; | |
29 | + } patch[5]; | |
30 | + }; | |
31 | + | |
32 | + patchdata makeVer1Patch(size_t, size_t, size_t); | |
33 | + patchdata makeVer2Patch(size_t, size_t, size_t); | |
34 | + | |
35 | + size_t recalc(size_t, size_t, const char*); | |
36 | + bool is_aup_path(const char*); | |
37 | + char* erase_exe_name(char*); | |
38 | + const void* memrchr(const void*, int, size_t); | |
39 | + | |
40 | + static constexpr size_t bufsize{0x1000}; | |
41 | + | |
42 | + extern coredata core; | |
43 | +} |
@@ -1,69 +1,38 @@ | ||
1 | 1 | #include "stdafx.h" |
2 | -#include <commdlg.h> | |
3 | -#include <algorithm> | |
4 | -#include <typeinfo> | |
2 | +#include <cstdio> | |
3 | +#include <cctype> | |
5 | 4 | |
6 | -#include "apihook.h" | |
7 | 5 | #include "command.h" |
8 | -#include "core.h" | |
9 | 6 | #include "parser.h" |
10 | -#include "ui.h" | |
11 | 7 | |
12 | 8 | namespace |
13 | 9 | { |
14 | 10 | bool is_comment(const char*); |
15 | - bool is_loading_script(const char*); | |
16 | - size_t starts_with(const char*, const char*); | |
17 | - size_t ends_with(const char*, const char*); | |
18 | - bool has_argument(const char*); | |
19 | - const char* skiparg(const char*); | |
20 | 11 | } |
21 | 12 | |
22 | 13 | bool SubParser(const char* script) |
23 | 14 | { |
24 | 15 | if(is_comment(script)) return false; |
25 | - if(is_loading_script(script)) return false; | |
26 | 16 | |
27 | - size_t match; | |
28 | - if(match = starts_with(script, "exedit ")){ | |
29 | - HMODULE base = GetModuleHandleA("exedit.auf"); | |
30 | - if(!base) return false; | |
17 | + if(size_t offset{}; sscanf_s(script, "%*[Ee]%*[Xx]%*[Ee]%*[Dd]%*[Ii]%*[Tt] %n", &offset) >= 0 && offset > 0){ | |
18 | + if(!GetModuleHandleA("exedit.auf")) return false; | |
31 | 19 | |
32 | - script += match; | |
20 | + script += offset; | |
33 | 21 | |
34 | - unsigned int params[4]; | |
35 | - if(sscanf_s(script, "new %u, %u, %u, %u", ¶ms[0], ¶ms[1], ¶ms[2], ¶ms[3]) == 4){ | |
36 | - AviUtlCommand::CreateProject(params[0], params[1], params[2], params[3]); | |
22 | + if(size_t cx, cy, fps, freq; sscanf_s(script, "%*[Nn]%*[Ee]%*[Ww] %u , %u , %u , %u", &cx, &cy, &fps, &freq) == 4){ | |
23 | + ExeditCommand::CreateProject(cx, cy, fps, freq); | |
37 | 24 | return false; |
38 | 25 | } |
39 | - else if(match = starts_with(script, "openexo ")){ | |
40 | - script += match; | |
41 | - AviUtlCommand::OpenExoFile(script); | |
26 | + else if(size_t offset{}; sscanf_s(script, "%*[Oo]%*[Pp]%*[Ee]%*[Nn]%*[Ee]%*[Xx]%*[Oo] %n", &offset) >= 0 && offset > 0){ | |
27 | + ExeditCommand::OpenExoFile(script + offset); | |
42 | 28 | return false; |
43 | 29 | } |
44 | - else if(sscanf_s(script, "switchscene #%u", ¶ms[0]) == 1){ | |
45 | - AviUtlCommand::SwitchScene(params[0]); | |
30 | + else if(size_t id; sscanf_s(script, "%*[Ss]%*[Ww]%*[Ii]%*[Tt]%*[Cc]%*[Hh]%*[Ss]%*[Cc]%*[Ee]%*[Nn]%*[Ee] #%u", &id) == 1){ | |
31 | + ExeditCommand::SwitchScene(id); | |
46 | 32 | return false; |
47 | 33 | } |
48 | - else if(match = starts_with(script, "transparentscene ")){ | |
49 | - script += match; | |
50 | - AviUtlCommand::TransparentScene(script[0] != 'f'); | |
51 | - return false; | |
52 | - } | |
53 | - } | |
54 | - else{ | |
55 | - script = skiparg(script); | |
56 | - if((script[0] == '-' || script[0] == '/') && (script[1] == 'q' || script[1] == 'Q')){ | |
57 | - script += 2; | |
58 | - if(!has_argument(script)){ | |
59 | - AviUtlCommand::Quit(); | |
60 | - return false; | |
61 | - } | |
62 | - } | |
63 | - else if((script[0] == '-' || script[0] == '/') && (script[1] == 'o' || script[1] == 'O')){ | |
64 | - script += 2; | |
65 | - while(*script == ' ') script++; | |
66 | - AviUtlCommand::SaveProject(script); | |
34 | + else if(size_t offset{}; sscanf_s(script, "%*[Tt]%*[Rr]%*[Aa]%*[Nn]%*[Ss]%*[Pp]%*[Aa]%*[Rr]%*[Ee]%*[Nn]%*[Tt]%*[Ss]%*[Cc]%*[Ee]%*[Nn]%*[Ee] %n", &offset) >= 0 && offset > 0){ | |
35 | + ExeditCommand::TransparentScene(std::toupper(script[offset]) != 'F'); | |
67 | 36 | return false; |
68 | 37 | } |
69 | 38 | } |
@@ -74,58 +43,9 @@ namespace | ||
74 | 43 | { |
75 | 44 | bool is_comment(const char* str) |
76 | 45 | { |
77 | - return str[0] == ';'; | |
78 | - } | |
46 | + static constexpr char head[]{"rem "}; | |
47 | + static constexpr size_t size{ sizeof(head) - sizeof(head[0]) }; | |
79 | 48 | |
80 | - bool is_loading_script(const char* script) | |
81 | - { | |
82 | - script = skiparg(script); | |
83 | - while(*script){ | |
84 | - if(*script != '-' && *script != '/'){ | |
85 | - if(*script == '\"'){ | |
86 | - if(ends_with(script, ".aus") || ends_with(script, ".aus\"")) return true; | |
87 | - } | |
88 | - else{ | |
89 | - if(ends_with(script, ".aus") || ends_with(script, ".aus ")) return true; | |
90 | - } | |
91 | - } | |
92 | - script = skiparg(script); | |
93 | - } | |
94 | - return false; | |
95 | - } | |
96 | - | |
97 | - size_t starts_with(const char* str, const char* pat) | |
98 | - { | |
99 | - size_t n = std::strlen(pat); | |
100 | - if(!_strnicmp(pat, str, n)) return n; | |
101 | - return 0; | |
102 | - } | |
103 | - | |
104 | - size_t ends_with(const char* str, const char* pat) | |
105 | - { | |
106 | - size_t m = std::strlen(str); | |
107 | - size_t n = std::strlen(pat); | |
108 | - if(m >= n && !_strnicmp(pat, str + m - n, n)) return n; | |
109 | - return 0; | |
110 | - } | |
111 | - | |
112 | - bool has_argument(const char* script) | |
113 | - { | |
114 | - while(*script == ' ') script++; | |
115 | - return !!*script; | |
116 | - } | |
117 | - | |
118 | - const char* skiparg(const char* script) | |
119 | - { | |
120 | - while(*script == ' ') script++; | |
121 | - if(!*script) return script; | |
122 | - | |
123 | - char del = ' '; | |
124 | - if(*script++ == '\"') del = '\"'; | |
125 | - while(*script){ | |
126 | - if(*script++ == del) break; | |
127 | - } | |
128 | - while(*script == ' ') script++; | |
129 | - return script; | |
49 | + return str[0] == ';' || !_memicmp(str, head, size); | |
130 | 50 | } |
131 | 51 | } |
@@ -1,12 +1,14 @@ | ||
1 | 1 | #include "stdafx.h" |
2 | 2 | #include <commdlg.h> |
3 | 3 | #include <algorithm> |
4 | +#include <memory> | |
4 | 5 | #include "core.h" |
5 | 6 | #include "ui.h" |
6 | 7 | |
7 | 8 | namespace |
8 | 9 | { |
9 | - int findmenu(HMENU, const char*, HMENU*); | |
10 | + int findmenu(HMENU, const char*); | |
11 | + void onImport(HWND, void*); | |
10 | 12 | } |
11 | 13 | |
12 | 14 | namespace AviUtlUI |
@@ -14,7 +16,8 @@ namespace AviUtlUI | ||
14 | 16 | HWND GetMainWindow() |
15 | 17 | { |
16 | 18 | HWND ret = nullptr; |
17 | - EnumThreadWindows(GetCurrentThreadId(), static_cast<WNDENUMPROC>([](HWND hwnd, LPARAM data) -> BOOL { | |
19 | + EnumThreadWindows(GetCurrentThreadId(), static_cast<WNDENUMPROC>( | |
20 | + [](HWND hwnd, LPARAM data) -> BOOL { | |
18 | 21 | char buf[16]; |
19 | 22 | GetClassNameA(hwnd, buf, std::size(buf)); |
20 | 23 | if(_strcmpi(buf, "AviUtl")) return TRUE; |
@@ -23,22 +26,23 @@ namespace AviUtlUI | ||
23 | 26 | return FALSE; |
24 | 27 | }), reinterpret_cast<LPARAM>(&ret)); |
25 | 28 | |
26 | - while(HWND owner = GetWindow(ret, GW_OWNER)) ret = owner; | |
29 | + while(HWND owner = GetWindow(ret, GW_OWNER)){ | |
30 | + ret = owner; | |
31 | + } | |
27 | 32 | |
28 | 33 | return ret; |
29 | 34 | } |
30 | 35 | |
31 | 36 | void AddMenu() |
32 | 37 | { |
33 | - HMENU file = GetSubMenu(GetMenu(GetMainWindow()), 0); | |
34 | - HMENU imp = nullptr; | |
35 | - findmenu(file, "インポート", &imp); | |
36 | - const int delpos = findmenu(imp, "Script Engine", nullptr); | |
38 | + const HMENU file = GetSubMenu(GetMenu(GetMainWindow()), 0); | |
39 | + const HMENU imp = GetSubMenu(file, findmenu(file, "インポート")); | |
40 | + const int delpos = findmenu(imp, "Script Engine"); | |
37 | 41 | if(delpos < 0) return; |
38 | - const int inspos = findmenu(file, "AVI出力 (Ctrl+S)", nullptr); | |
42 | + const int inspos = findmenu(file, "AVI出力 (Ctrl+S)"); | |
39 | 43 | if(inspos < 0) return; |
40 | 44 | |
41 | - UINT id = GetMenuItemID(imp, delpos); | |
45 | + const UINT id = GetMenuItemID(imp, delpos); | |
42 | 46 | DeleteMenu(imp, delpos, MF_BYPOSITION); |
43 | 47 | |
44 | 48 | const MENUITEMINFOA load { sizeof(load), MIIM_ID | MIIM_TYPE, MFT_STRING, MFS_ENABLED, id, nullptr, nullptr, nullptr, 0, const_cast<char*>("スクリプト読み込み"), 0, nullptr }; |
@@ -51,11 +55,7 @@ namespace AviUtlUI | ||
51 | 55 | BOOL WndProc(HWND hwnd, UINT msg, WPARAM, LPARAM, void* editp, FILTER*) |
52 | 56 | { |
53 | 57 | if(msg == WM_FILTER_IMPORT){ |
54 | - char path[MAX_PATH] = ""; | |
55 | - OPENFILENAMEA ofn{ sizeof(ofn), hwnd, nullptr, "Script Files(*.aus)\0*.aus\0\0", nullptr, 0, 1, path, std::size(path), nullptr, 0, "", nullptr, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, 0, 0, "aus", 0, nullptr, nullptr, nullptr, 0, 0 }; | |
56 | - if(!GetOpenFileNameA(&ofn)) return FALSE; | |
57 | - | |
58 | - LoadScript(path, editp); | |
58 | + onImport(hwnd, editp); | |
59 | 59 | } |
60 | 60 | return FALSE; |
61 | 61 | } |
@@ -63,20 +63,28 @@ namespace AviUtlUI | ||
63 | 63 | |
64 | 64 | namespace |
65 | 65 | { |
66 | - int findmenu(HMENU menu, const char* name, HMENU* psub) | |
66 | + int findmenu(HMENU menu, const char* name) | |
67 | 67 | { |
68 | - char buf[128]; | |
68 | + const size_t size = std::strlen(name) + 3; | |
69 | + const auto buf = std::make_unique<char[]>(size); | |
69 | 70 | |
70 | - int ncolumn = GetMenuItemCount(menu); | |
71 | + const int ncolumn = GetMenuItemCount(menu); | |
71 | 72 | for(int i = 0; i < ncolumn; i++){ |
72 | - MENUITEMINFOA mi { sizeof(mi), MIIM_TYPE | MIIM_SUBMENU, 0, 0, 0, nullptr, nullptr, nullptr, 0, buf, std::size(buf), nullptr }; | |
73 | + MENUITEMINFOA mi { sizeof(mi), MIIM_TYPE, 0, 0, 0, nullptr, nullptr, nullptr, 0, buf.get(), size, nullptr }; | |
73 | 74 | GetMenuItemInfoA(menu, i, TRUE, &mi); |
74 | - if(mi.fType != MFT_STRING || std::strcmp(buf, name)) continue; | |
75 | 75 | |
76 | - if(psub) *psub = mi.hSubMenu; | |
76 | + if(mi.fType != MFT_STRING || std::strcmp(buf.get(), name)) continue; | |
77 | 77 | return i; |
78 | 78 | } |
79 | - if(psub) *psub = nullptr; | |
80 | 79 | return -1; |
81 | 80 | } |
81 | + | |
82 | + void onImport(HWND hwnd, void* editp) | |
83 | + { | |
84 | + char path[MAX_PATH] = ""; | |
85 | + OPENFILENAMEA ofn{ sizeof(ofn), hwnd, nullptr, "Script Files(*.aus)\0*.aus\0\0", nullptr, 0, 1, path, std::size(path), nullptr, 0, "", nullptr, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, 0, 0, "aus", 0, nullptr, nullptr, nullptr, 0, 0 }; | |
86 | + if(!GetOpenFileNameA(&ofn)) return; | |
87 | + | |
88 | + LoadScript(path, editp); | |
89 | + } | |
82 | 90 | } |
@@ -0,0 +1,123 @@ | ||
1 | +#include "stdafx.h" | |
2 | +#include "command.h" | |
3 | +#include "coreimp.h" | |
4 | +#include "parser.h" | |
5 | +#include "ui.h" | |
6 | + | |
7 | +namespace | |
8 | +{ | |
9 | + void Socket(const void*, const char*, void*); | |
10 | + void ClearBuffer(); | |
11 | + void Reload(); | |
12 | + void Reset(); | |
13 | + void Loader(); | |
14 | + void Save(); | |
15 | +} | |
16 | + | |
17 | +namespace ScriptEngineCoreImplement | |
18 | +{ | |
19 | + patchdata makeVer1Patch(size_t offset_engine, size_t offset_saver, size_t offset_parser) | |
20 | + { | |
21 | + return { offset_parser + 0x48, offset_parser + 0x40, | |
22 | + { offset_engine, Socket }, | |
23 | + { | |
24 | + { offset_engine + 0x2D, ClearBuffer, 5 }, | |
25 | + { offset_parser + 0x07, Reload, 6 }, | |
26 | + { offset_parser + 0x2E, Reset, 5 }, | |
27 | + { offset_engine + 0x47, Loader, 5 }, | |
28 | + { offset_saver + 0x8E8, Save, 6 } | |
29 | + } | |
30 | + }; | |
31 | + } | |
32 | +} | |
33 | + | |
34 | +namespace | |
35 | +{ | |
36 | + void Socket(const void* proc, const char* path, void* editp) | |
37 | + { | |
38 | + reinterpret_cast<void(_cdecl*)(void*, const char*)>(proc)(editp, path); | |
39 | + } | |
40 | + | |
41 | + __declspec(naked) void ClearBuffer() | |
42 | + { | |
43 | + __asm{ | |
44 | + lea ecx, [esp+8] | |
45 | + pop edx | |
46 | + mov byte ptr [ecx], 0 | |
47 | + push ecx | |
48 | + push edx | |
49 | + ret | |
50 | + } | |
51 | + } | |
52 | + | |
53 | + __declspec(naked) void Reload() | |
54 | + { | |
55 | + __asm{ | |
56 | + mov eax, (ScriptEngineCoreImplement::core.ploaded) | |
57 | + push (ScriptEngineCoreImplement::core.scriptbuf) | |
58 | + push (ScriptEngineCoreImplement::core.oldoffset) | |
59 | + push [eax] | |
60 | + call ScriptEngineCoreImplement::recalc | |
61 | + mov edi, (ScriptEngineCoreImplement::core.ploaded) | |
62 | + add esp, 12 | |
63 | + mov [edi], eax | |
64 | + mov (ScriptEngineCoreImplement::core.oldoffset), eax | |
65 | + mov edi, [esp+0x14] | |
66 | + mov esi, ebp | |
67 | + ret | |
68 | + } | |
69 | + } | |
70 | + | |
71 | + __declspec(naked) void Reset() | |
72 | + { | |
73 | + __asm{ | |
74 | + mov (ScriptEngineCoreImplement::core.oldoffset), 0 | |
75 | + cmp eax, ScriptEngineCoreImplement::bufsize | |
76 | + ret | |
77 | + } | |
78 | + } | |
79 | + | |
80 | + __declspec(naked) void Loader() | |
81 | + { | |
82 | + __asm{ | |
83 | + lea edx, [esp+12] | |
84 | + push edx | |
85 | + push edx | |
86 | + call SubParser | |
87 | + add esp, 4 | |
88 | + test eax, eax | |
89 | + je SKIP_PARSE | |
90 | + call ScriptEngineCoreImplement::erase_exe_name | |
91 | + SKIP_PARSE: | |
92 | + add esp, 4 | |
93 | + pop edx | |
94 | + push eax | |
95 | + push edx | |
96 | + ret | |
97 | + } | |
98 | + } | |
99 | + | |
100 | + __declspec(naked) void Save() | |
101 | + { | |
102 | + __asm{ | |
103 | + cmp [ebp+0x4BC498], 0 | |
104 | + jne SAVE_AVI_OR_WAV | |
105 | + lea eax, [ebp+0x108] | |
106 | + push eax | |
107 | + call ScriptEngineCoreImplement::is_aup_path | |
108 | + add esp, 4 | |
109 | + test eax, eax | |
110 | + jne SAVE_AUP | |
111 | + SAVE_AVI_OR_WAV: | |
112 | + mov dl, [ebp+0x4BC198] | |
113 | + ret | |
114 | + SAVE_AUP: | |
115 | + lea eax, [ebp+0x108] | |
116 | + add dword ptr [esp], 0x10B | |
117 | + push eax | |
118 | + call AviUtlCommand::SaveProject | |
119 | + add esp, 4 | |
120 | + ret | |
121 | + } | |
122 | + } | |
123 | +} |
@@ -0,0 +1,117 @@ | ||
1 | +#include "stdafx.h" | |
2 | +#include "command.h" | |
3 | +#include "coreimp.h" | |
4 | +#include "parser.h" | |
5 | +#include "ui.h" | |
6 | + | |
7 | +namespace | |
8 | +{ | |
9 | + void Socket(const void*, const char*, void*); | |
10 | + void ClearBuffer(); | |
11 | + void Reload(); | |
12 | + void Reset(); | |
13 | + void Loader(); | |
14 | + void Save(); | |
15 | +} | |
16 | + | |
17 | +namespace ScriptEngineCoreImplement | |
18 | +{ | |
19 | + patchdata makeVer2Patch(size_t offset_engine, size_t offset_saver, size_t offset_parser) | |
20 | + { | |
21 | + return { offset_parser + 0x64, offset_parser + 0x5E, | |
22 | + { offset_engine, Socket }, | |
23 | + { | |
24 | + { offset_engine + 0x42D, ClearBuffer, 7 }, | |
25 | + { offset_parser + 0x20, Reload, 5 }, | |
26 | + { offset_parser + 0x48, Reset, 8 }, | |
27 | + { offset_engine + 0x450, Loader, 7 }, | |
28 | + { offset_saver + 0xC8D, Save, 7 } | |
29 | + } | |
30 | + }; | |
31 | + } | |
32 | +} | |
33 | + | |
34 | +namespace | |
35 | +{ | |
36 | + void Socket(const void* proc, const char* path, void* editp) | |
37 | + { | |
38 | + reinterpret_cast<void(__fastcall*)(void*, const char*)>(proc)(editp, path); | |
39 | + } | |
40 | + | |
41 | + __declspec(naked) void ClearBuffer() | |
42 | + { | |
43 | + __asm{ | |
44 | + lea edx, [esp+0x44C] | |
45 | + mov byte ptr [edx], 0 | |
46 | + ret | |
47 | + } | |
48 | + } | |
49 | + | |
50 | + __declspec(naked) void Reload() | |
51 | + { | |
52 | + __asm{ | |
53 | + push ecx | |
54 | + mov eax, (ScriptEngineCoreImplement::core.ploaded) | |
55 | + push (ScriptEngineCoreImplement::core.scriptbuf) | |
56 | + push (ScriptEngineCoreImplement::core.oldoffset) | |
57 | + push [eax] | |
58 | + call ScriptEngineCoreImplement::recalc | |
59 | + add esp, 12 | |
60 | + mov (ScriptEngineCoreImplement::core.oldoffset), eax | |
61 | + pop ecx | |
62 | + ret | |
63 | + } | |
64 | + } | |
65 | + | |
66 | + __declspec(naked) void Reset() | |
67 | + { | |
68 | + __asm{ | |
69 | + mov eax, dword ptr [ebp-8] | |
70 | + mov (ScriptEngineCoreImplement::core.oldoffset), 0 | |
71 | + cmp eax, ScriptEngineCoreImplement::bufsize | |
72 | + ret | |
73 | + } | |
74 | + } | |
75 | + | |
76 | + __declspec(naked) void Loader() | |
77 | + { | |
78 | + __asm{ | |
79 | + lea edx, [esp+0x44C] | |
80 | + push edx | |
81 | + push edx | |
82 | + call SubParser | |
83 | + add esp, 4 | |
84 | + test eax, eax | |
85 | + je SKIP_PARSE | |
86 | + call ScriptEngineCoreImplement::erase_exe_name | |
87 | + SKIP_PARSE: | |
88 | + add esp, 4 | |
89 | + mov edx, eax | |
90 | + ret | |
91 | + } | |
92 | + } | |
93 | + | |
94 | + __declspec(naked) void Save() | |
95 | + { | |
96 | + __asm{ | |
97 | + cmp [ebx+0x4BC498], 0 | |
98 | + jne SAVE_AVI_OR_WAV | |
99 | + lea eax, [ebx+0x108] | |
100 | + push eax | |
101 | + call ScriptEngineCoreImplement::is_aup_path | |
102 | + add esp, 4 | |
103 | + test eax, eax | |
104 | + jne SAVE_AUP | |
105 | + SAVE_AVI_OR_WAV: | |
106 | + cmp byte ptr [ebx+0x4BC198], 0 | |
107 | + ret | |
108 | + SAVE_AUP: | |
109 | + lea eax, [ebx+0x108] | |
110 | + add dword ptr [esp], 0xC01 | |
111 | + push eax | |
112 | + call AviUtlCommand::SaveProject | |
113 | + add esp, 4 | |
114 | + ret | |
115 | + } | |
116 | + } | |
117 | +} |