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

Annotation of /trunk/pcsx2/CDVD/CDVDaccess.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: 11864 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     #include "PrecompiledHeader.h"
18     #include "IopCommon.h"
19    
20     #define ENABLE_TIMESTAMPS
21    
22     #ifdef _WIN32
23     # include <wx/msw/wrapwin.h>
24     #endif
25    
26     #include <ctype.h>
27     #include <time.h>
28     #include <wx/datetime.h>
29     #include <exception>
30    
31     #include "IsoFS/IsoFS.h"
32     #include "IsoFS/IsoFSCDVD.h"
33     #include "CDVDisoReader.h"
34     #include "Utilities/ScopedPtr.h"
35    
36     const wxChar* CDVD_SourceLabels[] =
37     {
38     L"Iso",
39     L"Plugin",
40     L"NoDisc",
41     NULL
42     };
43    
44     // ----------------------------------------------------------------------------
45     // diskTypeCached
46     // Internal disc type cache, to reduce the overhead of disc type checks, which are
47     // performed quite liberally by many games (perhaps intended to keep the PS2 DVD
48     // from spinning down due to idle activity?).
49     // Cache is set to -1 for init and when the disc is removed/changed, which invokes
50     // a new DiskTypeCheck. All subsequent checks use the non-negative value here.
51     //
52     static int diskTypeCached = -1;
53    
54     // used to bridge the gap between the old getBuffer api and the new getBuffer2 api.
55     int lastReadSize;
56     int lastLSN; // needed for block dumping
57    
58     // Records last read block length for block dumping
59     //static int plsn = 0;
60     static isoFile *blockDumpFile = NULL;
61    
62     // Assertion check for CDVD != NULL (in devel and debug builds), because its handier than
63     // relying on DEP exceptions -- and a little more reliable too.
64     static void CheckNullCDVD()
65     {
66     pxAssertDev( CDVD != NULL, "Invalid CDVD object state (null pointer exception)" );
67     }
68    
69     //////////////////////////////////////////////////////////////////////////////////////////
70     // Disk Type detection stuff (from cdvdGigaherz)
71     //
72     static int CheckDiskTypeFS(int baseType)
73     {
74     IsoFSCDVD isofs;
75     IsoDirectory rootdir(isofs);
76     try {
77     IsoFile file( rootdir, L"SYSTEM.CNF;1");
78    
79     int size = file.getLength();
80    
81     ScopedArray<char> buffer((int)file.getLength()+1);
82     file.read((u8*)(buffer.GetPtr()),size);
83     buffer[size]='\0';
84    
85     char* pos = strstr(buffer.GetPtr(), "BOOT2");
86     if (pos == NULL)
87     {
88     pos = strstr(buffer.GetPtr(), "BOOT");
89     if (pos == NULL) return CDVD_TYPE_ILLEGAL;
90     return CDVD_TYPE_PSCD;
91     }
92    
93     return (baseType==CDVD_TYPE_DETCTCD) ? CDVD_TYPE_PS2CD : CDVD_TYPE_PS2DVD;
94     }
95     catch( Exception::FileNotFound& )
96     {
97     }
98    
99     try {
100     IsoFile file( rootdir, L"PSX.EXE;1");
101     return CDVD_TYPE_PSCD;
102     }
103     catch( Exception::FileNotFound& )
104     {
105     }
106    
107     try {
108     IsoFile file( rootdir, L"VIDEO_TS/VIDEO_TS.IFO;1");
109     return CDVD_TYPE_DVDV;
110     }
111     catch( Exception::FileNotFound& )
112     {
113     }
114    
115     return CDVD_TYPE_ILLEGAL; // << Only for discs which aren't ps2 at all.
116     }
117    
118     static int FindDiskType(int mType)
119     {
120     int dataTracks = 0;
121     int audioTracks = 0;
122     int iCDType = mType;
123     cdvdTN tn;
124    
125     CDVD->getTN(&tn);
126    
127     if (tn.strack != tn.etrack) // multitrack == CD.
128     {
129     iCDType = CDVD_TYPE_DETCTCD;
130     }
131     else if (mType < 0)
132     {
133     static u8 bleh[CD_FRAMESIZE_RAW];
134     cdvdTD td;
135    
136     CDVD->getTD(0,&td);
137     if (td.lsn > 452849)
138     {
139     iCDType = CDVD_TYPE_DETCTDVDS;
140     }
141     else
142     {
143     if (DoCDVDreadSector(bleh, 16, CDVD_MODE_2048) == 0)
144     {
145     //const cdVolDesc& volDesc = (cdVolDesc&)bleh;
146     //if(volDesc.rootToc.tocSize == 2048)
147     if(*(u16*)(bleh+166) == 2048)
148     iCDType = CDVD_TYPE_DETCTCD;
149     else
150     iCDType = CDVD_TYPE_DETCTDVDS;
151     }
152     }
153     }
154    
155     if (iCDType == CDVD_TYPE_DETCTDVDS)
156     {
157     s32 dlt = 0;
158     u32 l1s = 0;
159    
160     if(CDVD->getDualInfo(&dlt,&l1s)==0)
161     {
162     if (dlt > 0) iCDType = CDVD_TYPE_DETCTDVDD;
163     }
164     }
165    
166     switch(iCDType)
167     {
168     case CDVD_TYPE_DETCTCD:
169     Console.WriteLn(" * CDVD Disk Open: CD, %d tracks (%d to %d):", tn.etrack-tn.strack+1,tn.strack,tn.etrack);
170     break;
171    
172     case CDVD_TYPE_DETCTDVDS:
173     Console.WriteLn(" * CDVD Disk Open: DVD, Single layer or unknown:");
174     break;
175    
176     case CDVD_TYPE_DETCTDVDD:
177     Console.WriteLn(" * CDVD Disk Open: DVD, Double layer:");
178     break;
179     }
180    
181     audioTracks = dataTracks = 0;
182     for(int i = tn.strack; i <= tn.etrack; i++)
183     {
184     cdvdTD td,td2;
185    
186     CDVD->getTD(i,&td);
187    
188     if (tn.etrack > i)
189     CDVD->getTD(i+1,&td2);
190     else
191     CDVD->getTD(0,&td2);
192    
193     int tlength = td2.lsn - td.lsn;
194    
195     if (td.type == CDVD_AUDIO_TRACK)
196     {
197     audioTracks++;
198     Console.WriteLn(" * * Track %d: Audio (%d sectors)", i,tlength);
199     }
200     else
201     {
202     dataTracks++;
203     Console.WriteLn(" * * Track %d: Data (Mode %d) (%d sectors)", i,((td.type==CDVD_MODE1_TRACK)?1:2),tlength);
204     }
205     }
206    
207     if (dataTracks > 0)
208     {
209     iCDType=CheckDiskTypeFS(iCDType);
210     }
211    
212     if (audioTracks > 0)
213     {
214     switch (iCDType)
215     {
216     case CDVD_TYPE_PS2CD:
217     iCDType=CDVD_TYPE_PS2CDDA;
218     break;
219     case CDVD_TYPE_PSCD:
220     iCDType=CDVD_TYPE_PSCDDA;
221     break;
222     default:
223     iCDType=CDVD_TYPE_CDDA;
224     break;
225     }
226     }
227    
228     return iCDType;
229     }
230    
231     static void DetectDiskType()
232     {
233     if (CDVD->getTrayStatus() == CDVD_TRAY_OPEN)
234     {
235     diskTypeCached = CDVD_TYPE_NODISC;
236     return;
237     }
238    
239     int baseMediaType = CDVD->getDiskType();
240     int mType = -1;
241    
242     // Paranoid mode: do not trust the plugin's detection system to work correctly.
243     // (.. and there's no reason plugins should be doing their own detection anyway).
244    
245     switch(baseMediaType)
246     {
247     #if 0
248     case CDVD_TYPE_CDDA:
249     case CDVD_TYPE_PSCD:
250     case CDVD_TYPE_PS2CD:
251     case CDVD_TYPE_PSCDDA:
252     case CDVD_TYPE_PS2CDDA:
253     mType = CDVD_TYPE_DETCTCD;
254     break;
255    
256     case CDVD_TYPE_DVDV:
257     case CDVD_TYPE_PS2DVD:
258     mType = CDVD_TYPE_DETCTDVDS;
259     break;
260    
261     case CDVD_TYPE_DETCTDVDS:
262     case CDVD_TYPE_DETCTDVDD:
263     case CDVD_TYPE_DETCTCD:
264     mType = baseMediaType;
265     break;
266     #endif
267    
268     case CDVD_TYPE_NODISC:
269     diskTypeCached = CDVD_TYPE_NODISC;
270     return;
271     }
272    
273     diskTypeCached = FindDiskType(mType);
274     }
275    
276     static wxString m_SourceFilename[3];
277     static CDVD_SourceType m_CurrentSourceType = CDVDsrc_NoDisc;
278    
279     void CDVDsys_SetFile( CDVD_SourceType srctype, const wxString& newfile )
280     {
281     m_SourceFilename[srctype] = newfile;
282     }
283    
284     const wxString& CDVDsys_GetFile( CDVD_SourceType srctype )
285     {
286     return m_SourceFilename[srctype];
287     }
288    
289     CDVD_SourceType CDVDsys_GetSourceType()
290     {
291     return m_CurrentSourceType;
292     }
293    
294     void CDVDsys_ChangeSource( CDVD_SourceType type )
295     {
296     GetCorePlugins().Close( PluginId_CDVD );
297    
298     switch( m_CurrentSourceType = type )
299     {
300     case CDVDsrc_Iso:
301     CDVD = &CDVDapi_Iso;
302     break;
303    
304     case CDVDsrc_NoDisc:
305     CDVD = &CDVDapi_NoDisc;
306     break;
307    
308     case CDVDsrc_Plugin:
309     CDVD = &CDVDapi_Plugin;
310     break;
311    
312     jNO_DEFAULT;
313     }
314     }
315    
316     bool DoCDVDopen()
317     {
318     CheckNullCDVD();
319    
320     // the new disk callback is set on Init also, but just in case the plugin clears it for
321     // some reason on close, we re-send here:
322     CDVD->newDiskCB( cdvdNewDiskCB );
323    
324     // Win32 Fail: the old CDVD api expects MBCS on Win32 platforms, but generating a MBCS
325     // from unicode is problematic since we need to know the codepage of the text being
326     // converted (which isn't really practical knowledge). A 'best guess' would be the
327     // default codepage of the user's Windows install, but even that will fail and return
328     // question marks if the filename is another language.
329     // Likely Fix: Force new versions of CDVD plugins to expect UTF8 instead.
330    
331     int ret = CDVD->open( !m_SourceFilename[m_CurrentSourceType].IsEmpty() ?
332     m_SourceFilename[m_CurrentSourceType].ToUTF8() : (char*)NULL
333     );
334    
335     if( ret == -1 ) return false;
336    
337     int cdtype = DoCDVDdetectDiskType();
338    
339     if (EmuConfig.CdvdDumpBlocks && (cdtype != CDVD_TYPE_NODISC))
340     {
341     // TODO: Add a blockdumps configurable folder, and use that instead of CWD().
342    
343     // TODO: "Untitled" should use pnach/slus name resolution, slus if no patch,
344     // and finally an "Untitled-[ElfCRC]" if no slus.
345    
346     wxString somepick( Path::GetFilenameWithoutExt( m_SourceFilename[m_CurrentSourceType] ) );
347     if( somepick.IsEmpty() )
348     somepick = L"Untitled";
349    
350     wxString temp( Path::Combine( wxGetCwd(), somepick ) );
351    
352     #ifdef ENABLE_TIMESTAMPS
353     wxDateTime curtime( wxDateTime::GetTimeNow() );
354    
355     temp += wxsFormat( L" (%04d-%02d-%02d %02d-%02d-%02d)",
356     curtime.GetYear(), curtime.GetMonth(), curtime.GetDay(),
357     curtime.GetHour(), curtime.GetMinute(), curtime.GetSecond()
358     );
359     #endif
360     temp += L".dump";
361    
362     cdvdTD td;
363     CDVD->getTD(0, &td);
364    
365     blockDumpFile = isoCreate(temp.ToUTF8(), ISOFLAGS_BLOCKDUMP_V3);
366    
367     if( blockDumpFile != NULL )
368     {
369     int blockofs = 0, blocksize = CD_FRAMESIZE_RAW, blocks = td.lsn;
370    
371     // hack: Because of limitations of the current cdvd design, we can't query the blocksize
372     // of the underlying media. So lets make a best guess:
373    
374     switch(cdtype)
375     {
376     case CDVD_TYPE_PS2DVD:
377     case CDVD_TYPE_DVDV:
378     case CDVD_TYPE_DETCTDVDS:
379     case CDVD_TYPE_DETCTDVDD:
380     blocksize = 2048;
381     break;
382     }
383     isoSetFormat(blockDumpFile, blockofs, blocksize, blocks);
384     }
385     }
386     else
387     {
388     blockDumpFile = NULL;
389     }
390    
391     return true;
392     }
393    
394     void DoCDVDclose()
395     {
396     CheckNullCDVD();
397     if(blockDumpFile) isoClose(blockDumpFile);
398     if( CDVD->close != NULL )
399     CDVD->close();
400    
401     DoCDVDresetDiskTypeCache();
402     }
403    
404     s32 DoCDVDreadSector(u8* buffer, u32 lsn, int mode)
405     {
406     CheckNullCDVD();
407     int ret = CDVD->readSector(buffer,lsn,mode);
408    
409     if(ret == 0 && blockDumpFile != NULL )
410     {
411     isoWriteBlock(blockDumpFile, buffer, lsn);
412     }
413    
414     return ret;
415     }
416    
417     s32 DoCDVDreadTrack(u32 lsn, int mode)
418     {
419     CheckNullCDVD();
420    
421     // TEMP: until all the plugins use the new CDVDgetBuffer style
422     switch (mode)
423     {
424     case CDVD_MODE_2352:
425     lastReadSize = 2352;
426     break;
427     case CDVD_MODE_2340:
428     lastReadSize = 2340;
429     break;
430     case CDVD_MODE_2328:
431     lastReadSize = 2328;
432     break;
433     case CDVD_MODE_2048:
434     lastReadSize = 2048;
435     break;
436     }
437    
438     //DevCon.Warning("CDVD readTrack(lsn=%d,mode=%d)",params lsn, lastReadSize);
439     lastLSN = lsn;
440     return CDVD->readTrack(lsn,mode);
441     }
442    
443     s32 DoCDVDgetBuffer(u8* buffer)
444     {
445     CheckNullCDVD();
446     int ret = CDVD->getBuffer2(buffer);
447    
448     if (ret == 0 && blockDumpFile != NULL)
449     {
450     isoWriteBlock(blockDumpFile, buffer, lastLSN);
451     }
452    
453     return ret;
454     }
455    
456     s32 DoCDVDdetectDiskType()
457     {
458     CheckNullCDVD();
459     if(diskTypeCached < 0) DetectDiskType();
460     return diskTypeCached;
461     }
462    
463     void DoCDVDresetDiskTypeCache()
464     {
465     diskTypeCached = -1;
466     }
467    
468     ////////////////////////////////////////////////////////
469     //
470     // CDVD null interface for Run BIOS menu
471    
472    
473    
474     s32 CALLBACK NODISCopen(const char* pTitle)
475     {
476     return 0;
477     }
478    
479     void CALLBACK NODISCclose()
480     {
481     }
482    
483     s32 CALLBACK NODISCreadTrack(u32 lsn, int mode)
484     {
485     return -1;
486     }
487    
488     // return can be NULL (for async modes)
489     u8* CALLBACK NODISCgetBuffer()
490     {
491     return NULL;
492     }
493    
494     s32 CALLBACK NODISCreadSubQ(u32 lsn, cdvdSubQ* subq)
495     {
496     return -1;
497     }
498    
499     s32 CALLBACK NODISCgetTN(cdvdTN *Buffer)
500     {
501     return -1;
502     }
503    
504     s32 CALLBACK NODISCgetTD(u8 Track, cdvdTD *Buffer)
505     {
506     return -1;
507     }
508    
509     s32 CALLBACK NODISCgetTOC(void* toc)
510     {
511     return -1;
512     }
513    
514     s32 CALLBACK NODISCgetDiskType()
515     {
516     return CDVD_TYPE_NODISC;
517     }
518    
519     s32 CALLBACK NODISCgetTrayStatus()
520     {
521     return CDVD_TRAY_CLOSE;
522     }
523    
524     s32 CALLBACK NODISCdummyS32()
525     {
526     return 0;
527     }
528    
529     void CALLBACK NODISCnewDiskCB(void (* /* callback */)())
530     {
531     }
532    
533     s32 CALLBACK NODISCreadSector(u8* tempbuffer, u32 lsn, int mode)
534     {
535     return -1;
536     }
537    
538     s32 CALLBACK NODISCgetBuffer2(u8* buffer)
539     {
540     return -1;
541     }
542    
543     s32 CALLBACK NODISCgetDualInfo(s32* dualType, u32* _layer1start)
544     {
545     return -1;
546     }
547    
548     CDVD_API CDVDapi_NoDisc =
549     {
550     NODISCclose,
551     NODISCopen,
552     NODISCreadTrack,
553     NODISCgetBuffer,
554     NODISCreadSubQ,
555     NODISCgetTN,
556     NODISCgetTD,
557     NODISCgetTOC,
558     NODISCgetDiskType,
559     NODISCgetTrayStatus,
560     NODISCdummyS32,
561     NODISCdummyS32,
562    
563     NODISCnewDiskCB,
564    
565     NODISCreadSector,
566     NODISCgetBuffer2,
567     NODISCgetDualInfo,
568     };

  ViewVC Help
Powered by ViewVC 1.1.22