1515 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1616 */
1717
18+ #include " mdtools/ignore_unused_variable_warning.hh"
19+
1820#include < getopt.h>
21+ #include < mdcomp/comper.hh>
22+ #include < mdcomp/comperx.hh>
1923#include < mdcomp/kosinski.hh>
24+ #include < mdcomp/kosplus.hh>
25+ #include < mdcomp/lzkn1.hh>
2026#include < mdcomp/nemesis.hh>
27+ #include < mdcomp/rocket.hh>
28+ #include < mdcomp/saxman.hh>
29+ #include < mdcomp/snkrle.hh>
2130
2231#include < algorithm>
2332#include < cstdlib>
2433#include < cstring>
2534#include < fstream>
35+ #include < functional>
2636#include < iostream>
37+ #include < memory>
2738#include < sstream>
39+ #include < string>
40+ #include < unordered_map>
2841
2942using std::cerr;
3043using std::endl;
@@ -35,10 +48,15 @@ using std::ofstream;
3548using std::ostream;
3649using std::streamsize;
3750using std::string;
51+ using std::string_view;
3852using std::stringstream;
3953
54+ using namespace std ::literals::string_view_literals;
55+
4056static void usage () {
41- cerr << " Usage: recolor-art [-o|--format {unc|nem|kos}] [-m|--moduled] "
57+ cerr << " Usage: recolor-art [-o|--format "
58+ " {unc|comp|compx|kos|kos+|lzkn1|nem|rocket|snk}] "
59+ " [-m|--moduled] "
4260 " {-clr1 clr2}+ {input_art} {output_art}"
4361 << endl;
4462 cerr << " \t Recolors the art file, changing palette index clr1 to clr2. "
@@ -50,8 +68,6 @@ static void usage() {
5068 << endl;
5169}
5270
53- enum Formats { eInvalid = -1 , eUncompressed = 0 , eNemesis = 1 , eKosinski = 2 };
54-
5571using ColorMap = std::array<int , 16 >;
5672
5773struct Tile {
@@ -88,6 +104,30 @@ struct Tile {
88104 }
89105};
90106
107+ class uncompressed ;
108+ using basic_uncompressed = BasicDecoder<uncompressed, PadMode::PadEven>;
109+ using moduled_uncompressed = ModuledAdaptor<uncompressed, 4096U , 1U >;
110+
111+ class uncompressed : public basic_uncompressed , public moduled_uncompressed {
112+ friend basic_uncompressed;
113+ friend moduled_uncompressed;
114+ static bool encode (std::ostream& Dst, uint8_t const * data, size_t Size);
115+
116+ public:
117+ using basic_uncompressed::encode;
118+ static bool decode (std::istream& Src, std::iostream& Dst);
119+ };
120+
121+ bool uncompressed::encode (std::ostream& Dst, uint8_t const * data, size_t Size) {
122+ Dst.write (reinterpret_cast <const char *>(data), Size);
123+ return true ;
124+ }
125+
126+ bool uncompressed::decode (std::istream& Src, std::iostream& Dst) {
127+ Dst << Src.rdbuf ();
128+ return true ;
129+ }
130+
91131void recolor (istream& in, ostream& out, ColorMap& colormap) {
92132 Tile tile{};
93133 while (true ) {
@@ -99,6 +139,21 @@ void recolor(istream& in, ostream& out, ColorMap& colormap) {
99139 }
100140}
101141
142+ template <>
143+ size_t moduled_uncompressed::PadMaskBits = 1U ;
144+
145+ using encoder = decltype (&basic_uncompressed::encode);
146+ using decoder = decltype (&uncompressed::decode);
147+ using moduled_encoder = decltype (&uncompressed::moduled_encode);
148+ using moduled_decoder = decltype (&uncompressed::moduled_decode);
149+
150+ struct art_format {
151+ encoder encode;
152+ decoder decode;
153+ moduled_encoder moduled_encode;
154+ moduled_decoder moduled_decode;
155+ };
156+
102157int main (int argc, char * argv[]) {
103158 constexpr static const std::array long_options{
104159 option{" format" , required_argument, nullptr , ' o' },
@@ -111,7 +166,44 @@ int main(int argc, char* argv[]) {
111166 ColorMap colormap{0x0 , 0x1 , 0x2 , 0x3 , 0x4 , 0x5 , 0x6 , 0x7 ,
112167 0x8 , 0x9 , 0xA , 0xB , 0xC , 0xD , 0xE , 0xF };
113168 unsigned numcolors = 0 ;
114- Formats fmt = eUncompressed;
169+
170+ static const std::unordered_map<string_view, art_format>
171+ format_lut{
172+ {{" unc" sv,
173+ {uncompressed::encode, uncompressed::decode,
174+ uncompressed::moduled_encode,
175+ uncompressed::moduled_decode}},
176+ {" comp" sv,
177+ {comper::encode, comper::decode, comper::moduled_encode,
178+ comper::moduled_decode}},
179+ {" compx" sv,
180+ {comperx::encode, comperx::decode,
181+ comperx::moduled_encode, comperx::moduled_decode}},
182+ {" kos" sv,
183+ {kosinski::encode, kosinski::decode,
184+ kosinski::moduled_encode, kosinski::moduled_decode}},
185+ {" kos+" sv,
186+ {kosplus::encode, kosplus::decode,
187+ kosplus::moduled_encode, kosplus::moduled_decode}},
188+ {" lzkn1" sv,
189+ {lzkn1::encode, lzkn1::decode, lzkn1::moduled_encode,
190+ lzkn1::moduled_decode}},
191+ {" nem" sv,
192+ {nemesis::encode,
193+ +[](std::istream& Src, std::iostream& Dst) {
194+ return nemesis::decode (Src, Dst);
195+ },
196+ nemesis::moduled_encode, nemesis::moduled_decode}},
197+ {" rocket" sv,
198+ {rocket::encode, rocket::decode, rocket::moduled_encode,
199+ rocket::moduled_decode}},
200+ {" snk" sv,
201+ {snkrle::encode,
202+ +[](std::istream& Src, std::iostream& Dst) {
203+ return snkrle::decode (Src, Dst);
204+ },
205+ snkrle::moduled_encode, snkrle::moduled_decode}}}};
206+ auto fmt = format_lut.cend ();
115207
116208 while (true ) {
117209 int option_index = 0 ;
@@ -126,26 +218,14 @@ int main(int argc, char* argv[]) {
126218 option_char += (' a' - ' A' );
127219 }
128220
129- auto getFormat = [](auto optarg) {
130- if (optarg == nullptr ) {
131- return eInvalid;
132- }
133- if (strcmp (optarg, " unc" ) == 0 ) {
134- return eUncompressed;
135- }
136- if (strcmp (optarg, " nem" ) == 0 ) {
137- return eNemesis;
138- }
139- if (strcmp (optarg, " kos" ) == 0 ) {
140- return eKosinski;
141- }
142- return eInvalid;
143- };
144-
145221 switch (option_char) {
146222 case ' o' :
147- fmt = getFormat (optarg);
148- if (fmt == eInvalid) {
223+ if (optarg == nullptr ) {
224+ usage ();
225+ return 1 ;
226+ }
227+ fmt = format_lut.find (optarg);
228+ if (fmt == format_lut.cend ()) {
149229 usage ();
150230 return 1 ;
151231 }
@@ -220,17 +300,13 @@ int main(int argc, char* argv[]) {
220300 stringstream sin (ios::in | ios::out | ios::binary);
221301 stringstream sout (ios::in | ios::out | ios::binary);
222302
303+ auto const & [key, fmt_handler] = *fmt;
304+
223305 fin.seekg (0 );
224- if (fmt == eUncompressed) {
225- sin << fin.rdbuf ();
226- } else if (fmt == eNemesis) {
227- nemesis::decode (fin, sin);
228- } else { // if (fmt == eKosinski)
229- if (moduled) {
230- kosinski::moduled_decode (fin, sin);
231- } else {
232- kosinski::decode (fin, sin);
233- }
306+ if (moduled) {
307+ fmt_handler.moduled_decode (fin, sin, modulesize);
308+ } else {
309+ fmt_handler.decode (fin, sin);
234310 }
235311
236312 fin.close ();
@@ -246,17 +322,10 @@ int main(int argc, char* argv[]) {
246322 }
247323
248324 sout.seekg (0 );
249-
250- if (fmt == eUncompressed) {
251- fout << sout.rdbuf ();
252- } else if (fmt == eNemesis) {
253- nemesis::encode (sout, fout);
254- } else { // if (fmt == eKosinski)
255- if (moduled) {
256- kosinski::moduled_encode (sout, fout, modulesize);
257- } else {
258- kosinski::encode (sout, fout);
259- }
325+ if (moduled) {
326+ fmt_handler.moduled_encode (sout, fout, modulesize);
327+ } else {
328+ fmt_handler.encode (sout, fout);
260329 }
261330
262331 fout.close ();
0 commit comments