/[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 31 - (hide 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 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     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