/[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 273 - (show annotations) (download)
Fri Nov 12 01:10:22 2010 UTC (10 years, 5 months ago) by william
File size: 12022 byte(s)
Auto Commited Import of: pcsx2-0.9.7-DEBUG (upstream: v0.9.7.4013 local: v0.9.7.197-latest) in ./trunk
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;
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 static bool firstRun = true;
299 if (!firstRun) cdvdCtrlTrayOpen();
300 firstRun = false;
301
302 switch( m_CurrentSourceType = type )
303 {
304 case CDVDsrc_Iso:
305 CDVD = &CDVDapi_Iso;
306 break;
307
308 case CDVDsrc_NoDisc:
309 CDVD = &CDVDapi_NoDisc;
310 break;
311
312 case CDVDsrc_Plugin:
313 CDVD = &CDVDapi_Plugin;
314 break;
315
316 jNO_DEFAULT;
317 }
318 }
319
320 bool DoCDVDopen()
321 {
322 CheckNullCDVD();
323
324 // the new disk callback is set on Init also, but just in case the plugin clears it for
325 // some reason on close, we re-send here:
326 CDVD->newDiskCB( cdvdNewDiskCB );
327
328 // Win32 Fail: the old CDVD api expects MBCS on Win32 platforms, but generating a MBCS
329 // from unicode is problematic since we need to know the codepage of the text being
330 // converted (which isn't really practical knowledge). A 'best guess' would be the
331 // default codepage of the user's Windows install, but even that will fail and return
332 // question marks if the filename is another language.
333 // Likely Fix: Force new versions of CDVD plugins to expect UTF8 instead.
334
335 int ret = CDVD->open( !m_SourceFilename[m_CurrentSourceType].IsEmpty() ?
336 m_SourceFilename[m_CurrentSourceType].ToUTF8() : (char*)NULL
337 );
338
339 if( ret == -1 ) return false; // error! (handled by caller)
340 if( ret == 1 ) throw Exception::CancelEvent(L"User canceled the CDVD plugin's open dialog.");
341
342 int cdtype = DoCDVDdetectDiskType();
343
344 if (!EmuConfig.CdvdDumpBlocks || (cdtype == CDVD_TYPE_NODISC))
345 {
346 blockDumpFile.Close();
347 return true;
348 }
349
350 // TODO: Add a blockdumps configurable folder, and use that instead of CWD().
351
352 // TODO: "Untitled" should use pnach/slus name resolution, slus if no patch,
353 // and finally an "Untitled-[ElfCRC]" if no slus.
354
355 wxString somepick( Path::GetFilenameWithoutExt( m_SourceFilename[m_CurrentSourceType] ) );
356 if( somepick.IsEmpty() )
357 somepick = L"Untitled";
358
359 wxString temp( Path::Combine( wxGetCwd(), somepick ) );
360
361 #ifdef ENABLE_TIMESTAMPS
362 wxDateTime curtime( wxDateTime::GetTimeNow() );
363
364 temp += pxsFmt( L" (%04d-%02d-%02d %02d-%02d-%02d)",
365 curtime.GetYear(), curtime.GetMonth(), curtime.GetDay(),
366 curtime.GetHour(), curtime.GetMinute(), curtime.GetSecond()
367 );
368 #endif
369 temp += L".dump";
370
371 cdvdTD td;
372 CDVD->getTD(0, &td);
373
374 blockDumpFile.Create(temp, ISOFLAGS_BLOCKDUMP_V3);
375
376 if( blockDumpFile.IsOpened() )
377 {
378 int blockofs = 0;
379 uint blocksize = CD_FRAMESIZE_RAW;
380 uint blocks = td.lsn;
381
382 // hack: Because of limitations of the current cdvd design, we can't query the blocksize
383 // of the underlying media. So lets make a best guess:
384
385 switch(cdtype)
386 {
387 case CDVD_TYPE_PS2DVD:
388 case CDVD_TYPE_DVDV:
389 case CDVD_TYPE_DETCTDVDS:
390 case CDVD_TYPE_DETCTDVDD:
391 blocksize = 2048;
392 break;
393 }
394 blockDumpFile.WriteFormat(blockofs, blocksize, blocks);
395 }
396
397 return true;
398 }
399
400 void DoCDVDclose()
401 {
402 CheckNullCDVD();
403 blockDumpFile.Close();
404
405 if( CDVD->close != NULL )
406 CDVD->close();
407
408 DoCDVDresetDiskTypeCache();
409 }
410
411 s32 DoCDVDreadSector(u8* buffer, u32 lsn, int mode)
412 {
413 CheckNullCDVD();
414 int ret = CDVD->readSector(buffer,lsn,mode);
415
416 if (ret == 0 && blockDumpFile.IsOpened())
417 {
418 blockDumpFile.WriteBlock(buffer, lsn);
419 }
420
421 return ret;
422 }
423
424 s32 DoCDVDreadTrack(u32 lsn, int mode)
425 {
426 CheckNullCDVD();
427
428 // TEMP: until all the plugins use the new CDVDgetBuffer style
429 switch (mode)
430 {
431 case CDVD_MODE_2352:
432 lastReadSize = 2352;
433 break;
434 case CDVD_MODE_2340:
435 lastReadSize = 2340;
436 break;
437 case CDVD_MODE_2328:
438 lastReadSize = 2328;
439 break;
440 case CDVD_MODE_2048:
441 lastReadSize = 2048;
442 break;
443 }
444
445 //DevCon.Warning("CDVD readTrack(lsn=%d,mode=%d)",params lsn, lastReadSize);
446 lastLSN = lsn;
447 return CDVD->readTrack(lsn,mode);
448 }
449
450 s32 DoCDVDgetBuffer(u8* buffer)
451 {
452 CheckNullCDVD();
453 int ret = CDVD->getBuffer2(buffer);
454
455 if (ret == 0 && blockDumpFile.IsOpened())
456 {
457 blockDumpFile.WriteBlock(buffer, lastLSN);
458 }
459
460 return ret;
461 }
462
463 s32 DoCDVDdetectDiskType()
464 {
465 CheckNullCDVD();
466 if(diskTypeCached < 0) DetectDiskType();
467 return diskTypeCached;
468 }
469
470 void DoCDVDresetDiskTypeCache()
471 {
472 diskTypeCached = -1;
473 }
474
475 ////////////////////////////////////////////////////////
476 //
477 // CDVD null interface for Run BIOS menu
478
479
480
481 s32 CALLBACK NODISCopen(const char* pTitle)
482 {
483 return 0;
484 }
485
486 void CALLBACK NODISCclose()
487 {
488 }
489
490 s32 CALLBACK NODISCreadTrack(u32 lsn, int mode)
491 {
492 return -1;
493 }
494
495 // return can be NULL (for async modes)
496 u8* CALLBACK NODISCgetBuffer()
497 {
498 return NULL;
499 }
500
501 s32 CALLBACK NODISCreadSubQ(u32 lsn, cdvdSubQ* subq)
502 {
503 return -1;
504 }
505
506 s32 CALLBACK NODISCgetTN(cdvdTN *Buffer)
507 {
508 return -1;
509 }
510
511 s32 CALLBACK NODISCgetTD(u8 Track, cdvdTD *Buffer)
512 {
513 return -1;
514 }
515
516 s32 CALLBACK NODISCgetTOC(void* toc)
517 {
518 return -1;
519 }
520
521 s32 CALLBACK NODISCgetDiskType()
522 {
523 return CDVD_TYPE_NODISC;
524 }
525
526 s32 CALLBACK NODISCgetTrayStatus()
527 {
528 return CDVD_TRAY_CLOSE;
529 }
530
531 s32 CALLBACK NODISCdummyS32()
532 {
533 return 0;
534 }
535
536 void CALLBACK NODISCnewDiskCB(void (* /* callback */)())
537 {
538 }
539
540 s32 CALLBACK NODISCreadSector(u8* tempbuffer, u32 lsn, int mode)
541 {
542 return -1;
543 }
544
545 s32 CALLBACK NODISCgetBuffer2(u8* buffer)
546 {
547 return -1;
548 }
549
550 s32 CALLBACK NODISCgetDualInfo(s32* dualType, u32* _layer1start)
551 {
552 return -1;
553 }
554
555 CDVD_API CDVDapi_NoDisc =
556 {
557 NODISCclose,
558 NODISCopen,
559 NODISCreadTrack,
560 NODISCgetBuffer,
561 NODISCreadSubQ,
562 NODISCgetTN,
563 NODISCgetTD,
564 NODISCgetTOC,
565 NODISCgetDiskType,
566 NODISCgetTrayStatus,
567 NODISCdummyS32,
568 NODISCdummyS32,
569
570 NODISCnewDiskCB,
571
572 NODISCreadSector,
573 NODISCgetBuffer2,
574 NODISCgetDualInfo,
575 };

  ViewVC Help
Powered by ViewVC 1.1.22