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