/* USB ADVANCE Linux HDD installer Original source: Zer0-X @ ps2-scene.org Linux port: crazyc @ ps2-scene.org Current version: tesla @ nixCoders.org Changes: - added support for large files (DVD iso rips) - added retry on error when reading disks - added progress info - clean up code to make it compile without warnings Jah bless and enjoy! */ #define _GNU_SOURCE 1 #include #include #include #include #include #include #include #include #include #define WHRIL "\\|/-!" #define RETRYCOUNT 255 #define BUFSIZE (2048 * 8192) /* must be an even factor of 2^30 */ typedef struct { char name[32]; char file_name[15]; char part; char media; char pad1[4]; char unk; char pad2[10]; } usbex_info_t; int error_exit(const char *msg) { printf("%s: %s\n", strerror(errno), msg); exit(-1); } unsigned int crc32(char *string) { int crc, table, count, byte; unsigned int crctab[256]; for (table=0; table<256; table++) { crc = table << 24; for (count=8; count>0; count--) { if (crc < 0) crc = crc << 1; else crc = (crc << 1) ^ 0x04C11DB7; } crctab[255-table] = crc; } do { byte = string[count++]; crc = crctab[byte ^ ((crc >> 24) & 0xFF)] ^ ((crc << 8) & 0xFFFFFF00); } while (string[count-1] != 0); return crc; } int main(int argc, char **argv) { int fdin, fdout, ret, i, w_i, ret_control, retry_count = 0, part = 0; char outfile[MAXPATHLEN + 1]; void *buffer; usbex_info_t img_cnf; unsigned int crc = 0; unsigned long int r_bytes = 0; if(argc != 6) { printf("usage: %s SOURCE DEST TITLE EXECFILE CD/DVD\nExample: ui_install /dev/cdrom /mnt/usbdisk My\\ very\\ 1st\\ demo SLUS_123.45 CD\n",argv[0]); return 1; } if(strlen(argv[3]) > 31) { printf("Title %s is too long", argv[3]); exit(-1); } if(!strcasecmp(argv[5], "CD")) img_cnf.media = 0x12; else if(!strcasecmp(argv[5], "DVD")) img_cnf.media = 0x14; else { printf("Invalid media type %s", argv[5]); exit(-1); } strncpy(img_cnf.file_name, "ul.", 3); strncpy(&img_cnf.file_name[3], argv[4], 11); strncpy(img_cnf.name, argv[3], 31); img_cnf.unk = 0x08; crc = crc32(argv[3]); if((fdin = open(argv[1], O_RDONLY | O_LARGEFILE )) == -1) error_exit(argv[1]); /* ^^ Added to enable reading big iso files of DVD rips. Note: in order to make it read cue/bin images, convert them using bin2iso tool. */ buffer = (void *)malloc(BUFSIZE); sprintf(outfile, "%s/ul.%08X.%s.%02X", argv[2], crc, argv[4], part); if((fdout = open(outfile, O_WRONLY | O_TRUNC | O_CREAT)) == -1) error_exit(outfile); printf("\n\033[1m\033[33m*\033[37m USB ADVANCE Linux HDD instaler. \033[33m*\033[0m\n\n"); printf("=> Ripping \033[32m%s\033[0m to \033[32m%s\033[0m\n",argv[1],argv[2]); printf("=> Game title:\033[33m%s\033[0m\n",argv[3]); printf("=> Disk type:\033[32m%s\033[0m\n",argv[5]); printf("=> ELF:\033[32m%s\033[0m\n",argv[4]); w_i = 0; printf("%c [ %s:\033[1m\033[34mREAD\033[0m | HDD:\033[34mwrite\033[0m ] [ 0MB ]",WHRIL[w_i],argv[5]); for(i = 0; ret = read(fdin, buffer, BUFSIZE); i += ret_control) { w_i++; if(WHRIL[w_i] == '!') w_i = 0; if (ret != -1) { r_bytes += ret; ret_control = ret; printf("\r%c [ %s:\033[34mread\033[0m | HDD:\033[1m\033[34mWRITE\033[0m ] [ %dMB ],%d",WHRIL[w_i],argv[5],(r_bytes/1024)/1024,i); } else { ret_control = 0; printf("\r%c [ %s:\033[1m\033[31mERR!\033[0m | HDD:\033[1m\033[34mWAIT!\033[0m ] [ %dMB ] ERR:%d",WHRIL[w_i],argv[5],(r_bytes/1024)/1024,retry_count); close(fdin); if((fdin = open(argv[1], O_RDONLY | O_LARGEFILE )) == -1) error_exit(argv[1]); lseek(fdin,r_bytes,SEEK_SET); /* ^^ This is not a low level error handling. Just reopens file/device, sets pointer value to r_bytes and tries to read again. */ } w_i++; if(WHRIL[w_i] == '!') w_i = 0; fflush(stdout); if(ret == -1 && retry_count >= RETRYCOUNT) error_exit("read"); if(i == (1<<30)) { close(fdout); sprintf(outfile, "%s/ul.%08X.%s.%02X", argv[2], crc, argv[4], ++part); if((fdout = open(outfile, O_WRONLY | O_TRUNC | O_CREAT)) == -1) error_exit(outfile); i = 0; } if(ret != -1) { if(write(fdout, buffer, ret) == -1) error_exit("write"); } else { retry_count++; sleep(1); } printf("\r%c [ %s:\033[1m\033[34mREAD\033[0m | HDD:\033[34mwrite\033[0m ] [ %dMB ]",WHRIL[w_i],argv[5],(r_bytes/1024)/1024); fflush(stdout); } free(buffer); close(fdin); close(fdout); printf("\r=> Finished:\033[1m%d\033[0mMB in \033[1m%d\033[0m parts \n",(r_bytes/1024)/1024,(part+1)); img_cnf.part = ++part; sprintf(outfile, "%s/ul.cfg", argv[2]); if((fdout = open(outfile, O_WRONLY | O_APPEND | O_CREAT)) == -1) error_exit(outfile); write(fdout, &img_cnf, sizeof(img_cnf)); close(fdout); return 0; }