1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - tools - loadrun.TWL
3 File: loadrun.c
4
5 Copyright 2007-2008 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-07-15#$
14 $Rev: 7370 $
15 $Author: yada $
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 "isd_api.h"
29
30 #define SDK_BOOL_ALREADY_DEFINED_
31 #include <twl_win32.h>
32 #include <nitro/os/common/system.h>
33
34 extern const unsigned long SDK_DATE_OF_LATEST_FILE;
35
36 //---- Application name
37 #define EXEC_NAME "loadrun.TWL"
38 #define DEBUGGER_NAME "IS-TWL-DEBUGGER"
39
40
41 //---- Version string
42 #define VERSION_STRING " 1.7 Copyright 2007-2008 Nintendo. All right reserved."
43 // 1.7 Enabled HYBRID to run in NITRO mode (added -N)
44 // 1.6 Enabled display of final error
45 // 1.5 Made reference to debugging prohibit flag
46 // 1.4 Updated for matching only of end with serial specification
47 // 1.3 Official support for ISTD_DownloadGo function
48 // 1.2 Fixed print callback bug
49 // 1.1 Supported IS-TWL-DEBUGGER Ver.0.41
50 // 1.0 Published
51
52 //---- exit number
53 #define EXIT_NUM_NO_ERROR 207 // Successful exit (however, this will not result next time)
54 #define EXIT_NUM_USER_SIGNAL 206 // Forced exit by user (ctrl-C)
55 #define EXIT_NUM_EXEC_TIME_OUT 205 // Forced exit due to execution timeout
56 #define EXIT_NUM_TIME_OUT 204 // Forced exit due to display timeout
57 #define EXIT_NUM_SHOW_DEVICES 203 // Exit on device list display
58 #define EXIT_NUM_SHOW_USAGE 202 // Exit on help display
59 #define EXIT_NUM_SHOW_VERSION 201 // Exit on version display
60 #define EXIT_NUM_STRING_ABORT 200 // Forced exit by character string
61
62 #define EXIT_NUM_NO_DEVICE -1 // There are no available devices
63 #define EXIT_NUM_UNKNOWN_OPTION -2 // An unknown option was specified
64 #define EXIT_NUM_ILLEGAL_OPTION -3 // Illegal use of option
65 #define EXIT_NUM_NO_INPUT_FILE -4 // The specified file does not exist or cannot be opened
66 #define EXIT_NUM_NOT_CONNECT -5 // Failed to connect to device
67 #define EXIT_NUM_CANNOT_USE_CARTRIDGE -6 // Failed to lock cartridge
68 #define EXIT_NUM_CANNOT_USE_CARD -7 // Failed to lock card
69 #define EXIT_NUM_PRINTF_ERROR -8 // Error while handling printf data
70 #define EXIT_NUM_LOADING_ERROR -9 // Error during loading
71 #define EXIT_NUM_EXEC_PROHIBITION -10 // Execution is not allowed
72 #define EXIT_NUM_NO_HYBRID_NITRO -11 // Cannot execute HYBRID with NITRO
73
74 //---- Maximum console count
75 #define PRINT_CONSOLE_MAX 4
76
77 //---- ROM header information
78 #define RH_FLAG_OFFSET 0x1c // Various information flags in the ROM header
79 #define RH_FLAG_DEBUGGER_PROHIBITION (1<<3) // Cannot run debugger with this bit raised
80
81 //---- For device specification
82 char *gDeviceName[] = {
83 "TWLEMU", "TWLDEB", NULL
84 };
85 int gDeviceTypeArray[] = {
86 ISTD_DEVICE_IS_TWL_EMULATOR,
87 ISTD_DEVICE_IS_TWL_DEBUGGER,
88 };
89
90 //---- Operating mode
91 BOOL gQuietMode = FALSE; // Quiet mode
92 BOOL gVerboseMode = FALSE; // verbose mode
93 BOOL gDebugMode = FALSE; // Debug mode
94
95 BOOL gStdinMode = FALSE; // stdin mode
96
97 BOOL gIsForceNitro = FALSE; // Set hybrid to NITRO mode?
98
99 BOOL gIsTypeSpecified = FALSE; // Is there a device type specification?
100 int gSpecifiedType; // Device type if one is specified
101
102 BOOL gIsSerialSpecified = FALSE; // Is there a serial number specification?
103 int gSpecifiedSerial; // Serial number if one was specified
104
105 BOOL gIsCartridgeLocked = FALSE; // Should the cartridge slot be locked?
106 BOOL gIsCardLocked = FALSE; // Should the card slot be locked?
107
108 int gTimeOutTime = 0; // Timeout interval in sec (0 indicates no timeout)
109 BOOL gTimeOutOccured = FALSE; // Has a timeout occurred?
110
111 int gExecTimeOutTime = 0; // Execution timeout interval in sec (0 indicates no timeout)
112 int gExecTimeOutOccured = FALSE; // Has an execution timeout occurred?
113
114 char *gAbortString = NULL; // Abort string
115 BOOL gStringAborted = FALSE; // Has execution terminated due to the abort string?
116
117 BOOL gExitAborted = FALSE; // Exit from OS_Exit()
118 int gExitStatusNum = EXIT_NUM_STRING_ABORT; // Return value when terminated by OS_Exit()
119 int gExitStrLength; // Length of exit string
120
121 BOOL gShowArchitecture = FALSE; // Show the architecture?
122 BOOL gShowConsoleNum = FALSE; // Show the console number?
123
124
125 //---- For TWL library
126 HINSTANCE gDllInstance;
127 ISDDEVICEHANDLE gDeviceHandle;
128 ISDDEVICEID gDeviceId;
129
130 //Connected to the device? (for slot switch)
131 BOOL gDeviceConnected = FALSE;
132
133
134 //---- Device list
135 #define DEVICE_MAX_NUM 256
136 #define DEVICE_SERIAL_NONE 0x7fffffff // means no specified
137 ISTDDevice gDeviceList[DEVICE_MAX_NUM];
138 int gCurrentDevice = -1;
139 int gConnectedDeviceNum = 0;
140
141 int gDeviceTypeSpecified = ISTD_DEVICE_NONE;
142 int gDeviceSerialSpecified = DEVICE_SERIAL_NONE; // means no specified
143 #define DEVICE_SERIAL_STRING_MAX_SIZE 256
144 char gDeviceSerialString[DEVICE_SERIAL_STRING_MAX_SIZE];
145 int gDeviceSerialStringLen = 0;
146
147 //---- Input file
148 #define FILE_NAME_MAX_SIZE 1024
149 FILE *gInputFile;
150 char gInputFileNameString[FILE_NAME_MAX_SIZE];
151 BOOL gIsInputFileOpened = FALSE;
152
153 //---- Time
154 time_t gStartTime = 0; // Start time
155 BOOL gIsLineHead[PRINT_CONSOLE_MAX] = {TRUE, TRUE, TRUE, TRUE}; // Start of line?
156 BOOL gShowLapTime = FALSE;
157
158 //---- Signal
159 BOOL gStoppedByUser = FALSE; // Indicates whether execution was stopped by the user.
160
161 //---- Displayed?
162 volatile BOOL gIsOutputString = FALSE;
163
164
165 #define printfIfNotQuiet(str) do{if(!gQuietMode){fputs(str,stdout);}}while(0)
166
167 void displayErrorAndExit(int exitNum, char *message);
168 BOOL outputString(TWLArch arch, int console, char *buf, int bufSize);
169
170 static void printCallback( LPVOID user, ISDCPUARCH arch, DWORD console, const void* recvBuf, DWORD size );
171 void checkFileFlag(void);
172
173 /*---------------------------------------------------------------------------*
174 Name: myExit
175
176 Description: similar to exit()
177
178 Arguments: exitNum: exit() number
179
180 Returns: None.
181 *---------------------------------------------------------------------------*/
myExit(int exitNum)182 void myExit(int exitNum)
183 {
184 //---- Turns off the slot for the cartridge and card
185 if (gDeviceConnected)
186 {
187 // (void)ISNTD_CartridgeSlotPower(gDeviceHandle, FALSE);
188 // (void)ISNTD_CardSlotPower(gDeviceHandle, FALSE);
189 }
190
191 //---- Deallocate DLL memory
192 // ISNTD_FreeDll();
193 ISTD_FreeDll();
194
195 if (!gQuietMode)
196 {
197 if (exitNum == EXIT_NUM_USER_SIGNAL)
198 {
199 printf("\n*** %s: stopped by user.\n", EXEC_NAME);
200 }
201 else if (exitNum == EXIT_NUM_TIME_OUT)
202 {
203 printf("\n*** %s: stopped by print timeout.\n", EXEC_NAME);
204 }
205 else if (exitNum == EXIT_NUM_EXEC_TIME_OUT)
206 {
207 printf("\n*** %s: stopped by exec timeout.\n", EXEC_NAME);
208 }
209 else if (gStringAborted)
210 {
211 printf("\n*** %s: stopped by aborting string.\n", EXEC_NAME);
212 }
213 else if (gExitAborted)
214 {
215 exitNum = gExitStatusNum;
216 }
217 }
218
219 exit(exitNum);
220 }
221
222 /*---------------------------------------------------------------------------*
223 Name: listDevice
224
225 Description: Displays a list of devices and terminates
226
227 Arguments: None.
228
229 Returns: None.
230 *---------------------------------------------------------------------------*/
listDevice(void)231 void listDevice(void)
232 {
233 int n;
234
235 //---- Device read
236 gConnectedDeviceNum = ISTD_GetDeviceList(&gDeviceList[0], DEVICE_MAX_NUM);
237 if (gConnectedDeviceNum < 0)
238 {
239 displayErrorAndExit(EXIT_NUM_NO_DEVICE, "Cannot access devices.");
240 }
241
242 printf("---- Connected devices:\n");
243
244 for (n = 0; n < gConnectedDeviceNum; n++)
245 {
246 switch (gDeviceList[n].type)
247 {
248 case ISTD_DEVICE_IS_TWL_EMULATOR:
249 printf("%3d: [IS-TWL-DEBUGGER] serial:%8d\n", n, gDeviceList[n].serial);
250 break;
251 case ISTD_DEVICE_IS_TWL_DEBUGGER:
252 printf("%3d: [%s] serial:%8d\n", n, DEBUGGER_NAME, gDeviceList[n].serial);
253 break;
254 case ISTD_DEVICE_UNKNOWN:
255 printf("%3d: unknown device %x:%x\n", n, (int)gDeviceList[n].id.eType, (int)gDeviceList[n].id.nSerial );
256 break;
257 default:
258 printf("Illegal device\n");
259 break;
260 }
261 }
262
263 //---- Search result
264 printf("Found %d device%s.\n", gConnectedDeviceNum, (gConnectedDeviceNum<=1)?"":"s" );
265
266 myExit(EXIT_NUM_SHOW_DEVICES);
267 }
268
269 /*---------------------------------------------------------------------------*
270 Name: searchDevice
271
272 Description: search device
273
274 Arguments: None.
275
276 Returns: None.
277 *---------------------------------------------------------------------------*/
searchDevice(void)278 void searchDevice(void)
279 {
280 int tmpMatch = -1;
281 int tmpMatchCount = 0;
282
283 //---- If there is no device
284 if (gConnectedDeviceNum <= 0)
285 {
286 displayErrorAndExit(EXIT_NUM_NO_DEVICE, "found no device.");
287 }
288
289 //---- First one if no device has been specified
290 if (gDeviceTypeSpecified == ISTD_DEVICE_NONE && gDeviceSerialSpecified == DEVICE_SERIAL_NONE)
291 {
292 gCurrentDevice = 0;
293 }
294 //---- There is a device or serial specification
295 else
296 {
297 int n;
298 char tmpStr[DEVICE_SERIAL_STRING_MAX_SIZE];
299 char tmpStrLen;
300
301 gCurrentDevice = -1;
302 for (n = 0; n < gConnectedDeviceNum; n++)
303 {
304 //---- Matching with specified device
305 if (gDeviceTypeSpecified != ISTD_DEVICE_NONE && gDeviceTypeSpecified != gDeviceList[n].type)
306 {
307 continue;
308 }
309
310 //---- Matching with specified serial
311 if (gDeviceSerialSpecified != DEVICE_SERIAL_NONE )
312 {
313 //---- Equal
314 if ( gDeviceSerialSpecified == gDeviceList[n].serial )
315 {
316 gCurrentDevice = n;
317 break;
318 }
319
320 //---- Partial matching because not equal
321 sprintf( tmpStr, "%d", gDeviceList[n].serial );
322 tmpStrLen = strlen(tmpStr);
323
324 if ( ( tmpStrLen > gDeviceSerialStringLen ) &&
325 ( ! strcmp( &tmpStr[ tmpStrLen - gDeviceSerialStringLen ], gDeviceSerialString ) ) )
326 {
327 tmpMatch = n;
328 tmpMatchCount ++;
329 }
330 }
331 }
332 }
333
334 //---- If there is one partial match
335 if ( gCurrentDevice < 0 )
336 {
337 if ( tmpMatchCount == 1 )
338 {
339 gCurrentDevice = tmpMatch;
340 }
341 else if ( tmpMatchCount >= 2 )
342 {
343 displayErrorAndExit(EXIT_NUM_NO_DEVICE, "two or more devices matched to sperified serial number." );
344 }
345 }
346
347 //---- The specified device does not exist or is incorrect
348 if (gCurrentDevice < 0
349 || gDeviceList[gCurrentDevice].type == ISTD_DEVICE_NONE
350 || gDeviceList[gCurrentDevice].type == ISTD_DEVICE_UNKNOWN)
351 {
352 displayErrorAndExit(EXIT_NUM_NO_DEVICE, "illegal device.");
353 }
354 }
355
356 /*---------------------------------------------------------------------------*
357 Name: displayUsage
358
359 Description: Displays the usage
360
361 Arguments: None.
362
363 Returns: None.
364 *---------------------------------------------------------------------------*/
displayUsage(void)365 void displayUsage(void)
366 {
367 fprintf(stderr,
368 "TWL-SDK Development Tool - %s - Execute TWL ROM image\n"
369 "Build %lu\n\n"
370 "Usage: %s [OPTION] <SrlFile>\n"
371 "\tdownload TWL srl file to %s and execute.\n\n"
372 "Options:\n"
373 " --version : Show %s version.\n"
374 " --debuggerVersion : Show debugger version.\n"
375 " -h, --help : Show this help.\n"
376 " -q, --quiet : Quiet mode.\n"
377 " -v, --verbose : Verbose mode.\n"
378 " -L, --list : List connecting device.\n"
379 " -N, --nitro : Run hybrid rom as NITRO mode\n"
380 " -l, --lap : Show lap time at each line.\n"
381 // " -d, --type=DEVICE : Specify device type.\n"
382 // " DEVICE=TWLEMU|TWLDEB.\n"
383 " -A, --architecture : Show architecture at each line.\n"
384 " -n, --console : Show console number at each line.\n"
385 " -s, --serial=SERIAL : Specify serial number.\n"
386 " -t, --timeout=SECOND : Specify quit time after last print.\n"
387 " -T, --exec-timeout=SECOND : Specify quit time after execute program.\n"
388 " -a, --abort-string=STRING : Specify aborting string.\n"
389 " -c, --card-slot=SWITCH : Card slot SWITCH=ON|OFF, default OFF.\n"
390 " -C, --cartridge-slot=SWITCH : Cartridge slot SWITCH=ON|OFF, default OFF.\n",
391 // " --stdin, --standard-input : Read data from stdin instead of <SrlFile>.\n\n",
392 EXEC_NAME,
393 SDK_DATE_OF_LATEST_FILE,
394 EXEC_NAME,
395 DEBUGGER_NAME,
396 EXEC_NAME );
397 }
398
399 /*---------------------------------------------------------------------------*
400 Name: displayVersion
401
402 Description: Displays the version
403
404 Arguments: None.
405
406 Returns: None.
407 *---------------------------------------------------------------------------*/
displayVersion(void)408 void displayVersion(void)
409 {
410 printf("*** %s: %s\n", EXEC_NAME, VERSION_STRING);
411 }
412
413 /*---------------------------------------------------------------------------*
414 Name: displayDebuggerVersion
415
416 Description: Displays debugger version.
417
418 Arguments: None.
419
420 Returns: None.
421 *---------------------------------------------------------------------------*/
displayDebuggerVersion(void)422 void displayDebuggerVersion(void)
423 {
424 BOOL r;
425 DWORD major;
426 DWORD minor;
427 DWORD build;
428 DWORD revision;
429 r = ISTD_GetVersion( &major, &minor, &build, &revision);
430
431 if (r)
432 {
433 printf("*** %s: %s version is %d.%d.%04d.%04d\n",
434 EXEC_NAME, DEBUGGER_NAME, (int)major, (int)minor, (int)build, (int)revision);
435 }
436 else
437 {
438 printf("*** %s: failed to get %s version.\n", EXEC_NAME, DEBUGGER_NAME );
439 }
440 myExit(EXIT_NUM_NO_ERROR);
441 }
442
443 /*---------------------------------------------------------------------------*
444 Name: displayErrorAndExit
445
446 Description: Displays errors.
447
448 Arguments: None.
449
450 Returns: None.
451 *---------------------------------------------------------------------------*/
displayErrorAndExit(int exitNum,char * message)452 void displayErrorAndExit(int exitNum, char *message)
453 {
454 if (gDebugMode)
455 {
456 printf("last error=%lx\n", ISTD_GetLastError());
457 }
458
459 printf("*** %s: Error: %s\n", EXEC_NAME, message);
460
461 //---- Deallocate DLL memory
462 ISTD_FreeDll();
463
464 exit(exitNum);
465 }
466
467 /*---------------------------------------------------------------------------*
468 Name: parseOption
469
470 Description: parses the option line
471
472 Arguments: argc : argument count
473 argv: argument vector
474
475 Returns: result. less than 0 if error.
476 *---------------------------------------------------------------------------*/
parseOption(int argc,char * argv[])477 void parseOption(int argc, char *argv[])
478 {
479 int n;
480 int c;
481 BOOL helpFlag = FALSE;
482
483 struct option optionInfo[] = {
484 {"help", no_argument, NULL, 'h'},
485 {"quiet", no_argument, NULL, 'q'},
486 {"verbose", no_argument, NULL, 'v'},
487 {"list", no_argument, NULL, 'L'},
488 {"nitro", no_argument, NULL, 'N'},
489 {"lap", no_argument, NULL, 'l'},
490 {"debug", no_argument, NULL, 'D'}, //Hidden options
491 {"version", no_argument, NULL, '1'},
492 {"debuggerVersion", no_argument, NULL, '2'},
493 // {"stdin", no_argument, NULL, 'I'},
494 // {"standard-input", no_argument, NULL, 'I'},
495 {"type", required_argument, 0, 'd'}, //Hidden options
496 {"serial", required_argument, 0, 's'},
497 {"timeout", required_argument, 0, 't'},
498 {"exec-timeout", required_argument, 0, 'T'},
499 {"abort-string", required_argument, 0, 'a'},
500 {"card-slot", required_argument, 0, 'c'},
501 {"cartridge-slot", required_argument, 0, 'C'},
502 {"architecture", no_argument, NULL, 'A'},
503 {"console", no_argument, NULL, 'n'},
504 {NULL, 0, 0, 0}
505 };
506 int optionIndex;
507
508 char *optionStr = NULL;
509
510 //---- suppress error string of getopt_long()
511 opterr = 0;
512
513 while (1)
514 {
515 c = getopt_long(argc, argv, "+hqvLNlDd:s:t:T:a:c:C:An", &optionInfo[0], &optionIndex);
516
517 //printf("optind=%d optopt=%d %x(%c) \n", optind, optopt, c,c );
518
519 if (c == -1)
520 {
521 break;
522 }
523
524 switch (c)
525 {
526 case 'I': //---- Standard input
527 gStdinMode = TRUE;
528 break;
529 case 'h': //---- Help display
530 helpFlag = TRUE;
531 break;
532 case 'q': //---- Quiet mode
533 gQuietMode = TRUE;
534 break;
535 case 'v': //---- Verbose mode
536 gVerboseMode = TRUE;
537 break;
538 case 'D': //---- Debug mode
539 gDebugMode = TRUE;
540 break;
541 case '1': //---- Program version display
542 displayVersion();
543 myExit(EXIT_NUM_SHOW_VERSION);
544 break;
545 case '2': //---- Debugger version display
546 displayDebuggerVersion();
547 myExit(EXIT_NUM_SHOW_VERSION);
548 break;
549 case 'L': //---- Device list
550 listDevice();
551 break;
552 case 'N': //---- Set hybrid to NITRO mode
553 gIsForceNitro = TRUE;
554 break;
555 case 'l': //---- Lap time
556 gShowLapTime = TRUE;
557 break;
558 case 'A':
559 gShowArchitecture = TRUE; // Display architecture
560 break;
561 case 'n':
562 gShowConsoleNum = TRUE; // Display console number
563 break;
564 case 'd': //---- Device
565 optionStr = (char *)(optarg + ((*optarg == '=') ? 1 : 0));
566 {
567 int n;
568 for (n = 0; gDeviceName[n]; n++)
569 {
570 if (!strcmp(optionStr, gDeviceName[n]))
571 {
572 gDeviceTypeSpecified = gDeviceTypeArray[n];
573 break;
574 }
575 }
576
577 if (gDeviceTypeSpecified == ISTD_DEVICE_NONE)
578 {
579 displayErrorAndExit(EXIT_NUM_ILLEGAL_OPTION, "illegal device type.");
580 }
581 }
582 break;
583 case 's': //---- Serial specification
584 optionStr = (char *)(optarg + ((*optarg == '=') ? 1 : 0));
585 gDeviceSerialSpecified = atoi(optionStr);
586 strncpy(gDeviceSerialString, optionStr, DEVICE_SERIAL_STRING_MAX_SIZE);
587 gDeviceSerialString[DEVICE_SERIAL_STRING_MAX_SIZE-1] = '\0';
588 gDeviceSerialStringLen = strlen( gDeviceSerialString );
589 break;
590 case 'c': //---- Card slot lock
591 optionStr = (char *)(optarg + ((*optarg == '=') ? 1 : 0));
592 if (!strcmp(optionStr, "ON") || !strcmp(optionStr, "on"))
593 {
594 gIsCardLocked = TRUE;
595 }
596 else if (!strcmp(optionStr, "OFF") || !strcmp(optionStr, "off"))
597 {
598 gIsCardLocked = FALSE;
599 }
600 else
601 {
602 displayErrorAndExit(EXIT_NUM_ILLEGAL_OPTION, "illegal value for card slot option.");
603 }
604 break;
605 case 'C': //---- Cartridge slot lock
606 optionStr = (char *)(optarg + ((*optarg == '=') ? 1 : 0));
607 if (!strcmp(optionStr, "ON") || !strcmp(optionStr, "on"))
608 {
609 gIsCartridgeLocked = TRUE;
610 }
611 else if (!strcmp(optionStr, "OFF") || !strcmp(optionStr, "off"))
612 {
613 gIsCartridgeLocked = FALSE;
614 }
615 else
616 {
617 displayErrorAndExit(EXIT_NUM_ILLEGAL_OPTION,
618 "illegal value for cartridge slot option.");
619 }
620 break;
621 case 't': //---- Timeout interval beginning from final display
622 optionStr = (char *)(optarg + ((*optarg == '=') ? 1 : 0));
623 gTimeOutTime = atoi(optionStr);
624 if (gTimeOutTime <= 0)
625 {
626 displayErrorAndExit(EXIT_NUM_ILLEGAL_OPTION,
627 "illegal value for abort timeout option.");
628 }
629 break;
630 case 'T': //---- Execution timeout interval
631 optionStr = (char *)(optarg + ((*optarg == '=') ? 1 : 0));
632 gExecTimeOutTime = atoi(optionStr);
633 if (gExecTimeOutTime <= 0)
634 {
635 displayErrorAndExit(EXIT_NUM_ILLEGAL_OPTION,
636 "illegal value for abort exec timeout option.");
637 }
638 break;
639 case 'a': //---- Abort string
640 gAbortString = (char *)(optarg + ((*optarg == '=') ? 1 : 0));
641 {
642 int length = strlen(gAbortString);
643 if (length <= 0 || length > 256)
644 {
645 displayErrorAndExit(EXIT_NUM_ILLEGAL_OPTION,
646 "illegal value for abort string option.");
647 }
648 }
649 break;
650 default:
651 displayErrorAndExit(EXIT_NUM_UNKNOWN_OPTION, "unknown option.");
652 }
653 }
654
655 //---- Help display
656 {
657 BOOL isDisplayHelp = FALSE;
658
659 if (helpFlag)
660 {
661 isDisplayHelp = TRUE;
662 }
663 else if (argc <= optind && !gStdinMode)
664 {
665 isDisplayHelp = TRUE;
666 }
667 else if (argc > optind && gStdinMode)
668 {
669 isDisplayHelp = TRUE;
670 }
671
672 if (isDisplayHelp)
673 {
674 displayUsage();
675 exit(EXIT_NUM_SHOW_USAGE);
676 }
677 }
678
679 //---- Input file name
680 if (!gStdinMode)
681 {
682 strncpy(gInputFileNameString, argv[optind], FILE_NAME_MAX_SIZE);
683 }
684
685 if (gVerboseMode)
686 {
687 if (!gStdinMode)
688 {
689 printf("Input file is [%s]\n", gInputFileNameString);
690 }
691 else
692 {
693 printf("Input file is stdin\n");
694 }
695 }
696
697 //---- Information display
698 if (gVerboseMode)
699 {
700 printf("Print time out : %d sec.\n", gTimeOutTime);
701 printf("Execute time out : %d sec.\n", gExecTimeOutTime);
702 printf("Card lock : %s.\n", (gIsCardLocked) ? "ON" : "OFF");
703 printf("Cartridge lock : %s.\n", (gIsCartridgeLocked) ? "ON" : "OFF");
704
705 if (gAbortString)
706 {
707 printf("Abort string : [%s]\n", gAbortString);
708 }
709 }
710 }
711
712 /*---------------------------------------------------------------------------*
713 Name: loadFile
714
715 Description: loads file
716
717 Arguments: None.
718
719 Returns: None.
720 *---------------------------------------------------------------------------*/
loadFile(void)721 void loadFile(void)
722 {
723 unsigned int address = 0;
724
725 //---- File open
726 if (gStdinMode)
727 {
728 gInputFile = stdin;
729 _setmode(_fileno(gInputFile), O_BINARY);
730 }
731 else
732 {
733 if ((gInputFile = fopen(gInputFileNameString, "rb")) == NULL)
734 {
735 displayErrorAndExit(EXIT_NUM_NO_INPUT_FILE, "cannot open input file.");
736 }
737 }
738 gIsInputFileOpened = TRUE;
739
740 //---- Check file
741 checkFileFlag();
742
743 //---- Connected to device
744 if ((gDeviceHandle = ISTD_OpenEx(gDeviceList[gCurrentDevice].id)) == NULL)
745 {
746 displayErrorAndExit(EXIT_NUM_NOT_CONNECT, "cannot connect device.");
747 }
748 gDeviceConnected = TRUE;
749
750 //---- Issue reset
751 ISTD_Reset(gDeviceHandle, TRUE);
752 Sleep(1000);
753
754 //----- Specify print callback
755 ISTD_PrintfSetCB( gDeviceHandle, printCallback, (void*)0 );
756
757 //---- Set mode for hybrid
758 if ( ISTD_SetHybridMode )
759 {
760 ISTD_SetHybridMode( gDeviceHandle, gIsForceNitro? ISDHYBRID_NTR: ISDHYBRID_TWL );
761 }
762 else
763 {
764 if ( gIsForceNitro )
765 {
766 displayErrorAndExit(EXIT_NUM_LOADING_ERROR, "cannot run as NITRO mode. The required version of IS-TWL-DEBUGGER is v0.64 or later.");
767 }
768 }
769
770 //---- Download and startup ROM data
771 if ( ! ISTD_DownloadGo( gDeviceHandle, gInputFileNameString ) )
772 {
773 displayErrorAndExit(EXIT_NUM_LOADING_ERROR, "troubled while loading input file.");
774 }
775
776 #if 0
777 //---- Transfer every 16KB
778 while (1)
779 {
780 char buf[16384];
781 size_t size = fread(buf, 1, sizeof(buf), gInputFile);
782 static int progressCount = 0;
783
784 if (!size)
785 {
786 break;
787 }
788
789 //---- Transfer
790 if (!ISTD_WriteROM(gDeviceHandle, buf, address, size))
791 {
792 displayErrorAndExit(EXIT_NUM_LOADING_ERROR, "troubled while loading input file.");
793 }
794
795 address += size;
796
797 if (gVerboseMode)
798 {
799 if (!(progressCount++ % 32))
800 {
801 printf("*");
802 }
803 }
804 }
805 #endif
806
807 //---- File close
808 if (gStdinMode)
809 {
810 _setmode(_fileno(gInputFile), O_TEXT);
811 }
812 else
813 {
814 fclose(gInputFile);
815 }
816 gIsInputFileOpened = FALSE;
817
818 if (gVerboseMode)
819 {
820 printf("\nInput file size: %d (0x%x) byte\n", address, address);
821 }
822 }
823
824 /*---------------------------------------------------------------------------*
825 Name: checkFileFlag
826
827 Description: Checks ROM header execution flag.
828
829 Arguments: None.
830
831 Returns: None.
832 *---------------------------------------------------------------------------*/
checkFileFlag(void)833 void checkFileFlag(void)
834 {
835 char buf[0x100];
836
837 fseek( gInputFile, 0, SEEK_SET );
838 fread( buf, 1, sizeof(buf), gInputFile );
839
840 //---- Whether debugger can be run
841 if ( buf[RH_FLAG_OFFSET] & RH_FLAG_DEBUGGER_PROHIBITION )
842 {
843 displayErrorAndExit(EXIT_NUM_EXEC_PROHIBITION, "cannot exec this file. (debugger forbidden)");
844 }
845
846 //---- rewind
847 rewind( gInputFile );
848 }
849
850 /*---------------------------------------------------------------------------*
851 Name: setSlopPower
852
853 Description: Slot power process
854
855 Arguments: None.
856
857 Returns: None.
858 *---------------------------------------------------------------------------*/
setSlotPower(void)859 void setSlotPower(void)
860 {
861 //---- Should the cartridge slot be locked?
862 if (gIsCartridgeLocked)
863 {
864 // if (!ISNTD_CartridgeSlotPower(gDeviceHandle, TRUE))
865 if (0)
866 {
867 displayErrorAndExit(EXIT_NUM_CANNOT_USE_CARTRIDGE, "cannot use cartridge slot.");
868 }
869 }
870
871 //---- Should the card slot be locked?
872 if (gIsCardLocked)
873 {
874 // if (!ISNTD_CardSlotPower(gDeviceHandle, TRUE))
875 if (0)
876 {
877 displayErrorAndExit(EXIT_NUM_CANNOT_USE_CARD, "cannot use card slot.");
878 }
879 }
880
881 #if 0
882 //---- Cancel reset
883 Sleep(1000);
884 ISTD_Reset(gDeviceHandle, FALSE);
885 #endif
886 }
887
888
889 /*---------------------------------------------------------------------------*
890 Name: procPrint
891
892 Description: printf process
893
894 Arguments: None.
895
896 Returns: None.
897 *---------------------------------------------------------------------------*/
898 TWLArch archNum[] = {
899 TWLArchARM9,
900 TWLArchARM7
901 };
902
903 #define PRINT_ONETIME_SIZE 512
904 #define PRINT_CONSOLE_MAX 4
905
906 //---- Buffer for joint display
907 static char gConbineBuf[PRINT_CONSOLE_MAX][PRINT_ONETIME_SIZE * 2 + 2] = {"\0", "\0", "\0", "\0" };
908
909 static char *gConbineBufPtr[PRINT_CONSOLE_MAX] = {&gConbineBuf[0][0],
910 &gConbineBuf[1][0],
911 &gConbineBuf[2][0],
912 &gConbineBuf[3][0] };
913
914 //---- Buffer for joining and comparing character strings
915 static char gLineBuf[PRINT_ONETIME_SIZE + 1];
916
917
procPrintf(void)918 void procPrintf(void)
919 {
920 int blankTime = 0;
921
922 //---- Size of exit string
923 gExitStrLength = strlen(OS_EXIT_STRING_1);
924
925 while (1)
926 {
927 //---- When stopped by the user
928 if (gStoppedByUser)
929 {
930 myExit(EXIT_NUM_USER_SIGNAL);
931 }
932
933 //---- Exit?
934 if (gStringAborted || gExitAborted)
935 {
936 break;
937 }
938
939 //---- If text is not being displayed
940 if (!gIsOutputString)
941 {
942 Sleep(100);
943 blankTime += 100;
944
945 //---- Timeout decision
946 if (gTimeOutTime && blankTime > gTimeOutTime * 1000)
947 {
948 gTimeOutOccured = TRUE;
949 break;
950 }
951 }
952 //---- If text has been displayed
953 else
954 {
955 gIsOutputString = FALSE;
956 blankTime = 0;
957 }
958
959 //---- Timeout check
960 if (gExecTimeOutTime > 0)
961 {
962 time_t currentTime;
963 (void)time(¤tTime);
964
965 if (currentTime - gStartTime >= gExecTimeOutTime)
966 {
967 gExecTimeOutOccured = TRUE;
968 break;
969 }
970 }
971 }
972 }
973
974 /*---------------------------------------------------------------------------*
975 Name: printCallback
976
977 Description: Print callback
978
979 Arguments: user :
980 arch :
981 console :
982 recvBuf :
983 size:
984
985 Returns: None.
986 *---------------------------------------------------------------------------*/
printCallback(LPVOID user,ISDCPUARCH arch,DWORD console,const void * recvBuf,DWORD size)987 static void printCallback( LPVOID user, ISDCPUARCH arch, DWORD console, const void* recvBuf, DWORD size )
988 {
989 //printf("%d arch:%d console:%d buf:%x size:%d\n", (int)user, (int)arch, (int)console, (int)recvBuf, (int)size );
990 gIsOutputString = TRUE;
991 outputString(arch, console, (char*)recvBuf, size);
992 }
993
994 /*---------------------------------------------------------------------------*
995 Name: showLapTime
996
997 Description: displays lap time at line head
998
999 Arguments: None.
1000
1001 Returns: None.
1002 *---------------------------------------------------------------------------*/
showLapTime(void)1003 void showLapTime(void)
1004 {
1005 int lap;
1006 time_t currentTime;
1007
1008 (void)time(¤tTime);
1009 lap = currentTime - gStartTime;
1010
1011 printf("{%d:%02d}", lap / 60, lap % 60);
1012 }
1013
showAddition(TWLArch arch,int console)1014 void showAddition(TWLArch arch, int console)
1015 {
1016 static char* archStr[] = {"A9", "A7"};
1017 int archIndex = -1;
1018
1019 if ( gIsLineHead[console] )
1020 {
1021 if ( gShowArchitecture )
1022 {
1023 //---- Investigate architecture
1024 if ( arch == TWLArchARM9 )
1025 {
1026 archIndex=0;
1027 }
1028 else if ( arch == TWLArchARM7 )
1029 {
1030 archIndex=1;
1031 }
1032 }
1033 if ( !gShowConsoleNum )
1034 {
1035 console = -1;
1036 }
1037
1038 //---- Display architecture and console number
1039 if ( archIndex<0 && console<0 )
1040 {
1041 // do nothing
1042 }
1043 else if ( archIndex<0 )
1044 {
1045 printf("<%d>", console );
1046 }
1047 else if ( console<0 )
1048 {
1049 printf("<%s>", archStr[archIndex] );
1050 }
1051 else
1052 {
1053 printf("<%s:%d>", archStr[archIndex], console );
1054 }
1055
1056 //---- Time display
1057 if (!gQuietMode && gShowLapTime)
1058 {
1059 showLapTime();
1060 }
1061 }
1062 }
1063
1064 /*---------------------------------------------------------------------------*
1065 Name: outputString
1066
1067 Description: outputs string to stdout
1068
1069 Arguments: arch : architecture(TWLArchARM9, TWLArchARM7, None)
1070 console : console num (0-3, -1)
1071 buf: buffer
1072 bufSize: data size in buffer
1073
1074 Returns: FALSE if to do quit.
1075 *---------------------------------------------------------------------------*/
outputString(TWLArch arch,int console,char * buf,int bufSize)1076 BOOL outputString(TWLArch arch, int console, char *buf, int bufSize)
1077 {
1078 char *bufEnd = buf + bufSize;
1079 char *p = buf;
1080
1081 int abortStrLength = gAbortString ? strlen(gAbortString) : 0;
1082
1083 static int prevConsole = -1;
1084
1085 if ( prevConsole >= 0 && prevConsole != console )
1086 {
1087 gIsLineHead[prevConsole] = TRUE;
1088 printf("\n");
1089 }
1090 prevConsole = console;
1091
1092 while (p < bufEnd)
1093 {
1094 char *crPtr = strchr(p, '\n');
1095
1096 //---- \n missing
1097 if (!crPtr)
1098 {
1099 //---- Save for comparison
1100 strcat(gConbineBufPtr[console], p);
1101 gConbineBufPtr[console] += strlen(p);
1102
1103 //---- Additional information
1104 showAddition( arch, console );
1105 gIsLineHead[console] = FALSE;
1106
1107 //---- Display
1108 printfIfNotQuiet(p);
1109
1110 //---- Destroy if buffer overflows (the responsibility is on the output side to insert \n)
1111 if (gConbineBufPtr[console] - &gConbineBuf[console][0] > PRINT_ONETIME_SIZE)
1112 {
1113 gConbineBufPtr[console] = &gConbineBuf[console][0];
1114 *gConbineBufPtr[console] = '\0';
1115 }
1116
1117 break;
1118 }
1119
1120 //---- copy up to \n
1121 {
1122 int n = crPtr - p + 1;
1123
1124 //---- Combine for comparison
1125 strncpy(gConbineBufPtr[console], p, n);
1126 gConbineBufPtr[console][n] = '\0';
1127
1128 //---- For display
1129 strncpy(&gLineBuf[0], p, n);
1130 gLineBuf[n] = '\0';
1131 }
1132
1133 //---- Additional information
1134 showAddition( arch, console );
1135 gIsLineHead[console] = TRUE;
1136
1137 //---- Line display
1138 printfIfNotQuiet(gLineBuf);
1139
1140 //---- Compare with abort string
1141 if (gAbortString && !strncmp(gConbineBuf[console], gAbortString, abortStrLength))
1142 {
1143 gStringAborted = TRUE;
1144 return FALSE;
1145 }
1146
1147 //---- Exit using OS_Exit
1148 if (!strncmp(gConbineBuf[console], OS_EXIT_STRING_1, gExitStrLength))
1149 {
1150 gExitAborted = TRUE;
1151 gExitStatusNum = atoi(gConbineBuf[console] + gExitStrLength);
1152 return FALSE;
1153 }
1154
1155 gConbineBufPtr[console] = &gConbineBuf[console][0];
1156 *gConbineBufPtr[console] = '\0';
1157
1158 p = crPtr + 1;
1159 }
1160
1161 return TRUE;
1162 }
1163
1164 /*---------------------------------------------------------------------------*
1165 Name: signalHandler
1166
1167 Description: signal handler
1168
1169 Arguments: sig
1170 argv: argument vector
1171
1172 Returns: ---
1173 *---------------------------------------------------------------------------*/
signalHandler(int sig)1174 void signalHandler(int sig)
1175 {
1176 gStoppedByUser = TRUE;
1177 }
1178
1179 /*---------------------------------------------------------------------------*
1180 Name: Main
1181
1182 Description: main proc
1183
1184 Arguments: argc : argument count
1185 argv: argument vector
1186
1187 Returns: ---
1188 *---------------------------------------------------------------------------*/
main(int argc,char * argv[])1189 int main(int argc, char *argv[])
1190 {
1191 //---- Initialize DLL
1192 ISTD_InitDll();
1193
1194 //---- Disable buffering of standard output
1195 setvbuf(stdout, NULL, _IONBF, 0);
1196
1197 //---- Option parsing
1198 parseOption(argc, argv);
1199
1200 //---- Device read
1201 gConnectedDeviceNum = ISTD_GetDeviceList(&gDeviceList[0], DEVICE_MAX_NUM);
1202 if (gConnectedDeviceNum < 0)
1203 {
1204 displayErrorAndExit(EXIT_NUM_NO_DEVICE, "Cannot access devices.");
1205 }
1206
1207 //---- Search for device
1208 searchDevice();
1209
1210 //---- Read
1211 loadFile();
1212
1213 //---- Signal setting
1214 (void)signal(SIGINT, signalHandler);
1215
1216 //---- Slot
1217 setSlotPower();
1218
1219 //---- Get start time
1220 (void)time(&gStartTime);
1221
1222 //---- printf process
1223 procPrintf();
1224
1225 //---- End
1226 if (gExitAborted) //---- Exit from OS_Exit()
1227 {
1228 myExit(gExitStatusNum);
1229 }
1230 else if (gStringAborted) //---- Abort string
1231 {
1232 myExit(EXIT_NUM_STRING_ABORT);
1233 }
1234 else if (gTimeOutOccured) //---- Timeout
1235 {
1236 myExit(EXIT_NUM_TIME_OUT);
1237 }
1238 else if (gExecTimeOutOccured)
1239 {
1240 myExit(EXIT_NUM_EXEC_TIME_OUT);
1241 }
1242 else //---- Normal end
1243 {
1244 myExit(EXIT_NUM_NO_ERROR);
1245 }
1246 //---- never reached here
1247
1248 //---- dummy to avoid warning
1249 return 0;
1250 }
1251