Skip to content

Commit 85c5656

Browse files
committed
updated readme & source
1 parent 64aedfa commit 85c5656

File tree

5 files changed

+1253
-0
lines changed

5 files changed

+1253
-0
lines changed

README.md

+13
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,15 @@
1+
![license](https://img.shields.io/github/license/ZoneTool/technique-tool.svg)
2+
![stars](https://img.shields.io/github/stars/ZoneTool/technique-tool.svg)
3+
[![discord](https://discordapp.com/api/guilds/290238678352134145/widget.png)](https://discord.gg/a6JM2Tv)
4+
<p align="center"><img src="plutonium_logo.jpg" alt="Plutonium"/>
5+
16
# technique-tool
27
technique-tool, a command-line tool for mapping shader constants between Call of Duty: Modern Warfare 2 and Call of Duty: Online.
8+
9+
## Folder structure
10+
technique-tool\
11+
|- techniques\
12+
|- technique-tool.exe
13+
14+
## Usage
15+
Simply run ``./technique-tool.exe`` from your command-line.

plutonium_logo.jpg

31.7 KB
Loading

src/codo-technique-tool.cpp

+195
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
#define _CRT_SECURE_NO_WARNINGS
2+
3+
#include <string>
4+
#include <iostream>
5+
#include <filesystem>
6+
7+
#include "json11.hpp"
8+
#include <unordered_map>
9+
10+
std::string read_file(const std::filesystem::path& path)
11+
{
12+
std::string buffer;
13+
14+
if (std::filesystem::exists(path) && std::filesystem::is_regular_file(path))
15+
{
16+
const auto file_size = std::filesystem::file_size(path);
17+
if (file_size > 0)
18+
{
19+
buffer.resize(file_size);
20+
21+
const auto fp = fopen(path.string().data(), "rb");
22+
if (fp)
23+
{
24+
fread(&buffer[0], file_size, 1, fp);
25+
fclose(fp);
26+
}
27+
}
28+
}
29+
30+
return buffer;
31+
}
32+
33+
bool technique_exists(const std::filesystem::path& path, const std::string& game)
34+
{
35+
const auto filename = "techniques/" + path.filename().string() + "." + game + ".json";
36+
if (std::filesystem::exists(filename) && std::filesystem::is_regular_file(filename))
37+
{
38+
return true;
39+
}
40+
41+
return false;
42+
}
43+
44+
struct code_const
45+
{
46+
int first_row;
47+
int index;
48+
int row_count;
49+
};
50+
struct shader_arg
51+
{
52+
int type;
53+
code_const constant;
54+
};
55+
struct pass
56+
{
57+
std::vector<shader_arg> args;
58+
};
59+
struct technique
60+
{
61+
std::string name;
62+
std::vector<pass> passes;
63+
};
64+
65+
technique parse_technique(const std::string& filename)
66+
{
67+
const auto file_buffer = read_file("techniques/" + filename);
68+
if (file_buffer.empty())
69+
{
70+
return technique{};
71+
}
72+
73+
std::string err;
74+
auto json = json11::Json::parse(file_buffer, err);
75+
76+
if (!err.empty())
77+
{
78+
return technique{};
79+
}
80+
81+
technique tech;
82+
tech.name = json["name"].string_value();
83+
84+
for (auto& cur_pass : json["pass"].array_items())
85+
{
86+
pass parsed_pass;
87+
88+
for (auto& cur_arg : cur_pass["args"].array_items())
89+
{
90+
const auto type = cur_arg["type"].int_value();
91+
if (type != 3 && type != 5)
92+
{
93+
continue;
94+
}
95+
96+
shader_arg parsed_arg;
97+
parsed_arg.type = type;
98+
parsed_arg.constant.index = cur_arg["index"].int_value();
99+
100+
parsed_pass.args.push_back(parsed_arg);
101+
}
102+
103+
tech.passes.push_back(parsed_pass);
104+
}
105+
106+
return tech;
107+
}
108+
109+
int main()
110+
{
111+
std::cout << "technique-tool by RektInator." << std::endl;
112+
113+
std::vector<std::string> files_to_check;
114+
115+
for (auto& itr : std::filesystem::directory_iterator("techniques"))
116+
{
117+
if (itr.is_regular_file())
118+
{
119+
const auto filename_without_json = itr.path().filename().replace_extension("");
120+
const auto filename = std::filesystem::path(filename_without_json.string()).replace_extension("");
121+
122+
const auto itr = std::find(files_to_check.begin(), files_to_check.end(), filename.string());
123+
if (itr == files_to_check.end())
124+
{
125+
if (technique_exists(filename, "iw4") && technique_exists(filename, "codo"))
126+
{
127+
files_to_check.push_back(filename.string());
128+
}
129+
}
130+
}
131+
}
132+
133+
std::cout << "checking data for " << files_to_check.size() << " techniques..." << std::endl;
134+
135+
std::unordered_map<std::int32_t, std::int32_t> mapped_constants;
136+
137+
int i = 0;
138+
for (auto& file : files_to_check)
139+
{
140+
std::cout << "[" << i + 1 << "/" << files_to_check.size() << "]" << std::endl;
141+
142+
const auto iw4 = parse_technique(file + ".iw4.json");
143+
const auto codo = parse_technique(file + ".codo.json");
144+
145+
if (iw4.passes.size() != codo.passes.size())
146+
{
147+
std::cout << "amount of passes does not match for technique " << file << std::endl;
148+
}
149+
else
150+
{
151+
for (auto p = 0; p < iw4.passes.size(); p++)
152+
{
153+
if (iw4.passes.size() != codo.passes.size())
154+
{
155+
std::cout << "amount of args does not match for technique " << file << " with pass " << p << std::endl;
156+
break;
157+
}
158+
159+
for (auto a = 0; a < iw4.passes[p].args.size(); a++)
160+
{
161+
auto iw4_arg = &iw4.passes[p].args[a];
162+
auto codo_arg = &codo.passes[p].args[a];
163+
164+
if (iw4_arg->constant.index != codo_arg->constant.index)
165+
{
166+
const auto itr = mapped_constants.find(codo_arg->constant.index);
167+
if (itr == mapped_constants.end())
168+
{
169+
mapped_constants[codo_arg->constant.index] = iw4_arg->constant.index;
170+
}
171+
else
172+
{
173+
if (itr->second != iw4_arg->constant.index)
174+
{
175+
std::cout << "codeconst " << itr->second << " maps to multiple values! " << itr->second << " and " << iw4_arg->constant.index << "." << std::endl;
176+
}
177+
}
178+
}
179+
}
180+
}
181+
}
182+
183+
i++;
184+
}
185+
186+
auto fp = fopen("output.txt", "wb");
187+
fprintf(fp, "std::unordered_map<std::int32_t, std::int32_t> mapped_constants = {\n");
188+
for (auto& constant : mapped_constants)
189+
{
190+
fprintf(fp, "\t{ %i, %i },\n", constant.first, constant.second);
191+
}
192+
fprintf(fp, "};");
193+
fclose(fp);
194+
195+
}

0 commit comments

Comments
 (0)