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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (10 years, 5 months ago) by william
File size: 11864 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 #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