1 /*---------------------------------------------------------------------------*
2   Project:  Revolution THP Converting tool
3   File:     THPConv.c
4 
5   Copyright (C)2002-2006 Nintendo  All Rights Reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Log: THPConv.c,v $
14   Revision 1.1  02/08/2006 02:55:34  aka
15   Imported from Dolphin Tree.
16 
17 
18     22    03/12/24 4:20p Akagi
19     Revised frame rate check.
20 
21     21    03/12/24 1:36p Akagi
22     Removed a function copyFile().
23     Changed calling from copyFile() to THPUtyCopyTHPFile().
24     Added frame rate check.
25 
26     20    03/12/08 2:27p Akagi
27     Revised 2 error messages.
28 
29     19    03/09/21 6:48p Akagi
30     Added several file checks.
31 
32     18    03/09/18 10:07a Akagi
33     Added option check.
34 
35     17    03/09/17 9:59p Akagi
36     Fixed some bugs.
37 
38     16    03/07/03 2:58p Akagi
39     Fixed 2 trivial bugs.
40 
41     15    03/07/03 11:09a Akagi
42     Renamed some functions.
43 
44     14    03/07/02 4:20p Akagi
45     Renamed from THPConv_main.c to THPConv.c.
46 
47     13    03/07/02 4:13p Akagi
48     Rewrote with DolphinSDK coding style.
49 
50     12    03/07/02 1:02p Akagi
51     Modified appendAudioData().
52 
53     11    03/07/01 2:55p Akagi
54     Modified to divide old THPConv.exe into 2 DLLs and 1 EXE by
55     Ohki-san@NTSC.
56 
57     10    03/07/01 9:54a Akagi
58     Moved from securebuild/tools.
59 
60     9     02/10/16 11:28a Akagi
61     JPEG & WAV file Name bug fixed. (by iRD  tsuji)
62 
63     8     02/05/30 2:21p Akagi
64     Stop to support QuickTime MJPEG By Tsuji (IRD)
65 
66     7     02/05/27 9:45a Akagi
67     Modified output error messages in English, by Tsuji (IRD)
68 
69     6     02/05/08 2:31p Akagi
70     modified [-trk] option By Tsuji (IRD)
71 
72     5     02/05/01 3:09p Akagi
73     added JPEG files sort program. By Tsuji (IRD)
74 
75     4     02/03/28 11:15a Akagi
76     modified by Tsuji (IRD)
77 
78     2     02/01/22 10:10a Akagi
79     Add error message, when can't load "dsptools.dll" by Tsuji.
80 
81     1     02/01/16 4:58p Akagi
82     Initial revision made by Tsuji-san (IRD).
83 
84   $NoKeywords: $
85 
86  *---------------------------------------------------------------------------*/
87 
88 #include <windows.h>
89 #include <CRTDBG.h>
90 #include <stdlib.h>
91 #include <stdio.h>
92 #include <sys/types.h>
93 #include <sys/stat.h>
94 #include <assert.h>
95 #include <string.h>
96 
97 #include <revolution/types.h>
98 #include <revolution/thpfile.h>
99 #include <win32/thpcommon.h>
100 #include <win32/thpcore.h>
101 #include <win32/thputilities.h>
102 #include <win32/thpaudio.h>
103 
104 //-----------------------------------------------------------------------------
105 // <used THP library functions>
106 //
107 // #include <win32/thputilities.h>
108 //
109 //    THPUtyConvertToUnixFmt()
110 //    THPUtyHeaderInit()
111 //    THPUtyCreateTHP()
112 //    THPUtyChangeAudioTrack()
113 //    THPUtyReadTHPFileHeader()
114 //    THPUtyCopyTHPFile()
115 //
116 // #include <win32/thpaudio.h>
117 //
118 //    THPAudioInit()
119 //    THPAudioCreateHandle()
120 //    THPAudioGetInfo()
121 //    THPAudioGetMaxFrameSamples()
122 //    THPAudioGetTotalSamples()
123 //    THPAudioQuit()
124 //    THPAudioFreeHandle()
125 //
126 //-----------------------------------------------------------------------------
127 
128 //-----------------------------------------------------------------------------
129 //      Define
130 //-----------------------------------------------------------------------------
131 #define TMP_FILENAME "__tmp_VD"
132 
133 //-----------------------------------------------------------------------------
134 //      Static Value
135 //-----------------------------------------------------------------------------
136 static char** jpegFilesPtr = NULL;                 // JPEG File name string array pointer
137 static u32    num_JPGfiles = 0;                    // number of JPG files
138 
139 static char** waveFilesPtr = NULL;                 // WAV File name string array pointer
140 static u32    num_WAVfiles = 0;                    // number of WAV files
141 
142 static char*  inFile  = NULL;                      // input filename
143 static char*  outFile = NULL;                      // output filename
144 
145 static u32    pack_jpegs       = 0;                // convert jpegs files to THP flag (-j)
146 static u32    change_snd_data  = 0;                // change sound data flag (-c)
147 static u32    change_alltrack  = 0;                // change all track data flag (-s)
148 static u32    change_onetrack  = 0;                // change one track data flag (-trk)
149 static u8     change_framerate = 0;                // change framerate (-r)
150 static u8     change_videotype = 0;                // change videotype (-non/odd/even)
151 static u32    offset_mode      = 0;                // offset flag (-o)
152 static u32    resample_on_GC   = 0;                // resampling is done on GC flag
153                                                    // (default is on PC)
154 
155 static f32    frame_rate = 29.97F;                 // frame rate
156 static u32    videotype  = THP_VIDEO_NON_INTERLACE;// Video Type
157 
158 static u8     trackNo = 0;                         // track # (-trk)
159 
160 static u32    Convert_Verbose = 0;
161 
162 //-----------------------------------------------------------------------------
163 //      Function
164 //-----------------------------------------------------------------------------
165 static void Usage                   ( const char* progName );
166 static s32  verifyWriteOverInputData( const char* fileName );
167 static u32  getFileNameList         ( const char *sWildcardPattern, THPFileName* filename );
168 static int  compare                 ( const void *arg1, const void *arg2 );
169 static s32  checkArguments          ( u32 argument_count, char *argv[] );
170 static s32  convertJPEGtoTHP        ( void );
171 static s32  changeAudioTrack        ( THPFileHeader* fileHeader );
172 static s32  appendAudioData         ( THPFileHeader* fileHeader );
173 static s32  changeAudioData         ( void );
174 static void logPrintFunc            ( const char* format, va_list argptr );
175 
176 /*---------------------------------------------------------------------------*
177   Name:         Usage
178 
179   Description:  command usage display
180 
181   Arguments:    progName    a pointer to the program name
182 
183   Returns:      None.
184  *---------------------------------------------------------------------------*/
Usage(const char * progName)185 static void Usage(const char* progName)
186 {
187     fprintf(stderr, "usage: %s [-OPTIONS]\n", progName);
188     fprintf(stderr, "\n");
189     fprintf(stderr, "  <<JPEGs -> THP>>\n");
190     fprintf(stderr, "  -j   [*.jpg]               # some JPEGs are packed into one file\n");
191     fprintf(stderr, "  -d   [file.thp]            # output THP file name\n");
192     fprintf(stderr, "\n");
193     fprintf(stderr, "  <SubOptions>\n");
194     fprintf(stderr, "  -s   [file.wav] [file.wav] [file.wav] ...\n");
195     fprintf(stderr, "                             # input WAV file names\n");
196     fprintf(stderr, "  -o                         # put offset data in THP\n");
197     fprintf(stderr, "  -r   [f32 number]          # set FrameRate (default is 29.97)\n");
198     fprintf(stderr, "\n");
199     fprintf(stderr, "  (THP Video Type)\n");
200     fprintf(stderr, "  -non                       # default Video Type NON  Interlace\n");
201     fprintf(stderr, "  -odd                       # set     Video Type ODD  Interlace\n");
202     fprintf(stderr, "  -even                      # set     Video Type EVEN Interlace\n");
203     fprintf(stderr, "\n");
204     fprintf(stderr, "  (THP Audio Resampling)\n");
205     fprintf(stderr, "  -on                        # disable resampling audio data, and\n");
206     fprintf(stderr, "                             # adjust audio frequency for GC\n");
207     fprintf(stderr, "\n");
208     fprintf(stderr, "  -v                         # verbose mode\n");
209     fprintf(stderr, "  -h                         # show this usage\n");
210     fprintf(stderr, "\n");
211     fprintf(stderr, "  ------------------------------------------------------------------\n");
212     fprintf(stderr, "\n");
213     fprintf(stderr, "  <<Change THP sound file Data>>\n");
214     fprintf(stderr, "  -c   [file.thp]            # input THP file name\n");
215     fprintf(stderr, "  -s   [file.wav] [file.wav] [file.wav] ...\n");
216     fprintf(stderr, "                             # input WAV file names\n");
217     fprintf(stderr, "  -trk [u8 track No.] [file.wav] \n");
218     fprintf(stderr, "                             # change Track No.[0... ] & input WAV file name\n");
219     fprintf(stderr, "\n");
220     fprintf(stderr, "  <SubOptions>\n");
221     fprintf(stderr, "  -d   [file.thp]            # output THP file name\n");
222     fprintf(stderr, "  -o                         # put offset data in THP\n");
223     fprintf(stderr, "  -r   [f32 number]          # set FrameRate (default is 29.97)\n");
224     fprintf(stderr, "\n");
225     fprintf(stderr, "  (THP Video Type)\n");
226     fprintf(stderr, "  -non                       # default Video Type NON  Interlace \n");
227     fprintf(stderr, "  -odd                       # set     Video Type ODD  Interlace \n");
228     fprintf(stderr, "  -even                      # set     Video Type EVEN Interlace \n");
229     fprintf(stderr, "\n");
230     fprintf(stderr, "  (THP Audio Resampling)\n");
231     fprintf(stderr, "  -on                        # disable resampling audio data, and\n");
232     fprintf(stderr, "                             # adjust audio frequency for GC\n");
233     fprintf(stderr, "\n");
234     fprintf(stderr, "  -v                         # verbose mode\n");
235     fprintf(stderr, "  -h                         # show this usage\n");
236     fprintf(stderr, "\n");
237 }
238 
239 /*---------------------------------------------------------------------------*
240   Name:         verifyWriteOverInputData
241 
242   Description:  confirms overwriting of input file
243 
244   Arguments:    fileName    a pointer to the file name
245 
246   Returns:      TRUE        overwrite permission
247                 FALSE       overwrite denied
248  *---------------------------------------------------------------------------*/
verifyWriteOverInputData(const char * fileName)249 static s32 verifyWriteOverInputData(const char* fileName)
250 {
251     char  answer    = 0;
252     u8    loop_flag = 1;
253 
254     while (loop_flag)
255     {
256         printf("\a>Overwrite the inputfile[%s] by OutputData ? [Y/N] ", fileName);
257         answer = toupper(getchar());
258 
259         if (answer == 'Y')
260         {
261             loop_flag = 0;
262         }
263         else if (answer == 'N')
264         {
265             printf("\a\n Please try using [-d] option.\n");
266             return FALSE;
267         }
268         else
269         {
270             // Loop //
271         }
272     }
273 
274     return TRUE;
275 }
276 
277 /*---------------------------------------------------------------------------*
278   Name:         getFileNameList
279 
280   Description:  Searches for file names matching sWildcardPattern and stores them all in filename.
281                 The filename buffer must be allocated in advance.
282 
283   Arguments:    sWildcardPattern  file name including the wildcard
284                 filename          buffer storing the file names
285 
286   Returns:      number of files
287  *---------------------------------------------------------------------------*/
getFileNameList(const char * sWildcardPattern,THPFileName * filename)288 static u32 getFileNameList(const char *sWildcardPattern, THPFileName* filename)
289 {
290     u32              f_count = 0;
291     WIN32_FIND_DATA  wfd;
292     HANDLE           hFind;
293     struct           stat;
294 
295     if ((hFind = FindFirstFile(sWildcardPattern, &wfd)) == INVALID_HANDLE_VALUE)
296     {
297         return f_count;
298     }
299 
300     do
301     {
302         if (filename != NULL)
303         {
304             strcpy(filename[f_count].name, wfd.cFileName);
305             strlwr(filename[f_count].name);
306             filename[f_count].fileSize = wfd.nFileSizeLow;
307         }
308         f_count++;
309 
310     } while (FindNextFile(hFind, &wfd));
311 
312     FindClose(hFind);
313 
314     if (filename != NULL)
315     {
316         u32   i;
317         char  drive[_MAX_DRIVE];
318         char  dir[_MAX_DIR];
319         char  pathCopy[_MAX_PATH];
320         char  path[_MAX_PATH];
321 
322         qsort(filename, f_count, sizeof(THPFileName), compare);
323 
324         _splitpath(sWildcardPattern, drive, dir, NULL, NULL);
325         _makepath(path, drive, dir, NULL, NULL);
326 
327         for (i = 0; i < f_count; i++)
328         {
329             strcpy(pathCopy, path);
330             strcat(pathCopy, filename[i].name);
331             strcpy(filename[i].name, pathCopy);
332         }
333     }
334 
335     return f_count++;
336 }
337 
338 /*---------------------------------------------------------------------------*
339   Name:         compare
340 
341   Description:  the comparison function specified in qsort()
342 
343   Arguments:    arg1, arg2  the elements compared
344 
345   Returns:      negative      arg1 is less than arg2
346                 0           arg1 = arg2
347                 positive      arg1 is greater than arg2
348  *---------------------------------------------------------------------------*/
compare(const void * arg1,const void * arg2)349 static int compare(const void *arg1, const void *arg2)
350 {
351     // compares two strings until their ends
352     return strcmp(((THPFileName *)arg1)->name, ((THPFileName *)arg2)->name);
353 }
354 
355 /*---------------------------------------------------------------------------*
356   Name:         checkArguments
357 
358   Description:  argument checker
359 
360   Arguments:    argument_count  the number of arguments
361                 argv            an array of argument strings
362 
363   Returns:      TRUE   Ended successfully
364                 FALSE       ended in an error
365                 (when the argument is '-h', immediately use exit(0))
366  *---------------------------------------------------------------------------*/
367 /*---------------------------------------------------------------------------*
368   [flags]
369 
370   <required>
371 
372   -j option: create THP files from serial JPG file (group)
373     flag specifying serial JPG files   pack_jpegs            0    -> 1
374     serial JPG file's file name: jpegFilesPtr          NULL -> XXXX
375     number of serial JPG files: num_JPGfiles          0    -> XX
376 
377   -c option: exchange audio data in existing THP file
378     flag specifying the input THP file: change_snd_data      :  0    -> 1
379     input THP file's file name: inFile               :  NULL -> XXXX
380 
381   *** -j and -c are mutually exclusive ***
382 
383   <optional>
384 
385   -d option
386     output THP file name: outFile              : NULL -> XXXX
387 
388   *** required when using -j/optional when using -c ***
389 
390   -s option
391     flag specifying the input WAV file: change_alltrack      : 0    -> 1
392     input WAV file's file name: waveFilesPtr         : NULL -> XXXX
393     number of input WAV files: num_WAVfiles         : 0    -> XX
394 
395   *** not needed when using -j ***
396 
397   -trk option
398     audio track file exchange flag: change_onetrack      : 0    -> 1
399     exchange WAV file name: waveFilesPtr         : NULL -> XXXX
400     exchange track number: trackNo              : 0    -> XX
401 
402   *** invalid when using -j/when using -c, although -s and -trk are mutually exclusive, one of the two must be included ***
403 
404   <Miscellaneous>
405 
406   -r option
407     flag specifying frame rate: change_framerate     : 0    -> 1
408     frame rate: frame_rate           : 29.97f -> XXXXXX
409 
410   -o option
411     flag for creating offset table: offset_mode          : 0    -> 1
412 
413   -non/odd/even option
414     flag specifying display start field: change_videotype     : 0    -> 1
415     specified field: videotype            : THP_VIDEO_NON_INTERLACE -> XXXXX
416 
417   *** invalid when using -trk ***
418 
419   -on option
420     resampling flag: resample_on_GC       : 0    -> 1
421 
422   *** invalid when using -trk (maintained from existing audio data) ***
423 
424   -v option
425     verbose mode flag: Convert_Verbose      : 0    -> 1
426 
427  *---------------------------------------------------------------------------*/
428 
checkArguments(u32 argument_count,char * argv[])429 static s32 checkArguments(u32 argument_count, char *argv[])
430 {
431     u32  i;
432 
433     if (argument_count < 2)
434     {
435         Usage(argv[0]);
436         exit(0);
437     }
438 
439     // Check Options //
440     for (i = 1; i < argument_count; i++)
441     {
442         if (argv[i][0] == '-')
443         {
444             u8* option = argv[i];
445 
446             //
447             // -j : specify input JPEG file(s)
448             //
449             if (strcmp(option, "-j") == 0)
450             {
451                 // -j (pack_jpegs = 1) and -c (change_snd_data) are mutually exclusive
452                 if (change_snd_data)
453                 {
454                     printf("\aERROR : Can't use both [-j] and [-c] at the same time.\n");
455                     return FALSE;
456                 }
457 
458                 // -j can only be specified once
459                 if (pack_jpegs)
460                 {
461                     printf("\aERROR : [-j] is specified twice.\n");
462                     return FALSE;
463                 }
464 
465                 // check to see if there are subsequent file names
466                 i++;
467                 if (i >= argument_count)
468                 {
469                     printf("\aERROR : Must specify input filename after [-j].\n");
470                     return FALSE;
471                 }
472 
473                 jpegFilesPtr = &argv[i];
474 
475                 // check the number of specified JPG files
476                 while (i < argument_count && argv[i][0] != '-')
477                 {
478                     num_JPGfiles++;
479                     i++;
480                 }
481 
482                 if (num_JPGfiles == 0)
483                 {
484                     printf("\aERROR : There is no jpeg file after [-j].\n");
485                     return FALSE;
486                 }
487 
488                 i--;
489                 pack_jpegs = 1;
490             }
491 
492             //
493             // -c : specify input THP file
494             //
495             else if (strcmp(option, "-c") == 0)
496             {
497                 // -j (pack_jpegs = 1) and -c (change_snd_data) are mutually exclusive
498                 if (pack_jpegs)
499                 {
500                     printf("\aERROR : Can't use both [-j] and [-c] at the same time.\n");
501                     return FALSE;
502                 }
503 
504                 // -c can only be specified once
505                 if (change_snd_data)
506                 {
507                     printf("\aERROR : [-c] is specified twice.\n");
508                     return FALSE;
509                 }
510 
511                 // check to see if there are subsequent file names
512                 i++;
513                 if (i >= argument_count || argv[i][0] == '-')
514                 {
515                     printf("\aERROR : Must specify input filename after [-c].\n");
516                     return FALSE;
517                 }
518 
519                 // get input THP file name
520                 inFile = argv[i];
521                 THPUtyConvertToUnixFmt(inFile);
522 
523                 change_snd_data = 1;
524             }
525 
526             //
527             // -d : specify output THP file name
528             //
529             else if (strcmp(option, "-d") == 0)
530             {
531                 // -d can only be specified once
532                 if (outFile)
533                 {
534                     printf("\aERROR : [-d] is specified twice.\n");
535                     return FALSE;
536                 }
537 
538                 // check to see if there are subsequent file names
539                 i++;
540                 if (i >= argument_count || argv[i][0] == '-')
541                 {
542                     printf("\aERROR : Must specify output THP filename after [-d].\n");
543                     return FALSE;
544                 }
545 
546                 // get output THP file name
547                 outFile = argv[i];
548                 THPUtyConvertToUnixFmt(outFile);
549             }
550 
551             //
552             // -s : specify input WAV file(s)
553             //
554             else if (strcmp(option, "-s") == 0)
555             {
556                 // -s (change_alltrack = 1) and -trk (change_onetrack) are mutually exclusive
557                 if (change_onetrack)
558                 {
559                     printf("\aERROR : Can't use both [-s] and [-trk] at the same time.\n");
560                     return FALSE;
561                 }
562 
563                 // -s can only be specified once
564                 if (change_alltrack)
565                 {
566                     printf("\aERROR : [-s] is specified twice.\n");
567                     return FALSE;
568                 }
569 
570                 // check to see if there are subsequent file names
571                 i++;
572                 if (i >= argument_count)
573                 {
574                     printf("\aERROR : Must specify input filename after [-s].\n");
575                     return FALSE;
576                 }
577 
578                 waveFilesPtr = &argv[i];
579 
580                 // check the number of specified WAV files
581                 while ((i < argument_count) && argv[i][0] != '-')
582                 {
583                     num_WAVfiles++;
584                     i++;
585                 }
586 
587                 if (num_WAVfiles == 0)
588                 {
589                     printf("\aERROR : There is no WAV file after [-s].\n");
590                     return FALSE;
591                 }
592 
593                 i--;
594                 change_alltrack = 1;
595             }
596 
597             //
598             // -trk : specify track number and input WAV file
599             //
600             else if (strcmp(option, "-trk") == 0)
601             {
602                 // -s (change_alltrack = 1) and -trk (change_onetrack) are mutually exclusive
603                 if (change_alltrack)
604                 {
605                     printf("\aERROR : Can't use both [-s] and [-trk] at the same time.\n");
606                     return FALSE;
607                 }
608 
609                 // -trk can only be specified once
610                 if (change_onetrack)
611                 {
612                     printf("\aERROR : [-trk] is specified twice.\n");
613                     return FALSE;
614                 }
615 
616                 // check to see if there are subsequent track numbers and file names
617                 i++;
618                 if (i + 1 >= argument_count)
619                 {
620                     printf("\aERROR : Must specify trackNo and input filename after [-trk].\n");
621                     return FALSE;
622                 }
623 
624                 // get the track number
625                 if (argv[i][0] < '0' || argv[i][0] > '9')
626                 {
627                     printf("\aERROR : Invalid trackNo.\n");
628                     return FALSE;
629                 }
630 
631                 trackNo = atoi(argv[i]);
632 
633                 // get the input WAV file name
634                 i++;
635                 if (i >= argument_count || argv[i][0] == '-')
636                 {
637                     printf("\aERROR : Must specify trackNo and input filename after [-trk].\n");
638                     return FALSE;
639                 }
640                 waveFilesPtr = &argv[i];
641                 THPUtyConvertToUnixFmt(waveFilesPtr[0]);
642 
643                 change_onetrack = 1;
644             }
645 
646             //
647             // -r : specify frame rate
648             //
649             else if (strcmp(option, "-r") == 0)
650             {
651                 // check to see if there are subsequent specified frame rates
652                 i++;
653                 if (i >= argument_count)
654                 {
655                     printf("\aERROR : Must specify output framerate after [-r].\n");
656                     return FALSE;
657                 }
658 
659                 // get the frame rate
660                 frame_rate = (f32)atof(argv[i]);
661                 if (frame_rate > 59.94 ||  frame_rate < 1.0)
662                 {
663                     printf("\aERROR : Framarate should be between 1.0 to 59.94.\n");
664                     return FALSE;
665                 }
666 
667                 change_framerate = 1;
668             }
669 
670             //
671             // -o : specify making an offset table
672             //
673             else if (strcmp(option, "-o") == 0)
674             {
675                 offset_mode = 1;
676             }
677 
678             //
679             // -non : specify video type non-interlace
680             //
681             else if (strcmp(option, "-non") == 0)
682             {
683                 if (change_videotype)
684                 {
685                     printf("\aERROR : Already used -non/odd/even.\n");
686                     return FALSE;
687                 }
688 
689                 videotype = THP_VIDEO_NON_INTERLACE;
690                 change_videotype = 1;
691             }
692 
693             //
694             // -odd : specify video type interlace beginning from odd field
695             //
696             else if (strcmp(option, "-odd") == 0)
697             {
698                 if (change_videotype)
699                 {
700                     printf("\aERROR : Already used -non/odd/even.\n");
701                     return FALSE;
702                 }
703 
704                 videotype = THP_VIDEO_ODD_INTERLACE;
705                 change_videotype = 1;
706             }
707 
708             //
709             // -even : specify video type interlace beginning from even field
710             //
711             else if (strcmp(option, "-even") == 0)
712             {
713                 if (change_videotype)
714                 {
715                     printf("\aERROR : Already used -non/odd/even.\n");
716                     return FALSE;
717                 }
718 
719                 videotype = THP_VIDEO_EVEN_INTERLACE;
720                 change_videotype = 1;
721             }
722 
723             //
724             // -v : specify setting verbose mode
725             //
726             else if (strcmp(option, "-v") == 0)
727             {
728                 Convert_Verbose = 1;
729             }
730 
731             //
732             // -on : specify adjusting audio frequency
733             //
734             else if (strcmp(option, "-on") == 0)
735             {
736                 resample_on_GC = 1;
737             }
738 
739             //
740             // -h : specify display of usage
741             //
742             else if (strcmp(option, "-h") == 0)
743             {
744                 Usage(argv[0]);
745                 exit(0);
746             }
747 
748             //
749             // etc.
750             //
751             else
752             {
753                 printf("\aERROR : Unknown option <%s>.\n", option);
754                 return FALSE;
755             }
756 
757         } // if (argv[i][0] == '-')
758 
759         // invalid argument
760         else
761         {
762             printf("\aERROR : Invalid arguments!\n");
763             return FALSE;
764 
765         } // if (argv[i][0] == '-')
766 
767     } // for (i = 1; i < argument_count; i++)
768 
769 
770     // convert either (-j : pack_jpegs = 1) or audio exchange (-c : change_snd_data = 1)
771     // check to see that one is specified
772     if (!pack_jpegs && !change_snd_data)
773     {
774         printf("\aERROR : Must input either [-j] or [-c].\n");
775         return FALSE;
776     }
777 
778     // when converting from JPG to THP (-j : pack_jpegs = 1), check that the output THP file
779     // is specified (-d : outFile != NULL).
780     if (pack_jpegs)
781     {
782         if (outFile == NULL)
783         {
784             printf("\aERROR : Must specify output THP filename [-d] [file.thp].\n");
785             return FALSE;
786         }
787     }
788 
789     // when exchanging THP audio data (-c : change_snd_data = 1), check that the input WAV file
790     // is specified (-s : change_alltrack = 1 or -trk : change_one_track = 1).
791     if (change_snd_data)
792     {
793         if (!change_alltrack && !change_onetrack)
794         {
795             printf("\aERROR : Must input [-s] [file.wav] or [-trk] [track No.] [file.wav].\n");
796             return FALSE;
797         }
798     }
799 
800     return TRUE;
801 }
802 
803 /*---------------------------------------------------------------------------*
804   Name:         convertJPEGtoTHP
805 
806   Description:  converts serial JPG files to THP data
807 
808   Arguments:    None.
809 
810   Returns:      TRUE   Ended successfully
811                 FALSE       ended in an error
812  *---------------------------------------------------------------------------*/
convertJPEGtoTHP(void)813 static s32 convertJPEGtoTHP(void)
814 {
815     s32               rtn;
816     s32               error = TRUE;
817     u32               cnt;
818     FILE*             thpFp = NULL;
819     THPFileName*      jpegFileList = NULL;
820     THPAudioHandle**  audioHandle = NULL;
821     THPFileHeader     fileHeader;
822 
823     //
824     // create a JPG file list
825     //
826     if (num_JPGfiles == 1)
827     {
828         // when a single JPG file or wildcard is specified
829 
830         THPUtyConvertToUnixFmt(jpegFilesPtr[0]);
831 
832         // confirm the number of JPG files
833         num_JPGfiles = getFileNameList(jpegFilesPtr[0], NULL);
834         if (num_JPGfiles == 0)
835         {
836             printf("\aERROR : There is no jpeg files. Input right argument.\n");
837             error = FALSE;
838             goto ERROR_END;
839         }
840 
841         jpegFileList = (THPFileName*)malloc(sizeof(THPFileName) * num_JPGfiles);
842         if (jpegFileList == NULL)
843         {
844             printf("\aERROR : Can't alloc memory.\n");
845             error = FALSE;
846             goto ERROR_END;
847         }
848 
849         // save the JPG file name
850         getFileNameList(jpegFilesPtr[0], jpegFileList);
851     }
852 
853     else
854     {
855         // when multiple JPG files are specified
856 
857         jpegFileList = (THPFileName*)malloc(sizeof(THPFileName) * num_JPGfiles);
858         if (jpegFileList == NULL)
859         {
860             printf("\aERROR : Can't alloc memory.\n");
861             error = FALSE;
862             goto ERROR_END;
863         }
864 
865         for (cnt = 0; cnt < num_JPGfiles; cnt++)
866         {
867             struct stat  statBuf;
868             char         ext[_MAX_EXT];
869 
870             // save the JPG file name
871             strcpy(jpegFileList[cnt].name, jpegFilesPtr[cnt]);
872             THPUtyConvertToUnixFmt(jpegFileList[cnt].name);
873 
874             // confirm the extension
875             _splitpath(jpegFileList[cnt].name, NULL, NULL, NULL, ext);
876             if ((stricmp(ext, ".jpg") != 0) && (stricmp(ext, ".jpeg") != 0))
877             {
878                 printf("\aERROR : Please input filename is [***.jpg] or [***.jpeg].\n");
879                 error = FALSE;
880                 goto ERROR_END;
881             }
882 
883             // get the JPG file size
884             rtn = stat(jpegFileList[cnt].name, &statBuf);
885             if (rtn != 0)
886             {
887                 printf("\aERROR : Can't get JPEG file status!\n");
888                 error = FALSE;
889                 goto ERROR_END;
890             }
891 
892             jpegFileList[cnt].fileSize = statBuf.st_size;
893         }
894     }
895 
896     if (Convert_Verbose)
897     {
898         printf("Total Frames = %ld\n", num_JPGfiles);
899         printf("Frame Rate   = %f\n",  frame_rate);
900     }
901 
902     // set THPHeader
903     THPUtyHeaderInit(&fileHeader.header);
904     fileHeader.header.frameRate           = frame_rate;
905     fileHeader.header.numFrames           = num_JPGfiles;
906     fileHeader.header.compInfoDataOffsets = sizeof(THPHeader);
907     fileHeader.header.offsetDataOffsets   = offset_mode;
908 
909     // set THPFrameCompInfo
910     fileHeader.frameCompInfo.frameComp[0] = THP_VIDEO_COMP;
911     fileHeader.frameCompInfo.numComponents = 1;
912     for (cnt = 1; cnt < THP_COMP_MAX; cnt++)
913     {
914         fileHeader.frameCompInfo.frameComp[cnt] = THP_NOCOMP_COMP;
915     }
916 
917     // set THPVideoInfo
918     fileHeader.videoInfo.videoType = videotype;
919 
920     // audio data encoding settings
921     if (change_alltrack)
922     {
923         if (Convert_Verbose)
924         {
925             printf("START: Audio Initializing.\n");
926         }
927 
928         if (THPAudioInit() == FALSE)
929         {
930             printf("\aERROR : Fail to execute THPAudioInit().\n");
931             error = FALSE;
932             goto ERROR_END;
933         }
934 
935         audioHandle = (THPAudioHandle**)malloc(sizeof(THPAudioHandle*) * num_WAVfiles);
936         if (audioHandle == NULL)
937         {
938             printf("\aERROR : Can't alloc memory.\n");
939             error = FALSE;
940             goto ERROR_END;
941         }
942 
943         // create the WAV file list
944         for (cnt = 0; cnt < num_WAVfiles; cnt++)
945         {
946             THPUtyConvertToUnixFmt(waveFilesPtr[cnt]);
947 
948             audioHandle[cnt] = THPAudioCreateHandle(waveFilesPtr[cnt], frame_rate);
949             if (audioHandle[cnt] == NULL)
950             {
951                 printf("\aERROR : Fail to execute THPAudioCreateHandle().\n");
952                 error = FALSE;
953                 goto ERROR_END;
954             }
955 
956             // permission settings (common to all audio data) for resampling when creating THP data
957             audioHandle[cnt]->resampleFlag = resample_on_GC ^ 1;
958         }
959 
960         if (Convert_Verbose)
961         {
962             if (resample_on_GC)
963             {
964                 printf("    Disable audio resampling.\n");
965             }
966             else
967             {
968                 printf("    Enable audio resampling.\n");
969             }
970         }
971 
972         // Main Sound
973         rtn = THPAudioGetInfo(audioHandle[0], &fileHeader.audioInfo);
974         if (rtn == FALSE)
975         {
976             printf("\aERROR : Fail to execute THPAudioGetInfo().\n");
977             error = FALSE;
978             goto ERROR_END;
979         }
980 
981         if (Convert_Verbose)
982         {
983             printf("    [AudioData]:(%2ld Tracks)\n", num_WAVfiles);
984             printf("     >> Channels  = %ld\n", fileHeader.audioInfo.sndChannels);
985             printf("     >> Frequency = %ld\n", fileHeader.audioInfo.sndFrequency);
986             printf("    <+> Track%02d <= [%s]\n", 0, waveFilesPtr[0]);
987         }
988 
989         if (resample_on_GC)
990         {
991             fileHeader.audioInfo.sndFrequency
992                 = (u32)((1124.0/1125.0) * (f64)audioHandle[0]->audioInfo.frequency + 0.5);
993             if (Convert_Verbose)
994             {
995                 printf("    Adjust Frequency %d -> %d\n", audioHandle[0]->audioInfo.frequency,
996                                                           fileHeader.audioInfo.sndFrequency);
997             }
998         }
999 
1000         // Sub Sound
1001         for (cnt = 1; cnt < num_WAVfiles; cnt++)
1002         {
1003             THPAudioInfo  subAudioInfo;
1004 
1005             rtn = THPAudioGetInfo(audioHandle[cnt], &subAudioInfo);
1006             if (rtn == FALSE)
1007             {
1008                 printf("\aERROR : Fail to execute THPAudioGetInfo().\n");
1009                 error = FALSE;
1010                 goto ERROR_END;
1011             }
1012 
1013             // checks the number of channels in a WAV file
1014             if (audioHandle[0]->audioInfo.channel != subAudioInfo.sndChannels)
1015             {
1016                 printf("\aERROR : Channels of [%s] is %d (!= %d).\n",
1017                        waveFilesPtr[cnt],
1018                        subAudioInfo.sndChannels,
1019                        audioHandle[0]->audioInfo.channel);
1020                 error = FALSE;
1021                 goto ERROR_END;
1022             }
1023 
1024             // checks the playback frequency in a WAV file
1025             if (audioHandle[0]->audioInfo.frequency != subAudioInfo.sndFrequency)
1026             {
1027                 printf("\aERROR : Frequency of [%s] is %d (!= %d).\n",
1028                        waveFilesPtr[cnt],
1029                        subAudioInfo.sndFrequency,
1030                        audioHandle[0]->audioInfo.frequency);
1031                 error = FALSE;
1032                 goto ERROR_END;
1033             }
1034 
1035             if (Convert_Verbose)
1036             {
1037                 printf("    <+> Track%02d <= [%s]\n", cnt, waveFilesPtr[cnt]);
1038             }
1039         }
1040 
1041         if (Convert_Verbose)
1042         {
1043             printf("END  : Audio Initializing.\n");
1044         }
1045 
1046         // update THPHeader
1047         fileHeader.header.audioMaxSamples
1048             = THPAudioGetMaxFrameSamples(audioHandle[0], num_JPGfiles);
1049 
1050         // update THPAudioInfo
1051         fileHeader.audioInfo.sndNumTracks  = num_WAVfiles;
1052         fileHeader.audioInfo.sndNumSamples = THPAudioGetTotalSamples(audioHandle[0],
1053                                                                      num_JPGfiles);
1054 
1055         // update THPFrameCompInfo
1056         fileHeader.frameCompInfo.frameComp[1] = THP_AUDIO_COMP;
1057         fileHeader.frameCompInfo.numComponents++;
1058     }
1059 
1060     // Open Output File
1061     thpFp = fopen(outFile, "wb");
1062     if (thpFp == NULL)
1063     {
1064         THPPrintError("\aERROR : Can't output [%s].\n", outFile);
1065         THPPrintError("          Please input valid directory & file name.\n");
1066         error = FALSE;
1067         goto ERROR_END;
1068     }
1069 
1070     // convert serial JPGs to THP
1071     rtn = THPUtyCreateTHP(thpFp, THP_CREATETHP_FILEFLAG_JPEGS,
1072                                  (void*)jpegFileList,
1073                                  &fileHeader,
1074                                  audioHandle);
1075     if (rtn != THP_ERROR_NOERROR)
1076     {
1077         printf("\aERROR : Fail to execute THPUtyCreateTHP().\n");
1078         error = FALSE;
1079         goto ERROR_END;
1080     }
1081 
1082 ERROR_END:
1083 
1084     if (audioHandle)
1085     {
1086         THPAudioQuit();
1087         for (cnt = 0; cnt < num_WAVfiles; cnt++)
1088         {
1089             if (audioHandle[cnt] != NULL)
1090             {
1091                 THPAudioFreeHandle(audioHandle[cnt]);
1092             }
1093         }
1094         free(audioHandle);
1095     }
1096 
1097     if (jpegFileList != NULL)
1098     {
1099         free(jpegFileList);
1100     }
1101 
1102     if (thpFp != NULL)
1103     {
1104         fclose(thpFp);
1105     }
1106 
1107     return error;
1108 }
1109 
1110 /*---------------------------------------------------------------------------*
1111   Name:         changeAudioTrack
1112 
1113   Description:  replaces the audio tracks within THP file
1114 
1115   Arguments:    fileHeader  a pointer the THP file header
1116 
1117   Returns:      TRUE   Ended successfully
1118                 FALSE       ended in an error
1119  *---------------------------------------------------------------------------*/
changeAudioTrack(THPFileHeader * fileHeader)1120 static s32 changeAudioTrack(THPFileHeader* fileHeader)
1121 {
1122     s32              rtn;
1123     s32              error = TRUE;
1124     u32              cnt;
1125     u32              adjustFrequency;
1126     char             tmpFilename[_MAX_PATH];
1127     char*            fileName = NULL;
1128     FILE*            outTHPFp = NULL;
1129     FILE*            inTHPFp = NULL;
1130     THPAudioHandle** audioHandle = NULL;
1131     THPAudioInfo     audioInfo;
1132 
1133     // checks whether the THP file has an audio track
1134     for (cnt = 0; cnt < fileHeader->frameCompInfo.numComponents; cnt++)
1135     {
1136         if (fileHeader->frameCompInfo.frameComp[cnt] == THP_AUDIO_COMP)
1137         {
1138             break;
1139         }
1140     }
1141 
1142     if (cnt >= fileHeader->frameCompInfo.numComponents)
1143     {
1144         printf("\aERROR : [%s] doesn't have a Sound Data!\n", inFile);
1145         error = FALSE;
1146         goto ERROR_END;
1147     }
1148 
1149     // checks the THP file's number of channels and playback frequency
1150     if (fileHeader->audioInfo.sndChannels == 0 || fileHeader->audioInfo.sndFrequency == 0)
1151     {
1152         printf("\aERROR : [%s] doesn't have a Sound Data!\n", inFile);
1153         error = FALSE;
1154         goto ERROR_END;
1155     }
1156 
1157     // checks the number of THP file tracks
1158     if (trackNo >= fileHeader->audioInfo.sndNumTracks)
1159     {
1160         printf("\aERROR : Must input [u8 track No.] < %d.\n",
1161                fileHeader->audioInfo.sndNumTracks);
1162         error = FALSE;
1163         goto ERROR_END;
1164     }
1165 
1166     if (Convert_Verbose)
1167     {
1168         printf("START: Audio Initializing.\n");
1169     }
1170 
1171     // set THPAudioHandle
1172     audioHandle = (THPAudioHandle**)malloc(sizeof(THPAudioHandle*)
1173                                            * fileHeader->audioInfo.sndNumTracks);
1174     if (audioHandle == NULL)
1175     {
1176         printf("\aERROR : Can't alloc memory.\n");
1177         error = FALSE;
1178         goto ERROR_END;
1179     }
1180 
1181     for (cnt = 0; cnt < fileHeader->audioInfo.sndNumTracks; cnt++)
1182     {
1183         audioHandle[cnt] = NULL;
1184     }
1185 
1186     THPUtyConvertToUnixFmt(waveFilesPtr[0]);
1187 
1188     audioHandle[trackNo] = THPAudioCreateHandle(waveFilesPtr[0],
1189                                                 fileHeader->header.frameRate);
1190     if (audioHandle[trackNo] == NULL)
1191     {
1192         printf("\aERROR : Fail to execute THPAudioCreateHandle().\n");
1193         error = FALSE;
1194         goto ERROR_END;
1195     }
1196 
1197     // get additional audio data information
1198     rtn = THPAudioGetInfo(audioHandle[trackNo], &audioInfo);
1199     if (rtn == FALSE)
1200     {
1201         printf("\aERROR : Fail to execute THPAudioGetInfo().\n");
1202         error = FALSE;
1203         goto ERROR_END;
1204     }
1205 
1206     // check the number of channels
1207     if (fileHeader->audioInfo.sndChannels != audioInfo.sndChannels )
1208     {
1209         printf("\aERROR : Channels of [%s] is %d (!= %d).\n",
1210                waveFilesPtr[0],
1211                audioInfo.sndChannels,
1212                fileHeader->audioInfo.sndChannels);
1213         error = FALSE;
1214         goto ERROR_END;
1215     }
1216 
1217     // check the playback frequency
1218     if (fileHeader->audioInfo.sndFrequency == audioInfo.sndFrequency)
1219     {
1220         // resample when the found playback frequency is the same
1221         audioHandle[trackNo]->resampleFlag = 1;
1222     }
1223     else
1224     {
1225         // also consider when resampling_on_GC = 1
1226 
1227         adjustFrequency
1228             = (u32)((1124.0/1125.0) * (f64)audioInfo.sndFrequency + 0.5);
1229         if (adjustFrequency == fileHeader->audioInfo.sndFrequency)
1230         {
1231             // do not resample when the adjusted playback frequency is the same
1232             audioHandle[trackNo]->resampleFlag = 0;
1233         }
1234         else
1235         {
1236             printf("\aERROR : Frequency of [%s] is %d (!= %d).\n",
1237                    waveFilesPtr[0],
1238                    audioInfo.sndFrequency,
1239                    fileHeader->audioInfo.sndFrequency);
1240             error = FALSE;
1241             goto ERROR_END;
1242         }
1243     }
1244 
1245     if (Convert_Verbose)
1246     {
1247         printf("    [AudioData]:(%2ld Tracks)\n", fileHeader->audioInfo.sndNumTracks);
1248         printf("     >> Channels  = %ld\n", fileHeader->audioInfo.sndChannels);
1249         printf("     >> Frequency = %ld\n", fileHeader->audioInfo.sndFrequency);
1250         printf("    <+> Track%02d <= [%s]\n", trackNo, waveFilesPtr[0]);
1251 
1252         printf("END  : Audio Initializing.\n");
1253     }
1254 
1255     // open the input THP file
1256     inTHPFp = fopen(inFile, "rb");
1257     if (inTHPFp == NULL)
1258     {
1259         printf("\aERROR : Can't open [%s].\n", inFile);
1260         error = FALSE;
1261         goto ERROR_END;
1262     }
1263 
1264     // open the output THP file
1265     if (outFile != NULL)
1266     {
1267         fileName = outFile;
1268     }
1269     else
1270     {
1271         char drive[_MAX_DRIVE];
1272         char dir[_MAX_DIR];
1273         _splitpath(inFile, drive, dir, NULL, NULL);
1274         _makepath(tmpFilename, drive, dir, TMP_FILENAME, NULL);
1275         fileName = tmpFilename;
1276     }
1277 
1278     outTHPFp = fopen(fileName, "w+b");
1279     if (outTHPFp == NULL)
1280     {
1281         printf("\aERROR : Can't open [%s].\n", fileName);
1282         error = FALSE;
1283         goto ERROR_END;
1284     }
1285 
1286     // copy the input THP file to the output THP file
1287     rtn = THPUtyCopyTHPFile(inTHPFp, fileHeader, outTHPFp);
1288     if (rtn != THP_ERROR_NOERROR)
1289     {
1290         printf("\aERROR : Fail to execute THPUtyCopyTHPFile().\n");
1291         error = FALSE;
1292         goto ERROR_END;
1293     }
1294 
1295     rtn = fseek(outTHPFp, 0, SEEK_SET);
1296     if (rtn != 0)
1297     {
1298         THPPrintError("\aERROR : Can't rewind output THP file.\n");
1299         error = FALSE;
1300         goto ERROR_END;
1301     }
1302 
1303     // exchange the audio track
1304     rtn = THPUtyChangeAudioTrack(outTHPFp, fileHeader, audioHandle);
1305     if (rtn != THP_ERROR_NOERROR)
1306     {
1307         printf("\aERROR : Fail to execute THPUtyChangeAudioTrack().\n");
1308         error = FALSE;
1309         goto ERROR_END;
1310     }
1311 
1312 ERROR_END:
1313 
1314     if (audioHandle)
1315     {
1316         for (cnt = 0; cnt < fileHeader->audioInfo.sndNumTracks; cnt++)
1317         {
1318             if (audioHandle[cnt] != NULL)
1319             {
1320                 THPAudioFreeHandle(audioHandle[cnt]);
1321             }
1322         }
1323         free(audioHandle);
1324     }
1325 
1326     if (inTHPFp != NULL)
1327     {
1328         fclose(inTHPFp);
1329     }
1330 
1331     if (outTHPFp != NULL)
1332     {
1333         fclose(outTHPFp);
1334     }
1335 
1336     // temporarily rename the file during an overwrite
1337     if (outFile == NULL)
1338     {
1339         if (error == TRUE)
1340         {
1341             if (remove(inFile) == -1)
1342             {
1343                 printf("\aERROR : Can't remove old THP file[%s].\n", inFile);
1344             }
1345 
1346             if (rename(fileName, inFile))
1347             {
1348                 printf("\aERROR : Can't rename THP file[%s -> %s].\n", fileName, inFile);
1349             }
1350         }
1351         else
1352         {
1353             if (fileName)
1354             {
1355                 if (remove(fileName) == -1)
1356                 {
1357                     printf("\aERROR : Can't remove temporary THP file[%s].\n", fileName);
1358                 }
1359             }
1360         }
1361     }
1362 
1363     return error;
1364 }
1365 
1366 /*---------------------------------------------------------------------------*
1367   Name:         appendAudioData
1368 
1369   Description:  Adds audio data when none exists.
1370                 If it does exist, replace it.
1371                 (with the -s option)
1372 
1373   Arguments:    fileHeader  a pointer to the file header
1374 
1375   Returns:      TRUE   Ended successfully
1376                 FALSE       ended in an error
1377  *---------------------------------------------------------------------------*/
appendAudioData(THPFileHeader * fileHeader)1378 static s32 appendAudioData(THPFileHeader* fileHeader)
1379 {
1380     s32              rtn;
1381     s32              error = TRUE;
1382     u32              cnt;
1383     char             tmpFilename[_MAX_PATH];
1384     char*            fileName = NULL;
1385     FILE*            outTHPFp = NULL;
1386     FILE*            inTHPFp = NULL;
1387     THPAudioHandle** audioHandle = NULL;
1388 
1389     // open the input THP file
1390     inTHPFp = fopen(inFile, "rb");
1391     if (inTHPFp == NULL)
1392     {
1393         printf("\aERROR : Can't open [%s].\n", inFile);
1394         error = FALSE;
1395         goto ERROR_END;
1396     }
1397 
1398     // open the output THP file
1399     if (outFile != NULL)
1400     {
1401         fileName = outFile;
1402     }
1403     else
1404     {
1405         char drive[_MAX_DRIVE];
1406         char dir[_MAX_DIR];
1407         _splitpath(inFile, drive, dir, NULL, NULL);
1408         _makepath(tmpFilename, drive, dir, TMP_FILENAME, NULL);
1409         fileName = tmpFilename;
1410     }
1411 
1412     outTHPFp = fopen(fileName, "wb");
1413     if (outTHPFp == NULL)
1414     {
1415         printf("\aERROR : Can't open [%s].\n", fileName);
1416         error = FALSE;
1417         goto ERROR_END;
1418     }
1419 
1420     if (Convert_Verbose)
1421     {
1422         printf("START: Audio Initializing.\n");
1423     }
1424 
1425     // update THPAudioInfo (number of tracks: sndNumTracks)
1426     fileHeader->audioInfo.sndNumTracks = num_WAVfiles;
1427 
1428     audioHandle = (THPAudioHandle**)malloc(sizeof(THPAudioHandle*) * num_WAVfiles);
1429     if (audioHandle == NULL)
1430     {
1431         printf("\aERROR : Can't alloc memory.\n");
1432         error = FALSE;
1433         goto ERROR_END;
1434     }
1435 
1436     // create the WAV file list
1437     for (cnt = 0; cnt < num_WAVfiles; cnt++)
1438     {
1439         THPUtyConvertToUnixFmt(waveFilesPtr[cnt]);
1440 
1441         audioHandle[cnt] = THPAudioCreateHandle(waveFilesPtr[cnt],
1442                                                 fileHeader->header.frameRate);
1443         if (audioHandle[cnt] == NULL)
1444         {
1445             printf("\aERROR : Fail to execute THPAudioCreateHandle().\n");
1446             error = FALSE;
1447             goto ERROR_END;
1448         }
1449 
1450         // permission settings (common to all audio data) for resampling when creating THP data
1451         audioHandle[cnt]->resampleFlag = resample_on_GC ^ 1;
1452     }
1453 
1454     if (Convert_Verbose)
1455     {
1456         if (resample_on_GC)
1457         {
1458             printf("    Disable audio resampling.\n");
1459         }
1460         else
1461         {
1462             printf("    Enable audio resampling.\n");
1463         }
1464     }
1465 
1466     // Main Sound
1467     rtn = THPAudioGetInfo(audioHandle[0], &fileHeader->audioInfo);
1468     if (rtn == FALSE)
1469     {
1470         printf("\aERROR : Fail to execute THPAudioGetInfo().\n");
1471         error = FALSE;
1472         goto ERROR_END;
1473     }
1474 
1475     if (Convert_Verbose)
1476     {
1477         printf("    [AudioData]:(%2ld Tracks)\n", num_WAVfiles);
1478         printf("     >> Channels  = %ld\n", fileHeader->audioInfo.sndChannels);
1479         printf("     >> Frequency = %ld\n", fileHeader->audioInfo.sndFrequency);
1480         printf("    <+> Track%02d <= [%s]\n", 0, waveFilesPtr[0]);
1481     }
1482 
1483     if (resample_on_GC)
1484     {
1485         fileHeader->audioInfo.sndFrequency
1486             = (u32)((1124.0/1125.0) * (f64)audioHandle[0]->audioInfo.frequency + 0.5);
1487         if (Convert_Verbose)
1488         {
1489             printf("    Adjust Frequency %d -> %d\n", audioHandle[0]->audioInfo.frequency,
1490                                                       fileHeader->audioInfo.sndFrequency);
1491         }
1492     }
1493 
1494     // Sub Sound
1495     for (cnt = 1; cnt < num_WAVfiles; cnt++)
1496     {
1497         THPAudioInfo subAudioInfo;
1498 
1499         rtn = THPAudioGetInfo(audioHandle[cnt], &subAudioInfo);
1500         if (rtn == FALSE)
1501         {
1502             printf("\aERROR : Fail to execute THPAudioGetInfo().\n");
1503             error = FALSE;
1504             goto ERROR_END;
1505         }
1506 
1507         // checks the number of channels in a WAV file
1508         if (audioHandle[0]->audioInfo.channel != subAudioInfo.sndChannels)
1509         {
1510             printf("\aERROR : Channels of [%s] is %d (!= %d).\n",
1511                    waveFilesPtr[cnt],
1512                    subAudioInfo.sndChannels,
1513                    audioHandle[0]->audioInfo.channel);
1514             error = FALSE;
1515             goto ERROR_END;
1516         }
1517 
1518         // checks the playback frequency in a WAV file
1519         if (audioHandle[0]->audioInfo.frequency != subAudioInfo.sndFrequency)
1520         {
1521             printf("\aERROR : Frequency of [%s] is %d (!= %d).\n",
1522                    waveFilesPtr[cnt],
1523                    subAudioInfo.sndFrequency,
1524                    audioHandle[0]->audioInfo.frequency);
1525             error = FALSE;
1526             goto ERROR_END;
1527         }
1528 
1529         if (Convert_Verbose)
1530         {
1531             printf("    <+> Track%02d <= [%s]\n", cnt, waveFilesPtr[cnt]);
1532         }
1533     }
1534 
1535     if (Convert_Verbose)
1536     {
1537         printf("END  : Audio Initializing.\n");
1538     }
1539 
1540     // update THPHeader
1541     fileHeader->header.audioMaxSamples
1542         = THPAudioGetMaxFrameSamples(audioHandle[0], fileHeader->header.numFrames);
1543 
1544     // update THPAudioInfo
1545     fileHeader->audioInfo.sndNumTracks = num_WAVfiles;
1546     fileHeader->audioInfo.sndNumSamples
1547         = THPAudioGetTotalSamples(audioHandle[0], fileHeader->header.numFrames);
1548 
1549     // update THPFrameCompInfo
1550     if (fileHeader->frameCompInfo.frameComp[1] == THP_NOCOMP_COMP)
1551     {
1552         fileHeader->frameCompInfo.numComponents++;
1553         fileHeader->frameCompInfo.frameComp[1] = THP_AUDIO_COMP;
1554     }
1555 
1556     // add/exchange audio data in THP data
1557     rtn = THPUtyCreateTHP(outTHPFp, THP_CREATETHP_FILEFLAG_THP,
1558                                     (void*)inTHPFp,
1559                                     fileHeader,
1560                                     audioHandle);
1561     if (rtn != THP_ERROR_NOERROR)
1562     {
1563         printf("\aERROR : Fail to execute THPUtyCreateTHP().\n");
1564         error = FALSE;
1565         goto ERROR_END;
1566     }
1567 
1568 ERROR_END:
1569 
1570     if (audioHandle)
1571     {
1572         for (cnt = 0; cnt < num_WAVfiles; cnt++)
1573         {
1574             if (audioHandle[cnt] != NULL)
1575             {
1576                 THPAudioFreeHandle(audioHandle[cnt]);
1577             }
1578         }
1579         free(audioHandle);
1580     }
1581 
1582     if (inTHPFp != NULL)
1583     {
1584         fclose(inTHPFp);
1585     }
1586 
1587     if (outTHPFp != NULL)
1588     {
1589         fclose(outTHPFp);
1590     }
1591 
1592     // temporarily rename the file during an overwrite
1593     if (outFile == NULL)
1594     {
1595         if (error == TRUE)
1596         {
1597             if (remove(inFile) == -1)
1598             {
1599                 printf("\aERROR : Can't remove old THP file[%s].\n", inFile);
1600             }
1601 
1602             if (rename(fileName, inFile))
1603             {
1604                 printf("\aERROR : Can't rename THP file[%s -> %s].\n", fileName, inFile);
1605             }
1606         }
1607         else
1608         {
1609             if (fileName)
1610             {
1611                 if (remove(fileName) == -1)
1612                 {
1613                     printf("\aERROR : Can't remove temporary THP file[%s].\n", fileName);
1614                 }
1615             }
1616         }
1617     }
1618 
1619     return error;
1620 }
1621 
1622 /*---------------------------------------------------------------------------*
1623   Name:         changeAudioData
1624 
1625   Description:  add or replace audio data
1626 
1627   Arguments:    None.
1628 
1629   Returns:      TRUE   Ended successfully
1630                 FALSE       ended in an error
1631  *---------------------------------------------------------------------------*/
changeAudioData(void)1632 static s32 changeAudioData(void)
1633 {
1634     THPFileHeader fileHeader;
1635     FILE*         inTHPFp = NULL;
1636     s32           rtn;
1637     s32           error = TRUE;
1638 
1639     if (THPAudioInit() == FALSE)
1640     {
1641         printf("\aERROR : Fail to execute THPAudioInit().\n");
1642         error = FALSE;
1643         goto ERROR_END;
1644     }
1645 
1646     // open the input THP file
1647     inTHPFp = fopen(inFile, "rb");
1648     if (inTHPFp == NULL)
1649     {
1650         printf("\aERROR : Can't open [%s].\n", inFile);
1651         error = FALSE;
1652         goto ERROR_END;
1653     }
1654 
1655     // read the input THP file's THPFileHeader
1656     rtn = THPUtyReadTHPFileHeader(inTHPFp, &fileHeader);
1657     if (rtn != THP_ERROR_NOERROR)
1658     {
1659         printf("\aERROR : Can't read THPHeader of [%s].\n", inFile);
1660         fclose(inTHPFp);
1661         error = FALSE;
1662         goto ERROR_END;
1663     }
1664 
1665     fclose(inTHPFp);
1666 
1667     // add or replace audio data
1668     if (change_onetrack)
1669     {
1670         // when replacing audio data for a specific track (-trk)
1671 
1672         if (Convert_Verbose)
1673         {
1674             printf("Replace audio data of one track.\n");
1675         }
1676 
1677         // -o/-r/-non/-odd/-even are ignored
1678 
1679         error = changeAudioTrack(&fileHeader);
1680 
1681     }
1682     else
1683     {
1684         // when replacing audio data for all tracks (-s)
1685 
1686         if (Convert_Verbose)
1687         {
1688             printf("Append/Replace audio data of all tracks.\n");
1689         }
1690 
1691         // frame rate update (-r)
1692         if (change_framerate)
1693         {
1694             fileHeader.header.frameRate = frame_rate;
1695         }
1696 
1697         // update existence of offset table (-o)
1698         if (offset_mode)
1699         {
1700             fileHeader.header.offsetDataOffsets = offset_mode;
1701         }
1702 
1703         // update the specification of the display start field (-non/odd/even)
1704         if (change_videotype)
1705         {
1706             fileHeader.videoInfo.videoType = videotype;
1707         }
1708 
1709         error = appendAudioData(&fileHeader);
1710     }
1711 
1712 ERROR_END:
1713 
1714     THPAudioQuit();
1715 
1716     return error;
1717 }
1718 
1719 /*---------------------------------------------------------------------------*
1720   Name:         logPrintFunc
1721 
1722   Description:  outputs messages, logs and errors
1723 
1724   Arguments:    ...
1725 
1726   Returns:      None.
1727  *---------------------------------------------------------------------------*/
logPrintFunc(const char * format,va_list argptr)1728 static void logPrintFunc(const char* format, va_list argptr)
1729 {
1730     vfprintf(stdout, format, argptr);
1731 }
1732 
1733 /*---------------------------------------------------------------------------*
1734   Name:         main
1735 
1736   Description:  THPConv main
1737 
1738   Arguments:    (references Usage())
1739 
1740   Returns:      0  ended normally
1741                 1           ends in an error
1742  *---------------------------------------------------------------------------*/
main(int argc,char * argv[])1743 int main(int argc, char *argv[])
1744 {
1745     s32  error = 0;
1746 
1747     // hooks the function for output of messages by the THP Library
1748     THPPrintFunc      = logPrintFunc;
1749     THPPrintLogFunc   = logPrintFunc;
1750     THPPrintErrorFunc = logPrintFunc;
1751 
1752     // argument checker
1753     error = checkArguments(argc, argv);
1754 
1755     // sets the verbose mode flag for the THP Library
1756     THPVerboseFlag = Convert_Verbose;
1757 
1758     if (Convert_Verbose)
1759     {
1760         printf("Dolphin Jpegs to THP converter. Copyright 2002-2003 Nintendo.\n");
1761         printf("Built : %s %s\n\n", __DATE__, __TIME__);
1762     }
1763 
1764     if ((error == FALSE) || (argc == 1))
1765     {
1766         exit(1);
1767     }
1768 
1769     printf("THP file Version is %X.%X\n", THP_VERSION >> 16, THP_VERSION & 0xFFFF);
1770 
1771     // create THP
1772     if (pack_jpegs)
1773     {
1774         // converting from JPG to THP (-j)
1775 
1776         if (Convert_Verbose)
1777         {
1778             printf("Convert from JPEGs to THP...\n");
1779         }
1780 
1781         error = convertJPEGtoTHP();
1782     }
1783 
1784     else if (change_snd_data)
1785     {
1786         // adding/replacing audio data in existing THP (-c)
1787 
1788         if (Convert_Verbose)
1789         {
1790             printf("Append/Replace audio data...\n");
1791         }
1792 
1793         // overwrite confirmation
1794         if (outFile == NULL)
1795         {
1796             if (verifyWriteOverInputData(inFile) == FALSE)
1797             {
1798                 exit(0);
1799             }
1800         }
1801 
1802         error = changeAudioData();
1803     }
1804 
1805     if (error == FALSE)
1806     {
1807         printf("WARNING : Errors occurred while converting to THP.\n");
1808         printf("          Please check for error messages above!\n");
1809 
1810         exit(1);
1811     }
1812     else
1813     {
1814         if (outFile)
1815         {
1816             printf("Successfully generated [%s].\n", outFile);
1817         }
1818         else
1819         {
1820             printf("Successfully overwrote [%s].\n", inFile);
1821         }
1822     }
1823 
1824     exit(0);
1825 }
1826