1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - tools - loadrun
3 File: loadrun.c
4
5 Copyright 2005-2007 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-05-23#$
14 $Rev: 6187 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17 #include <windows.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include <sys/fcntl.h>
23 #include <sys/stat.h>
24 #include <getopt.h>
25 #include <signal.h>
26 #include <time.h>
27
28 #include "ISNITRODLL.h"
29 #include "isd_api.h"
30
31 #define SDK_BOOL_ALREADY_DEFINED_
32 #include <nitro_win32.h>
33 #include <nitro/os/common/system.h>
34
35 extern const unsigned long SDK_DATE_OF_LATEST_FILE;
36
37 //---- Version string
38 #define VERSION_STRING " 1.13 Copyright 2005-2008 Nintendo. All right reserved."
39 // 1.13 Fixed print callback bug
40 // 1.12 Corrected help display
41 // 1.11 Deleted device type
42 // 1.10 Displayed latest time stamp of source file
43 // 1.9 Changed exit status of loadrun itself
44 // 1.8 Supported terminating character string from OS_EXIT()
45 // 1.7 Allowed data to be read from standard input
46 // 1.6 Disabled buffering of standard output
47 // 1.5 Allowed character string termination even in Quiet Mode
48 // 1.4 Implemented wrap display
49 // 1.3 Implemented execution timeout
50 // 1.2 Changed processing when execution is stopped using ctrl-c
51 // 1.1 Made it so the slot is turned off when execution is stopped using ctrl-c
52 // 1.0 Published
53
54 //---- exit number
55 #define EXIT_NUM_NO_ERROR 207 // Successful exit (however, this will not result next time)
56 #define EXIT_NUM_USER_SIGNAL 206 // Forced exit by user (ctrl-C)
57 #define EXIT_NUM_EXEC_TIME_OUT 205 // Forced exit due to execution timeout
58 #define EXIT_NUM_TIME_OUT 204 // Forced exit due to display timeout
59 #define EXIT_NUM_SHOW_DEVICES 203 // Exit on device list display
60 #define EXIT_NUM_SHOW_USAGE 202 // Exit on help display
61 #define EXIT_NUM_SHOW_VERSION 201 // Exit on version display
62 #define EXIT_NUM_STRING_ABORT 200 // Forced exit by character string
63
64 #define EXIT_NUM_NO_DEVICE -1 // There are no available devices
65 #define EXIT_NUM_UNKNOWN_OPTION -2 // An unknown option was specified
66 #define EXIT_NUM_ILLEGAL_OPTION -3 // Illegal use of option
67 #define EXIT_NUM_NO_INPUT_FILE -4 // The specified file does not exist or cannot be opened
68 #define EXIT_NUM_NOT_CONNECT -5 // Failed to connect to device
69 #define EXIT_NUM_CANNOT_USE_CARTRIDGE -6 // Failed to lock cartridge
70 #define EXIT_NUM_CANNOT_USE_CARD -7 // Failed to lock card
71 #define EXIT_NUM_PRINTF_ERROR -8 // Error while handling printf data
72 #define EXIT_NUM_LOADING_ERROR -9 // Error during loading
73
74 //---- For device specification
75 char *gDeviceName[] = {
76 "CGBUSB", "CGBSCSI", "NITROUSB", "NITROUIC", NULL
77 };
78 int gDeviceTypeArray[] = {
79 ISNTD_DEVICE_CGB_EMULATOR_USB,
80 ISNTD_DEVICE_CGB_EMULATOR_SCSI,
81 ISNTD_DEVICE_IS_NITRO_EMULATOR,
82 ISNTD_DEVICE_IS_NITRO_UIC
83 };
84
85 //---- Operating mode
86 BOOL gQuietMode = FALSE; // Quiet mode
87 BOOL gVerboseMode = FALSE; // verbose mode
88 BOOL gDebugMode = FALSE; // Debug mode
89
90 BOOL gStdinMode = FALSE; // stdin mode
91
92 BOOL gIsTypeSpecified = FALSE; // Is there a device type specification?
93 int gSpecifiedType; // Device type if one is specified
94
95 BOOL gIsSerialSpecified = FALSE; // Is there a serial number specification?
96 int gSpecifiedSerial; // Serial number if one was specified
97
98 BOOL gIsCartridgeLocked = FALSE; // Should the cartridge slot be locked?
99 BOOL gIsCardLocked = FALSE; // Should the card slot be locked?
100
101 int gTimeOutTime = 0; // Timeout interval in sec (0 indicates no timeout)
102 BOOL gTimeOutOccured = FALSE; // Has a timeout occurred?
103
104 int gExecTimeOutTime = 0; // Execution timeout interval in sec (0 indicates no timeout)
105 int gExecTimeOutOccured = FALSE; // Has an execution timeout occurred?
106
107 char *gAbortString = NULL; // Abort string
108 BOOL gStringAborted = FALSE; // Has execution terminated due to the abort string?
109
110 BOOL gExitAborted = FALSE; // Exit from OS_Exit()
111 int gExitStatusNum = EXIT_NUM_STRING_ABORT; // Return value when terminated by OS_Exit()
112 int gExitStrLength; // Length of exit string
113
114 //---- For NITRO library
115 HINSTANCE gDllInstance;
116 NITRODEVICEHANDLE gDeviceHandle;
117 NITRODEVICEID gDeviceId;
118
119 //Connected to the device? (for slot switch)
120 BOOL gDeviceConnected = FALSE;
121
122
123 //---- Device list
124 #define DEVICE_MAX_NUM 256
125 #define DEVICE_SERIAL_NONE 0x7fffffff // means no specified
126 ISNTDDevice gDeviceList[DEVICE_MAX_NUM];
127 int gCurrentDevice = -1;
128 int gConnectedDeviceNum = 0;
129
130 int gDeviceTypeSpecified = ISNTD_DEVICE_NONE;
131 int gDeviceSerialSpecified = DEVICE_SERIAL_NONE; // means no specified
132
133 //---- Input file
134 #define FILE_NAME_MAX_SIZE 1024
135 FILE *gInputFile;
136 char gInputFileNameString[FILE_NAME_MAX_SIZE];
137 BOOL gIsInputFileOpened = FALSE;
138
139 //---- Time
140 time_t gStartTime = 0; // Start time
141 BOOL gIsLineHead = TRUE; // Start of line?
142 BOOL gShowLapTime = FALSE;
143
144 //---- Signal
145 BOOL gStoppedByUser = FALSE; // Indicates whether execution was stopped by the user.
146
147
148 #define printfIfNotQuiet(str) do{if(!gQuietMode){fputs(str,stdout);}}while(0)
149
150 void displayErrorAndExit(int exitNum, char *message);
151 BOOL outputString(char *buf, int bufSize);
152
153 /*---------------------------------------------------------------------------*
154 Name: myExit
155
156 Description: similar to exit()
157
158 Arguments: exitNum: exit() number
159
160 Returns: None.
161 *---------------------------------------------------------------------------*/
myExit(int exitNum)162 void myExit(int exitNum)
163 {
164 //---- Turns off the slot for the cartridge and card
165 if (gDeviceConnected)
166 {
167 (void)ISNTD_CartridgeSlotPower(gDeviceHandle, FALSE);
168 (void)ISNTD_CardSlotPower(gDeviceHandle, FALSE);
169 }
170
171 //---- Deallocate DLL memory
172 ISNTD_FreeDll();
173
174 if (!gQuietMode)
175 {
176 if (exitNum == EXIT_NUM_USER_SIGNAL)
177 {
178 printf("\n*** loadrun: stopped by user.\n");
179 }
180 else if (exitNum == EXIT_NUM_TIME_OUT)
181 {
182 printf("\n*** loadrun: stopped by print timeout.\n");
183 }
184 else if (exitNum == EXIT_NUM_EXEC_TIME_OUT)
185 {
186 printf("\n*** loadrun: stopped by exec timeout.\n");
187 }
188 else if (gStringAborted)
189 {
190 printf("\n*** loadrun: stopped by aborting string.\n");
191 }
192 else if (gExitAborted)
193 {
194 exitNum = gExitStatusNum;
195 }
196 }
197
198 exit(exitNum);
199 }
200
201 /*---------------------------------------------------------------------------*
202 Name: listDevice
203
204 Description: Displays a list of devices and terminates
205
206 Arguments: None.
207
208 Returns: None.
209 *---------------------------------------------------------------------------*/
listDevice(void)210 void listDevice(void)
211 {
212 int n;
213
214 //---- Device read
215 gConnectedDeviceNum = ISNTD_GetDeviceList(&gDeviceList[0], DEVICE_MAX_NUM);
216 if (gConnectedDeviceNum < 0)
217 {
218 displayErrorAndExit(EXIT_NUM_NO_DEVICE, "Cannot access devices.");
219 }
220
221 printf("---- Connected devices:\n");
222
223 for (n = 0; n < gConnectedDeviceNum; n++)
224 {
225 switch (gDeviceList[n].type)
226 {
227 case ISNTD_DEVICE_CGB_EMULATOR_USB:
228 printf("%3d: [CGBUSB] IS-CGB-EMU(USB) serial:%8d\n", n, gDeviceList[n].serial);
229 break;
230 case ISNTD_DEVICE_CGB_EMULATOR_SCSI:
231 printf("%3d: [CGBSCSI] IS-CGB-EMULATOR serial(host-id):%02d%02d\n", n,
232 gDeviceList[n].host, gDeviceList[n].serial);
233 break;
234 case ISNTD_DEVICE_IS_NITRO_EMULATOR:
235 printf("%3d: [NITROUSB] IS-NITRO-EMULATOR serial:%08d\n", n, gDeviceList[n].serial);
236 break;
237 case ISNTD_DEVICE_IS_NITRO_UIC:
238 printf("%3d: [NITROUIC] IS-NITRO-UIC serial: %08d\n", n, gDeviceList[n].serial);
239 break;
240 case ISNTD_DEVICE_UNKNOWN:
241 printf("%3d: unknown device %x\n", n, (int)gDeviceList[n].ntdId);
242 break;
243 default:
244 printf("Illegal device\n");
245 break;
246 }
247 }
248
249 //---- Search result
250 printf("%d device(s) found.\n", gConnectedDeviceNum);
251
252 myExit(EXIT_NUM_SHOW_DEVICES);
253 }
254
255 /*---------------------------------------------------------------------------*
256 Name: searchDevice
257
258 Description: search device
259
260 Arguments: None.
261
262 Returns: None.
263 *---------------------------------------------------------------------------*/
searchDevice(void)264 void searchDevice(void)
265 {
266 //---- If there is no device
267 if (gConnectedDeviceNum <= 0)
268 {
269 displayErrorAndExit(EXIT_NUM_NO_DEVICE, "found no device.");
270 }
271
272 //---- If there was some kind of specification
273 if (gDeviceTypeSpecified != ISNTD_DEVICE_NONE || gDeviceSerialSpecified != DEVICE_SERIAL_NONE)
274 {
275 int n;
276 gCurrentDevice = -1;
277 for (n = 0; n < gConnectedDeviceNum; n++)
278 {
279 //---- Matching with specified device
280 if (gDeviceTypeSpecified != ISNTD_DEVICE_NONE
281 && gDeviceTypeSpecified != gDeviceList[n].type)
282 {
283 continue;
284 }
285
286 //---- Matching with specified serial
287 if (gDeviceSerialSpecified != DEVICE_SERIAL_NONE
288 && gDeviceSerialSpecified != gDeviceList[n].serial)
289 {
290 continue;
291 }
292
293 gCurrentDevice = n;
294 break;
295 }
296 }
297 //---- First one if there is no specification
298 else
299 {
300 gCurrentDevice = 0;
301 }
302
303 //---- The specified device does not exist or is incorrect
304 if (gCurrentDevice < 0
305 || gDeviceList[gCurrentDevice].type == ISNTD_DEVICE_NONE
306 || gDeviceList[gCurrentDevice].type == ISNTD_DEVICE_UNKNOWN)
307 {
308 displayErrorAndExit(EXIT_NUM_NO_DEVICE, "illegal device.");
309 }
310 }
311
312 /*---------------------------------------------------------------------------*
313 Name: displayUsage
314
315 Description: Displays the usage
316
317 Arguments: None.
318
319 Returns: None.
320 *---------------------------------------------------------------------------*/
displayUsage(void)321 void displayUsage(void)
322 {
323 fprintf(stderr,
324 "NITRO-SDK Development Tool - loadrun - Execute NITRO ROM image\n"
325 "Build %lu\n\n"
326 "Usage: loadrun [OPTION] <SrlFile>\n"
327 "\t\tdownload Nitro srl file to debugger and execute.\n\n"
328 "Options:\n"
329 " --version : Show version.\n"
330 " -h, --help : Show this help.\n"
331 " -q, --quiet : Quiet mode.\n"
332 " -v, --verbose : Verbose mode.\n"
333 " -L, --list : List connecting device.\n"
334 " -l, --lap : Show lap time at each line.\n"
335 // " -d, --type=DEVICE : Specify device type.\n"
336 // " DEVICE=CGBUSB|CGBSCSI|NITROUSB|NITROUIC.\n"
337 " -s, --serial=SERIAL : Specify serial number.\n"
338 " -t, --timeout=SECOND : Specify quit time after last print.\n"
339 " -T, --exec-timeout=SECOND : Specify quit time after execute program.\n"
340 " -a, --abort-string=STRING : Specify aborting string.\n"
341 " -c, --card-slot=SWITCH : Card slot SWITCH=ON|OFF, default OFF.\n"
342 " -C, --cartridge-slot=SWITCH : Cartridge slot SWITCH=ON|OFF, default OFF.\n"
343 " --stdin, --standard-input : Read data from stdin instead of <SrlFile>.\n\n",
344 SDK_DATE_OF_LATEST_FILE);
345 }
346
347 /*---------------------------------------------------------------------------*
348 Name: displayVersion
349
350 Description: Displays the version
351
352 Arguments: None.
353
354 Returns: None.
355 *---------------------------------------------------------------------------*/
displayVersion(void)356 void displayVersion(void)
357 {
358 printf("*** loadrun: %s\n", VERSION_STRING);
359 }
360
361 /*---------------------------------------------------------------------------*
362 Name: displayErrorAndExit
363
364 Description: Displays errors.
365
366 Arguments: None.
367
368 Returns: None.
369 *---------------------------------------------------------------------------*/
displayErrorAndExit(int exitNum,char * message)370 void displayErrorAndExit(int exitNum, char *message)
371 {
372 printf("*** loadrun: Error: %s\n", message);
373
374 //---- Deallocate DLL memory
375 ISNTD_FreeDll();
376
377 exit(exitNum);
378 }
379
380 /*---------------------------------------------------------------------------*
381 Name: parseOption
382
383 Description: parses the option line
384
385 Arguments: argc : argument count
386 argv: argument vector
387
388 Returns: result. less than 0 if error.
389 *---------------------------------------------------------------------------*/
parseOption(int argc,char * argv[])390 void parseOption(int argc, char *argv[])
391 {
392 int n;
393 int c;
394 BOOL helpFlag = FALSE;
395
396 struct option optionInfo[] = {
397 {"help", no_argument, NULL, 'h'},
398 {"quiet", no_argument, NULL, 'q'},
399 {"verbose", no_argument, NULL, 'v'},
400 {"list", no_argument, NULL, 'L'},
401 {"lap", no_argument, NULL, 'l'},
402 {"debug", no_argument, NULL, 'D'}, //Hidden options
403 {"version", no_argument, NULL, '1'},
404 {"stdin", no_argument, NULL, 'I'},
405 {"standard-input", no_argument, NULL, 'I'},
406 {"type", required_argument, 0, 'd'}, //Hidden options
407 {"serial", required_argument, 0, 's'},
408 {"timeout", required_argument, 0, 't'},
409 {"exec-timeout", required_argument, 0, 'T'},
410 {"abort-string", required_argument, 0, 'a'},
411 {"card-slot", required_argument, 0, 'c'},
412 {"cartridge-slot", required_argument, 0, 'C'},
413 {NULL, 0, 0, 0}
414 };
415 int optionIndex;
416
417 char *optionStr = NULL;
418
419 //---- suppress error string of getopt_long()
420 opterr = 0;
421
422 while (1)
423 {
424 c = getopt_long(argc, argv, "+hqvlLDd:s:t:T:a:c:C:", &optionInfo[0], &optionIndex);
425
426 //printf("optind=%d optopt=%d %x(%c) \n", optind, optopt, c,c );
427
428 if (c == -1)
429 {
430 break;
431 }
432
433 switch (c)
434 {
435 case 'I': //---- Standard input
436 gStdinMode = TRUE;
437 break;
438 case 'h': //---- Help display
439 helpFlag = TRUE;
440 break;
441 case 'q': //---- Quiet mode
442 gQuietMode = TRUE;
443 break;
444 case 'v': //---- Verbose mode
445 gVerboseMode = TRUE;
446 break;
447 case 'D': //---- Debug mode
448 gDebugMode = TRUE;
449 break;
450 case '1': //---- Version display
451 displayVersion();
452 myExit(EXIT_NUM_SHOW_VERSION);
453 break;
454 case 'L': //---- Device list
455 listDevice();
456 break;
457 case 'l': //---- Lap time
458 gShowLapTime = TRUE;
459 break;
460 case 'd': //---- Device
461 optionStr = (char *)(optarg + ((*optarg == '=') ? 1 : 0));
462 {
463 int n;
464 for (n = 0; gDeviceName[n]; n++)
465 {
466 if (!strcmp(optionStr, gDeviceName[n]))
467 {
468 gDeviceTypeSpecified = gDeviceTypeArray[n];
469 break;
470 }
471 }
472
473 if (gDeviceTypeSpecified == ISNTD_DEVICE_NONE)
474 {
475 displayErrorAndExit(EXIT_NUM_ILLEGAL_OPTION, "illegal device type.");
476 }
477 }
478 break;
479 case 's': //---- Serial specification
480 optionStr = (char *)(optarg + ((*optarg == '=') ? 1 : 0));
481 gDeviceSerialSpecified = atoi(optionStr);
482 break;
483 case 'c': //---- Card slot lock
484 optionStr = (char *)(optarg + ((*optarg == '=') ? 1 : 0));
485 if (!strcmp(optionStr, "ON") || !strcmp(optionStr, "on"))
486 {
487 gIsCardLocked = TRUE;
488 }
489 else if (!strcmp(optionStr, "OFF") || !strcmp(optionStr, "off"))
490 {
491 gIsCardLocked = FALSE;
492 }
493 else
494 {
495 displayErrorAndExit(EXIT_NUM_ILLEGAL_OPTION, "illegal value for card slot option.");
496 }
497 break;
498 case 'C': //---- Cartridge slot lock
499 optionStr = (char *)(optarg + ((*optarg == '=') ? 1 : 0));
500 if (!strcmp(optionStr, "ON") || !strcmp(optionStr, "on"))
501 {
502 gIsCartridgeLocked = TRUE;
503 }
504 else if (!strcmp(optionStr, "OFF") || !strcmp(optionStr, "off"))
505 {
506 gIsCartridgeLocked = FALSE;
507 }
508 else
509 {
510 displayErrorAndExit(EXIT_NUM_ILLEGAL_OPTION,
511 "illegal value for cartridge slot option.");
512 }
513 break;
514 case 't': //---- Timeout interval beginning from final display
515 optionStr = (char *)(optarg + ((*optarg == '=') ? 1 : 0));
516 gTimeOutTime = atoi(optionStr);
517 if (gTimeOutTime <= 0)
518 {
519 displayErrorAndExit(EXIT_NUM_ILLEGAL_OPTION,
520 "illegal value for abort timeout option.");
521 }
522 break;
523 case 'T': //---- Execution timeout interval
524 optionStr = (char *)(optarg + ((*optarg == '=') ? 1 : 0));
525 gExecTimeOutTime = atoi(optionStr);
526 if (gExecTimeOutTime <= 0)
527 {
528 displayErrorAndExit(EXIT_NUM_ILLEGAL_OPTION,
529 "illegal value for abort exec timeout option.");
530 }
531 break;
532 case 'a': //---- Abort string
533 gAbortString = (char *)(optarg + ((*optarg == '=') ? 1 : 0));
534 {
535 int length = strlen(gAbortString);
536 if (length <= 0 || length > 256)
537 {
538 displayErrorAndExit(EXIT_NUM_ILLEGAL_OPTION,
539 "illegal value for abort string option.");
540 }
541 }
542 break;
543 default:
544 displayErrorAndExit(EXIT_NUM_UNKNOWN_OPTION, "unknown option.");
545 }
546 }
547
548 //---- Help display
549 {
550 BOOL isDisplayHelp = FALSE;
551
552 if (helpFlag)
553 {
554 isDisplayHelp = TRUE;
555 }
556 else if (argc <= optind && !gStdinMode)
557 {
558 isDisplayHelp = TRUE;
559 }
560 else if (argc > optind && gStdinMode)
561 {
562 isDisplayHelp = TRUE;
563 }
564
565 if (isDisplayHelp)
566 {
567 displayUsage();
568 exit(EXIT_NUM_SHOW_USAGE);
569 }
570 }
571
572 //---- Input file name
573 if (!gStdinMode)
574 {
575 strncpy(gInputFileNameString, argv[optind], FILE_NAME_MAX_SIZE);
576 }
577
578 if (gVerboseMode)
579 {
580 if (!gStdinMode)
581 {
582 printf("Input file is [%s]\n", gInputFileNameString);
583 }
584 else
585 {
586 printf("Input file is stdin\n");
587 }
588 }
589
590 //---- Information display
591 if (gVerboseMode)
592 {
593 printf("Print time out : %d sec.\n", gTimeOutTime);
594 printf("Execute time out : %d sec.\n", gExecTimeOutTime);
595 printf("Card lock : %s.\n", (gIsCardLocked) ? "ON" : "OFF");
596 printf("Cartridge lock : %s.\n", (gIsCartridgeLocked) ? "ON" : "OFF");
597
598 if (gAbortString)
599 {
600 printf("Abort string : [%s]\n", gAbortString);
601 }
602 }
603 }
604
605 /*---------------------------------------------------------------------------*
606 Name: loadFile
607
608 Description: loads file
609
610 Arguments: None.
611
612 Returns: None.
613 *---------------------------------------------------------------------------*/
loadFile(void)614 void loadFile(void)
615 {
616 unsigned int address = 0;
617 //int fileSize;
618
619 //---- File open
620 if (gStdinMode)
621 {
622 gInputFile = stdin;
623 _setmode(_fileno(gInputFile), O_BINARY);
624 }
625 else
626 {
627 if ((gInputFile = fopen(gInputFileNameString, "rb")) == NULL)
628 {
629 displayErrorAndExit(EXIT_NUM_NO_INPUT_FILE, "cannot open input file.");
630 }
631 }
632 gIsInputFileOpened = TRUE;
633
634 //---- Connected to device
635 if ((gDeviceHandle = ISNTD_DeviceOpen(gDeviceList[gCurrentDevice].ntdId)) == NULL)
636 {
637 displayErrorAndExit(EXIT_NUM_NOT_CONNECT, "cannot connect device.");
638 }
639 gDeviceConnected = TRUE;
640
641 //---- Issue reset
642 ISNTD_Reset(gDeviceHandle, TRUE);
643 Sleep(1000);
644
645 //---- Get file size
646 //fseek( gInputFile, 0L, SEEK_END );
647 //fileSize = ftell( gInputFile );
648 //fseek( gInputFile, 0L, SEEK_SET );
649
650 //---- Transfer every 16KB
651 while (1)
652 {
653 char buf[16384];
654 size_t size = fread(buf, 1, sizeof(buf), gInputFile);
655 static int progressCount = 0;
656
657 if (!size)
658 {
659 break;
660 }
661
662 //---- Transfer
663 if (!ISNTD_WriteROM(gDeviceHandle, buf, address, size))
664 {
665 displayErrorAndExit(EXIT_NUM_LOADING_ERROR, "troubled while loading input file.");
666 }
667
668 address += size;
669
670 if (gVerboseMode)
671 {
672 if (!(progressCount++ % 32))
673 {
674 printf("*");
675 }
676 }
677 }
678
679 //---- File close
680 if (gStdinMode)
681 {
682 _setmode(_fileno(gInputFile), O_TEXT);
683 }
684 else
685 {
686 fclose(gInputFile);
687 }
688 gIsInputFileOpened = FALSE;
689
690 if (gVerboseMode)
691 {
692 printf("\nInput file size: %d (0x%x) byte\n", address, address);
693 }
694 }
695
696 /*---------------------------------------------------------------------------*
697 Name: setSlopPower
698
699 Description: Slot power process
700
701 Arguments: None.
702
703 Returns: None.
704 *---------------------------------------------------------------------------*/
setSlotPower(void)705 void setSlotPower(void)
706 {
707 //---- Should the cartridge slot be locked?
708 if (gIsCartridgeLocked)
709 {
710 if (!ISNTD_CartridgeSlotPower(gDeviceHandle, TRUE))
711 {
712 displayErrorAndExit(EXIT_NUM_CANNOT_USE_CARTRIDGE, "cannot use cartridge slot.");
713 }
714 }
715
716 //---- Should the card slot be locked?
717 if (gIsCardLocked)
718 {
719 if (!ISNTD_CardSlotPower(gDeviceHandle, TRUE))
720 {
721 displayErrorAndExit(EXIT_NUM_CANNOT_USE_CARD, "cannot use card slot.");
722 }
723 }
724
725 //---- Cancel reset
726 Sleep(1000);
727 ISNTD_Reset(gDeviceHandle, FALSE);
728 }
729
730 /*---------------------------------------------------------------------------*
731 Name: procPrint
732
733 Description: printf process
734
735 Arguments: None.
736
737 Returns: None.
738 *---------------------------------------------------------------------------*/
739 NITROArch archNum[] = {
740 NITROArchARM9,
741 NITROArchARM7
742 };
743
744 #define PRINT_ONETIME_SIZE 512
745 //#define PRINT_ONETIME_SIZE 16
746
747 //---- Buffer for joint display
748 static char gConbineBuf[PRINT_ONETIME_SIZE * 2 + 2] = "\0";
749 static char *gConbineBufPtr = &gConbineBuf[0];
750
751 //---- Buffer for joining and comparing character strings
752 static char gLineBuf[PRINT_ONETIME_SIZE + 1];
753
754
procPrintf(void)755 void procPrintf(void)
756 {
757 int blankTime = 0;
758
759 //---- Size of exit string
760 gExitStrLength = strlen(OS_EXIT_STRING_1);
761
762 while (1)
763 {
764 BOOL isOutputString = FALSE;
765
766 //---- When stopped by the user
767 if (gStoppedByUser)
768 {
769 myExit(EXIT_NUM_USER_SIGNAL);
770 }
771
772 //printf("[######]\n" );
773 {
774 int n;
775 int dataSize;
776 char tmpBuf[PRINT_ONETIME_SIZE + 1];
777
778 for (n = 0; n < 2; n++)
779 {
780 //---- Get display data
781 if (!ISNTD_GetDebugPrint
782 (gDeviceHandle, archNum[n], tmpBuf, &dataSize, PRINT_ONETIME_SIZE))
783 {
784 ISNTD_DeviceClose(gDeviceHandle);
785 displayErrorAndExit(EXIT_NUM_PRINTF_ERROR,
786 "troubled while receiving print data.");
787 }
788 tmpBuf[dataSize] = '\0';
789
790 //---- If there is data to be displayed, display it
791 if (dataSize)
792 {
793 //---- Record that data was displayed
794 isOutputString = TRUE;
795
796 //---- Output
797 if (!outputString(tmpBuf, dataSize))
798 {
799 break;
800 }
801 }
802 }
803 }
804
805 //---- Exit?
806 if (gStringAborted || gExitAborted)
807 {
808 break;
809 }
810
811 //---- If text is not being displayed
812 if (!isOutputString)
813 {
814 Sleep(100);
815 blankTime += 100;
816
817 //---- Timeout decision
818 if (gTimeOutTime && blankTime > gTimeOutTime * 1000)
819 {
820 gTimeOutOccured = TRUE;
821 break;
822 }
823 }
824 //---- If text has been displayed
825 else
826 {
827 blankTime = 0;
828 }
829
830 //---- Timeout check
831 if (gExecTimeOutTime > 0)
832 {
833 time_t currentTime;
834 (void)time(¤tTime);
835
836 if (currentTime - gStartTime >= gExecTimeOutTime)
837 {
838 gExecTimeOutOccured = TRUE;
839 break;
840 }
841 }
842 }
843 }
844
845
846 /*---------------------------------------------------------------------------*
847 Name: showLapTime
848
849 Description: displays lap time at line head
850
851 Arguments: None.
852
853 Returns: None.
854 *---------------------------------------------------------------------------*/
showLapTime(void)855 void showLapTime(void)
856 {
857 int lap;
858 time_t currentTime;
859
860 (void)time(¤tTime);
861 lap = currentTime - gStartTime;
862
863 printf("{%d:%02d}", lap / 60, lap % 60);
864 }
865
866 /*---------------------------------------------------------------------------*
867 Name: outputString
868
869 Description: outputs string to stdout
870
871 Arguments: buf: buffer
872 bufSize: data size in buffer
873
874 Returns: FALSE if to do quit.
875 *---------------------------------------------------------------------------*/
outputString(char * buf,int bufSize)876 BOOL outputString(char *buf, int bufSize)
877 {
878 char *bufEnd = buf + bufSize;
879 char *p = buf;
880
881 int abortStrLength = gAbortString ? strlen(gAbortString) : 0;
882
883 while (p < bufEnd)
884 {
885 char *crPtr = strchr(p, '\n');
886
887 //---- \n missing
888 if (!crPtr)
889 {
890 //---- Save for comparison
891 strcat(gConbineBufPtr, p);
892 gConbineBufPtr += strlen(p);
893
894 //---- Time display
895 if (!gQuietMode && gIsLineHead && gShowLapTime)
896 {
897 showLapTime();
898 }
899 gIsLineHead = FALSE;
900
901 //---- Display
902 printfIfNotQuiet(p);
903
904 //---- Destroy if buffer overflows (the responsibility is on the output side to insert \n)
905 if (gConbineBufPtr - &gConbineBuf[0] > PRINT_ONETIME_SIZE)
906 {
907 gConbineBufPtr = &gConbineBuf[0];
908 *gConbineBufPtr = '\0';
909 }
910
911 break;
912 }
913
914 //---- copy up to \n
915 {
916 int n = crPtr - p + 1;
917
918 //---- Combine for comparison
919 strncpy(gConbineBufPtr, p, n);
920 gConbineBufPtr[n] = '\0';
921
922 //---- For display
923 strncpy(&gLineBuf[0], p, n);
924 gLineBuf[n] = '\0';
925 }
926
927 //---- Time display
928 if (!gQuietMode && gIsLineHead && gShowLapTime)
929 {
930 showLapTime();
931 }
932 gIsLineHead = TRUE;
933
934 //---- Line display
935 printfIfNotQuiet(gLineBuf);
936
937 //---- Compare with abort string
938 if (gAbortString && !strncmp(gConbineBuf, gAbortString, abortStrLength))
939 {
940 gStringAborted = TRUE;
941 return FALSE;
942 }
943
944 //---- Exit using OS_Exit
945 if (!strncmp(gConbineBuf, OS_EXIT_STRING_1, gExitStrLength))
946 {
947 gExitAborted = TRUE;
948 gExitStatusNum = atoi(gConbineBuf + gExitStrLength);
949 return FALSE;
950 }
951
952 gConbineBufPtr = &gConbineBuf[0];
953 *gConbineBufPtr = '\0';
954
955 p = crPtr + 1;
956 }
957
958 return TRUE;
959 }
960
961 /*---------------------------------------------------------------------------*
962 Name: signalHandler
963
964 Description: signal handler
965
966 Arguments: sig
967 argv: argument vector
968
969 Returns: ---
970 *---------------------------------------------------------------------------*/
signalHandler(int sig)971 void signalHandler(int sig)
972 {
973 gStoppedByUser = TRUE;
974 }
975
976 /*---------------------------------------------------------------------------*
977 Name: Main
978
979 Description: main proc
980
981 Arguments: argc : argument count
982 argv: argument vector
983
984 Returns: ---
985 *---------------------------------------------------------------------------*/
main(int argc,char * argv[])986 int main(int argc, char *argv[])
987 {
988 //---- Initialize DLL
989 ISNTD_InitDll();
990
991 //---- Disable buffering of standard output
992 setvbuf(stdout, NULL, _IONBF, 0);
993
994 //---- Option parsing
995 parseOption(argc, argv);
996
997 //---- Device read
998 gConnectedDeviceNum = ISNTD_GetDeviceList(&gDeviceList[0], DEVICE_MAX_NUM);
999 if (gConnectedDeviceNum < 0)
1000 {
1001 displayErrorAndExit(EXIT_NUM_NO_DEVICE, "Cannot access devices.");
1002 }
1003
1004 //---- Search for device
1005 searchDevice();
1006
1007 //---- Read
1008 loadFile();
1009
1010 //---- Signal setting
1011 (void)signal(SIGINT, signalHandler);
1012
1013 //---- Slot
1014 setSlotPower();
1015
1016 //---- Get start time
1017 (void)time(&gStartTime);
1018
1019 //---- printf process
1020 procPrintf();
1021
1022 //---- End
1023 if (gExitAborted) //---- Exit from OS_Exit()
1024 {
1025 myExit(gExitStatusNum);
1026 }
1027 else if (gStringAborted) //---- Abort string
1028 {
1029 myExit(EXIT_NUM_STRING_ABORT);
1030 }
1031 else if (gTimeOutOccured) //---- Timeout
1032 {
1033 myExit(EXIT_NUM_TIME_OUT);
1034 }
1035 else if (gExecTimeOutOccured)
1036 {
1037 myExit(EXIT_NUM_EXEC_TIME_OUT);
1038 }
1039 else //---- Normal end
1040 {
1041 myExit(EXIT_NUM_NO_ERROR);
1042 }
1043 //---- never reached here
1044
1045 //---- dummy to avoid warning
1046 return 0;
1047 }
1048