/[pcsx2_0.9.7]/trunk/pcsx2/CDVD/IsoFileFormats.cpp
ViewVC logotype

Contents of /trunk/pcsx2/CDVD/IsoFileFormats.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (10 years, 7 months ago) by william
File size: 10296 byte(s)
committing r3113 initial commit again...
1 /* PCSX2 - PS2 Emulator for PCs
2 * Copyright (C) 2002-2010 PCSX2 Dev Team
3 *
4 * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5 * of the GNU Lesser General Public License as published by the Free Software Found-
6 * ation, either version 3 of the License, or (at your option) any later version.
7 *
8 * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 * PURPOSE. See the GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License along with PCSX2.
13 * If not, see <http://www.gnu.org/licenses/>.
14 */
15
16
17 #include "PrecompiledHeader.h"
18 #include "IopCommon.h"
19
20 #include <stdio.h>
21 #include <fcntl.h>
22 #include <errno.h>
23
24 #include "IsoFileFormats.h"
25
26 static bool detect(isoFile *iso)
27 {
28 u8 buf[2456];
29 u8* pbuf;
30
31 if (!isoReadBlock(iso, buf, 16)) return false; // Not readable
32
33 pbuf = (( iso->flags & ISOFLAGS_BLOCKDUMP_V3 ) ? buf : (buf + 24));
34
35 if (strncmp((char*)(pbuf+1), "CD001", 5)) return false; // Not ISO 9660 compliant
36
37 if (*(u16*)(pbuf+166) == 2048)
38 iso->type = ISOTYPE_CD;
39 else
40 iso->type = ISOTYPE_DVD;
41
42 return true; // We can deal with this.
43 }
44
45 static bool _isoReadDtable(isoFile *iso)
46 {
47 uint ret;
48
49 _seekfile(iso->handle, 0, SEEK_END);
50 iso->dtablesize = (_tellfile(iso->handle) - 16) / (iso->blocksize + 4);
51 iso->dtable = (u32*)malloc(iso->dtablesize * 4);
52
53 for (int i = 0; i < iso->dtablesize; i++)
54 {
55 _seekfile(iso->handle, 16 + (iso->blocksize + 4) * i, SEEK_SET);
56 ret = _readfile(iso->handle, &iso->dtable[i], 4);
57 if (ret < 4) return false;
58 }
59
60 return true;
61 }
62
63 static bool tryIsoType(isoFile *iso, u32 size, s32 offset, s32 blockofs)
64 {
65 iso->blocksize = size;
66 iso->offset = offset;
67 iso->blockofs = blockofs;
68
69 return detect(iso);
70 }
71
72 // based on florin's CDVDbin detection code :)
73 // Returns true if the image is valid/known/supported, or false if not (iso->type == ISOTYPE_ILLEGAL).
74 bool isoDetect(isoFile *iso)
75 {
76 char buf[32];
77 int len;
78
79 iso->type = ISOTYPE_ILLEGAL;
80
81 len = strlen(iso->filename);
82
83 _seekfile(iso->handle, 0, SEEK_SET);
84 _readfile(iso->handle, buf, 4);
85
86 if (strncmp(buf, "BDV2", 4) == 0)
87 {
88 iso->flags = ISOFLAGS_BLOCKDUMP_V2;
89 _readfile(iso->handle, &iso->blocksize, 4);
90 _readfile(iso->handle, &iso->blocks, 4);
91 _readfile(iso->handle, &iso->blockofs, 4);
92 _isoReadDtable(iso);
93 return (detect(iso));
94 }
95 else if (strncmp(buf, "BDV3", 4) == 0)
96 {
97 iso->flags = ISOFLAGS_BLOCKDUMP_V3;
98 _readfile(iso->handle, &iso->blocksize, 4);
99 _readfile(iso->handle, &iso->blocks, 4);
100 _readfile(iso->handle, &iso->blockofs, 4);
101 _isoReadDtable(iso);
102 return (detect(iso));
103 }
104 else
105 {
106 iso->blocks = 16;
107 }
108
109 if (tryIsoType(iso, 2048, 0, 24)) return true; // ISO 2048
110 if (tryIsoType(iso, 2336, 0, 16)) return true; // RAW 2336
111 if (tryIsoType(iso, 2352, 0, 0)) return true; // RAW 2352
112 if (tryIsoType(iso, 2448, 0, 0)) return true; // RAWQ 2448
113 if (tryIsoType(iso, 2048, 150 * 2048, 24)) return true; // NERO ISO 2048
114 if (tryIsoType(iso, 2352, 150 * 2048, 0)) return true; // NERO RAW 2352
115 if (tryIsoType(iso, 2448, 150 * 2048, 0)) return true; // NERO RAWQ 2448
116 if (tryIsoType(iso, 2048, -8, 24)) return true; // ISO 2048
117 if (tryIsoType(iso, 2352, -8, 0)) return true; // RAW 2352
118 if (tryIsoType(iso, 2448, -8, 0)) return true; // RAWQ 2448
119
120 iso->offset = 0;
121 iso->blocksize = CD_FRAMESIZE_RAW;
122 iso->blockofs = 0;
123 iso->type = ISOTYPE_AUDIO;
124 return true;
125 }
126
127 isoFile *isoOpen(const char *filename)
128 {
129 isoFile *iso;
130
131 iso = (isoFile*)malloc(sizeof(isoFile));
132 if (iso == NULL) return NULL;
133
134 memzero( *iso );
135 strcpy(iso->filename, filename);
136
137 iso->handle = _openfile( iso->filename, O_RDONLY);
138 if (iso->handle == NULL)
139 {
140 Console.Error("error loading %s", iso->filename);
141 return NULL;
142 }
143
144 if (!isoDetect(iso)) return NULL;
145
146 Console.WriteLn("detected blocksize = %u", iso->blocksize);
147
148 if ((strlen(iso->filename) > 3) && strncmp(iso->filename + (strlen(iso->filename) - 3), "I00", 3) == 0)
149 {
150 int i;
151
152 _closefile(iso->handle);
153 iso->flags |= ISOFLAGS_MULTI;
154 iso->blocks = 0;
155
156 for (i = 0; i < 8; i++)
157 {
158 iso->filename[strlen(iso->filename) - 1] = '0' + i;
159 iso->multih[i].handle = _openfile(iso->filename, O_RDONLY);
160
161 if (iso->multih[i].handle == NULL)
162 {
163 break;
164 }
165
166 iso->multih[i].slsn = iso->blocks;
167 _seekfile(iso->multih[i].handle, 0, SEEK_END);
168 iso->blocks += (u32)((_tellfile(iso->multih[i].handle) - iso->offset) / (iso->blocksize));
169 iso->multih[i].elsn = iso->blocks - 1;
170 }
171
172 if (i == 0)
173 {
174 return NULL;
175 }
176 }
177
178 if (iso->flags == 0)
179 {
180 _seekfile(iso->handle, 0, SEEK_END);
181 iso->blocks = (u32)((_tellfile(iso->handle) - iso->offset) / (iso->blocksize));
182 }
183
184 switch(iso->type)
185 {
186 case ISOTYPE_CD: Console.Write("isoOpen(CD): "); break;
187 case ISOTYPE_DVD: Console.Write("isoOpen(DVD): "); break;
188 case ISOTYPE_AUDIO: Console.Write("isoOpen(Audio CD): "); break;
189 case ISOTYPE_DVDDL: Console.Write("isoOpen(DVDDL): "); break;
190 case ISOTYPE_ILLEGAL:
191 default: Console.Write("isoOpen(illegal media): "); break;
192 }
193 Console.WriteLn("%s ok.", iso->filename);
194 Console.WriteLn("The iso has %u blocks (size %u).", iso->blocks, iso->blocksize);
195 Console.WriteLn("The isos offset is %d, and the block offset is %d.", iso->offset, iso->blockofs);
196
197 return iso;
198 }
199
200 isoFile *isoCreate(const char *filename, int flags)
201 {
202 isoFile *iso;
203 char Zfile[256];
204
205 iso = (isoFile*)malloc(sizeof(isoFile));
206 if (iso == NULL) return NULL;
207
208 memset(iso, 0, sizeof(isoFile));
209 strcpy(iso->filename, filename);
210
211 iso->flags = flags;
212 iso->offset = 0;
213 iso->blockofs = 24;
214 iso->blocksize = 2048;
215
216 if (iso->flags & (ISOFLAGS_Z | ISOFLAGS_Z2 | ISOFLAGS_BZ2))
217 {
218 sprintf(Zfile, "%s.table", iso->filename);
219 iso->htable = _openfile(Zfile, O_WRONLY);
220
221 if (iso->htable == NULL) return NULL;
222 }
223
224 iso->handle = _openfile(iso->filename, O_WRONLY | O_CREAT);
225
226 if (iso->handle == NULL)
227 {
228 Console.Error("Error loading %s", iso->filename);
229 return NULL;
230 }
231
232 Console.WriteLn("isoCreate: %s ok", iso->filename);
233 Console.WriteLn("offset = %d", iso->offset);
234
235 return iso;
236 }
237
238 bool isoSetFormat(isoFile *iso, int blockofs, uint blocksize, uint blocks)
239 {
240 iso->blocksize = blocksize;
241 iso->blocks = blocks;
242 iso->blockofs = blockofs;
243
244 Console.WriteLn("blockofs = %d", iso->blockofs);
245 Console.WriteLn("blocksize = %u", iso->blocksize);
246 Console.WriteLn("blocks = %u", iso->blocks);
247
248 if (iso->flags & ISOFLAGS_BLOCKDUMP_V2)
249 {
250 if (_writefile(iso->handle, "BDV2", 4) < 4) return false;
251 if (_writefile(iso->handle, &blocksize, 4) < 4) return false;
252 if (_writefile(iso->handle, &blocks, 4) < 4) return false;
253 if (_writefile(iso->handle, &blockofs, 4) < 4) return false;
254 }
255 else if (iso->flags & ISOFLAGS_BLOCKDUMP_V3)
256 {
257 if (_writefile(iso->handle, "BDV3", 4) < 4) return false;
258 if (_writefile(iso->handle, &blocksize, 4) < 4) return false;
259 if (_writefile(iso->handle, &blocks, 4) < 4) return false;
260 }
261
262 return true;
263 }
264
265 bool _isoReadBlock(isoFile *iso, u8 *dst, int lsn)
266 {
267 u64 ofs = (u64)lsn * iso->blocksize + iso->offset;
268
269 memset(dst, 0, iso->blockofs);
270 _seekfile(iso->handle, ofs, SEEK_SET);
271
272 uint ret = _readfile(iso->handle, dst + iso->blockofs, iso->blocksize);
273
274 if (ret < iso->blocksize)
275 {
276 Console.Error("read error in _isoReadBlock." );
277 return false;
278 }
279
280 return true;
281 }
282
283 bool _isoReadBlockD(isoFile *iso, u8 *dst, uint lsn)
284 {
285 uint ret;
286
287 // Console.WriteLn("_isoReadBlockD %u, blocksize=%u, blockofs=%u\n", lsn, iso->blocksize, iso->blockofs);
288
289 memset(dst, 0, iso->blockofs);
290 for (int i = 0; i < iso->dtablesize; i++)
291 {
292 if (iso->dtable[i] != lsn) continue;
293
294 _seekfile(iso->handle, 16 + i * (iso->blocksize + 4) + 4, SEEK_SET);
295 ret = _readfile(iso->handle, dst + iso->blockofs, iso->blocksize);
296
297 if (ret < iso->blocksize) return false;
298
299 return true;
300 }
301 Console.WriteLn("Block %u not found in dump", lsn);
302
303 return false;
304 }
305
306 bool _isoReadBlockM(isoFile *iso, u8 *dst, uint lsn)
307 {
308 u64 ofs;
309 uint ret, i;
310
311 for (i = 0; i < 8; i++)
312 {
313 if ((lsn >= iso->multih[i].slsn) && (lsn <= iso->multih[i].elsn))
314 {
315 break;
316 }
317 }
318
319 if (i == 8) return false;
320
321 ofs = (u64)(lsn - iso->multih[i].slsn) * iso->blocksize + iso->offset;
322
323 // Console.WriteLn("_isoReadBlock %u, blocksize=%u, blockofs=%u\n", lsn, iso->blocksize, iso->blockofs);
324
325 memset(dst, 0, iso->blockofs);
326 _seekfile(iso->multih[i].handle, ofs, SEEK_SET);
327 ret = _readfile(iso->multih[i].handle, dst + iso->blockofs, iso->blocksize);
328
329 if (ret < iso->blocksize)
330 {
331 Console.Error("read error in _isoReadBlockM");
332 return false;
333 }
334
335 return true;
336 }
337
338 bool isoReadBlock(isoFile *iso, u8 *dst, uint lsn)
339 {
340 bool ret;
341
342 if (lsn > iso->blocks)
343 {
344 Console.WriteLn("isoReadBlock: %u > %u", lsn, iso->blocks);
345 return false;
346 }
347
348 if (iso->flags & ISOFLAGS_BLOCKDUMP_V2)
349 ret = _isoReadBlockD(iso, dst, lsn);
350 else if( iso->flags & ISOFLAGS_BLOCKDUMP_V3 )
351 ret = _isoReadBlockD(iso, dst, lsn);
352 else if (iso->flags & ISOFLAGS_MULTI)
353 ret = _isoReadBlockM(iso, dst, lsn);
354 else
355 ret = _isoReadBlock(iso, dst, lsn);
356
357 if (!ret) return false;
358
359 if (iso->type == ISOTYPE_CD)
360 {
361 lsn_to_msf(dst + 12, lsn);
362 dst[15] = 2;
363 }
364
365 return true;
366 }
367
368
369 bool _isoWriteBlock(isoFile *iso, u8 *src, uint lsn)
370 {
371 uint ret;
372 u64 ofs = (u64)lsn * iso->blocksize + iso->offset;
373
374 _seekfile(iso->handle, ofs, SEEK_SET);
375 ret = _writefile(iso->handle, src + iso->blockofs, iso->blocksize);
376 if (ret < iso->blocksize) return false;
377
378 return true;
379 }
380
381 bool _isoWriteBlockD(isoFile *iso, u8 *src, uint lsn)
382 {
383 uint ret;
384
385 ret = _writefile(iso->handle, &lsn, 4);
386 if (ret < 4) return false;
387 ret = _writefile(iso->handle, src + iso->blockofs, iso->blocksize);
388
389 if (ret < iso->blocksize) return false;
390
391 return true;
392 }
393
394 bool isoWriteBlock(isoFile *iso, u8 *src, uint lsn)
395 {
396 if (iso->flags & ISOFLAGS_BLOCKDUMP_V3)
397 return _isoWriteBlockD(iso, src, lsn);
398 else
399 return _isoWriteBlock(iso, src, lsn);
400 }
401
402 void isoClose(isoFile *iso)
403 {
404 if (iso == NULL ) return;
405 if (iso->handle) _closefile(iso->handle);
406 if (iso->htable) _closefile(iso->htable);
407 safe_free( iso->buffer );
408 safe_free( iso->dtable );
409 safe_free( iso );
410 }
411

  ViewVC Help
Powered by ViewVC 1.1.22