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

Annotation of /trunk/pcsx2/CDVD/CDVDisoReader.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.22