1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
// This file is part of the 64k demo project.
// It implements the asset packer tool for demoscene resource management.
// Converts external files into embedded C++ byte arrays and look-up records.
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <vector>
int main(int argc, char *argv[]) {
if (argc != 4) {
std::cerr << "Usage: " << argv[0]
<< " <assets.txt_path> <output_assets_h_path> "
"<output_assets_data_cc_path>\n";
return 1;
}
std::string assets_txt_path = argv[1];
std::string output_assets_h_path = argv[2];
std::string output_assets_data_cc_path = argv[3];
std::ifstream assets_txt_file(assets_txt_path);
if (!assets_txt_file.is_open()) {
std::cerr << "Error: Could not open assets.txt at " << assets_txt_path
<< "\n";
return 1;
}
std::ofstream assets_h_file(output_assets_h_path);
if (!assets_h_file.is_open()) {
std::cerr << "Error: Could not open output assets.h at "
<< output_assets_h_path << "\n";
return 1;
}
std::ofstream assets_data_cc_file(output_assets_data_cc_path);
if (!assets_data_cc_file.is_open()) {
std::cerr << "Error: Could not open output assets_data.cc at "
<< output_assets_data_cc_path << "\n";
return 1;
}
// Generate assets.h
assets_h_file << "// This file is auto-generated by asset_packer.cc. Do not edit.\n\n";
assets_h_file << "#pragma once\n";
assets_h_file << "#include <cstdint>\n\n";
assets_h_file << "enum class AssetId : uint16_t {\n";
// Generate assets_data.cc header
assets_data_cc_file << "// This file is auto-generated by asset_packer.cc. Do not edit.\n\n";
assets_data_cc_file << "#include \"util/asset_manager.h\"\n";
assets_data_cc_file << "#include \"assets.h\"\n\n";
std::string line;
int asset_id_counter = 0;
std::vector<std::string> asset_names;
while (std::getline(assets_txt_file, line)) {
if (line.empty() || line[0] == '#')
continue;
size_t first_comma = line.find(',');
if (first_comma == std::string::npos)
continue;
std::string asset_name = line.substr(0, first_comma);
asset_name.erase(0, asset_name.find_first_not_of(" \t\r\n"));
asset_name.erase(asset_name.find_last_not_of(" \t\r\n") + 1);
size_t second_comma = line.find(',', first_comma + 1);
if (second_comma == std::string::npos)
continue;
std::string filename =
line.substr(first_comma + 1, second_comma - first_comma - 1);
filename.erase(0, filename.find_first_not_of(" \t\r\n"));
filename.erase(filename.find_last_not_of(" \t\r\n") + 1);
std::string base_dir =
assets_txt_path.substr(0, assets_txt_path.find_last_of("/\\") + 1);
std::ifstream asset_file(base_dir + filename, std::ios::binary);
if (!asset_file.is_open()) {
std::cerr << "Error: Could not open asset file: " << base_dir + filename
<< "\n";
return 1;
}
std::vector<uint8_t> buffer((std::istreambuf_iterator<char>(asset_file)),
std::istreambuf_iterator<char>());
asset_file.close();
asset_names.push_back(asset_name);
// Add to assets.h enum
assets_h_file << " ASSET_" << asset_name << " = " << asset_id_counter
<< ",\n";
// Write data to assets_data.cc
assets_data_cc_file << "static const uint8_t ASSET_DATA_" << asset_name
<< "[] = {";
for (size_t i = 0; i < buffer.size(); ++i) {
if (i % 12 == 0)
assets_data_cc_file << "\n ";
assets_data_cc_file << "0x" << std::hex << (int)buffer[i] << std::dec
<< (i == buffer.size() - 1 ? "" : ", ");
}
assets_data_cc_file << "\n};\n\n";
asset_id_counter++;
}
assets_h_file << "};\n\n";
assets_h_file << "#include \"util/asset_manager.h\"\n";
assets_h_file.close();
// Generate the lookup array in assets_data.cc
assets_data_cc_file << "extern const AssetRecord g_assets[] = {\n";
for (const std::string &name : asset_names) {
assets_data_cc_file << " { ASSET_DATA_" << name << ", sizeof(ASSET_DATA_"
<< name << ") },\n";
}
assets_data_cc_file << "};\n\n";
assets_data_cc_file << "extern const size_t g_assets_count = "
"sizeof(g_assets) / sizeof(g_assets[0]);\n";
assets_data_cc_file.close();
std::cout << "Asset packer successfully generated records for "
<< asset_names.size() << " assets.\n";
return 0;
}
|