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

Contents of /trunk/pcsx2/CDVD/CDVDisoReader.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: 10843 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 /*
18 * Original code from libcdvd by Hiryu & Sjeep (C) 2002
19 * Modified by Florin for PCSX2 emu
20 * Fixed CdRead by linuzappz
21 */
22
23 #include "PrecompiledHeader.h"
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <fcntl.h>
28
29 #include "CDVDisoReader.h"
30
31 static u8 *pbuffer;
32 static u8 cdbuffer[2352] = {0};
33 static isoFile *iso = NULL;
34
35 static int psize, cdtype;
36
37 static s32 layer1start = -1;
38
39 void CALLBACK ISOclose()
40 {
41 isoClose(iso);
42 iso = NULL;
43 }
44
45 s32 CALLBACK ISOopen(const char* pTitle)
46 {
47 ISOclose(); // just in case
48
49 if( (pTitle == NULL) || (pTitle[0] == 0) )
50 {
51 Console.Error( "CDVDiso Error: No filename specified." );
52 return -1;
53 }
54
55 iso = isoOpen(pTitle);
56 if (iso == NULL)
57 {
58 Console.Error( "CDVDiso Error: Failed loading %s", pTitle );
59 return -1;
60 }
61
62 switch (iso->type)
63 {
64 case ISOTYPE_DVD:
65 cdtype = CDVD_TYPE_PS2DVD;
66 break;
67 case ISOTYPE_AUDIO:
68 cdtype = CDVD_TYPE_CDDA;
69 break;
70 default:
71 cdtype = CDVD_TYPE_PS2CD;
72 break;
73 }
74
75 layer1start = -1;
76
77 return 0;
78 }
79
80 s32 CALLBACK ISOreadSubQ(u32 lsn, cdvdSubQ* subq)
81 {
82 // fake it
83 u8 min, sec, frm;
84 subq->ctrl = 4;
85 subq->mode = 1;
86 subq->trackNum = itob(1);
87 subq->trackIndex = itob(1);
88
89 lba_to_msf(lsn, &min, &sec, &frm);
90 subq->trackM = itob(min);
91 subq->trackS = itob(sec);
92 subq->trackF = itob(frm);
93
94 subq->pad = 0;
95
96 lba_to_msf(lsn + (2*75), &min, &sec, &frm);
97 subq->discM = itob(min);
98 subq->discS = itob(sec);
99 subq->discF = itob(frm);
100
101 return 0;
102 }
103
104 s32 CALLBACK ISOgetTN(cdvdTN *Buffer)
105 {
106 Buffer->strack = 1;
107 Buffer->etrack = 1;
108
109 return 0;
110 }
111
112 s32 CALLBACK ISOgetTD(u8 Track, cdvdTD *Buffer)
113 {
114 if (Track == 0)
115 {
116 Buffer->lsn = iso->blocks;
117 }
118 else
119 {
120 Buffer->type = CDVD_MODE1_TRACK;
121 Buffer->lsn = 0;
122 }
123
124 return 0;
125 }
126
127 #include "gui/App.h"
128 #include "Utilities/HashMap.h"
129
130 static bool testForPartitionInfo( const u8 (&tempbuffer)[CD_FRAMESIZE_RAW] )
131 {
132 const int off = iso->blockofs;
133
134 // test for: CD001
135 return (
136 (tempbuffer[off+1] == 0x43) &&
137 (tempbuffer[off+2] == 0x44) &&
138 (tempbuffer[off+3] == 0x30) &&
139 (tempbuffer[off+4] == 0x30) &&
140 (tempbuffer[off+5] == 0x31)
141 );
142 }
143
144 static bool FindLayer1Start()
145 {
146 if( (layer1start != -1) || (iso->blocks < 0x230540) ) return true;
147
148 Console.WriteLn("CDVDiso: searching for layer1...");
149
150 int blockresult = -1;
151
152 // Check the ini file cache first:
153 // Cache is stored in LayerBreakCache.ini, and is associated by hex-encoded hash key of the
154 // complete filename/path of the iso file. :)
155
156 wxString layerCacheFile( Path::Combine(GetSettingsFolder().ToString(), L"LayerBreakCache.ini") );
157 wxFileConfig layerCacheIni( wxEmptyString, wxEmptyString, layerCacheFile, wxEmptyString, wxCONFIG_USE_RELATIVE_PATH );
158
159 wxString cacheKey;
160 cacheKey.Printf( L"%X", HashTools::Hash( iso->filename, strlen( iso->filename ) ) );
161
162 blockresult = layerCacheIni.Read( cacheKey, -1 );
163 if( blockresult != -1 )
164 {
165 u8 tempbuffer[CD_FRAMESIZE_RAW];
166 isoReadBlock(iso, tempbuffer, blockresult);
167
168 if( testForPartitionInfo( tempbuffer ) )
169 {
170 Console.WriteLn( "CDVDiso: loaded second layer from settings cache, sector=0x%8.8x", blockresult );
171 layer1start = blockresult;
172 }
173 else
174 {
175 Console.Warning( "CDVDiso: second layer info in the settings cache appears to be obsolete or invalid." );
176 }
177 }
178 else
179 {
180 DevCon.WriteLn( "CDVDiso: no cached info for second layer found." );
181 }
182
183 if( layer1start == -1 )
184 {
185
186 // Layer sizes are arbitrary, and either layer could be the smaller (GoW and Rogue Galaxy
187 // both have Layer1 larger than Layer0 for example), so we have to brute-force the search
188 // from some arbitrary start position.
189 //
190 // Method: Inside->out. We start at the middle of the image and work our way out toward
191 // both the beginning and end of the image at the same time. Most images have the layer
192 // break quite close to the middle of the image, so this should be pretty fast in most cases.
193
194 // [TODO] Layer searching can be slow, especially for compressed disc images, so it would
195 // be quite courteous to pop up a status dialog bar that lets the user know that it's
196 // thinking. Since we're not on the GUI thread, we'll need to establish some messages
197 // to create the window and pass progress increments back to it.
198
199
200 uint midsector = (iso->blocks / 2) & ~0xf;
201 uint deviation = 0;
202
203 while( (layer1start == -1) && (deviation < midsector-16) )
204 {
205 u8 tempbuffer[CD_FRAMESIZE_RAW];
206 isoReadBlock(iso, tempbuffer, midsector-deviation);
207
208 if(testForPartitionInfo( tempbuffer ))
209 layer1start = midsector-deviation;
210 else
211 {
212 isoReadBlock(iso, tempbuffer, midsector+deviation);
213 if( testForPartitionInfo( tempbuffer ) )
214 layer1start = midsector+deviation;
215 }
216
217 if( layer1start != -1 )
218 {
219 if( !pxAssertDev( tempbuffer[iso->blockofs] == 0x01, "Layer1-Detect: CD001 tag found, but the partition type is invalid." ) )
220 {
221 Console.Error( "CDVDiso: Invalid partition type on layer 1!? (type=0x%x)", tempbuffer[iso->blockofs] );
222 }
223 }
224 deviation += 16;
225 }
226
227 if( layer1start == -1 )
228 {
229 Console.Warning("CDVDiso: Couldn't find second layer... ignoring");
230 return false;
231 }
232 else
233 {
234 Console.WriteLn("CDVDiso: second layer found at sector 0x%8.8x", layer1start);
235
236 // Save layer information to configuration:
237
238 layerCacheIni.Write( cacheKey, layer1start );
239 }
240 }
241 return true;
242 }
243
244 // Should return 0 if no error occurred, or -1 if layer detection FAILED.
245 s32 CALLBACK ISOgetDualInfo(s32* dualType, u32* _layer1start)
246 {
247 if( !FindLayer1Start() ) return -1;
248
249 if(layer1start<0)
250 {
251 *dualType = 0;
252 *_layer1start = iso->blocks;
253 }
254 else
255 {
256 *dualType = 1;
257 *_layer1start = layer1start;
258 }
259 return 0;
260 }
261
262 s32 CALLBACK ISOgetDiskType()
263 {
264 return cdtype;
265 }
266
267 s32 CALLBACK ISOgetTOC(void* toc)
268 {
269 u8 type = ISOgetDiskType();
270 u8* tocBuff = (u8*)toc;
271
272 //CDVD_LOG("CDVDgetTOC\n");
273
274 if (type == CDVD_TYPE_DVDV || type == CDVD_TYPE_PS2DVD)
275 {
276 // get dvd structure format
277 // scsi command 0x43
278 memset(tocBuff, 0, 2048);
279
280 FindLayer1Start();
281
282 if (layer1start < 0)
283 {
284 // fake it
285 tocBuff[ 0] = 0x04;
286 tocBuff[ 1] = 0x02;
287 tocBuff[ 2] = 0xF2;
288 tocBuff[ 3] = 0x00;
289 tocBuff[ 4] = 0x86;
290 tocBuff[ 5] = 0x72;
291
292 tocBuff[16] = 0x00;
293 tocBuff[17] = 0x03;
294 tocBuff[18] = 0x00;
295 tocBuff[19] = 0x00;
296 return 0;
297 }
298 else
299 {
300 // dual sided
301 tocBuff[ 0] = 0x24;
302 tocBuff[ 1] = 0x02;
303 tocBuff[ 2] = 0xF2;
304 tocBuff[ 3] = 0x00;
305 tocBuff[ 4] = 0x41;
306 tocBuff[ 5] = 0x95;
307
308 tocBuff[14] = 0x60; // dual sided, ptp
309
310 tocBuff[16] = 0x00;
311 tocBuff[17] = 0x03;
312 tocBuff[18] = 0x00;
313 tocBuff[19] = 0x00;
314
315 s32 l1s = layer1start + 0x30000 - 1;
316 tocBuff[20] = (l1s >> 24);
317 tocBuff[21] = (l1s >> 16) & 0xff;
318 tocBuff[22] = (l1s >> 8) & 0xff;
319 tocBuff[23] = (l1s >> 0) & 0xff;
320 }
321 }
322 else if ((type == CDVD_TYPE_CDDA) || (type == CDVD_TYPE_PS2CDDA) ||
323 (type == CDVD_TYPE_PS2CD) || (type == CDVD_TYPE_PSCDDA) || (type == CDVD_TYPE_PSCD))
324 {
325 // cd toc
326 // (could be replaced by 1 command that reads the full toc)
327 u8 min, sec, frm;
328 s32 i, err;
329 cdvdTN diskInfo;
330 cdvdTD trackInfo;
331 memset(tocBuff, 0, 1024);
332 if (ISOgetTN(&diskInfo) == -1)
333 {
334 diskInfo.etrack = 0;
335 diskInfo.strack = 1;
336 }
337 if (ISOgetTD(0, &trackInfo) == -1) trackInfo.lsn = 0;
338
339 tocBuff[0] = 0x41;
340 tocBuff[1] = 0x00;
341
342 //Number of FirstTrack
343 tocBuff[2] = 0xA0;
344 tocBuff[7] = itob(diskInfo.strack);
345
346 //Number of LastTrack
347 tocBuff[12] = 0xA1;
348 tocBuff[17] = itob(diskInfo.etrack);
349
350 //DiskLength
351 lba_to_msf(trackInfo.lsn, &min, &sec, &frm);
352 tocBuff[22] = 0xA2;
353 tocBuff[27] = itob(min);
354 tocBuff[28] = itob(sec);
355
356 for (i = diskInfo.strack; i <= diskInfo.etrack; i++)
357 {
358 err = ISOgetTD(i, &trackInfo);
359 lba_to_msf(trackInfo.lsn, &min, &sec, &frm);
360 tocBuff[i*10+30] = trackInfo.type;
361 tocBuff[i*10+32] = err == -1 ? 0 : itob(i); //number
362 tocBuff[i*10+37] = itob(min);
363 tocBuff[i*10+38] = itob(sec);
364 tocBuff[i*10+39] = itob(frm);
365 }
366 }
367 else
368 return -1;
369
370 return 0;
371 }
372
373 s32 CALLBACK ISOreadSector(u8* tempbuffer, u32 lsn, int mode)
374 {
375 int _lsn = lsn;
376
377 if (_lsn < 0) lsn = iso->blocks + _lsn;
378 if (lsn > iso->blocks) return -1;
379
380 if(mode == CDVD_MODE_2352)
381 {
382 isoReadBlock(iso, tempbuffer, lsn);
383 return 0;
384 }
385
386 isoReadBlock(iso, cdbuffer, lsn);
387
388 pbuffer = cdbuffer;
389
390 switch (mode)
391 {
392 case CDVD_MODE_2352:
393 psize = 2352;
394 break;
395 case CDVD_MODE_2340:
396 pbuffer += 12;
397 psize = 2340;
398 break;
399 case CDVD_MODE_2328:
400 pbuffer += 24;
401 psize = 2328;
402 break;
403 case CDVD_MODE_2048:
404 pbuffer += 24;
405 psize = 2048;
406 break;
407 }
408
409 // version 3 blockdumps have no pbuffer header, so lets reset back to the
410 // original pointer. :)
411 if( iso->flags & ISOFLAGS_BLOCKDUMP_V3 )
412 pbuffer = cdbuffer;
413
414 memcpy_fast(tempbuffer,pbuffer,psize);
415
416 return 0;
417 }
418
419 s32 CALLBACK ISOreadTrack(u32 lsn, int mode)
420 {
421 int _lsn = lsn;
422
423 if (_lsn < 0) lsn = iso->blocks + _lsn;
424 if (lsn > iso->blocks) return -1;
425
426 isoReadBlock(iso, cdbuffer, lsn);
427 pbuffer = cdbuffer;
428
429 switch (mode)
430 {
431 case CDVD_MODE_2352:
432 psize = 2352;
433 break;
434 case CDVD_MODE_2340:
435 pbuffer += 12;
436 psize = 2340;
437 break;
438 case CDVD_MODE_2328:
439 pbuffer += 24;
440 psize = 2328;
441 break;
442 case CDVD_MODE_2048:
443 pbuffer += 24;
444 psize = 2048;
445 break;
446 }
447
448 // version 3 blockdumps have no pbuffer header, so lets reset back to the
449 // original pointer. :)
450 if( iso->flags & ISOFLAGS_BLOCKDUMP_V3 )
451 pbuffer = cdbuffer;
452
453 return 0;
454 }
455
456 s32 CALLBACK ISOgetBuffer2(u8* buffer)
457 {
458 memcpy_fast(buffer,pbuffer,psize);
459 return 0;
460 }
461
462 u8* CALLBACK ISOgetBuffer()
463 {
464 return pbuffer;
465 }
466
467 s32 CALLBACK ISOgetTrayStatus()
468 {
469 return CDVD_TRAY_CLOSE;
470 }
471
472 s32 CALLBACK ISOctrlTrayOpen()
473 {
474 return 0;
475 }
476 s32 CALLBACK ISOctrlTrayClose()
477 {
478 return 0;
479 }
480
481 s32 CALLBACK ISOdummyS32()
482 {
483 return 0;
484 }
485
486 void CALLBACK ISOnewDiskCB(void(* /* callback */)())
487 {
488 }
489
490 CDVD_API CDVDapi_Iso =
491 {
492 ISOclose,
493
494 ISOopen,
495 ISOreadTrack,
496 ISOgetBuffer, // emu shouldn't use this one.
497 ISOreadSubQ,
498 ISOgetTN,
499 ISOgetTD,
500 ISOgetTOC,
501 ISOgetDiskType,
502 ISOdummyS32, // trayStatus
503 ISOdummyS32, // trayOpen
504 ISOdummyS32, // trayClose
505
506 ISOnewDiskCB,
507
508 ISOreadSector,
509 ISOgetBuffer2,
510 ISOgetDualInfo,
511 };

  ViewVC Help
Powered by ViewVC 1.1.22