PageRenderTime 32ms CodeModel.GetById 1ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 1ms

/pc/iso2opl/src/iso2opl.c

https://bitbucket.org/ifcaro/open-ps2-loader/
C | 608 lines | 413 code | 82 blank | 113 comment | 91 complexity | 3d5751501a71fa0450906ac71372783e MD5 | raw file
  1/*
  2  Copyright 2009, jimmikaelkael
  3  Copyright (c) 2002, A.Lee & Nicholas Van Veen  
  4  Licenced under Academic Free License version 3.0
  5  Review OpenUsbLd README & LICENSE files for further details.
  6
  7  Some parts of the code are taken from libcdvd by A.Lee & Nicholas Van Veen
  8  Review license_libcdvd file for further details.
  9*/
 10
 11#include "iso2opl.h"
 12
 13#define WR_SIZE		524288
 14
 15u32 crctab[0x400];
 16u8 systemcnf_buf[65536];
 17
 18//-----------------------------------------------------------------------
 19void printVer(void)
 20{
 21#ifdef _WIN32
 22	printf("%s version %s (Win32 Build)\n", PROGRAM_EXTNAME, PROGRAM_VER);
 23#else
 24	printf("%s version %s\n", PROGRAM_EXTNAME, PROGRAM_VER);
 25#endif
 26}
 27
 28//-----------------------------------------------------------------------
 29void printUsage(void)
 30{
 31	printVer();
 32	printf("Usage: %s [SOURCE_ISO] [DEST_DRIVE] [GAME_NAME] [TYPE]\n", PROGRAM_NAME);
 33	printf("%s command-line version %s\n\n", PROGRAM_EXTNAME, PROGRAM_VER);
 34#ifdef _WIN32
 35	printf("Example 1: %s C:\\ISO\\WORMS4.ISO E WORMS_4_MAYHEM DVD\n", PROGRAM_NAME);
 36	printf("Example 2: %s \"C:\\ISO\\WORMS 4.ISO\" E \"WORMS 4: MAYHEM\" DVD\n", PROGRAM_NAME);
 37	printf("Example 3: %s \"C:\\ISO\\MICRO MACHINES V4.ISO\" E \"Micro Machines v4\" CD\n", PROGRAM_NAME);
 38	printf("Example 4: %s \"C:\\ISO\\WORMS 4.ISO\" E:\\MyDir WORMS_4 DVD\n", PROGRAM_NAME);
 39	printf("Example 5: %s \"C:\\ISO\\WORMS 4.ISO\" \\\\MyComputer\\PS2SMB WORMS_4 DVD\n", PROGRAM_NAME);
 40#else
 41	printf("Example 1: %s /home/user/WORMS4.ISO /media/disk WORMS_4_MAYHEM DVD\n", PROGRAM_NAME);
 42	printf("Example 2: %s \"/home/user/WORMS 4.ISO\" /media/disk \"WORMS 4: MAYHEM\" DVD\n", PROGRAM_NAME);
 43	printf("Example 3: %s \"/home/user/MICRO MACHINES V4.ISO\" /media/disk \"Micro Machines v4\" CD\n", PROGRAM_NAME);
 44#endif
 45}
 46
 47//-----------------------------------------------------------------------
 48u32 crc32(const char *string)
 49{
 50    int crc, table, count, byte;
 51
 52    for (table=0; table<256; table++) {
 53        crc = table << 24;
 54
 55        for (count=8; count>0; count--) {
 56            if (crc < 0) crc = crc << 1;
 57            else crc = (crc << 1) ^ 0x04C11DB7;
 58        }
 59        crctab[255-table] = crc;
 60    }
 61
 62    do {
 63        byte = string[count++];
 64        crc = crctab[byte ^ ((crc >> 24) & 0xFF)] ^ ((crc << 8) & 0xFFFFFF00);
 65    } while (string[count-1] != 0);
 66
 67    return crc;
 68}
 69
 70//-----------------------------------------------------------------------
 71int check_cfg(const char *drive, const char *game_name, const char *game_id)
 72{
 73	int r;
 74	//int fh_cfg;
 75	FILE *fh_cfg;
 76	cfg_t cfg;
 77	char cfg_path[256];
 78	char cfg_image[256];
 79
 80#ifdef DEBUG
 81	printf("check_cfg drive:%s name:%s id:%s\n", drive, game_name, game_id);
 82#endif
 83
 84#ifdef _WIN32
 85	sprintf(cfg_path, "%s:\\ul.cfg", drive);
 86#else
 87	sprintf(cfg_path, "%s/ul.cfg", drive);
 88#endif
 89	sprintf(cfg_image, "ul.%s", game_id);
 90
 91	/*fh_cfg = open(cfg_path, O_RDONLY);
 92	if (fh_cfg >= 0) {
 93		while ((r = read(fh_cfg, &cfg, sizeof(cfg_t))) != 0) {
 94			if (r != sizeof(cfg_t)) {
 95				close(fh_cfg);
 96				return -3;
 97			}
 98			if (!strcmp(cfg.name, game_name)) {
 99				close(fh_cfg);
100				return -1;
101			}
102			if (!strcmp(cfg.image, cfg_image)) {
103				close(fh_cfg);
104				return -2;
105			}
106		}
107		close(fh_cfg);
108	}*/
109	fh_cfg = fopen(cfg_path, "rb");
110	if (fh_cfg) {
111		while ((r = fread(&cfg, 1, sizeof(cfg_t), fh_cfg)) != 0) {
112			if (r != sizeof(cfg_t)) {
113				fclose(fh_cfg);
114				return -3;
115			}
116			if (!strcmp(cfg.name, game_name)) {
117				fclose(fh_cfg);
118				return -1;
119			}
120			if (!strcmp(cfg.image, cfg_image)) {
121				fclose(fh_cfg);
122				return -2;
123			}
124		}
125		fclose(fh_cfg);
126	}
127
128	return 0;
129}
130
131//-----------------------------------------------------------------------
132int write_cfg(const char *drive, const char *game_name, const char *game_id, const char *media, int parts)
133{
134	//int fh_cfg;
135	FILE *fh_cfg;
136	cfg_t cfg;
137	char cfg_path[256];
138	int r;
139
140#ifdef DEBUG
141	printf("write_cfg drive:%s name:%s id:%s media:%s parts:%d\n", drive, game_name, game_id, media, parts);
142#endif
143
144#ifdef _WIN32
145	if (strlen(drive) == 1) 
146		sprintf(cfg_path, "%s:\\ul.cfg", drive);
147	else
148		sprintf(cfg_path, "%s\\ul.cfg", drive);
149#else
150	sprintf(cfg_path, "%s/ul.cfg", drive);
151#endif
152	memset(&cfg, 0, sizeof(cfg_t));
153
154	strncpy(cfg.name, game_name, 32);
155	sprintf(cfg.image, "ul.%s", game_id);
156	cfg.parts = parts;
157	cfg.pad[4] = 0x08; // To be like USBA
158
159	if (!strcmp(media, "CD"))
160		cfg.media = 0x12;
161	else if (!strcmp(media, "DVD"))
162		cfg.media = 0x14;
163
164	/*
165	fh_cfg = open(cfg_path, O_WRONLY|O_CREAT|O_APPEND);
166	if (fh_cfg < 0)
167		return -1;
168
169	r = write(fh_cfg, &cfg, sizeof(cfg_t));
170	if (r != sizeof(cfg_t)) {
171		close(fh_cfg);
172		return -2;
173	}
174
175	close(fh_cfg);
176	*/
177	fh_cfg = fopen(cfg_path, "ab");
178	if (!fh_cfg)
179		return -1;
180
181	r = fwrite(&cfg, 1, sizeof(cfg_t), fh_cfg);
182	if (r != sizeof(cfg_t)) {
183		fclose(fh_cfg);
184		return -2;
185	}
186
187	fclose(fh_cfg);
188
189	return 0;
190}
191
192//----------------------------------------------------------------
193int write_parts(const char *drive, const char *game_name, const char *game_id, s64 filesize, int parts)
194{
195	//int fh_part;
196	FILE *fh_part;
197	char part_path[256];
198	int i, r;
199	u8 *buf;
200	u32 size; 
201	s64 nbytes, rpos, iso_pos;
202
203#ifdef DEBUG
204	printf("write_parts drive:%s name:%s id:%s filesize:0x%llx parts:%d\n", drive, game_name, game_id, filesize, parts);
205#endif
206
207	iso_pos = 0;
208	buf = malloc(WR_SIZE+2048);
209	if (!buf)
210		return -1;
211
212	for (i=0; i<parts; i++) {
213#ifdef _WIN32
214		if (strlen(drive) == 1)
215			sprintf(part_path, "%s:\\ul.%08X.%s.%02d", drive, crc32(game_name), game_id, i);
216		else
217			sprintf(part_path, "%s\\ul.%08X.%s.%02d", drive, crc32(game_name), game_id, i);
218#else
219		sprintf(part_path, "%s/ul.%08X.%s.%02d", drive, crc32(game_name), game_id, i);
220#endif
221/*
222		fh_part = open(part_path, O_WRONLY|O_TRUNC|O_CREAT);
223		if (fh_part < 0) {
224			free(buf);
225			return -2;
226		}
227
228		nbytes = filesize;
229		if (nbytes > 1073741824)
230			nbytes = 1073741824;
231
232		rpos = 0;
233		if (nbytes) {
234			do {
235				if (nbytes > WR_SIZE)
236					size = WR_SIZE;
237				else
238					size = nbytes;
239
240				r = isofs_ReadISO(iso_pos, size, buf);
241				if (r != size) {
242					free(buf);
243					close(fh_part);
244				return -3;
245				}
246
247				printf("Writing %d sectors to %s - LBA: %d\n", WR_SIZE >> 11, part_path, (int)(iso_pos >> 11));
248
249				// write to file
250				r = write(fh_part, buf, size);
251				if (r != size) {
252					free(buf);
253					close(fh_part);
254				return -4;
255				}
256
257				size = r;
258				rpos += size;
259				iso_pos += size;
260				nbytes -= size;
261
262			} while (nbytes);
263		}
264		filesize -= rpos;
265		close(fh_part);
266	}
267*/
268		fh_part = fopen(part_path, "wb");
269		if (!fh_part) {
270			free(buf);
271			return -2;
272		}
273
274		nbytes = filesize;
275		if (nbytes > 1073741824)
276			nbytes = 1073741824;
277
278		rpos = 0;
279		if (nbytes) {
280			do {
281				if (nbytes > WR_SIZE)
282					size = WR_SIZE;
283				else
284					size = nbytes;
285
286				r = isofs_ReadISO(iso_pos, size, buf);
287				if (r != size) {
288					free(buf);
289					fclose(fh_part);
290				return -3;
291				}
292
293				printf("Writing %d sectors to %s - LBA: %d\n", WR_SIZE >> 11, part_path, (int)(iso_pos >> 11));
294
295				// write to file
296				r = fwrite(buf, 1, size, fh_part);
297				if (r != size) {
298					free(buf);
299					fclose(fh_part);
300				return -4;
301				}
302
303				size = r;
304				rpos += size;
305				iso_pos += size;
306				nbytes -= size;
307
308			} while (nbytes);
309		}
310		filesize -= rpos;
311		fclose(fh_part);
312	}
313
314	free(buf);
315
316	return 0;
317}
318
319//----------------------------------------------------------------
320int ParseSYSTEMCNF(char *system_cnf, char *boot_path)
321{
322	int fd, r, fsize;
323	char *p, *p2;
324	int path_found = 0;
325
326#ifdef DEBUG
327	printf("ParseSYSTEMCNF %s\n", system_cnf);
328#endif
329
330	fd = isofs_Open("\\SYSTEM.CNF;1");
331	if (fd < 0)
332		return -1;
333
334	fsize = isofs_Seek(fd, 0, SEEK_END);
335	isofs_Seek(fd, 0, SEEK_SET);
336
337	r = isofs_Read(fd, systemcnf_buf, fsize);
338	if (r != fsize) {
339		isofs_Close(fd);
340		return -2;
341	}
342
343	isofs_Close(fd);
344	
345#ifdef DEBUG
346	printf("ParseSYSTEMCNF trying to retrieve elf path...\n");
347#endif
348
349	p = strtok((char *)systemcnf_buf, "\n");
350
351	while (p) {
352		p2 = strstr(p, "BOOT2");
353		if (p2) {
354			p2 += 5;
355
356			while ((*p2 <= ' ') && (*p2 > '\0'))
357				p2++;
358
359			if (*p2 != '=')
360				return -3;
361			p2++;
362
363			while ((*p2 <= ' ') && (*p2 > '\0')	&& (*p2!='\r') && (*p2!='\n'))
364				p2++;
365
366			if (*p2 == '\0')
367				return -3;
368
369			path_found = 1;
370			strcpy(boot_path, p2);
371		}
372		p = strtok(NULL, "\n");
373	}
374
375	if (!path_found)
376		return -4;
377
378	return 0;
379}
380
381//-----------------------------------------------------------------------
382s64 GetGameID(char *isofile, int isBigEndian, short closeOnEnd, char *GameID)
383{
384	int ret;
385	char ElfPath[256];
386	char *p;
387	s64 filesize;
388
389	// Init isofs
390	filesize = isofs_Init(isofile, isBigEndian);
391	if (!filesize) {
392		printf("Error: failed to open ISO file: %s\n", isofile);
393		return 0;
394	}
395
396	// parse system.cnf in ISO file
397	ret = ParseSYSTEMCNF("\\SYSTEM.CNF;1", ElfPath);
398	if (ret < 0) {
399		switch (ret) {
400			case -1:
401				printf("Error: can't open SYSTEM.CNF from ISO file: %s\n", isofile);
402				break;
403			case -2:
404				printf("Error: failed to read SYSTEM.CNF from ISO file: %s\n", isofile);
405				break;
406			case -3:
407				printf("Error: failed to parse SYSTEM.CNF from ISO file: %s\n", isofile);
408				break;
409			case -4:
410				printf("Error: failed to locate elf path from ISO file: %s\n", isofile);
411				break;
412		}
413		return 0;
414	}
415
416#ifdef DEBUG
417	printf("Elf Path: %s\n", ElfPath);
418#endif
419
420	// get GameID
421	strcpy(GameID, &ElfPath[8]);
422	p = strstr(GameID, ";1");
423	*p = 0;
424
425#ifdef DEBUG
426	printf("Game ID: %s\n", GameID);
427#endif
428
429	if (closeOnEnd)
430		isofs_Reset();
431
432	return filesize;
433}
434
435//----------------------------------------------------------------
436int compute_name(const char *drive, const char *game_name, const char *game_id)
437{
438#ifdef DEBUG
439	printf("rename_iso drive:%s name:%s id:%s\n", drive, game_name, game_id);
440#endif
441
442#ifdef _WIN32
443	if (strlen(drive) == 1)
444		printf("%s:\\ul.%08X.%s.00\n", drive, crc32(game_name), game_id);
445	else
446		printf("%s\\ul.%08X.%s.00\n", drive, crc32(game_name), game_id);
447#else
448	printf("%s/ul.%08X.%s.00\n", drive, crc32(game_name), game_id);
449#endif
450	return 0;
451}
452
453//----------------------------------------------------------------
454void scan_dir(int isBigEndian)
455{
456	struct dirent* ent;
457	int size;
458	char GameID[256];
459	char *name;
460	char fullname[512];
461	char newname[512];
462	struct stat buf;
463
464	DIR* rep = opendir(".");
465	if (rep != NULL) {
466		while ((ent = readdir(rep)) != NULL) {
467			name = ent->d_name;
468			size = strlen(name);
469			sprintf(fullname,"./%s", name);
470			if ( ! stat(fullname, &buf) && ! S_ISDIR(buf.st_mode) ) {
471				if (strstr(name, ".iso")) {
472					if ((size >= 17) && (name[4] == '_') && (name[8] == '.') && (name[11] == '.')) {
473						printf("%s seems to be correctly named\n", fullname);
474					}
475					else if (GetGameID(fullname, isBigEndian, 1, GameID)) {
476						sprintf(newname,"./%s.%s", GameID, name);
477						if (rename(fullname, newname) == 0)
478						{
479							printf("%s renamed to: %s\n", fullname, newname);
480						}
481					}
482				}
483			}
484		}
485		closedir(rep);
486	}
487}
488
489//-----------------------------------------------------------------------
490int main(int argc, char **argv, char **env)
491{
492	int ret;
493	char GameID[256];
494	s64 num_parts;
495	char *p;
496	s64 filesize;
497	int isBigEnd;
498
499	// Big Endianness test
500	p = (char *)&isBigEnd;
501	memset(p, 0, 4);
502	p[3] = 1;
503
504	if (isBigEnd != 1)
505		isBigEnd = 0;
506
507#ifdef DEBUG
508	printf("DEBUG_MODE ON\n");
509	printf("Endianness: %d\n", isBigEnd);
510	printf("isofs Init...\n");
511#endif
512
513	// args check
514	if ((argc > 1) && (strcmp(argv[1], "SCAN") == 0))
515	{
516		scan_dir(isBigEnd);
517		exit(EXIT_SUCCESS);
518	}
519
520	if ((argc < 5) || (strcmp(argv[4], "CD") && strcmp(argv[4], "DVD")) || (strlen(argv[3]) > 32)) {
521		printUsage();
522		exit(EXIT_FAILURE);
523	}
524
525#ifdef DEBUG
526	printf("DEBUG_MODE ON\n");
527#endif
528
529	filesize = GetGameID(argv[1], isBigEnd, 0, GameID);
530	if (filesize==0) {
531		isofs_Reset();
532		exit(EXIT_FAILURE);
533	}
534
535	// check for existing game
536	ret = check_cfg(argv[2], argv[3], GameID);
537	if (ret < 0) {
538		switch (ret) {
539			case -1:
540				printf("Error: a game with the same name is already installed on drive!\n");
541				break;
542			case -2:
543				printf("Error: a game with the same ID is already installed on drive!\n");
544				break;
545			case -3:
546				printf("Error: can't read ul.cfg on drive!\n");
547				break;
548		}
549		isofs_Reset();
550		exit(EXIT_FAILURE);
551	}
552
553	// get needed number of parts
554	num_parts = filesize / 1073741824;
555	if (filesize & 0x3fffffff)
556		num_parts++;
557
558#ifdef DEBUG
559	printf("ISO filesize: 0x%llx\n", filesize);
560	printf("Number of parts: %d\n", num_parts);
561	//return 0;
562#endif
563
564	// write ISO parts to drive
565	ret = write_parts(argv[2], argv[3], GameID, filesize, num_parts);
566	if (ret < 0) {
567		switch (ret) {
568			case -1:
569				printf("Error: failed to allocate memory to read ISO!\n");
570				break;			
571			case -2:
572				printf("Error: game part creation failed!\n");
573				break;
574			case -3:
575				printf("Error: failed to read datas from ISO file!\n");
576				break;
577			case -4:
578				printf("Error: failed to write datas to part file!\n");
579				break;
580		}
581		isofs_Reset();
582		exit(EXIT_FAILURE);
583	}
584
585	// append the game to ul.cfg
586	ret = write_cfg(argv[2], argv[3], GameID, argv[4], num_parts);
587	if (ret < 0) {
588		switch (ret) {
589			case -1:
590				printf("Error: can't open ul.cfg!\n");
591				break;
592			case -2:
593				printf("Error: write to ul.cfg failed!\n");
594				break;
595		}
596		isofs_Reset();
597		exit(EXIT_FAILURE);
598	}
599
600	isofs_Reset();
601
602	printf("%s is installed!\n", argv[3]);
603
604	// End program
605	exit(EXIT_SUCCESS);
606
607	return 0;
608}