1+ //
2+ // Created by user on 03.05.2020.
3+ //
4+ #include < filesystem>
5+ #include < VbfFile.h>
6+ #include < ImageSection.h>
7+ #include < miniz_zip.h>
8+ #include < utils.h>
9+ #include < EifConverter.h>
10+ #include < cxxopts.hpp>
11+
12+ namespace fs = std::filesystem;
13+
14+ struct Opts {
15+ fs::path conf_p;
16+ fs::path out_p;
17+ fs::path vbf_p;
18+ bool pack;
19+ };
20+
21+ void parse_opts (int argc, char **argv, Opts& opts) {
22+
23+ try {
24+ cxxopts::Options options (" imgunpkr" , " Ford IMG resources unpacker" );
25+ options.add_options ()
26+ (" p,pack" ," Pack VBF file" )
27+ (" u,unpack" ," Unpack VBF file" )
28+ (" c,conf" ," Config file" , cxxopts::value<string>())
29+ (" o,output" ," Output file" , cxxopts::value<string>())
30+ (" v,vbf" ," VBF file which will be patched" , cxxopts::value<string>())
31+ (" h,help" ," Print help" );
32+
33+ // options.parse_positional({"vbf"});
34+ auto result = options.parse (argc, argv);
35+
36+ if (result.arguments ().empty () || result.count (" help" )){
37+ cout << options.help () << std::endl;
38+ exit (0 );
39+ }
40+
41+ if (result.count (" pack" )) {
42+ opts.pack = true ;
43+
44+ if (!result.count (" conf" )){
45+ cout << " Please, specify VBF file" << std::endl;
46+ exit (0 );
47+ }
48+
49+ opts.conf_p = result[" conf" ].as <string>();
50+ if (!fs::exists (opts.conf_p )) {
51+ cout << " VBF file not found" << std::endl;
52+ exit (0 );
53+ }
54+
55+ } else if (!result.count (" unpack" )) {
56+ cout << " Please, specify mode (pack|unpack)" << std::endl;
57+ exit (0 );
58+ }
59+
60+ if (!result.count (" vbf" )){
61+ cout << " Please, specify vbf file" << std::endl;
62+ exit (0 );
63+ }
64+
65+ fs::path in_file (result[" vbf" ].as <string>());
66+ if (!fs::exists (in_file)) {
67+ cout << " Input file not found" << std::endl;
68+ exit (0 );
69+ }
70+
71+ fs::path out_path;
72+ if (result.count (" output" )){
73+ out_path = result[" output" ].as <string>();
74+ if (!fs::exists (out_path) || !fs::is_directory (out_path)) {
75+ cout << " Output dir not found" << std::endl;
76+ exit (0 );
77+ }
78+ } else {
79+ out_path = in_file.parent_path ();
80+ }
81+
82+ opts.vbf_p = in_file;
83+ opts.out_p = out_path;
84+
85+ } catch (const cxxopts::OptionException& e){
86+ cout << " error parsing options: " << e.what () << endl;
87+ exit (-1 );
88+ }
89+ }
90+
91+ int UnpackImg (const fs::path& in_path, const fs::path& out_path) {
92+
93+ // unpack vbf
94+ VbfFile vbf;
95+ vbf.OpenFile (in_path);
96+ if (!vbf.IsOpen ()) {
97+ return -1 ; // can't parse vbf
98+ }
99+
100+ std::vector<uint8_t > img_sec_bin;
101+ if (vbf.GetSectionRaw (1 , img_sec_bin)) {
102+ return -1 ; // can't get image function
103+ }
104+
105+ // unpack image section
106+ ImageSection img_sec;
107+ img_sec.Parse (img_sec_bin);
108+
109+ img_sec.Export (out_path);
110+
111+ // unpack eifs
112+ int zip_items = img_sec.GetItemsCount (ImageSection::RT_ZIP);
113+
114+ fs::path eifs_path = out_path/" eif" ;
115+ fs::path bmps_path = out_path/" bmp" ;
116+
117+ fs::create_directory (eifs_path);
118+ fs::create_directory (bmps_path);
119+
120+ for (int i = 0 ; i < zip_items; i++) {
121+ std::vector<uint8_t > img_zip_bin;
122+ img_sec.GetItemData (ImageSection::RT_ZIP, i, img_zip_bin);
123+
124+ // unzip eif
125+ mz_zip_archive zip_archive;
126+ memset (&zip_archive, 0 , sizeof (zip_archive));
127+ if (!mz_zip_reader_init_mem (&zip_archive,
128+ (const void *)img_zip_bin.data (), img_zip_bin.size (), 0 ))
129+ {
130+ throw runtime_error (" Can't get image name form archive" );
131+ }
132+ unsigned file_index =0 ;
133+ mz_zip_archive_file_stat file_stat;
134+ mz_zip_reader_file_stat (&zip_archive, file_index , &file_stat);
135+ vector<uint8_t > eif (file_stat.m_uncomp_size );
136+ mz_zip_reader_extract_to_mem (&zip_archive, file_index, (void *)eif.data (), eif.size (), 0 );
137+ mz_zip_reader_end (&zip_archive);
138+
139+ FTUtils::bufferToFile (eifs_path/file_stat.m_filename , (char *)eif.data (), eif.size ());
140+
141+ // convert eif to bmp
142+ auto p = bmps_path/file_stat.m_filename ;
143+ p.replace_extension (" .bmp" );
144+ EIF::EifConverter::eifToBmpFile (eif, p.string ());
145+
146+ }
147+ return 0 ;
148+ }
149+
150+ int PackImg (const fs::path& config_path, const fs::path& vbf_path, const fs::path& out_path) {
151+
152+ // open image section config
153+ // pack image section
154+ ImageSection section;
155+ section.Import (config_path);
156+
157+ vector<uint8_t > v;
158+ fs::path tmp_f = out_path/" ft.tmp" ;
159+ section.SaveToFile (tmp_f);
160+ FTUtils::fileToVector (tmp_f, v);
161+ fs::remove (tmp_f);
162+
163+ // open vbf
164+ VbfFile vbf;
165+ vbf.OpenFile (vbf_path);
166+ if (!vbf.IsOpen ()) {
167+ throw runtime_error (" Can't open vbf" );
168+ }
169+
170+ // replace vbf image content
171+ vbf.ReplaceSectionRaw (1 , v);
172+
173+ // pack vbf
174+ vbf.SaveToFile (out_path/" patched.vbf" );
175+
176+ return 0 ;
177+ }
178+
179+ int main (int argc, char **argv) {
180+
181+ Opts opts = {};
182+ parse_opts (argc, argv, opts);
183+
184+ if (opts.pack ) {
185+ PackImg (opts.conf_p , opts.vbf_p , opts.out_p );
186+ } else {
187+ UnpackImg (opts.vbf_p , opts.out_p );
188+ }
189+
190+ return 0 ;
191+ }
0 commit comments