dropped aas, moved to maxmod
[gbajam21] / tools / mmutil / main.c
1 /****************************************************************************
2  *                                                          __              *
3  *                ____ ___  ____ __  ______ ___  ____  ____/ /              *
4  *               / __ `__ \/ __ `/ |/ / __ `__ \/ __ \/ __  /               *
5  *              / / / / / / /_/ />  </ / / / / / /_/ / /_/ /                *
6  *             /_/ /_/ /_/\__,_/_/|_/_/ /_/ /_/\____/\__,_/                 *
7  *                                                                          *
8  *         Copyright (c) 2008, Mukunda Johnson (mukunda@maxmod.org)         *
9  *                                                                          *
10  * Permission to use, copy, modify, and/or distribute this software for any *
11  * purpose with or without fee is hereby granted, provided that the above   *
12  * copyright notice and this permission notice appear in all copies.        *
13  *                                                                          *
14  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES *
15  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF         *
16  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR  *
17  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES   *
18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN    *
19  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF  *
20  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.           *
21  ****************************************************************************/
22
23 // this is
24 // VERSION 1.8e
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <ctype.h>
30
31 #include "defs.h"
32 #include "mas.h"
33 #include "mod.h"
34 #include "s3m.h"
35 #include "xm.h"
36 #include "it.h"
37 #include "gba.h"
38 #include "nds.h"
39 #include "files.h"
40 #include "errors.h"
41 #include "simple.h"
42 #include "msl.h"
43 #include "systems.h"
44 #include "wav.h"
45 #include "samplefix.h"
46
47 extern void kiwi_start(void);
48
49 int target_system;
50
51 bool ignore_sflags;
52 int PANNING_SEP;
53
54 int number_of_inputs;
55
56 #define USAGE "\n\
57 ************************\n\
58 * Maxmod Utility *\n\
59 ************************\n\
60 \n\
61 Usage:\n\
62   mmutil [options] input files ...\n\
63 \n\
64  Input may be MOD, S3M, XM, IT, and/or WAV\n\
65 \n\
66 .------------.----------------------------------------------------.\n\
67 | Option     | Description                                        |\n\
68 |------------|----------------------------------------------------|\n\
69 | -o<output> | Set output file.                                   |\n\
70 | -h<header> | Set header output file.                            |\n\
71 | -m         | Output MAS file rather than soundbank.             |\n\
72 | -d         | Use for NDS projects.                              |\n\
73 | -b         | Create test ROM. (use -d for .nds, otherwise .gba) |\n\
74 | -i         | Ignore sample flags.                               |\n\
75 | -v         | Enable verbose output.                             |\n\
76 | -p         | Set initial panning separation for MOD/S3M.        |\n\
77 `-----------------------------------------------------------------'\n\
78 \n\
79 .-----------------------------------------------------------------.\n\
80 | Examples:                                                       |\n\
81 |-----------------------------------------------------------------|\n\
82 | Create DS soundbank file (soundbank.bin) from input1.xm         |\n\
83 | and input2.it Also output header file (soundbank.h)             |\n\
84 |                                                                 |\n\
85 | mmutil -d input1.xm input2.it -osoundbank.bin -hsoundbank.h     |\n\
86 |-----------------------------------------------------------------|\n\
87 | Create test GBA ROM from two inputs                             |\n\
88 |                                                                 |\n\
89 | mmutil -b input1.mod input2.s3m -oTEST.gba                      |\n\
90 |-----------------------------------------------------------------|\n\
91 | Create test NDS ROM from three inputs                           |\n\
92 |                                                                 |\n\
93 | mmutil -d -b input1.xm input2.s3m testsound.wav                 |\n\
94 `-----------------------------------------------------------------'\n\
95  www.maxmod.org\n\
96 "
97
98 void print_usage( void )
99 {
100         printf( USAGE );
101 }
102
103 void print_error( int err )
104 {
105         switch( err )
106         {
107         case ERR_INVALID_MODULE:
108                 printf( "Invalid module!\n" );
109                 break;
110         case ERR_MANYARGS:
111                 printf( "Too many arguments!\n" );
112                 break;
113         case ERR_NOINPUT:
114                 printf( "No input file!\n" );
115                 break;
116         case ERR_NOWRITE:
117                 printf( "Unable to write file!\n" );
118                 break;
119         case ERR_BADINPUT:
120                 printf( "Cannot parse input filename!\n" );
121                 break;
122         }
123 }
124
125 int GetYesNo( void )
126 {
127         char c = 0;
128         c = tolower(getchar());
129         while( getchar() != '\n' );
130         while( c != 'y' && c != 'n' )
131         {
132                 printf( "Was that a yes? " );
133                 c = tolower(getchar());
134                 while( getchar() != '\n' );
135         }
136         return c == 'y' ? 1 : 0;
137 }
138
139 //------------------------------------------------------------------------------------------------
140 int main(int argc, char* argv[])
141 //------------------------------------------------------------------------------------------------
142 {
143         char* str_input=NULL;
144         char* str_output=NULL;
145         char* str_header=NULL;
146         
147         MAS_Module mod;
148
149         int strl;
150
151         int input_type=0;
152
153         int strp;
154         int strpi;
155
156         bool g_flag=false;
157         bool v_flag=false;
158         bool m_flag=false;
159         bool z_flag=false;
160         int a;
161
162         int output_size;
163
164         ignore_sflags=false;
165
166         number_of_inputs=0;
167
168         PANNING_SEP = 128;
169
170         //------------------------------------------------------------------------
171         // parse arguments
172         //------------------------------------------------------------------------
173         
174         for( a = 1; a < argc; a++ )
175         {
176                 if( argv[a][0] == '-' )
177                 {
178                         if( argv[a][1] == 'b' )
179                                 g_flag = true;
180                         else if( argv[a][1] == 'v' )
181                                 v_flag = true;
182                         else if( argv[a][1] == 'd' )
183                                 target_system = SYSTEM_NDS;
184                         else if( argv[a][1] == 'i' )
185                                 ignore_sflags = true;
186                         else if( argv[a][1] == 'p' )
187                                 PANNING_SEP = ((argv[a][2] - '0') * 256)/9;
188                         else if( argv[a][1] == 'o' )
189                                 str_output = argv[a]+2;
190                         else if( argv[a][1] == 'h' )
191                                 str_header = argv[a]+2;
192                         else if( argv[a][1] == 'm' )
193                                 m_flag = true;
194                         else if( argv[a][1] == 'z' )
195                                 z_flag = true;
196                 }
197                 else if( !str_input )
198                 {
199                         str_input = argv[a];
200                         number_of_inputs=1;
201                 }
202                 else
203                 {
204                         number_of_inputs++;
205                 }
206         }
207         
208         if( number_of_inputs==0 )
209         {
210                 print_usage();
211                 return 0;
212         }
213         
214         if( z_flag )
215         {
216                 kiwi_start();
217                 file_open_read( str_input );
218                 Sample s;
219                 
220                 Load_WAV( &s, false,false );
221                 
222                 s.name[0] = '%';
223                 s.name[1] = 'c';
224                 s.name[2] = 0;
225                 
226                 FixSample( &s );
227                 
228                 file_close_read();
229                 file_open_write( str_output );
230                 
231                 int i;
232                 for( i = 0; i < s.sample_length; i++ )
233                         write8( ((u8*)s.data)[i] );
234                 
235                 file_close_write();
236                 printf("okay\n");
237                 return 0;
238         }
239
240         if( m_flag & g_flag )
241         {
242                 printf("-m and -g cannot be combined.\n");
243                 return -1;
244         }
245         
246         if( m_flag && number_of_inputs != 1 )
247         {
248                 printf( "-m only supports one input.\n" );
249                 return -1;
250         }
251
252         //---------------------------------------------------------------------------
253         // m/g generate output target if not given
254         //---------------------------------------------------------------------------
255
256         if( m_flag || g_flag)
257         {
258                 if( !str_output )
259                 {
260                         if( number_of_inputs == 1 )
261                         {
262                                 if( strlen(str_input) < 4 )
263                                 {
264                                         print_error( ERR_BADINPUT );
265                                         return -1;
266                                 }
267                                 strp = strlen(str_input);
268                                 str_output = (char*)malloc( strp+2 );
269                                 strcpy(str_output, str_input);
270                                 strp=strlen(str_output)-1;
271                                 
272                                 for( strpi=strp; str_output[strpi] != '.' && strpi != 0; strpi-- );
273                                 if( strpi == 0 )
274                                 {
275                                         print_error( ERR_BADINPUT );
276                                         return -1;
277                                 }
278                                 
279                                 str_output[strpi++] = '.';
280                                 if( !g_flag )
281                                 {
282                                         str_output[strpi++] = 'm';
283                                         str_output[strpi++] = 'a';
284                                         str_output[strpi++] = 's';
285                                         str_output[strpi++] = 0;
286                                 }
287                                 else
288                                 {
289                                         if( target_system == SYSTEM_GBA )
290                                         {
291                                                 str_output[strpi++] = 'g';
292                                                 str_output[strpi++] = 'b';
293                                                 str_output[strpi++] = 'a';
294                                                 str_output[strpi++] = 0;
295                                         }
296                                         else if( target_system == SYSTEM_NDS )
297                                         {
298                                                 str_output[strpi++] = 'n';
299                                                 str_output[strpi++] = 'd';
300                                                 str_output[strpi++] = 's';
301                                                 str_output[strpi++] = 0;
302                                         }
303                                         else
304                                         {
305                                                 // error!
306                                         }
307                                 }
308                                 str_output[strpi++] = 0;
309                         }
310                         else
311                         {
312                                 printf( "No output file! (-o option)\n" );
313                                 return -1;
314                         }
315                 }
316         }
317         
318         // catch filename too small
319         strl=strlen(str_input);
320         if( strl < 4 )
321         {
322                 print_error( ERR_BADINPUT );
323                 return -1;
324         }
325
326         if( m_flag )
327         {
328                 if( file_open_read( str_input ) )
329                 {
330                         printf( "Cannot open %s for reading!\n", str_input );
331                         return -1;
332                 }
333                 input_type = get_ext( str_input );
334
335                 switch( input_type )
336                 {
337                 //------------------------------------------------------
338                 case INPUT_TYPE_MOD:
339                 //------------------------------------------------------
340                         if( Load_MOD( &mod, v_flag ) )
341                         {
342                                 print_error( ERR_INVALID_MODULE );
343                                 file_close_read();
344                                 return -1;
345                         }
346                         break;
347                 //------------------------------------------------------
348                 case INPUT_TYPE_S3M:
349                 //------------------------------------------------------
350                         if( Load_S3M( &mod, v_flag ) )
351                         {
352                                 print_error( ERR_INVALID_MODULE );
353                                 file_close_read();
354                                 return -1;
355                         }
356                         break;
357                 //------------------------------------------------------
358                 case INPUT_TYPE_XM:
359                 //------------------------------------------------------
360                         if( Load_XM( &mod, v_flag ) )
361                         {
362                                 print_error( ERR_INVALID_MODULE );
363                                 file_close_read();
364                                 return -1;
365                         }
366                         break;
367                 //------------------------------------------------------
368                 case INPUT_TYPE_IT:
369                 //------------------------------------------------------
370                         if( Load_IT( &mod, v_flag ) )
371                         {
372                                 // ERROR!
373                                 print_error( ERR_INVALID_MODULE );
374                                 file_close_read();
375                                 return -1;
376                         }
377                         break;
378                 }
379                 
380                 file_close_read();
381
382                 if( file_exists( str_output ) )
383                 {
384                         printf( "Output file exists! Overwrite? (y/n) " );
385                         if( !GetYesNo() )
386                         {
387                                 printf( "Operation Canceled!\n" );
388                                 return -1;
389                         }
390                         
391                 }
392
393                 if( file_open_write( str_output ) )
394                 {
395                         print_error( ERR_NOWRITE );
396                         return -1;
397                 }
398
399                 printf( "Writing .mas............\n" );
400
401                 // output MAS
402                 output_size = Write_MAS( &mod, v_flag, false );
403
404                 
405                 file_close_write();
406
407                 Delete_Module( &mod );
408
409                 if( v_flag )
410                 {
411 #ifdef SUPER_ASCII
412                         printf( "Success! \x02 \n" );
413 #else
414                         printf( "Success! :) \n" );
415 #endif
416                 }
417         }
418         else if( g_flag )
419         {
420                 int i;
421
422                 MSL_Create( argv, argc, "tempSH308GK.bin", 0, v_flag );
423
424                 if( file_exists( str_output ) )
425                 {
426                         printf( "Output file exists! Overwrite? (y/n) " );
427                         if( !GetYesNo() )
428                         {
429                                 printf( "Operation Canceled!\n" );
430                                 return -1;
431                         }
432                         
433                 }
434
435                 if( file_open_write( str_output ) )
436                 {
437                         print_error( ERR_NOWRITE );
438                         return -1;
439                 }
440
441                 if( target_system == SYSTEM_GBA )
442                 {
443                         if( v_flag )
444                                 printf( "Making GBA ROM.......\n" );
445                         Write_GBA();
446                 }
447                 else if( target_system == SYSTEM_NDS )
448                 {
449                         if( v_flag )
450                                 printf( "Making NDS ROM.......\n" );
451                         Write_NDS();
452                 }
453
454                 output_size = file_size( "tempSH308GK.bin" );
455                 file_open_read( "tempSH308GK.bin" );
456
457                 if( target_system == SYSTEM_GBA )
458                 {
459                         write32( (output_size < 248832) ? 1 : 0 );
460                 }
461
462                 for( i = 0; i < output_size; i++ )
463                 {
464                         write8( read8() );
465                 }
466
467                 file_close_read();
468                 file_close_write();
469                 
470                 file_delete( "tempSH308GK.bin" );
471
472                 if( g_flag && target_system == SYSTEM_NDS )
473                         Validate_NDS( str_output, output_size );
474                 
475                 if( v_flag )
476                 {
477                         printf( "Success! :D\n" );
478
479                         if( g_flag && target_system == SYSTEM_GBA )
480                         {
481                                 if( output_size < 262144 )
482                                 {
483                                         printf("ROM can be multibooted!!\n" );
484                                 }
485                         }
486                 }       
487         }
488         else
489         {
490                 MSL_Create( argv, argc, str_output, str_header, v_flag );
491         }
492         return 0;
493 }