Disabling auto-refresh of game list by default, as it is causing bugs sometimes
[open-ps2-loader.git] / pc / opl2iso / src / opl2iso.c
blob90da45cbbc4638f9f4d3a50783ba9c1359f7d3f4
1 /*
2 Copyright 2010, volca
3 Parts Copyright 2009, jimmikaelkael
4 Copyright (c) 2002, A.Lee & Nicholas Van Veen
5 Licenced under Academic Free License version 3.0
6 Review OpenUsbLd README & LICENSE files for further details.
8 Some parts of the code are taken from libcdvd by A.Lee & Nicholas Van Veen
9 Review license_libcdvd file for further details.
12 #include "opl2iso.h"
14 u32 crctab[0x400];
16 #define EXIT_OK 0
17 #define EXIT_FAILURE 1
19 //-----------------------------------------------------------------------
20 void printVer(void)
22 printf("%s version %s\n", PROGRAM_EXTNAME, PROGRAM_VER);
25 //-----------------------------------------------------------------------
26 char spin(int i) {
28 switch (i % 4) {
29 case 0: return '|';
30 case 1: return '/';
31 case 2: return '-';
32 default:
33 case 3: return '\\';
37 //-----------------------------------------------------------------------
38 u32 crc32(const char *string)
40 int crc, table, count, byte;
42 for (table=0; table<256; table++) {
43 crc = table << 24;
45 for (count=8; count>0; count--) {
46 if (crc < 0) crc = crc << 1;
47 else crc = (crc << 1) ^ 0x04C11DB7;
49 crctab[255-table] = crc;
52 do {
53 byte = string[count++];
54 crc = crctab[byte ^ ((crc >> 24) & 0xFF)] ^ ((crc << 8) & 0xFFFFFF00);
55 } while (string[count-1] != 0);
57 return crc;
60 //----------------------------------------------------------------
61 void compute_name(char* buffer, int maxlen, const char *game_name, const char *game_id, int partid)
63 if (strlen(game_id) <= 3) {
64 buffer[0] = '\0';
65 return;
68 snprintf(buffer, maxlen, "ul.%08X.%s.%02d",crc32(game_name), &game_id[3], partid);
71 //----------------------------------------------------------------
72 int listGames(void) {
73 // open ul.cfg, list all contents
74 FILE* ul = fopen("ul.cfg", "rb");
76 if (ul == NULL) {
77 printf("No ul.cfg in the current directory!\n");
78 return EXIT_FAILURE;
81 fseek(ul, 0, SEEK_END);
82 size_t fsize = ftell(ul);
83 fseek(ul, 0, SEEK_SET);
86 size_t items = fsize / 64;
88 printf(" GAME_ID GAME_NAME PARTS\n");
89 while (items-- > 0) {
90 cfg_t item;
92 memset(item.name, 0, 33);
93 memset(item.image, 0, 16);
95 fread(item.name, 1, 32, ul);
96 fread(item.image, 1, 15, ul);
97 fread(&item.parts, 1, sizeof(item.parts), ul);
98 fread(&item.media, 1, sizeof(item.media), ul);
99 fread(item.pad, 1, sizeof(item.pad), ul);
101 printf("%15s: %32s %8d\n", item.image, item.name, item.parts);
104 fclose(ul);
105 return EXIT_OK;
108 //-----------------------------------------------------------------------
109 int findGame(const char* gameid, cfg_t* item) {
110 // open ul.cfg
111 FILE* ul = fopen("ul.cfg", "rb");
113 if (!item) {
114 printf("Invalid target record (internal error)!\n");
115 return EXIT_FAILURE;
118 if (ul == NULL) {
119 printf("No ul.cfg in the current directory!\n");
120 return EXIT_FAILURE;
123 fseek(ul, 0, SEEK_END);
124 size_t fsize = ftell(ul);
125 fseek(ul, 0, SEEK_SET);
127 size_t items = fsize / 64;
129 while (items-- > 0) {
130 memset(item->name, 0, 33);
131 memset(item->image, 0, 16);
133 fread(item->name, 1, 32, ul);
134 fread(item->image, 1, 15, ul);
135 fread(&item->parts, 1, sizeof(item->parts), ul);
136 fread(&item->media, 1, sizeof(item->media), ul);
137 fread(item->pad, 1, sizeof(item->pad), ul);
139 // in the ul.????_???.?? form?
140 if (strncmp(item->image, gameid, 15) == 0)
141 return 1;
143 // in the ????_???.?? form?
144 if (strncmp(&item->image[3], gameid, 12) == 0)
145 return 1;
147 // game name itself?
148 if (strncmp(item->name, gameid, 32) == 0)
149 return 1;
151 // in the ul.????????.????_???.??.?? form? (Drag-Dropped part-file name)
152 char *temp;
153 #ifdef _WIN32
154 temp = strrchr(gameid, '\\');
155 #else
156 temp = strrchr(gameid, '/');
157 #endif
158 if(temp == NULL) temp = (char *)gameid;
159 else temp++;
160 if ( (strlen(temp) >= 23) //Minimum part file name length is really 26
161 && (strncmp("ul.", temp, 3) == 0) //"ul." at start
162 && (strncmp(&item->image[2], &(temp[11]), 12) == 0) //.game_ID after CRC
164 return 1;
167 fclose(ul);
168 return EXIT_OK;
171 //-----------------------------------------------------------------------
172 int exportGame(const char* gameid) {
173 cfg_t grecord;
175 // first try to load the game record with specified code
176 if (!findGame(gameid, &grecord)) {
177 printf("Game not found in the ul.cfg!\n");
178 return EXIT_FAILURE;
181 char rname[255];
182 const char *mediatype;
184 // CD: 0x12, DVD: 0x14
186 if (grecord.media == 0x12) {
187 mediatype = "CD";
188 } else if (grecord.media == 0x14) {
189 mediatype = "DVD";
190 } else {
191 printf("Invalid media ID!\n");
192 return EXIT_FAILURE;
195 if (strlen(grecord.image) <= 3) {
196 printf("Invalid game record image name\n");
197 return EXIT_FAILURE;
200 char temp_ID[12];
201 strncpy(temp_ID, grecord.image+3, 11);
202 temp_ID[11] = 0;
204 #ifdef _WIN32
205 snprintf(rname, 255, "%s\\%s.%s.iso", mediatype, temp_ID, grecord.name);
206 #else
207 snprintf(rname, 255, "%s/%s.%s.iso", mediatype, temp_ID, grecord.name);
208 #endif
210 printf("Game found in the ul.cfg. Resulting file name: '%s'\n", rname);
212 FILE* fdest = fopen(rname, "wb");
214 if (!fdest) {
215 printf("Could not open destination file '%s', exiting\n", rname);
216 return EXIT_FAILURE;
219 int part;
220 for (part = 0; part < grecord.parts; part++) {
221 char sname[128];
223 compute_name(sname, 128, grecord.name, grecord.image, part);
225 printf("Processing part %d/%d: '%s'...\n", part+1, grecord.parts, sname);
227 FILE* fsrc = fopen(sname, "rb");
229 if (!fsrc) {
230 fclose(fdest);
231 printf("Could not open source file '%s', resulting file will be invalid\n", sname);
232 return EXIT_FAILURE;
235 unsigned char block[65536];
236 int i = 0;
238 while (!feof(fsrc)) {
239 printf("\r%c\r", spin(i++));
240 size_t read = fread(block, 1, 65536, fsrc);
241 if (read != fwrite(block, 1, read, fdest)) {
242 printf("Could not write to destination file '%s' (Insufficient disk space?). Resulting file will be invalid\n", rname);
243 fclose(fdest);
244 return EXIT_FAILURE;
249 fclose(fdest);
251 printf("* All parts processed...\n");
253 return EXIT_OK;
256 //-----------------------------------------------------------------------
257 int main(int argc, char **argv, char **env)
259 #ifdef _WIN32
260 printf("%s - %s version %s (Win32 Build)\n", PROGRAM_NAME, PROGRAM_EXTNAME, PROGRAM_VER);
261 #else
262 printf("%s - %s version %s\n", PROGRAM_NAME, PROGRAM_EXTNAME, PROGRAM_VER);
263 #endif
264 printf(" * This is a one-purpose utility used to convert games from ul.cfg\n");
265 printf(" * back to iso format into CD/DVD directories, to be directly usable\n");
266 printf(" * by open PS2 loader again\n");
268 // args check
269 if (argc <= 1) {
270 return listGames();
271 } else if (argc == 2) {
272 return exportGame(argv[1]);
275 return EXIT_FAILURE;