Get rid of a useless copy instruction in the SH1 32*32->64bit multiply routines ...
[kugel-rb.git] / utils / zenutils / source / firmware_make / main.cpp
blob35d036e601c5f93b3491faa6b47401ef62494e05
1 /* zenutils - Utilities for working with creative firmwares.
2 * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <iostream>
20 #include <sstream>
21 #include <getpot/getpot.hpp>
22 #include <file.h>
23 #include <firmware.h>
24 #include <utils.h>
27 static const char VERSION[] = "0.1";
29 void print_version()
31 std::cout
32 << "firmware_make - Creates a Creative firmware archive." << std::endl
33 << "Version " << VERSION << std::endl
34 << "Copyright (c) 2007 Rasmus Ry" << std::endl;
37 void print_help()
39 print_version();
40 std::cout << std::endl
41 << "Usage: firmware_make [command] [options]" << std::endl
42 << std::endl
43 << " Commands:" << std::endl
44 << " -h,--help" << std::endl
45 << " prints this message." << std::endl
46 << " -m,--makefile [file]" << std::endl
47 << " specifies the .mk file to build the firmware archive from."
48 << std::endl << std::endl
49 << " Options:" << std::endl
50 << " -V,--verbose" << std::endl
51 << " prints verbose messages." << std::endl
52 << " -f,--firmware [file]" << std::endl
53 << " specifies the output firmware file name" << std::endl
54 << std::endl
58 dword get_tag_value(std::string tag)
60 if (tag[0] == '0' && tag[1] == 'x')
62 dword val = 0;
63 if (sscanf(tag.c_str(), "0x%08X", &val) == 1)
64 return val;
65 if (sscanf(tag.c_str(), "0x%08x", &val) == 1)
66 return val;
68 else
70 return shared::swap(*(dword*)&tag[0]);
72 return 0;
75 bool process_child(const GetPot& mkfile, const std::string& root, int index,
76 zen::firmware_entry& entry)
78 std::stringstream sstm;
79 sstm << root << "/" << index;
80 std::string var = sstm.str() + "/tag";
81 std::string tag = mkfile(var.c_str(), "");
82 var = sstm.str() + "/name";
83 std::string name = mkfile(var.c_str(), "");
84 var = sstm.str() + "/file";
85 std::string file = mkfile(var.c_str(), "");
87 if (file.empty() || tag.empty())
89 std::cerr << "Invalid file or tag for var: " << sstm.str()
90 << std::endl;
91 return false;
94 shared::bytes buffer;
95 if (!shared::read_file(file, buffer))
97 std::cerr << "Failed to read the file: " << file << std::endl;
98 return false;
101 entry.get_bytes().clear();
102 entry.get_header().tag = get_tag_value(tag);
103 size_t contoff = entry.get_content_offset();
104 if (contoff)
106 entry.get_bytes().resize(contoff, 0);
107 if (!name.empty())
109 size_t endoff = entry.is_big_endian() ? 1 : 0;
110 for (int i = 0; i < name.size(); ++i)
111 entry.get_bytes()[i * 2 + endoff] = name[i];
114 entry.get_bytes().insert(entry.get_bytes().end(), buffer.begin(),
115 buffer.end());
117 entry.get_header().size = entry.get_bytes().size();
119 return true;
122 int process_arguments(int argc, char* argv[])
124 //--------------------------------------------------------------------
125 // Parse input variables.
126 //--------------------------------------------------------------------
128 GetPot cl(argc, argv);
129 if (cl.size() == 1 || cl.search(2, "-h", "--help"))
131 print_help();
132 return 1;
135 std::string makefile;
136 if (cl.search("-m") || cl.search("--makefile"))
137 makefile = cl.next("");
138 if (makefile.empty())
140 std::cerr << "Makefile must be specified." << std::endl;
141 return 2;
144 std::string firmware;
145 if (cl.search("-f") || cl.search("--firmware"))
146 firmware = cl.next("");
147 if (firmware.empty())
149 std::cerr << "Firmware must be specified." << std::endl;
150 return 3;
153 bool verbose = false;
154 if (cl.search("-V") || cl.search("--verbose"))
155 verbose = true;
157 GetPot mkfile(makefile.c_str());
158 if (verbose)
159 mkfile.print();
161 bool big_endian;
162 std::string endian = mkfile("endian", "little");
163 if (endian == "little")
165 big_endian = false;
167 else if (endian == "big")
169 big_endian = true;
171 else
173 std::cerr << "Invalid value of 'endian'" << std::endl;
174 return 4;
177 zen::firmware_archive archive(big_endian);
178 int childcount = mkfile("children/count", 0);
179 if (!childcount)
181 std::cerr << "A firmware archive must have at least one child entry."
182 << std::endl;
183 return 5;
186 for (int i = 0; i < childcount; i++)
188 zen::firmware_entry entry(big_endian);
189 if (!process_child(mkfile, "children", i, entry))
191 return 6;
193 archive.get_children().push_back(entry);
196 int neighbourcount = mkfile("neighbours/count", 0);
197 for (int i = 0; i < neighbourcount; i++)
199 zen::firmware_entry entry(big_endian);
200 if (!process_child(mkfile, "neighbours", i, entry))
202 return 7;
204 archive.get_neighbours().push_back(entry);
207 std::ofstream ofs;
208 ofs.open(firmware.c_str(), std::ios::out|std::ios::binary|std::ios::trunc);
209 if (!ofs)
211 std::cerr << "Failed to create the firmware file." << std::endl;
212 return 8;
215 if (!archive.write(ofs))
217 std::cerr << "Failed to save the firmware archive." << std::endl;
218 return 9;
220 ofs.close();
222 size_t length = archive.calc_size();
223 if (!length)
225 std::cerr << "Failed to determine the size of the firmware archive."
226 << std::endl;
227 return 10;
230 int align = length % 4;
231 if (align)
233 shared::bytes padding(4 - align, 0);
234 if (!shared::write_file(firmware, padding, false, length))
236 std::cerr << "Failed to write padding data." << std::endl;
237 return 11;
241 return 0;
244 int main(int argc, char* argv[])
248 return process_arguments(argc, argv);
250 catch (const std::exception& xcpt)
252 std::cerr << "Exception caught: " << xcpt.what() << std::endl;
253 return -1;
255 catch (...)
257 std::cerr << "Unknown exception caught." << std::endl;
258 return -2;
260 return -3;