Пример #1
0
int main(int argc, char **argv) {
	int fd;
  int count;
	int index;
	struct termios oldtio,newtio;
	Uint8 buffer[257];	// temporary buffer for reads, largest response is a DATA response from an N64 DexDrive
	Uint32 length;
	DDType type;		// detected type
	DDResponse response;
	char *tmp;
	Uint32 framesdump;	// frames to dump (size of card)
	Uint32 framesize;	// size of each frame
	Uint16 i, j;
	FILE *outfile;
	struct timespec wait;
	Uint32 barsize;		// current length of the progress bar
	Uint32 barstep;		// pages per each progress bar char
	char *animation;
	Uint32 animlength;

	char *serialport = "/dev/ttyUSB0";
	char *memcardfile ="memcard.mcr";
	int blinklight = FALSE;

	//animation = ".oOo. ";
	animation = "-\\|/";
	animlength = strlen(animation);

	while((count = getopt (argc, argv, "bdf:hs:")) != -1)
		switch(count) {
			case 'b':
				blinklight = TRUE;
				break;
			case 'd':
				debug = TRUE;
				break;
			case 'f':
				memcardfile = optarg;
				break;
			case 'h':
				show_help();
				exit(-1);
				break;
			case 's':
				serialport = optarg;
				break;
			case '?':
				if ((optopt == 'f')||(optopt == 'm'))
					fprintf(stderr, "Option '-%c' requires an argument.\n", optopt);
				else if (isprint (optopt))
					fprintf(stderr, "Unknown option '-%c'.\n", optopt);
				else
				  fprintf(stderr, "Unknown option character '\\x%x'.\n", optopt);
				exit(-1);
			default:
				abort();
		}		
     
	if (debug) {
		fprintf(stdout, "DEBUG: serialport = %s, memcardfile = %s, blinklight = %d, debug = %d\n",
			      				serialport, memcardfile, blinklight, debug);
	}
															     
	
	for (index = optind; index < argc; index++) {
		fprintf(stderr, "Non-option argument %s\n", argv[index]);
		exit(-1);
	}

	if (access(memcardfile, F_OK) == 0) {
		fprintf(stderr, "File %s already exist, aborting.\n", memcardfile);
		exit(-1);
	}

	fd = open(serialport, O_RDWR | O_NOCTTY ); 
	if (fd < 0) {
		perror(serialport);
		cleanup(fd, oldtio, -1);
	}

	tcgetattr(fd,&oldtio); /* save current port settings */

	bzero(&newtio, sizeof(newtio));
	newtio.c_cflag = B38400 | CS8 | CLOCAL | CREAD ; // 38400 baud 8 bits no parity 1 stop bit
	newtio.c_iflag = IGNPAR | IXON | IXOFF;
	newtio.c_oflag = 0;

	/* set input mode (non-canonical, no echo,...) */
	newtio.c_lflag = 0;
 
	newtio.c_cc[VTIME]    = 100;	//Some operations are slow so give the device
									//a lot of time to complete (10 seconds)
	newtio.c_cc[VMIN]     = 0;		//Get whatever is available by the timeout

	tcflush(fd, TCIFLUSH);
	tcsetattr(fd,TCSANOW,&newtio);
	response = DDInit(fd, buffer, &length);
	if(response != ID) {
		tmp = DDStrResponse(response);
		fprintf(stderr, "Couldn't initialize device: %s.\n", tmp);
		free(tmp);
		cleanup(fd, oldtio, -1);
	}
	if(length != 5) {
		fprintf(stderr, "Device returned incomplete init response.\n");
		cleanup(fd, oldtio, -1);
	} else {
		tmp = HexOut(buffer, 5);
		fprintf(stdout, "Device initialized, returned %s\n", tmp);
		free(tmp);
		if(memcmp(&buffer[1], "PSX", 3) == 0) {
			fprintf(stdout, "Playstation DexDrive detected.\n");
			type = PSX;
			framesdump = 0x400;
			framesize = 128;
		} else if(memcmp(&buffer[1], "N64", 3) == 0) {
			fprintf(stdout, "Nintendo 64 DexDrive detected.\n");
			type = N64;
			framesdump = 0x80;
			framesize = 256;
		} else {
			fprintf(stderr, "Unknown DexDrive detected.\n");
			cleanup(fd, oldtio, -1);
		}
		barstep = framesdump / BARMAXSIZE;
	}
	response = DDHandshake(fd);
	if(response == ERROR) {
		if(type == PSX) {
			fprintf(stdout, "Handshake returned expected ERROR response for a Playstation dexdrive.\n");
		} else {
			fprintf(stderr, "N64 DexDrive returned ERROR in response to handshake.\n");
			cleanup(fd, oldtio, -1);
		}
	}
	response = DDStatus(fd, buffer, &length);
	fprintf(stdout, "%s.\n", DDStrResponse(response));
	switch(response) {
		case NOCARD:
			cleanup(fd, oldtio, -1);
			break;
		case CARD_NEW:
			break;
		case CARD:
			if(type == PSX && length == 1) {
				switch(buffer[0]) {
					case 0x00:
						fprintf(stdout, "Playstation DexDrive reports a successful write since last reset.\n");
						break;
					case 0x10:
						fprintf(stdout, "Playstation DexDrive reports no successful writes since last reset.\n");
						break;
					default:
						fprintf(stderr, "Playstation DexDrive returned an unknown status: %X.", buffer[0]);
						break;
				}
			}
			break;
		default:
			cleanup(fd, oldtio, -1);
			break;
	}
	outfile = fopen(memcardfile, "wb");
	if(outfile == NULL) {
		fprintf(stderr, "Couldn't open file for writing.\n");
		cleanup(fd, oldtio, -1);
	}
	wait.tv_sec = 0;
	wait.tv_nsec = 10000000;
	for(i = 0; i < framesdump; i++) {

		//print progress bar
		fputc('\r', stderr);
		fputc('|', stderr);
		barsize = i / barstep;
		for(j = 0; j < barsize; j++) {
			fputc('=', stderr);
		}
		for(j = 0; j < BARMAXSIZE - barsize; j++) {
			fputc('-', stderr);
		}
		fprintf(stderr, "| %c %i/%i", animation[i % animlength], i + 1, framesdump);

		if (debug) {
			fprintf(stdout, "\n");
		}

		if (blinklight) {
			response = DDLight(fd, 1);
		}

		response = DDRead(fd, i, buffer, &length, framesize + 1);
		if(length < framesize + 1) {
			fprintf(stderr, "Incomplete DATA response, expected %d bytes, got %d.\n", framesize + 1, length);
			if (blinklight) {
				response = DDLight(fd, 0);
			}
			cleanup(fd, oldtio, -1);
		}

		switch(response) {
			case NOCARD:
				fprintf(stderr, "No card is inserted or card removed.\n");
				if (blinklight) {
					response = DDLight(fd, 0);
				}
				cleanup(fd, oldtio, -1);
				break;
			case DATA:
				fwrite(buffer, sizeof(Uint8), framesize, outfile);
				break;
			default:
				tmp = DDStrResponse(response);
				fprintf(stderr, "Got an unexpected response: %s.\n", tmp);
				free(tmp);
				if (blinklight) {
					response = DDLight(fd, 0);
				}
				cleanup(fd, oldtio, -1);
				break;
		}

		if (blinklight) {
			response = DDLight(fd, 0);
		}

		nanosleep(&wait, NULL);
	}

	fclose(outfile);
	fprintf(stdout, "\nDump complete and saved as %s\n", memcardfile);
	cleanup(fd, oldtio, 0);
}
Пример #2
0
int main(int argc, char **argv) {
	int fd;
	struct termios oldtio,newtio;
	Uint8 buffer[257];	// temporary buffer for reads, largest response is a DATA response from an N64 DexDrive
	Uint32 length;
	DDType type;		// detected type
	DDResponse response;
	char *tmp;
	Uint32 framesdump;	// frames to dump (size of card)
	Uint32 framesize;	// size of each frame
	Uint16 i, j;
	FILE *outfile;
	struct timespec wait;
	Uint32 barsize;		// current length of the progress bar
	Uint32 barstep;		// pages per each progress bar char
	char *animation;
	Uint32 animlength;

	animation = ".oOo. ";
	animlength = strlen(animation);

	if(argc < 2) {
		fprintf(stderr, "USAGE: %s <serial device> [output file]\n", argv[0]);
		exit(-1);
	} else {
		fd = open(argv[1], O_RDWR | O_NOCTTY ); 
	}

	if (fd < 0) {
		perror(argv[1]);
		cleanup(fd, oldtio, -1);
	}

	tcgetattr(fd,&oldtio); /* save current port settings */

	bzero(&newtio, sizeof(newtio));
	newtio.c_cflag = B38400 | CS8 | CLOCAL | CREAD ; // 38400 baud 8 bits no parity 1 stop bit
	newtio.c_iflag = IGNPAR | IXON | IXOFF;
	newtio.c_oflag = 0;

	/* set input mode (non-canonical, no echo,...) */
	newtio.c_lflag = 0;
 
	newtio.c_cc[VTIME]    = 100;	//Some operations are slow so give the device
									//a lot of time to complete (10 seconds)
	newtio.c_cc[VMIN]     = 0;		//Get whatever is available by the timeout

	tcflush(fd, TCIFLUSH);
	tcsetattr(fd,TCSANOW,&newtio);
	response = DDInit(fd, buffer, &length);
	if(response != ID) {
		tmp = DDStrResponse(response);
		fprintf(stderr, "Couldn't initialize device: %s.\n", tmp);
		free(tmp);
		cleanup(fd, oldtio, -1);
	}
	if(length != 5) {
		fprintf(stderr, "Device returned incomplete init response.\n");
		cleanup(fd, oldtio, -1);
	} else {
		tmp = HexOut(buffer, 5);
		fprintf(stderr, "Device initialized, returned %s\n", tmp);
		free(tmp);
		if(memcmp(&buffer[1], "PSX", 3) == 0) {
			fprintf(stderr, "Playstation DexDrive detected.\n");
			type = PSX;
			framesdump = 0x400;
			framesize = 128;
		} else if(memcmp(&buffer[1], "N64", 3) == 0) {
			fprintf(stderr, "Nintendo 64 DexDrive detected.\n");
			type = N64;
			framesdump = 0x80;
			framesize = 256;
		} else {
			fprintf(stderr, "Unknown DexDrive detected.\n");
			cleanup(fd, oldtio, -1);
		}
		barstep = framesdump / BARMAXSIZE;
	}
	response = DDHandshake(fd);
	if(response == ERROR) {
		if(type == PSX) {
			fprintf(stderr, "Handshake returned expected ERROR response for a Playstation dexdrive.\n");
		} else {
			fprintf(stderr, "N64 DexDrive returned ERROR in response to handshake.\n");
			cleanup(fd, oldtio, -1);
		}
	}
	response = DDStatus(fd, buffer, &length);
	fprintf(stderr, "%s.\n", DDStrResponse(response));
	switch(response) {
		case NOCARD:
			cleanup(fd, oldtio, -1);
			break;
		case CARD_NEW:
			break;
		case CARD:
			if(type == PSX && length == 1) {
				switch(buffer[0]) {
					case 0x00:
						fprintf(stderr, "Playstation DexDrive reports a successful write since last reset.\n");
						break;
					case 0x10:
						fprintf(stderr, "Playstation DexDrive reports no successful writes since last reset.\n");
						break;
					default:
						fprintf(stderr, "Playstation DexDrive returned an unknown status: %X.", buffer[0]);
						break;
				}
			}
			break;
		default:
			cleanup(fd, oldtio, -1);
			break;
	}

	if(argc > 2) {
		outfile = fopen(argv[1], "wb");
	} else {
		outfile = fopen("memcard.bin", "wb");
	}

	if(outfile == NULL) {
		fprintf(stderr, "Couldn't open file for writing.\n");
		cleanup(fd, oldtio, -1);
	}

	wait.tv_sec = 0;
	wait.tv_nsec = 10000000;
	for(i = 0; i < framesdump; i++) {
#ifndef DEBUG
		fputc('\r', stderr);
		fputc('|', stderr);
		barsize = i / barstep;
		for(j = 0; j < barsize; j++) {
			fputc('=', stderr);
		}
		for(j = 0; j < BARMAXSIZE - barsize; j++) {
			fputc('-', stderr);
		}
		fprintf(stderr, "| %c %i/%i", animation[i % animlength], i + 1, framesdump);
#endif
#ifdef BLINKLIGHT
		response = DDLight(fd, 1);
#endif
		response = DDRead(fd, i, buffer, &length, framesize + 1);
		if(length < framesize + 1) {
			fprintf(stderr, "Incomplete DATA response, expected %d bytes, got %d.\n", framesize + 1, length);
#ifdef BLINKLIGHT
			response = DDLight(fd, 0);
#endif
			cleanup(fd, oldtio, -1);
		}
		switch(response) {
			case NOCARD:
				fprintf(stderr, "No card is inserted or card removed.\n");
#ifdef BLINKLIGHT
				response = DDLight(fd, 0);
#endif
				cleanup(fd, oldtio, -1);
				break;
			case DATA:
				fwrite(buffer, sizeof(Uint8), framesize, outfile);
				break;
			default:
				tmp = DDStrResponse(response);
				fprintf(stderr, "Got an unexpected response: %s.\n", tmp);
				free(tmp);
#ifdef BLINKLIGHT
				response = DDLight(fd, 0);
#endif
				cleanup(fd, oldtio, -1);
				break;
		}
#ifdef BLINKLIGHT
		response = DDLight(fd, 0);
#endif
		nanosleep(&wait, NULL);
	}

	fclose(outfile);
	cleanup(fd, oldtio, 0);
}