1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - tools - buryarg.TWL
3   File:     buryarg.c
4 
5   Copyright 2008-2009 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   $Date:: 2009-06-17#$
14   $Rev: 10762 $
15   $Author: mizutani_nakaba $
16  *---------------------------------------------------------------------------*/
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <sys/fcntl.h>
22 #include <sys/stat.h>
23 #include <getopt.h>
24 
25 #include <nitro_win32.h>
26 
27 //---- Error code
28 #define ERROR_OVER_AREA  		                0
29 #define ERROR_NO_FILE     		                1
30 #define ERROR_CANNOT_OPEN_FILE                  2
31 #define ERROR_CANNOT_OPEN_REP_FILE              3
32 #define ERROR_MARK_NOT_FOUND	                4
33 #define ERROR_BAD_MARK_POSITION	                5
34 #define ERROR_BAD_ARGUMENT_SIZE                 6
35 #define ERROR_UNKNOWN_OPTION                    7
36 #define ERROR_OUTFILE_NOT_SPECIFIED             8
37 #define ERROR_REPLACEMENTFILE_NOT_SPECIFIED   	9
38 #define ERROR_REPLACEMENTFILE_TOO_BIG           10
39 #define ERROR_ILLEGAL_OPTIONS                   11
40 #define ERROR_FILE_ERROR                        12
41 #define ERROR_NLF_FILE_SPECIFIED                13
42 #define ERROR_NOT_TWL_SRL                       14
43 #define ERROR_ILLEGAL_TLF_FILE					15
44 
45 //---- Version
46 #define VERSION_STRING     " 1.2  Copyright 2008 Nintendo. All right reserved."
47 // Version 1.2: Changed argument data position to same position as buryarg
48 // Version 1.1: Fixed bug on --stdout option
49 // Version 1.0: Applied for TWL
50 
51 //---- Output default added string
52 #define ADDED_OUTPUT_NAME  ".argAdded"
53 
54 //---- Output for stdout
55 const char gNameForStdout[] = "-";
56 
57 //---- Argument buffer identification string
58 const char gArgIdString[] = OS_ARGUMENT_ID_STRING;
59 
60 //---- Input bin file
61 #define FILE_NAME_MAX_SIZE  1024
62 FILE   *gInputFile;
63 char    gInputFileNameString[FILE_NAME_MAX_SIZE];
64 BOOL    gIsInputFileOpened = FALSE;
65 
66 //---- Output file
67 FILE   *gOutputFile;
68 char    gOutputFileNameString[FILE_NAME_MAX_SIZE];
69 char   *gOutputFileName = NULL;
70 BOOL    gIsOutputFileOpened = FALSE;
71 
72 //---- Replacement file
73 FILE   *gReplacementFile;
74 char   *gReplacementFileName = NULL;
75 BOOL    gIsReplacementFileOpened = FALSE;
76 
77 //---- TLF file
78 FILE   *gTlfFile;
79 char   *gTlfFileName = NULL;
80 BOOL    gIsTlfFileOpened = FALSE;
81 char    gTlfDirectoryNameString[FILE_NAME_MAX_SIZE];
82 
83 //---- Argument buffer for replacement
84 #define ARGUMENT_BUF_SIZE 0x10000
85 char    gArgString[ARGUMENT_BUF_SIZE];
86 int     gArgStringSize;
87 int     gArgStringIndex = 0;
88 
89 //---- Mode
90 BOOL    gQuietMode = FALSE;
91 BOOL    gVerboseMode = FALSE;
92 BOOL    gReplacementMode = TRUE;
93 BOOL    gDebugMode = FALSE;
94 BOOL    gTlfInputMode = FALSE;
95 BOOL    gStdoutMode = FALSE;
96 
97 //---- Declaration of prototype
98 void    analyzeTlfFile(void);
99 void    closeFiles(void);
100 
101 //================================================================================
102 //                      Message display
103 //================================================================================
104 /*---------------------------------------------------------------------------*
105   Name:         displayMessage
106 
107   Description:  Displays message.
108 
109   Arguments:    message: Message array
110 
111   Returns:      None.
112  *---------------------------------------------------------------------------*/
displayMessage(char * message[])113 void displayMessage(char *message[])
114 {
115     int     n;
116     //---- Show help messages
117     for (n = 0; message[n]; n++)
118     {
119         printf(message[n]);
120     }
121 }
122 
123 
124 /*---------------------------------------------------------------------------*
125   Name:         displayUsage
126 
127   Description:  Displays how to use.
128 
129   Arguments:    None.
130 
131   Returns:      None.
132  *---------------------------------------------------------------------------*/
displayUsage(void)133 void displayUsage(void)
134 {
135     char   *usageString[] = {
136         "Usage: buryarg.TWL [OPTION]... <TWL srl filename> [argument]...\n",
137         "Bury argument strings to TWL srl file.",
138         "\n",
139         "Options:\n",
140         "  --version           : Show version.\n",
141         "  -h, --help          : Show this help.\n",
142         "  -q, --quiet         : Quiet mode.\n",
143         "  -v, --verbose       : Verbose mode.\n",
144         "  -r, --remain        : Remain original file.\n",
145         "  -o, --output=FILE   : Output file (default: srcfile.argAdded)\n",
146         "                        if \"-\" is specified, output to stdout.\n",
147         "      --stdout        : Mean '-o-' .\n",
148         "  -f, --file=FILE     : Specify replacement buffer data.\n",
149         "                        This is used instead of data from arguments.\n",
150         "  -d, --debug         : Debug mode. Show replacement buffer.\n",
151         0
152     };
153 
154     displayMessage(usageString);
155 }
156 
157 /*---------------------------------------------------------------------------*
158   Name:         displayVersion
159 
160   Description:  Displays version.
161 
162   Arguments:    None.
163 
164   Returns:      None.
165  *---------------------------------------------------------------------------*/
displayVersion(void)166 void displayVersion(void)
167 {
168     printf("buryarg %s\n", VERSION_STRING);
169 }
170 
171 /*---------------------------------------------------------------------------*
172   Name:         displayError
173 
174   Description:  Displays error
175 
176   Arguments:    errorNumber: Error number
177 
178   Returns:      None.
179  *---------------------------------------------------------------------------*/
displayError(int errorNumber)180 void displayError(int errorNumber)
181 {
182     fprintf(stderr, "Error: buryarg: ");
183 
184     switch (errorNumber)
185     {
186     case ERROR_OVER_AREA:
187         fprintf(stderr, "arguments too long.\n");
188         break;
189 
190     case ERROR_NO_FILE:
191         fprintf(stderr, "cannot open binary file.\n");
192         break;
193 
194     case ERROR_CANNOT_OPEN_FILE:
195         fprintf(stderr, "cannot open output file.\n");
196         break;
197 
198     case ERROR_CANNOT_OPEN_REP_FILE:
199         fprintf(stderr, "cannot open replacement file.\n");
200         break;
201 
202     case ERROR_MARK_NOT_FOUND:
203         fprintf(stderr, "cannot replace because bin file has no argument id string.\n");
204         break;
205 
206     case ERROR_BAD_MARK_POSITION:
207         fprintf(stderr, "bad argument mark position.\n");
208         break;
209 
210     case ERROR_BAD_ARGUMENT_SIZE:
211         fprintf(stderr, "bad argument size.\n");
212         break;
213 
214     case ERROR_UNKNOWN_OPTION:
215         fprintf(stderr, "unknown option or invalid usage. try --help.\n");
216         break;
217 
218     case ERROR_OUTFILE_NOT_SPECIFIED:
219         fprintf(stderr, "output file is not specified.\n");
220         break;
221 
222     case ERROR_REPLACEMENTFILE_NOT_SPECIFIED:
223         fprintf(stderr, "replacement file is not specified.\n");
224         break;
225 
226     case ERROR_REPLACEMENTFILE_TOO_BIG:
227         fprintf(stderr, "replacement file is too big.\n");
228         break;
229 
230     case ERROR_ILLEGAL_OPTIONS:
231         fprintf(stderr, "specified illegal option set.\n");
232         break;
233 
234     case ERROR_FILE_ERROR:
235         fprintf(stderr, "error occurred in renaming file.\n");
236         break;
237 
238 	case ERROR_NLF_FILE_SPECIFIED:
239 		fprintf(stderr, "cannot access to nlf file.\n");
240 		break;
241 
242 	case ERROR_NOT_TWL_SRL:
243         fprintf(stderr, "ROM is not for TWL.\n");
244         break;
245 
246     case ERROR_ILLEGAL_TLF_FILE:
247         fprintf(stderr, "illegal tlf file.\n");
248         break;
249 
250     default:
251         fprintf(stderr, "unknown error (%d).\n", errorNumber);
252         break;
253     }
254 
255     closeFiles();
256     exit(2);
257 }
258 
259 
260 //================================================================================
261 //                      Display for debug
262 //================================================================================
263 //---- For debug
264 //     Display buffer
displayBuffer(void)265 void displayBuffer(void)
266 {
267     const int showSize = 256;
268     int     n;
269 
270     for (n = 0; n < showSize; n++)
271     {
272         int     k = n % 16;
273         int     c;
274 
275         if (k == 0)
276         {
277             printf("%4x ", n);
278         }
279 
280         c = (int)gArgString[n];
281 
282         if (0x20 <= c && c <= 0x7f)
283         {
284             printf("%c  ", gArgString[n]);
285         }
286         else if (c == 0)
287         {
288             printf(".  ");
289         }
290         else
291         {
292             printf("-  ");
293         }
294 
295         if (k == 15)
296         {
297             printf("\n");
298         }
299     }
300 }
301 
302 
303 //================================================================================
304 //              Parse filename
305 //================================================================================
306 /*---------------------------------------------------------------------------*
307   Name:         getTailFileName
308 
309   Description:  Searches for tail pointer of filename.
310                 Example: If d:/aaa/bbb.srl was input, outputs bbb.srl.
311 
312   Arguments:    fileName: Filename
313 
314   Returns:      Tail pointer of original string.
315  *---------------------------------------------------------------------------*/
getTailFileName(const char * fileName)316 const char *getTailFileName(const char *fileName)
317 {
318     const char *p = fileName;
319     const char *tailPtr = p;
320 
321     while (*p)
322     {
323         if (*p == '\\' || *p == '/' || *p == ':')
324         {
325             tailPtr = (p + 1);
326         }
327 
328         p++;
329     }
330 
331     return tailPtr;
332 }
333 
334 //================================================================================
335 //              Option parse and buffer creation
336 //================================================================================
337 /*---------------------------------------------------------------------------*
338   Name:         checkOverBuffer
339 
340   Description:  Checks if buffer is over.
341 				(If error occurred, never return.)
342 
343   Arguments:    None.
344 
345   Returns:      None.
346  *---------------------------------------------------------------------------*/
checkOverBuffer(void)347 void checkOverBuffer(void)
348 {
349     if (gArgStringIndex >= ARGUMENT_BUF_SIZE)
350     {
351         displayError(ERROR_OVER_AREA);
352     }
353 }
354 
355 /*---------------------------------------------------------------------------*
356   Name:         addString
357 
358   Description:  Adds string to TWL argument string area.
359 
360   Arguments:    str: String to add
361 
362   Returns:      None.
363  *---------------------------------------------------------------------------*/
addString(const char * str)364 void addString(const char *str)
365 {
366     const char *p = str;
367 
368     if (!str)
369     {
370         printf("internal error: tend to add NULL string.\n");
371         exit(2);
372     }
373 
374     while (*p)
375     {
376         checkOverBuffer();
377         gArgString[gArgStringIndex++] = *p++;
378     }
379 
380     checkOverBuffer();
381     gArgString[gArgStringIndex++] = '\0';
382 }
383 
384 /*---------------------------------------------------------------------------*
385   Name:         checkTwlHeader
386 
387   Description:  Checks if the specified ROM is for TWL.
388 
389   Arguments:    None.
390 
391   Returns:      None.
392  *---------------------------------------------------------------------------*/
393 #define ROM_TYPE_OFS 12
checkTwlHeader(void)394 void checkTwlHeader(void)
395 {
396 	const int readSize=32;
397    	char romHeader[readSize];
398 	int  romType;
399 
400     fseek(gTlfFile, 0, SEEK_SET);
401 	size_t  size = fread(romHeader, 1, readSize, gTlfFile);
402 
403 	romType = (int)romHeader[ ROM_TYPE_OFS ];
404 
405 	if (size != readSize || !(romType & 0x2) )
406 	{
407         displayError(ERROR_NOT_TWL_SRL);
408 	}
409 }
410 
411 /*---------------------------------------------------------------------------*
412   Name:         parseOption
413 
414   Description:  Parses the option line.
415 
416   Arguments:    argc: Argument count
417                 argv: Argument vector
418 
419   Returns:      Result. Less than 0 if error.
420  *---------------------------------------------------------------------------*/
parseOption(int argc,char * argv[])421 void parseOption(int argc, char *argv[])
422 {
423     int     n;
424     BOOL    helpFlag = FALSE;
425 
426     int     c;
427 
428     struct option optionInfo[] = {
429         {"help", no_argument, NULL, 'h'},
430         {"quiet", no_argument, NULL, 'q'},
431         {"verbose", no_argument, NULL, 'v'},
432         {"replacement", no_argument, NULL, 'r'},
433         {"version", no_argument, NULL, 'a'},
434         {"debug", no_argument, NULL, 'd'},
435         {"output", required_argument, 0, 'o'},
436         {"stdout", no_argument, NULL, 'O'},
437         {"file", required_argument, 0, 'f'},
438         {NULL, 0, 0, 0}
439     };
440     int     optionIndex;
441 
442     //---- Suppress error string of getopt_long()
443     opterr = 0;
444 
445     while (1)
446     {
447         c = getopt_long(argc, argv, "+hqvrdo:f:", &optionInfo[0], &optionIndex);
448 
449         //printf("optind=%d optopt=%d  %x(%c) \n", optind, optopt, c,c );
450 
451         if (c == -1)
452         {
453             break;
454         }
455 
456         switch (c)
457         {
458         case 'h':
459             helpFlag = TRUE;
460             break;
461         case 'q':
462             gQuietMode = TRUE;
463             break;
464         case 'v':
465             gVerboseMode = TRUE;
466             break;
467         case 'r':
468             gReplacementMode = FALSE;
469             break;
470         case 'd':
471             gDebugMode = TRUE;
472             break;
473         case 'a':
474             displayVersion();
475             exit(1);
476             break;
477         case 'o':
478             gOutputFileName = (*optarg == '=') ? optarg + 1 : optarg;
479             if (!*gOutputFileName)
480             {
481                 displayError(ERROR_OUTFILE_NOT_SPECIFIED);
482             }
483             gReplacementMode = FALSE;
484             break;
485         case 'O':
486             gOutputFileName = (char *)gNameForStdout;
487             gReplacementMode = FALSE;
488             break;
489         case 'f':
490             gReplacementFileName = (*optarg == '=') ? optarg + 1 : optarg;
491             if (!*gReplacementFileName)
492             {
493                 displayError(ERROR_REPLACEMENTFILE_NOT_SPECIFIED);
494             }
495             break;
496         default:
497             displayError(ERROR_UNKNOWN_OPTION);
498         }
499     }
500 
501     //---- No specified bin file or "-h" of "--help" to display usage
502     if (helpFlag || argc <= optind)
503     {
504         displayUsage();
505         exit(1);
506     }
507 
508     //---- Input filename
509     strncpy(gInputFileNameString, argv[optind], FILE_NAME_MAX_SIZE);
510 
511     //---- Check if TLF file
512     if ((gTlfFile = fopen(gInputFileNameString, "rb")) == NULL)
513     {
514         displayError(ERROR_NO_FILE);
515     }
516     gIsTlfFileOpened = TRUE;
517 
518     //---- Check NLF and TLF ID string
519     {
520         char    idString[4];
521         size_t  size = fread(idString, 1, 4, gTlfFile);
522         if (size == 4 && !strncmp(idString, (char *)"#NLF", 4))
523         {
524 			displayError(ERROR_NLF_FILE_SPECIFIED);
525         }
526 
527 		if (size == 4 && !strncmp(idString, (char *)"#TLF", 4))
528 		{
529             gTlfFileName = argv[optind];
530 
531             //---- Determine input filename
532             analyzeTlfFile();
533 		}
534     }
535 
536 	//---- Check if TWL header
537 	if (gTlfFileName == NULL)
538 	{
539 		checkTwlHeader();
540 	}
541 
542     //---- Close file
543     fclose(gTlfFile);
544     gIsTlfFileOpened = FALSE;
545 
546     //---- Add string to replacement buffer
547     for (n = optind; n < argc; n++)
548     {
549         if (n == optind)
550         {
551             if (!gTlfFileName)
552             {
553                 addString(getTailFileName(argv[n]));
554             }
555         }
556         else
557         {
558             addString(argv[n]);
559         }
560     }
561 
562     //---- End mark
563     checkOverBuffer();
564     gArgString[gArgStringIndex++] = '\0';
565 }
566 
567 //================================================================================
568 //                      File operations
569 //================================================================================
570 /*---------------------------------------------------------------------------*
571   Name:         analyzeTlfFile
572 
573   Description:  Analyzes TLF file.
574 
575   Arguments:    None.
576 
577   Returns:      None.
578  *---------------------------------------------------------------------------*/
analyzeTlfFile(void)579 void analyzeTlfFile(void)
580 {
581     char    lineBuffer[1024];
582     BOOL    isFound_T = FALSE;
583     BOOL    isFound_9 = FALSE;
584 
585     fseek(gTlfFile, 0, SEEK_SET);
586 
587     //---- Analyze
588     while (fgets(lineBuffer, 1024, gTlfFile))
589     {
590         if (!strncmp(lineBuffer, "T,", 2))
591         {
592             char   *sp = &lineBuffer[0];
593             char   *dp = &gTlfDirectoryNameString[0];
594 
595             while (*sp++ != '\"')
596             {
597             }
598             while (*sp != '\"')
599             {
600                 *dp++ = *sp++;
601             }
602             *dp = '\0';
603 
604             isFound_T = TRUE;
605         }
606 
607 		if (!strncmp(lineBuffer, "9,", 2) && isFound_T)
608 		{
609 			char *sp = &lineBuffer[0];
610 			char *dp = &gInputFileNameString[0];
611 			int count=0;
612 
613 			while (*sp && count <=2)
614 			{
615 				if (*sp++ == '\"')
616 				{
617 					count++;
618 				}
619 			}
620 			while (*sp != '\"')
621 			{
622 				*dp++ = *sp++;
623 			}
624 			*dp = '\0';
625 
626 			//---- Set argv[0]
627 			addString(getTailFileName(gInputFileNameString));
628 
629 			isFound_9 = TRUE;
630 		}
631     }
632 
633     //---- Check if found filename
634     if (!isFound_9)
635     {
636         displayError(ERROR_ILLEGAL_TLF_FILE);
637     }
638 }
639 
640 /*---------------------------------------------------------------------------*
641   Name:         openFiles
642 
643   Description:  Opens original file and output file.
644 
645   Arguments:    None.
646 
647   Returns:      None.
648  *---------------------------------------------------------------------------*/
openFiles(void)649 void openFiles(void)
650 {
651     //---- Replacement file
652     if (gReplacementFileName)
653     {
654         if (gVerboseMode)
655         {
656             printf("replacement file    : %s\n", gReplacementFileName);
657         }
658         if ((gReplacementFile = fopen(gReplacementFileName, "rb")) == NULL)
659         {
660             displayError(ERROR_CANNOT_OPEN_REP_FILE);
661         }
662         gIsReplacementFileOpened = TRUE;
663 
664         //---- Replace buffer
665         {
666             int n;
667             int c;
668 
669             if (gVerboseMode)
670             {
671                 struct stat repFileStat;
672                 stat(gReplacementFileName, &repFileStat);
673                 printf("replacement file size is 0x%x byte (%d byte).\n", (int)repFileStat.st_size,
674                        (int)repFileStat.st_size);
675             }
676 
677             //---- Clear buffer
678             for (n = 0; n < ARGUMENT_BUF_SIZE; n++)
679             {
680                 gArgString[n] = 0;
681             }
682 
683             //---- Get replacement strings
684             n = 0;
685             while (n < ARGUMENT_BUF_SIZE && (c = fgetc(gReplacementFile)) != EOF)
686             {
687                 gArgString[n] = c;
688                 n++;
689             }
690             fclose(gReplacementFile);
691             gIsReplacementFileOpened = FALSE;
692 
693             //---- Check over buffer
694             if (c != EOF)
695             {
696                 //displayError( ERROR_REPLACEMENTFILE_TOO_BIG );
697                 if (!gQuietMode)
698                 {
699                     printf("warning: replacement file is bigger than required size.");
700                 }
701             }
702         }
703     }
704 
705     //---- Do not overwrite original file
706     if (!gReplacementMode)
707     {
708         //---- Written filename
709         if (gOutputFileName)
710         {
711             strncpy(gOutputFileNameString, gOutputFileName, FILE_NAME_MAX_SIZE);
712         }
713         else
714         {
715             strcat(gOutputFileNameString, gInputFileNameString);
716             strncat(gOutputFileNameString, ADDED_OUTPUT_NAME, FILE_NAME_MAX_SIZE);
717         }
718 
719         //---- Check if stdout specified
720         if (!strncmp(gOutputFileNameString, "-", 1))
721         {
722             gStdoutMode = TRUE;
723         }
724 
725         //---- Output file
726         if (gVerboseMode)
727         {
728             if (gStdoutMode)
729             {
730                 printf("destination         : stdout\n");
731             }
732             else
733             {
734                 printf("destination bin file: %s\n", gOutputFileNameString);
735             }
736         }
737         if (gStdoutMode)
738         {
739             gOutputFile = stdout;
740 
741             //---- Set stdout to binary mode
742             _setmode(_fileno(gOutputFile), O_BINARY);
743         }
744         else
745         {
746             if ((gOutputFile = fopen(gOutputFileNameString, "wb")) == NULL)
747             {
748                 displayError(ERROR_CANNOT_OPEN_FILE);
749            }
750             gIsOutputFileOpened = TRUE;
751         }
752     }
753 
754     //---- Input file
755     if (gTlfFileName)
756     {
757         if (gVerboseMode)
758         {
759             printf("tlf current directory is %s\n", gTlfDirectoryNameString);
760         }
761         //---- Change current directory
762         if (chdir(gTlfDirectoryNameString) != 0)
763         {
764             displayError(ERROR_ILLEGAL_TLF_FILE);
765         }
766     }
767 
768 
769     if (gVerboseMode)
770     {
771         printf("original bin file   : %s\n", gInputFileNameString);
772     }
773     if ((gInputFile = fopen(gInputFileNameString, (gReplacementMode) ? "rb+" : "rb")) == NULL)
774     {
775         displayError(ERROR_NO_FILE);
776     }
777     gIsInputFileOpened = TRUE;
778 }
779 
780 /*---------------------------------------------------------------------------*
781   Name:         closeFiles
782 
783   Description:  Closes files.
784 
785   Arguments:    None.
786 
787   Returns:      None.
788  *---------------------------------------------------------------------------*/
closeFiles(void)789 void closeFiles(void)
790 {
791     if (gStdoutMode)
792     {
793         //---- Flush stdout
794         fflush(stdout);
795 
796         //---- Set stdout to text mode
797         _setmode(_fileno(gOutputFile), O_TEXT);
798     }
799 
800     if (gIsInputFileOpened)
801     {
802         fclose(gInputFile);
803         gIsInputFileOpened = FALSE;
804     }
805     if (gIsOutputFileOpened)
806     {
807         fclose(gOutputFile);
808         gIsOutputFileOpened = FALSE;
809     }
810     if (gIsReplacementFileOpened)
811     {
812         fclose(gReplacementFile);
813         gIsReplacementFileOpened = FALSE;
814     }
815     if (gIsTlfFileOpened)
816     {
817         fclose(gTlfFile);
818         gIsTlfFileOpened = FALSE;
819     }
820 }
821 
822 //================================================================================
823 //                      Replace buffer
824 //================================================================================
replaceToSpecifiedString(void)825 void replaceToSpecifiedString(void)
826 {
827     BOOL    isFindMark = FALSE;
828     int     markIndex = 0;
829     long    bufPosition;
830     int     n;
831     int     inputChar;
832 
833     const int markLength = strlen(gArgIdString);
834 
835     //---- Search argument identification string in bin file
836     while (1)
837     {
838         if ((inputChar = fgetc(gInputFile)) == EOF)
839         {
840             break;
841         }
842 
843         if (inputChar == gArgIdString[markIndex])
844         {
845             markIndex++;
846             if (markIndex == markLength)
847             {
848                 long    topPosition = ftell(gInputFile) - markLength;
849                 bufPosition = topPosition + OS_ARGUMENT_ID_STRING_BUFFER_SIZE + sizeof(u16);
850 
851                 if (gVerboseMode)
852                 {
853                     printf("found argument identification string at 0x%x byte from top.\n",
854                            (int)topPosition);
855                 }
856                 isFindMark = TRUE;
857                 break;
858             }
859         }
860         else
861         {
862             if (markIndex > 0)
863             {
864                 markIndex = 0;
865                 if (inputChar == gArgIdString[0])
866                 {
867                     markIndex++;
868                 }
869             }
870         }
871     }
872 
873     //---- Check if mark not found
874     if (!isFindMark)
875     {
876         displayError(ERROR_MARK_NOT_FOUND);
877     }
878 
879     //---- Position check
880     if (bufPosition < 0)
881     {
882         displayError(ERROR_BAD_MARK_POSITION);
883     }
884 
885     //---- Get buffer size
886     fseek(gInputFile, bufPosition - sizeof(u16), SEEK_SET);
887     gArgStringSize = (int)(fgetc(gInputFile) + (fgetc(gInputFile) << 8));
888 
889     if (gVerboseMode)
890     {
891         printf("buffer size = 0x%x byte\n", gArgStringSize);
892     }
893 
894     if (gArgStringSize < 0 || gArgStringSize > ARGUMENT_BUF_SIZE)
895     {
896         displayError(ERROR_BAD_ARGUMENT_SIZE);
897     }
898 
899     //---- Put forced endmark to replace buffer
900     gArgString[gArgStringSize - 2] = '\0';
901     gArgString[gArgStringSize - 1] = '\0';
902 
903     //---- Replacement
904     if (gReplacementMode)
905     {
906         fseek(gInputFile, bufPosition, SEEK_SET);
907         for (n = 0; n < gArgStringSize; n++)
908         {
909             fputc(gArgString[n], gInputFile);
910         }
911 
912         if (gVerboseMode)
913         {
914             printf("replaced 0x%x byte.\n", (int)gArgStringSize);
915         }
916     }
917     else
918     {
919         fseek(gInputFile, 0, SEEK_SET);
920         n = 0;
921         while ((inputChar = fgetc(gInputFile)) != EOF)
922         {
923             if (bufPosition <= n && n < bufPosition + gArgStringSize)
924             {
925                 fputc(gArgString[n - bufPosition], gOutputFile);
926             }
927             else
928             {
929                 fputc(inputChar, gOutputFile);
930             }
931 
932             n++;
933         }
934 
935         if (gVerboseMode)
936         {
937             printf("output 0x%x byte (%d byte).\n", n, n);
938         }
939     }
940 }
941 
942 //================================================================================
943 //                      Main routine
944 //================================================================================
945 /*---------------------------------------------------------------------------*
946   Name:         Main
947 
948   Description:  Main proc.
949 
950   Arguments:    argc: Argument count
951                 argv: Argument vector
952 
953   Returns:      ---
954  *---------------------------------------------------------------------------*/
main(int argc,char * argv[])955 int main(int argc, char *argv[])
956 {
957     //---- Option parsing
958     parseOption(argc, argv);
959 
960     //---- File open
961     openFiles();
962 
963     //---- Buffer internal display (for debugging)
964     if (gDebugMode)
965     {
966         displayBuffer();
967     }
968 
969     //---- Replacement processing
970     replaceToSpecifiedString();
971 
972     //---- File close
973     closeFiles();
974 
975     //---- End
976     if (!gQuietMode)
977     {
978         printf("Success.\n");
979     }
980     return 0;
981 }
982