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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (10 years, 7 months ago) by william
File size: 53301 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 #include "PrecompiledHeader.h"
17 #include "IopCommon.h"
18 #include "AppConfig.h"
19
20 #include <ctype.h>
21 #include <wx/datetime.h>
22
23 #include "CDVD.h"
24 #include "CDVD_internal.h"
25 #include "CDVDisoReader.h"
26
27 #include "GS.h" // for gsRegionMode
28 #include "Elfheader.h"
29 #include "ps2/BiosTools.h"
30 #include "DataBase_Loader.h"
31
32 ScopedPtr<DataBase_Loader> GameDB;
33
34 wxString DiscID;
35
36 static cdvdStruct cdvd;
37
38 static __forceinline void SetResultSize(u8 size)
39 {
40 cdvd.ResultC = size;
41 cdvd.ResultP = 0;
42 cdvd.sDataIn&=~0x40;
43 }
44
45 static void CDVDREAD_INT(int eCycle)
46 {
47 PSX_INT(IopEvt_CdvdRead, eCycle);
48 }
49
50 static void CDVD_INT(int eCycle)
51 {
52 if( eCycle == 0 )
53 cdvdActionInterrupt();
54 else
55 PSX_INT(IopEvt_Cdvd, eCycle);
56 }
57
58 // Sets the cdvd IRQ and the reason for the IRQ, and signals the IOP for a branch
59 // test (which will cause the exception to be handled).
60 static void cdvdSetIrq( uint id = (1<<Irq_CommandComplete) )
61 {
62 cdvd.PwOff |= id;
63 iopIntcIrq( 2 );
64 hwIntcIrq(INTC_SBUS);
65 psxSetNextBranchDelta( 20 );
66 }
67
68 static int mg_BIToffset(u8 *buffer)
69 {
70 int i, ofs = 0x20;
71 for (i=0; i<*(u16*)&buffer[0x1A]; i++)
72 ofs+=0x10;
73
74 if (*(u16*)&buffer[0x18] & 1) ofs += buffer[ofs];
75 if ((*(u16*)&buffer[0x18] & 0xF000) == 0) ofs += 8;
76
77 return ofs + 0x20;
78 }
79
80 FILE *_cdvdOpenMechaVer()
81 {
82 FILE* fd;
83
84 // get the name of the bios file
85
86 wxFileName mecfile(EmuConfig.BiosFilename);
87 mecfile.SetExt( L"mec" );
88 const wxCharBuffer file( mecfile.GetFullPath().ToUTF8() );
89
90 // if file doesnt exist, create empty one
91 fd = fopen(file, "r+b");
92 if (fd == NULL)
93 {
94 Console.Warning("MEC File Not Found , Creating Blank File");
95 fd = fopen(file, "wb");
96 if (fd == NULL)
97 {
98 Console.Error( "MEC File Creation failed!" );
99 throw Exception::CannotCreateStream( file );
100 //Msgbox::Alert( "_cdvdOpenMechaVer: Error creating %s", file);
101 //exit(1);
102 }
103
104 fputc(0x03, fd);
105 fputc(0x06, fd);
106 fputc(0x02, fd);
107 fputc(0x00, fd);
108 }
109 return fd;
110 }
111
112 s32 cdvdGetMechaVer(u8* ver)
113 {
114 FILE* fd = _cdvdOpenMechaVer();
115 if (fd == NULL) return 1;
116 fseek(fd, 0, SEEK_SET);
117 fread(ver, 1, 4, fd);
118 fclose(fd);
119 return 0;
120 }
121
122 FILE *_cdvdOpenNVM()
123 {
124 FILE* fd;
125
126 wxFileName nvmfile(EmuConfig.BiosFilename);
127 nvmfile.SetExt( L"nvm" );
128 const wxCharBuffer file( nvmfile.GetFullPath().ToUTF8() );
129
130 // if file doesn't exist, create empty one
131 fd = fopen(file, "r+b");
132 if (fd == NULL)
133 {
134 Console.Warning("NVM File Not Found , Creating Blank File");
135 fd = fopen(file, "wb");
136 if (fd == NULL)
137 {
138 Console.Error( "NVM File Creation failed!" );
139 throw Exception::CannotCreateStream( file );
140 }
141 for (int i=0; i<1024; i++) fputc(0, fd);
142 }
143 return fd;
144 }
145
146 //
147 // the following 'cdvd' functions all return 0 if successful
148 //
149
150 s32 cdvdReadNVM(u8 *dst, int offset, int bytes) {
151 FILE* fd = _cdvdOpenNVM();
152 if (fd == NULL) return 1;
153
154 fseek(fd, offset, SEEK_SET);
155 fread(dst, 1, bytes, fd);
156 fclose(fd);
157
158 return 0;
159 }
160 s32 cdvdWriteNVM(const u8 *src, int offset, int bytes) {
161 FILE* fd = _cdvdOpenNVM();
162 if (fd == NULL) return 1;
163
164 fseek(fd, offset, SEEK_SET);
165 fwrite(src, 1, bytes, fd);
166 fclose(fd);
167
168 return 0;
169 }
170
171 NVMLayout* getNvmLayout(void)
172 {
173 NVMLayout* nvmLayout = NULL;
174 s32 nvmIdx;
175
176 for(nvmIdx=0; nvmIdx<NVM_FORMAT_MAX; nvmIdx++)
177 {
178 if(nvmlayouts[nvmIdx].biosVer <= BiosVersion)
179 nvmLayout = &nvmlayouts[nvmIdx];
180 }
181 return nvmLayout;
182 }
183
184 s32 getNvmData(u8* buffer, s32 offset, s32 size, s32 fmtOffset)
185 {
186 // find the correct bios version
187 NVMLayout* nvmLayout = getNvmLayout();
188 if (nvmLayout == NULL) return 1;
189
190 // get data from eeprom
191 return cdvdReadNVM(buffer, *(s32*)(((u8*)nvmLayout)+fmtOffset) + offset, size);
192 }
193 s32 setNvmData(const u8* buffer, s32 offset, s32 size, s32 fmtOffset)
194 {
195 // find the correct bios version
196 NVMLayout* nvmLayout = getNvmLayout();
197 if (nvmLayout == NULL) return 1;
198
199 // set data in eeprom
200 return cdvdWriteNVM(buffer, *(s32*)(((u8*)nvmLayout)+fmtOffset) + offset, size);
201 }
202
203 s32 cdvdReadConsoleID(u8* id)
204 {
205 return getNvmData(id, 0, 8, offsetof(NVMLayout, consoleId));
206 }
207 s32 cdvdWriteConsoleID(const u8* id)
208 {
209 return setNvmData(id, 0, 8, offsetof(NVMLayout, consoleId));
210 }
211
212 s32 cdvdReadILinkID(u8* id)
213 {
214 return getNvmData(id, 0, 8, offsetof(NVMLayout, ilinkId));
215 }
216 s32 cdvdWriteILinkID(const u8* id)
217 {
218 return setNvmData(id, 0, 8, offsetof(NVMLayout, ilinkId));
219 }
220
221 s32 cdvdReadModelNumber(u8* num, s32 part)
222 {
223 return getNvmData(num, part, 8, offsetof(NVMLayout, modelNum));
224 }
225 s32 cdvdWriteModelNumber(const u8* num, s32 part)
226 {
227 return setNvmData(num, part, 8, offsetof(NVMLayout, modelNum));
228 }
229
230 s32 cdvdReadRegionParams(u8* num)
231 {
232 return getNvmData(num, 0, 8, offsetof(NVMLayout,regparams));
233 }
234
235 s32 cdvdWriteRegionParams(const u8* num)
236 {
237 return setNvmData(num, 0, 8, offsetof(NVMLayout,regparams));
238 }
239
240 s32 cdvdReadMAC(u8* num)
241 {
242 return getNvmData(num, 0, 8, offsetof(NVMLayout,mac));
243 }
244
245 s32 cdvdWriteMAC(const u8* num)
246 {
247 return setNvmData(num, 0, 8, offsetof(NVMLayout,mac));
248 }
249
250 s32 cdvdReadConfig(u8* config)
251 {
252 // make sure its in read mode
253 if(cdvd.CReadWrite != 0)
254 {
255 config[0] = 0x80;
256 memset(&config[1], 0x00, 15);
257 return 1;
258 }
259 // check if block index is in bounds
260 else if(cdvd.CBlockIndex >= cdvd.CNumBlocks)
261 return 1;
262 else if(
263 ((cdvd.COffset == 0) && (cdvd.CBlockIndex >= 4))||
264 ((cdvd.COffset == 1) && (cdvd.CBlockIndex >= 2))||
265 ((cdvd.COffset == 2) && (cdvd.CBlockIndex >= 7))
266 )
267 {
268 memzero_ptr<16>(config);
269 return 0;
270 }
271
272 // get config data
273 switch (cdvd.COffset)
274 {
275 case 0:
276 return getNvmData(config, (cdvd.CBlockIndex++)*16, 16, offsetof(NVMLayout, config0));
277 break;
278 case 2:
279 return getNvmData(config, (cdvd.CBlockIndex++)*16, 16, offsetof(NVMLayout, config2));
280 break;
281 default:
282 return getNvmData(config, (cdvd.CBlockIndex++)*16, 16, offsetof(NVMLayout, config1));
283 }
284 }
285 s32 cdvdWriteConfig(const u8* config)
286 {
287 // make sure its in write mode && the block index is in bounds
288 if ((cdvd.CReadWrite != 1) || (cdvd.CBlockIndex >= cdvd.CNumBlocks))
289 return 1;
290 else if(
291 ((cdvd.COffset == 0) && (cdvd.CBlockIndex >= 4))||
292 ((cdvd.COffset == 1) && (cdvd.CBlockIndex >= 2))||
293 ((cdvd.COffset == 2) && (cdvd.CBlockIndex >= 7))
294 )
295 return 0;
296
297 // get config data
298 switch (cdvd.COffset)
299 {
300 case 0:
301 return setNvmData(config, (cdvd.CBlockIndex++)*16, 16, offsetof(NVMLayout, config0));
302 break;
303 case 2:
304 return setNvmData(config, (cdvd.CBlockIndex++)*16, 16, offsetof(NVMLayout, config2));
305 break;
306 default:
307 return setNvmData(config, (cdvd.CBlockIndex++)*16, 16, offsetof(NVMLayout, config1));
308 }
309 }
310
311 static MutexRecursive Mutex_NewDiskCB;
312
313 // Sets ElfCRC to the CRC of the game bound to the CDVD plugin.
314 static __forceinline ElfObject *loadElf( const wxString filename )
315 {
316 if (filename.StartsWith(L"host"))
317 return new ElfObject(filename.After(':'), Path::GetFileSize(filename.After(':')));
318
319 IsoFSCDVD isofs;
320 IsoFile file(isofs, filename);
321 ElfObject *elfptr;
322
323 elfptr = new ElfObject(filename, file);
324 return elfptr;
325 }
326
327 static __forceinline void _reloadElfInfo(wxString elfpath)
328 {
329 ScopedPtr<ElfObject> elfptr;
330
331 // Now's a good time to reload the ELF info...
332 ScopedLock locker( Mutex_NewDiskCB );
333
334 if (elfpath == LastELF)
335 return;
336
337 LastELF = elfpath;
338
339 wxString fname = elfpath.AfterLast('\\');
340 if (!fname)
341 fname = elfpath.AfterLast('/');
342 if (!fname)
343 fname = elfpath.AfterLast(':');
344 if (fname.Matches(L"????_???.??*"))
345 DiscID = fname(0,4) + L"-" + fname(5,3) + fname(9,2);
346
347 Console.WriteLn("Disc ID = %s", DiscID.ToUTF8().data());
348 elfptr = loadElf(elfpath);
349
350 ElfCRC = elfptr->getCRC();
351 Console.WriteLn("ELF (%s) CRC = %8.8X", elfpath.ToUTF8().data(), ElfCRC);
352
353 ElfEntry = elfptr->header.e_entry;
354 Console.WriteLn("Entry point = 0x%08x", ElfEntry);
355
356 elfptr.Delete();
357
358 // Set the Game DataBase to the correct game based on Game Serial Code...
359 if (GameDB) {
360 wxString gameSerial = DiscID;
361 if (DiscID.IsEmpty()) { // Search for crc if no Serial Code
362 gameSerial = wxString(wxsFormat( L"%8.8x", ElfCRC ));
363 }
364 if (GameDB->setGame(gameSerial.ToUTF8().data())) { // Game Found
365 Console.WriteLn ("Game = %s (%s)", GameDB->getString("Name").c_str(), GameDB->getString("Region").c_str());
366 }
367 else Console.Warning(L"Game not found in database [%s]", gameSerial.c_str());
368 }
369 }
370
371 void cdvdReloadElfInfo(wxString elfoverride)
372 {
373 if (!elfoverride.IsEmpty())
374 {
375 _reloadElfInfo(elfoverride);
376 return;
377 }
378
379 wxString elfpath;
380 u32 discType = GetPS2ElfName(elfpath);
381
382 switch (discType)
383 {
384 case 2: // Is a PS2 disc.
385 _reloadElfInfo(elfpath);
386 break;
387 case 1: // Is a PS1 disc.
388 if (ENABLE_LOADING_PS1_GAMES) _reloadElfInfo(elfpath);
389 break;
390 default: // Isn't a disc we recognise.
391 break;
392 }
393 }
394
395 static __forceinline s32 StrToS32(const wxString& str, int base = 10)
396 {
397 long l;
398 str.ToLong(&l, base);
399 return l;
400 }
401
402 void cdvdReadKey(u8 arg0, u16 arg1, u32 arg2, u8* key)
403 {
404 s32 numbers, letters;
405 u32 key_0_3;
406 u8 key_4, key_14;
407
408 cdvdReloadElfInfo();
409
410 // convert the number characters to a real 32 bit number
411 numbers = StrToS32(DiscID(5,5));
412
413 // combine the lower 7 bits of each char
414 // to make the 4 letters fit into a single u32
415 letters = (s32)((DiscID[3]&0x7F)<< 0) |
416 (s32)((DiscID[2]&0x7F)<< 7) |
417 (s32)((DiscID[1]&0x7F)<<14) |
418 (s32)((DiscID[0]&0x7F)<<21);
419
420 // calculate magic numbers
421 key_0_3 = ((numbers & 0x1FC00) >> 10) | ((0x01FFFFFF & letters) << 7); // numbers = 7F letters = FFFFFF80
422 key_4 = ((numbers & 0x0001F) << 3) | ((0x0E000000 & letters) >> 25); // numbers = F8 letters = 07
423 key_14 = ((numbers & 0x003E0) >> 2) | 0x04; // numbers = F8 extra = 04 unused = 03
424
425 // clear key values
426 memzero_ptr<16>(key);
427
428 // store key values
429 key[ 0] = (key_0_3&0x000000FF)>> 0;
430 key[ 1] = (key_0_3&0x0000FF00)>> 8;
431 key[ 2] = (key_0_3&0x00FF0000)>>16;
432 key[ 3] = (key_0_3&0xFF000000)>>24;
433 key[ 4] = key_4;
434
435 switch (arg2)
436 {
437 case 75:
438 key[14] = key_14;
439 key[15] = 0x05;
440 break;
441
442 // case 3075:
443 // key[15] = 0x01;
444 // break;
445
446 case 4246:
447 // 0x0001F2F707 = sector 0x0001F2F7 dec 0x07
448 key[ 0] = 0x07;
449 key[ 1] = 0xF7;
450 key[ 2] = 0xF2;
451 key[ 3] = 0x01;
452 key[ 4] = 0x00;
453 key[15] = 0x01;
454 break;
455
456 default:
457 key[15] = 0x01;
458 break;
459 }
460
461 Console.WriteLn( "CDVD.KEY = %02X,%02X,%02X,%02X,%02X,%02X,%02X",
462 cdvd.Key[0],cdvd.Key[1],cdvd.Key[2],cdvd.Key[3],cdvd.Key[4],cdvd.Key[14],cdvd.Key[15] );
463 }
464
465 s32 cdvdGetToc(void* toc)
466 {
467 s32 ret = CDVD->getTOC(toc);
468 if (ret == -1) ret = 0x80;
469 return ret;
470 }
471
472 s32 cdvdReadSubQ(s32 lsn, cdvdSubQ* subq)
473 {
474 s32 ret = CDVD->readSubQ(lsn, subq);
475 if (ret == -1) ret = 0x80;
476 return ret;
477 }
478
479 s32 cdvdCtrlTrayOpen()
480 {
481 s32 ret = CDVD->ctrlTrayOpen();
482 if (ret == -1) ret = 0x80;
483 return ret;
484 }
485
486 s32 cdvdCtrlTrayClose()
487 {
488 s32 ret = CDVD->ctrlTrayClose();
489 if (ret == -1) ret = 0x80;
490 return ret;
491 }
492
493 // Modified by (efp) - 16/01/2006
494 // checks if tray was opened since last call to this func
495 s32 cdvdGetTrayStatus()
496 {
497 s32 ret = CDVD->getTrayStatus();
498
499 if (ret == -1)
500 return(CDVD_TRAY_CLOSE);
501 else
502 return(ret);
503 }
504
505 // Note: Is tray status being kept as a var here somewhere?
506 // cdvdNewDiskCB() can update it's status as well...
507
508 // Modified by (efp) - 16/01/2006
509 static __forceinline void cdvdGetDiskType()
510 {
511 cdvd.Type = DoCDVDdetectDiskType();
512 }
513
514 // check whether disc is single or dual layer
515 // if its dual layer, check what the disctype is and what sector number
516 // layer1 starts at
517 //
518 // args: gets value for dvd type (0=single layer, 1=ptp, 2=otp)
519 // gets value for start lsn of layer1
520 // returns: 1 if on dual layer disc
521 // 0 if not on dual layer disc
522 static s32 cdvdReadDvdDualInfo(s32* dualType, u32* layer1Start)
523 {
524 *dualType = 0;
525 *layer1Start = 0;
526
527 return CDVD->getDualInfo(dualType,layer1Start);
528 }
529
530 static uint cdvdBlockReadTime( CDVD_MODE_TYPE mode )
531 {
532 return (PSXCLK * cdvd.BlockSize) / (((mode==MODE_CDROM) ? PSX_CD_READSPEED : PSX_DVD_READSPEED) * cdvd.Speed);
533 }
534
535 void cdvdReset()
536 {
537 memzero(cdvd);
538
539 cdvd.Type = CDVD_TYPE_NODISC;
540 cdvd.Spinning = false;
541
542 cdvd.sDataIn = 0x40;
543 cdvd.Ready = CDVD_READY2;
544 cdvd.Speed = 4;
545 cdvd.BlockSize = 2064;
546 cdvd.Action = cdvdAction_None;
547 cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM );
548
549 // CDVD internally uses GMT+9. If you think the time's wrong, you're wrong.
550 // Set up your time zone and winter/summer in the BIOS. No PS2 BIOS I know of features automatic DST.
551 wxDateTime curtime( wxDateTime::GetTimeNow() );
552 cdvd.RTC.second = (u8)curtime.GetSecond();
553 cdvd.RTC.minute = (u8)curtime.GetMinute();
554 cdvd.RTC.hour = (u8)curtime.GetHour(wxDateTime::GMT9);
555 cdvd.RTC.day = (u8)curtime.GetDay(wxDateTime::GMT9);
556 cdvd.RTC.month = (u8)curtime.GetMonth(wxDateTime::GMT9) + 1; // WX returns Jan as "0"
557 cdvd.RTC.year = (u8)(curtime.GetYear(wxDateTime::GMT9) - 2000);
558
559 if( !GameDB ) GameDB = new DataBase_Loader("GameIndex.dbf");
560 }
561
562 struct Freeze_v10Compat
563 {
564 u8 Action;
565 u32 SeekToSector;
566 u32 ReadTime;
567 bool Spinning;
568 };
569
570 void SaveStateBase::cdvdFreeze()
571 {
572 FreezeTag( "cdvd" );
573 Freeze( cdvd );
574
575 if (IsLoading())
576 {
577 // Make sure the Cdvd plugin has the expected track loaded into the buffer.
578 // If cdvd.Readed is cleared it means we need to load the SeekToSector (ie, a
579 // seek is in progress!)
580
581 if( cdvd.Reading )
582 cdvd.RErr = DoCDVDreadTrack( cdvd.Readed ? cdvd.Sector : cdvd.SeekToSector, cdvd.ReadMode);
583 }
584 }
585
586 static void cdvdDetectDisk()
587 {
588 wxString str;
589 cdvd.Type = DoCDVDdetectDiskType();
590 cdvdReloadElfInfo();
591 }
592
593 void cdvdNewDiskCB()
594 {
595 ScopedTryLock lock( Mutex_NewDiskCB );
596 if( lock.Failed() ) return;
597
598 DoCDVDresetDiskTypeCache();
599 cdvdDetectDisk();
600 }
601
602 static void mechaDecryptBytes( u32 madr, int size )
603 {
604 int shiftAmount = (cdvd.decSet>>4) & 7;
605 int doXor = (cdvd.decSet) & 1;
606 int doShift = (cdvd.decSet) & 2;
607
608 u8* curval = iopPhysMem( madr );
609 for( int i=0; i<size; ++i, ++curval )
610 {
611 if( doXor ) *curval ^= cdvd.Key[4];
612 if( doShift ) *curval = (*curval >> shiftAmount) | (*curval << (8-shiftAmount) );
613 }
614 }
615
616 int cdvdReadSector() {
617 s32 bcr;
618
619 CDVD_LOG("SECTOR %d (BCR %x;%x)", cdvd.Sector, HW_DMA3_BCR_H16, HW_DMA3_BCR_L16);
620
621 bcr = (HW_DMA3_BCR_H16 * HW_DMA3_BCR_L16) *4;
622 if (bcr < cdvd.BlockSize) {
623 CDVD_LOG( "READBLOCK: bcr < cdvd.BlockSize; %x < %x", bcr, cdvd.BlockSize );
624 if (HW_DMA3_CHCR & 0x01000000) {
625 HW_DMA3_CHCR &= ~0x01000000;
626 psxDmaInterrupt(3);
627 }
628 return -1;
629 }
630
631 // DMAs use physical addresses (air)
632 u8* mdest = iopPhysMem( HW_DMA3_MADR );
633
634 // if raw dvd sector 'fill in the blanks'
635 if (cdvd.BlockSize == 2064)
636 {
637 // get info on dvd type and layer1 start
638 u32 layer1Start;
639 s32 dualType;
640 s32 layerNum;
641 u32 lsn = cdvd.Sector;
642
643 cdvdReadDvdDualInfo(&dualType, &layer1Start);
644
645 if((dualType == 1) && (lsn >= layer1Start))
646 {
647 // dual layer ptp disc
648 layerNum = 1;
649 lsn = lsn - layer1Start + 0x30000;
650 }
651 else if((dualType == 2) && (lsn >= layer1Start))
652 {
653 // dual layer otp disc
654 layerNum = 1;
655 lsn = ~(layer1Start+0x30000 - 1);
656 }
657 else
658 {
659 // Assuming the other dualType is 0,
660 // single layer disc, or on first layer of dual layer disc.
661 layerNum = 0;
662 lsn += 0x30000;
663 }
664
665 mdest[0] = 0x20 | layerNum;
666 mdest[1] = (u8)(lsn >> 16);
667 mdest[2] = (u8)(lsn >> 8);
668 mdest[3] = (u8)(lsn );
669
670 // sector IED (not calculated at present)
671 mdest[4] = 0;
672 mdest[5] = 0;
673
674 // sector CPR_MAI (not calculated at present)
675 mdest[6] = 0;
676 mdest[7] = 0;
677 mdest[8] = 0;
678 mdest[9] = 0;
679 mdest[10] = 0;
680 mdest[11] = 0;
681
682 // normal 2048 bytes of sector data
683 memcpy_const(&mdest[12], cdr.Transfer, 2048);
684
685 // 4 bytes of edc (not calculated at present)
686 mdest[2060] = 0;
687 mdest[2061] = 0;
688 mdest[2062] = 0;
689 mdest[2063] = 0;
690 }
691 else
692 {
693 memcpy_fast( mdest, cdr.Transfer, cdvd.BlockSize);
694 }
695
696 // decrypt sector's bytes
697 if( cdvd.decSet ) mechaDecryptBytes( HW_DMA3_MADR, cdvd.BlockSize );
698
699 // Added a clear after memory write .. never seemed to be necessary before but *should*
700 // be more correct. (air)
701 psxCpu->Clear( HW_DMA3_MADR, cdvd.BlockSize/4 );
702
703 // Console.WriteLn("sector %x;%x;%x", PSXMu8(madr+0), PSXMu8(madr+1), PSXMu8(madr+2));
704
705 HW_DMA3_BCR_H16 -= (cdvd.BlockSize / (HW_DMA3_BCR_L16*4));
706 HW_DMA3_MADR += cdvd.BlockSize;
707
708 return 0;
709 }
710
711 // inlined due to being referenced in only one place.
712 __forceinline void cdvdActionInterrupt()
713 {
714 switch( cdvd.Action )
715 {
716 case cdvdAction_Seek:
717 case cdvdAction_Standby:
718 cdvd.Spinning = true;
719 cdvd.Ready = CDVD_READY1;
720 cdvd.Sector = cdvd.SeekToSector;
721 cdvd.Status = CDVD_STATUS_SEEK_COMPLETE;
722 break;
723
724 case cdvdAction_Stop:
725 cdvd.Spinning = false;
726 cdvd.Ready = CDVD_READY1;
727 cdvd.Sector = 0;
728 cdvd.Status = CDVD_STATUS_NONE;
729 break;
730
731 case cdvdAction_Break:
732 // Make sure the cdvd action state is pretty well cleared:
733 cdvd.Reading = 0;
734 cdvd.Readed = 0;
735 cdvd.Ready = CDVD_READY2; // should be CDVD_READY1 or something else?
736 cdvd.Status = CDVD_STATUS_NONE;
737 cdvd.RErr = 0;
738 cdvd.nCommand = 0;
739 break;
740 }
741 cdvd.Action = cdvdAction_None;
742
743 cdvd.PwOff |= 1<<Irq_CommandComplete;
744 psxHu32(0x1070)|= 0x4;
745 hwIntcIrq(INTC_SBUS);
746 }
747
748 // inlined due to being referenced in only one place.
749 __forceinline void cdvdReadInterrupt()
750 {
751 //Console.WriteLn("cdvdReadInterrupt %x %x %x %x %x", cpuRegs.interrupt, cdvd.Readed, cdvd.Reading, cdvd.nSectors, (HW_DMA3_BCR_H16 * HW_DMA3_BCR_L16) *4);
752
753 cdvd.Ready = CDVD_NOTREADY;
754 if (!cdvd.Readed)
755 {
756 // Seeking finished. Process the track we requested before, and
757 // then schedule another CDVD read int for when the block read finishes.
758
759 // NOTE: The first CD track was read when the seek was initiated, so no need
760 // to call CDVDReadTrack here.
761
762 cdvd.Spinning = true;
763 cdvd.RetryCntP = 0;
764 cdvd.Reading = 1;
765 cdvd.Readed = 1;
766 cdvd.Status = CDVD_STATUS_SEEK_COMPLETE;
767 cdvd.Sector = cdvd.SeekToSector;
768
769 CDVD_LOG( "Cdvd Seek Complete > Scheduling block read interrupt at iopcycle=%8.8x.",
770 psxRegs.cycle + cdvd.ReadTime );
771
772 CDVDREAD_INT(cdvd.ReadTime);
773 return;
774 }
775 else
776 {
777 if( cdvd.RErr == 0 )
778 {
779 while( (cdvd.RErr = DoCDVDgetBuffer(cdr.Transfer)), cdvd.RErr == -2 )
780 {
781 // not finished yet ... block on the read until it finishes.
782 Threading::Sleep( 0 );
783 Threading::SpinWait();
784 }
785 }
786
787 if (cdvd.RErr == -1)
788 {
789 cdvd.RetryCntP++;
790
791 if (cdvd.RetryCntP <= cdvd.RetryCnt)
792 {
793 CDVD_LOG( "CDVD read err, retrying... (attempt %d of %d)", cdvd.RetryCntP, cdvd.RetryCnt );
794 cdvd.RErr = DoCDVDreadTrack(cdvd.Sector, cdvd.ReadMode);
795 CDVDREAD_INT(cdvd.ReadTime);
796 }
797 else
798 Console.Error("CDVD READ ERROR, sector = 0x%08x", cdvd.Sector);
799
800 return;
801 }
802
803 cdvd.Reading = false;
804
805 // Any other value besides 0 should be considered invalid here (wtf is that wacky
806 // plugin trying to do?)
807 jASSUME( cdvd.RErr == 0 );
808 }
809
810 if (cdvdReadSector() == -1)
811 {
812 // This means that the BCR/DMA hasn't finished yet, and rather than fire off the
813 // sector-finished notice too early (which might overwrite game data) we delay a
814 // bit and try to read the sector again later.
815 // An arbitrary delay of some number of cycles probably makes more sense here,
816 // but for now it's based on the cdvd.ReadTime value. -- air
817
818 pxAssume((int)cdvd.ReadTime > 0 );
819 CDVDREAD_INT(cdvd.ReadTime/4);
820 return;
821 }
822
823 cdvd.Sector++;
824
825 if (--cdvd.nSectors <= 0)
826 {
827 cdvd.PwOff |= 1<<Irq_CommandComplete;
828 psxHu32(0x1070)|= 0x4;
829 hwIntcIrq(INTC_SBUS);
830
831 HW_DMA3_CHCR &= ~0x01000000;
832 psxDmaInterrupt(3);
833 cdvd.Ready = CDVD_READY2;
834
835 // All done! :D
836 return;
837 }
838
839 cdvd.RetryCntP = 0;
840 cdvd.Reading = 1;
841 cdvd.RErr = DoCDVDreadTrack(cdvd.Sector, cdvd.ReadMode);
842 CDVDREAD_INT(cdvd.ReadTime);
843
844 return;
845 }
846
847 // Returns the number of IOP cycles until the event completes.
848 static uint cdvdStartSeek( uint newsector, CDVD_MODE_TYPE mode )
849 {
850 cdvd.SeekToSector = newsector;
851
852 uint delta = abs( (s32)(cdvd.SeekToSector - cdvd.Sector) );
853 uint seektime;
854
855 cdvd.Ready = CDVD_NOTREADY;
856 cdvd.Reading = 0;
857 cdvd.Readed = 0;
858 cdvd.Status = CDVD_STATUS_NONE;
859
860 if( !cdvd.Spinning )
861 {
862 CDVD_LOG( "CdSpinUp > Simulating CdRom Spinup Time, and seek to sector %d", cdvd.SeekToSector );
863 seektime = PSXCLK / 3; // 333ms delay
864 cdvd.Spinning = true;
865 }
866 else if( (tbl_ContigiousSeekDelta[mode] == 0) || (delta >= tbl_ContigiousSeekDelta[mode]) )
867 {
868 // Select either Full or Fast seek depending on delta:
869
870 if( delta >= tbl_FastSeekDelta[mode] )
871 {
872 // Full Seek
873 CDVD_LOG( "CdSeek Begin > to sector %d, from %d - delta=%d [FULL]", cdvd.SeekToSector, cdvd.Sector, delta );
874 seektime = Cdvd_FullSeek_Cycles;
875 }
876 else
877 {
878 CDVD_LOG( "CdSeek Begin > to sector %d, from %d - delta=%d [FAST]", cdvd.SeekToSector, cdvd.Sector, delta );
879 seektime = Cdvd_FastSeek_Cycles;
880 }
881 }
882 else
883 {
884 CDVD_LOG( "CdSeek Begin > Contiguous block without seek - delta=%d sectors", delta );
885
886 // seektime is the time it takes to read to the destination block:
887 seektime = delta * cdvd.ReadTime;
888
889 if( delta == 0 )
890 {
891 cdvd.Status = CDVD_STATUS_SEEK_COMPLETE;
892 cdvd.Readed = 1; // Note: 1, not 0, as implied by the next comment. Need to look into this. --arcum42
893 cdvd.RetryCntP = 0;
894
895 // setting Readed to 0 skips the seek logic, which means the next call to
896 // cdvdReadInterrupt will load a block. So make sure it's properly scheduled
897 // based on sector read speeds:
898
899 seektime = cdvd.ReadTime;
900 }
901 }
902
903 return seektime;
904 }
905
906 u8 monthmap[13] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
907
908 void cdvdVsync() {
909 cdvd.RTCcount++;
910 if (cdvd.RTCcount < ((gsRegionMode == Region_NTSC) ? 60 : 50)) return;
911 cdvd.RTCcount = 0;
912
913 cdvd.RTC.second++;
914 if (cdvd.RTC.second < 60) return;
915 cdvd.RTC.second = 0;
916
917 cdvd.RTC.minute++;
918 if (cdvd.RTC.minute < 60) return;
919 cdvd.RTC.minute = 0;
920
921 cdvd.RTC.hour++;
922 if (cdvd.RTC.hour < 24) return;
923 cdvd.RTC.hour = 0;
924
925 cdvd.RTC.day++;
926 if (cdvd.RTC.day <= (cdvd.RTC.month == 2 && cdvd.RTC.year % 4 == 0 ? 29 : monthmap[cdvd.RTC.month-1])) return;
927 cdvd.RTC.day = 1;
928
929 cdvd.RTC.month++;
930 if (cdvd.RTC.month <= 12) return;
931 cdvd.RTC.month = 1;
932
933 cdvd.RTC.year++;
934 if (cdvd.RTC.year < 100) return;
935 cdvd.RTC.year = 0;
936 }
937
938 static __forceinline u8 cdvdRead18(void) // SDATAOUT
939 {
940 u8 ret = 0;
941
942 if (((cdvd.sDataIn & 0x40) == 0) && (cdvd.ResultP < cdvd.ResultC))
943 {
944 cdvd.ResultP++;
945 if (cdvd.ResultP >= cdvd.ResultC) cdvd.sDataIn|= 0x40;
946 ret = cdvd.Result[cdvd.ResultP-1];
947 }
948 CDVD_LOG("cdvdRead18(SDataOut) %x (ResultC=%d, ResultP=%d)", ret, cdvd.ResultC, cdvd.ResultP);
949
950 return ret;
951 }
952
953 u8 cdvdRead(u8 key)
954 {
955 switch (key)
956 {
957 case 0x04: // NCOMMAND
958 CDVD_LOG("cdvdRead04(NCMD) %x", cdvd.nCommand);
959 return cdvd.nCommand;
960 break;
961
962 case 0x05: // N-READY
963 CDVD_LOG("cdvdRead05(NReady) %x", cdvd.Ready);
964 return cdvd.Ready;
965 break;
966
967 case 0x06: // ERROR
968 CDVD_LOG("cdvdRead06(Error) %x", cdvd.Error);
969 return cdvd.Error;
970 break;
971
972 case 0x07: // BREAK
973 CDVD_LOG("cdvdRead07(Break) %x", 0);
974 return 0;
975 break;
976
977 case 0x08: // STATUS
978 CDVD_LOG("cdvdRead08(Status) %x", cdvd.Status);
979 return cdvd.Status;
980 break;
981
982 case 0x0A: // STATUS
983 CDVD_LOG("cdvdRead0A(Status) %x", cdvd.Status);
984 return cdvd.Status;
985 break;
986
987 case 0x0B: // TRAY-STATE (if tray has been opened)
988 {
989 u8 tray = cdvdGetTrayStatus();
990 CDVD_LOG("cdvdRead0B(Tray) %x", tray);
991 return tray;
992 break;
993 }
994 case 0x0C: // CRT MINUTE
995 CDVD_LOG("cdvdRead0C(Min) %x", itob((u8)(cdvd.Sector/(60*75))));
996 return itob((u8)(cdvd.Sector/(60*75)));
997 break;
998
999 case 0x0D: // CRT SECOND
1000 CDVD_LOG("cdvdRead0D(Sec) %x", itob((u8)((cdvd.Sector/75)%60)+2));
1001 return itob((u8)((cdvd.Sector/75)%60)+2);
1002 break;
1003
1004 case 0x0E: // CRT FRAME
1005 CDVD_LOG("cdvdRead0E(Frame) %x", itob((u8)(cdvd.Sector%75)));
1006 return itob((u8)(cdvd.Sector%75));
1007 break;
1008
1009 case 0x0F: // TYPE
1010 CDVD_LOG("cdvdRead0F(Disc Type) %x", cdvd.Type);
1011 cdvdGetDiskType();
1012 return cdvd.Type;
1013 break;
1014
1015 case 0x13: // UNKNOWN
1016 CDVD_LOG("cdvdRead13(Unknown) %x", 4);
1017 return 4;
1018 break;
1019
1020 case 0x15: // RSV
1021 CDVD_LOG("cdvdRead15(RSV)");
1022 return 0x01; // | 0x80 for ATAPI mode
1023 break;
1024
1025 case 0x16: // SCOMMAND
1026 CDVD_LOG("cdvdRead16(SCMD) %x", cdvd.sCommand);
1027 return cdvd.sCommand;
1028 break;
1029
1030 case 0x17: // SREADY
1031 CDVD_LOG("cdvdRead17(SReady) %x", cdvd.sDataIn);
1032 return cdvd.sDataIn;
1033 break;
1034
1035 case 0x18:
1036 return cdvdRead18();
1037 break;
1038
1039 case 0x20:
1040 case 0x21:
1041 case 0x22:
1042 case 0x23:
1043 case 0x24:
1044 {
1045 int temp = key - 0x20;
1046
1047 CDVD_LOG("cdvdRead%d(Key%d) %x", key, temp, cdvd.Key[temp]);
1048 return cdvd.Key[temp];
1049 break;
1050 }
1051 case 0x28:
1052 case 0x29:
1053 case 0x2A:
1054 case 0x2B:
1055 case 0x2C:
1056 {
1057 int temp = key - 0x23;
1058
1059 CDVD_LOG("cdvdRead%d(Key%d) %x", key, temp, cdvd.Key[temp]);
1060 return cdvd.Key[temp];
1061 break;
1062 }
1063
1064 case 0x30:
1065 case 0x31:
1066 case 0x32:
1067 case 0x33:
1068 case 0x34:
1069 {
1070 int temp = key - 0x26;
1071
1072 CDVD_LOG("cdvdRead%d(Key%d) %x", key, temp, cdvd.Key[temp]);
1073 return cdvd.Key[temp];
1074 break;
1075 }
1076
1077 case 0x38: // valid parts of key data (first and last are valid)
1078 CDVD_LOG("cdvdRead38(KeysValid) %x", cdvd.Key[15]);
1079
1080 return cdvd.Key[15];
1081 break;
1082
1083 case 0x39: // KEY-XOR
1084 CDVD_LOG("cdvdRead39(KeyXor) %x", cdvd.KeyXor);
1085
1086 return cdvd.KeyXor;
1087 break;
1088
1089 case 0x3A: // DEC_SET
1090 CDVD_LOG("cdvdRead3A(DecSet) %x", cdvd.decSet);
1091
1092 Console.WriteLn("DecSet Read: %02X", cdvd.decSet);
1093 return cdvd.decSet;
1094 break;
1095
1096 default:
1097 // note: notify the console since this is a potentially serious emulation problem:
1098 PSXHW_LOG("*Unknown 8bit read at address 0x1f4020%x", key);
1099 Console.Error( "IOP Unknown 8bit read from addr 0x1f4020%x", key );
1100 return 0;
1101 break;
1102 }
1103 }
1104
1105 static void cdvdWrite04(u8 rt) { // NCOMMAND
1106 CDVD_LOG("cdvdWrite04: NCMD %s (%x) (ParamP = %x)", nCmdName[rt], rt, cdvd.ParamP);
1107
1108 cdvd.nCommand = rt;
1109 cdvd.Status = CDVD_STATUS_NONE;
1110 cdvd.PwOff = Irq_None; // good or bad?
1111
1112 switch (rt) {
1113 case N_CD_SYNC: // CdSync
1114 case N_CD_NOP: // CdNop_
1115 cdvdSetIrq();
1116 break;
1117
1118 case N_CD_STANDBY: // CdStandby
1119
1120 // Seek to sector zero. The cdvdStartSeek function will simulate
1121 // spinup times if needed.
1122
1123 DevCon.Warning( "CdStandby : %d", rt );
1124 cdvd.Action = cdvdAction_Standby;
1125 cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM );
1126 CDVD_INT( cdvdStartSeek( 0, MODE_DVDROM ) );
1127 break;
1128
1129 case N_CD_STOP: // CdStop
1130 DevCon.Warning( "CdStop : %d", rt );
1131 cdvd.Action = cdvdAction_Stop;
1132 CDVD_INT( PSXCLK / 6 ); // 166ms delay?
1133 break;
1134
1135 // from an emulation point of view there is not much need to do anything for this one
1136 case N_CD_PAUSE: // CdPause
1137 cdvdSetIrq();
1138 break;
1139
1140 case N_CD_SEEK: // CdSeek
1141 cdvd.Action = cdvdAction_Seek;
1142 cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM );
1143 CDVD_INT( cdvdStartSeek( *(uint*)(cdvd.Param+0), MODE_DVDROM ) );
1144 break;
1145
1146 case N_CD_READ: // CdRead
1147 // Assign the seek to sector based on cdvd.Param[0]-[3], and the number of sectors based on cdvd.Param[4]-[7].
1148 cdvd.SeekToSector = *(u32*) (cdvd.Param+0);
1149 cdvd.nSectors = *(u32*)(cdvd.Param+4);
1150 cdvd.RetryCnt = (cdvd.Param[8] == 0) ? 0x100 : cdvd.Param[8];
1151 cdvd.SpindlCtrl = cdvd.Param[9];
1152 cdvd.Speed = 24;
1153 switch (cdvd.Param[10]) {
1154 case 2: cdvd.ReadMode = CDVD_MODE_2340; cdvd.BlockSize = 2340; break;
1155 case 1: cdvd.ReadMode = CDVD_MODE_2328; cdvd.BlockSize = 2328; break;
1156 case 0:
1157 default: cdvd.ReadMode = CDVD_MODE_2048; cdvd.BlockSize = 2048; break;
1158 }
1159
1160 CDVD_LOG( "CdRead > startSector=%d, nSectors=%d, RetryCnt=%x, Speed=%x(%x), ReadMode=%x(%x) (1074=%x)",
1161 cdvd.Sector, cdvd.nSectors, cdvd.RetryCnt, cdvd.Speed, cdvd.Param[9], cdvd.ReadMode, cdvd.Param[10], psxHu32(0x1074));
1162
1163 if( EmuConfig.CdvdVerboseReads )
1164 Console.WriteLn("CdRead: Reading Sector %d(%d Blocks of Size %d) at Speed=%dx",
1165 cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed);
1166
1167 cdvd.ReadTime = cdvdBlockReadTime( MODE_CDROM );
1168 CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector,MODE_CDROM ) );
1169
1170 // Read-ahead by telling the plugin about the track now.
1171 // This helps improve performance on actual from-cd emulation
1172 // (ie, not using the hard drive)
1173 cdvd.RErr = DoCDVDreadTrack( cdvd.SeekToSector, cdvd.ReadMode );
1174
1175 // Set the reading block flag. If a seek is pending then Readed will
1176 // take priority in the handler anyway. If the read is contiguous then
1177 // this'll skip the seek delay.
1178 cdvd.Reading = 1;
1179 break;
1180
1181 case N_CD_READ_CDDA: // CdReadCDDA
1182 case N_CD_READ_XCDDA: // CdReadXCDDA
1183 // Assign the seek to sector based on cdvd.Param[0]-[3], and the number of sectors based on cdvd.Param[4]-[7].
1184 cdvd.SeekToSector = *(u32*) (cdvd.Param+0);
1185 cdvd.nSectors = *(u32*)(cdvd.Param+4);
1186
1187 if (cdvd.Param[8] == 0)
1188 cdvd.RetryCnt = 0x100;
1189 else
1190 cdvd.RetryCnt = cdvd.Param[8];
1191
1192 cdvd.SpindlCtrl = cdvd.Param[9];
1193
1194 switch (cdvd.Param[9]) {
1195 case 0x01: cdvd.Speed = 1; break;
1196 case 0x02: cdvd.Speed = 2; break;
1197 case 0x03: cdvd.Speed = 4; break;
1198 case 0x04: cdvd.Speed = 12; break;
1199 default: cdvd.Speed = 24; break;
1200 }
1201
1202 switch (cdvd.Param[10]) {
1203 case 1: cdvd.ReadMode = CDVD_MODE_2368; cdvd.BlockSize = 2368; break;
1204 case 2:
1205 case 0: cdvd.ReadMode = CDVD_MODE_2352; cdvd.BlockSize = 2352; break;
1206 }
1207
1208 CDVD_LOG( "CdReadCDDA > startSector=%d, nSectors=%d, RetryCnt=%x, Speed=%xx(%x), ReadMode=%x(%x) (1074=%x)",
1209 cdvd.Sector, cdvd.nSectors, cdvd.RetryCnt, cdvd.Speed, cdvd.Param[9], cdvd.ReadMode, cdvd.Param[10], psxHu32(0x1074));
1210
1211 if( EmuConfig.CdvdVerboseReads )
1212 Console.WriteLn("CdAudioRead: Reading Sector %d(%d Blocks of Size %d) at Speed=%dx",
1213 cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed);
1214
1215 cdvd.ReadTime = cdvdBlockReadTime( MODE_CDROM );
1216 CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector, MODE_CDROM ) );
1217
1218 // Read-ahead by telling the plugin about the track now.
1219 // This helps improve performance on actual from-cd emulation
1220 // (ie, not using the hard drive)
1221 cdvd.RErr = DoCDVDreadTrack( cdvd.SeekToSector, cdvd.ReadMode );
1222
1223 // Set the reading block flag. If a seek is pending then Readed will
1224 // take priority in the handler anyway. If the read is contiguous then
1225 // this'll skip the seek delay.
1226 cdvd.Reading = 1;
1227 break;
1228
1229 case N_DVD_READ: // DvdRead
1230 // Assign the seek to sector based on cdvd.Param[0]-[3], and the number of sectors based on cdvd.Param[4]-[7].
1231 cdvd.SeekToSector = *(u32*) (cdvd.Param+0);
1232 cdvd.nSectors = *(u32*)(cdvd.Param+4);
1233
1234 if (cdvd.Param[8] == 0)
1235 cdvd.RetryCnt = 0x100;
1236 else
1237 cdvd.RetryCnt = cdvd.Param[8];
1238
1239 cdvd.SpindlCtrl = cdvd.Param[9];
1240 cdvd.Speed = 4;
1241 cdvd.ReadMode = CDVD_MODE_2048;
1242 cdvd.BlockSize = 2064; // Why oh why was it 2064
1243
1244 CDVD_LOG( "DvdRead > startSector=%d, nSectors=%d, RetryCnt=%x, Speed=%x(%x), ReadMode=%x(%x) (1074=%x)",
1245 cdvd.Sector, cdvd.nSectors, cdvd.RetryCnt, cdvd.Speed, cdvd.Param[9], cdvd.ReadMode, cdvd.Param[10], psxHu32(0x1074));
1246
1247 if( EmuConfig.CdvdVerboseReads )
1248 Console.WriteLn("DvdRead: Reading Sector %d(%d Blocks of Size %d) at Speed=%dx",
1249 cdvd.Sector, cdvd.nSectors,cdvd.BlockSize,cdvd.Speed);
1250
1251 cdvd.ReadTime = cdvdBlockReadTime( MODE_DVDROM );
1252 CDVDREAD_INT( cdvdStartSeek( cdvd.SeekToSector, MODE_DVDROM ) );
1253
1254 // Read-ahead by telling the plugin about the track now.
1255 // This helps improve performance on actual from-cd emulation
1256 // (ie, not using the hard drive)
1257 cdvd.RErr = DoCDVDreadTrack( cdvd.SeekToSector, cdvd.ReadMode );
1258
1259 // Set the reading block flag. If a seek is pending then Readed will
1260 // take priority in the handler anyway. If the read is contiguous then
1261 // this'll skip the seek delay.
1262 cdvd.Reading = 1;
1263 break;
1264
1265 case N_CD_GET_TOC: // CdGetToc & cdvdman_call19
1266 //Param[0] is 0 for CdGetToc and any value for cdvdman_call19
1267 //the code below handles only CdGetToc!
1268 //if(cdvd.Param[0]==0x01)
1269 //{
1270 DevCon.WriteLn("CDGetToc Param[0]=%d, Param[1]=%d", cdvd.Param[0],cdvd.Param[1]);
1271 //}
1272 cdvdGetToc( iopPhysMem( HW_DMA3_MADR ) );
1273 cdvdSetIrq( (1<<Irq_CommandComplete) ); //| (1<<Irq_DataReady) );
1274 HW_DMA3_CHCR &= ~0x01000000;
1275 psxDmaInterrupt(3);
1276 break;
1277
1278 case N_CD_READ_KEY: // CdReadKey
1279 {
1280 u8 arg0 = cdvd.Param[0];
1281 u16 arg1 = cdvd.Param[1] | (cdvd.Param[2]<<8);
1282 u32 arg2 = cdvd.Param[3] | (cdvd.Param[4]<<8) | (cdvd.Param[5]<<16) | (cdvd.Param[6]<<24);
1283 DevCon.WriteLn("cdvdReadKey(%d, %d, %d)", arg0, arg1, arg2);
1284 cdvdReadKey(arg0, arg1, arg2, cdvd.Key);
1285 cdvd.KeyXor = 0x00;
1286 cdvdSetIrq();
1287 }
1288 break;
1289
1290 case N_CD_CHG_SPDL_CTRL: // CdChgSpdlCtrl
1291 Console.Warning("sceCdChgSpdlCtrl(%d)", cdvd.Param[0]);
1292 cdvdSetIrq();
1293 break;
1294
1295 default:
1296 Console.Warning("NCMD Unknown %x", rt);
1297 cdvdSetIrq();
1298 break;
1299 }
1300 cdvd.ParamP = 0;
1301 cdvd.ParamC = 0;
1302 }
1303
1304 static __forceinline void cdvdWrite05(u8 rt) { // NDATAIN
1305 CDVD_LOG("cdvdWrite05(NDataIn) %x", rt);
1306
1307 if (cdvd.ParamP < 32) {
1308 cdvd.Param[cdvd.ParamP++] = rt;
1309 cdvd.ParamC++;
1310 }
1311 }
1312
1313 static __forceinline void cdvdWrite06(u8 rt) { // HOWTO
1314 CDVD_LOG("cdvdWrite06(HowTo) %x", rt);
1315 cdvd.HowTo = rt;
1316 }
1317
1318 static __forceinline void cdvdWrite07(u8 rt) // BREAK
1319 {
1320 CDVD_LOG("cdvdWrite07(Break) %x", rt);
1321
1322 // If we're already in a Ready state or already Breaking, then do nothing:
1323 if ((cdvd.Ready != CDVD_NOTREADY) || (cdvd.Action == cdvdAction_Break)) return;
1324
1325 DbgCon.WriteLn("*PCSX2*: CDVD BREAK %x", rt);
1326
1327 // Aborts any one of several CD commands:
1328 // Pause, Seek, Read, Status, Standby, and Stop
1329
1330 psxRegs.interrupt &= ~( (1<<IopEvt_Cdvd) | (1<<IopEvt_CdvdRead) );
1331
1332 cdvd.Action = cdvdAction_Break;
1333 CDVD_INT( 64 );
1334
1335 // Clear the cdvd status:
1336 cdvd.Readed = 0;
1337 cdvd.Reading = 0;
1338 cdvd.Status = CDVD_STATUS_NONE;
1339 //cdvd.nCommand = 0;
1340 }
1341
1342 static __forceinline void cdvdWrite08(u8 rt) { // INTR_STAT
1343 CDVD_LOG("cdvdWrite08(IntrReason) = ACK(%x)", rt);
1344 cdvd.PwOff &= ~rt;
1345 }
1346
1347 static __forceinline void cdvdWrite0A(u8 rt) { // STATUS
1348 CDVD_LOG("cdvdWrite0A(Status) %x", rt);
1349 }
1350
1351 static __forceinline void cdvdWrite0F(u8 rt) { // TYPE
1352 CDVD_LOG("cdvdWrite0F(Type) %x", rt);
1353 DevCon.WriteLn("*PCSX2*: CDVD TYPE %x", rt);
1354 }
1355
1356 static __forceinline void cdvdWrite14(u8 rt) { // PS1 MODE??
1357 u32 cycle = psxRegs.cycle;
1358
1359 if (rt == 0xFE)
1360 Console.Warning("*PCSX2*: go PS1 mode DISC SPEED = FAST");
1361 else
1362 Console.Warning("*PCSX2*: go PS1 mode DISC SPEED = %dX", rt);
1363
1364 psxReset();
1365 psxHu32(0x1f801450) = 0x8;
1366 psxHu32(0x1f801078) = 1;
1367 psxRegs.cycle = cycle;
1368 }
1369
1370 static __forceinline void fail_pol_cal()
1371 {
1372 Console.Error("[MG] ERROR - Make sure the file is already decrypted!!!");
1373 cdvd.Result[0] = 0x80;
1374 }
1375
1376 static void cdvdWrite16(u8 rt) // SCOMMAND
1377 {
1378 // cdvdTN diskInfo;
1379 // cdvdTD trackInfo;
1380 // int i, lbn, type, min, sec, frm, address;
1381 int address;
1382 u8 tmp;
1383
1384 CDVD_LOG("cdvdWrite16: SCMD %s (%x) (ParamP = %x)", sCmdName[rt], rt, cdvd.ParamP);
1385
1386 cdvd.sCommand = rt;
1387 switch (rt) {
1388 // case 0x01: // GetDiscType - from cdvdman (0:1)
1389 // SetResultSize(1);
1390 // cdvd.Result[0] = 0;
1391 // break;
1392
1393 case 0x02: // CdReadSubQ (0:11)
1394 SetResultSize(11);
1395 cdvd.Result[0] = cdvdReadSubQ(cdvd.Sector, (cdvdSubQ*)&cdvd.Result[1]);
1396 break;
1397
1398 case 0x03: // Mecacon-command
1399 switch (cdvd.Param[0])
1400 {
1401 case 0x00: // get mecha version (1:4)
1402 SetResultSize(4);
1403 cdvdGetMechaVer(&cdvd.Result[0]);
1404 break;
1405
1406 case 0x44: // write console ID (9:1)
1407 SetResultSize(1);
1408 cdvd.Result[0] = cdvdWriteConsoleID(&cdvd.Param[1]);
1409 break;
1410
1411 case 0x45: // read console ID (1:9)
1412 SetResultSize(9);
1413 cdvd.Result[0] = cdvdReadConsoleID(&cdvd.Result[1]);
1414 break;
1415
1416 case 0xFD: // _sceCdReadRenewalDate (1:6) BCD
1417 SetResultSize(6);
1418 cdvd.Result[0] = 0;
1419 cdvd.Result[1] = 0x04;//year
1420 cdvd.Result[2] = 0x12;//month
1421 cdvd.Result[3] = 0x10;//day
1422 cdvd.Result[4] = 0x01;//hour
1423 cdvd.Result[5] = 0x30;//min
1424 break;
1425
1426 default:
1427 SetResultSize(1);
1428 cdvd.Result[0] = 0x80;
1429 Console.WriteLn("*Unknown Mecacon Command param[0]=%02X", cdvd.Param[0]);
1430 break;
1431 }
1432 break;
1433
1434 case 0x05: // CdTrayReqState (0:1) - resets the tray open detection
1435 SetResultSize(1);
1436 cdvd.Result[0] = 0;
1437 break;
1438
1439 case 0x06: // CdTrayCtrl (1:1)
1440 SetResultSize(1);
1441 if(cdvd.Param[0] == 0)
1442 cdvd.Result[0] = cdvdCtrlTrayOpen();
1443 else
1444 cdvd.Result[0] = cdvdCtrlTrayClose();
1445 break;
1446
1447 case 0x08: // CdReadRTC (0:8)
1448 SetResultSize(8);
1449 cdvd.Result[0] = 0;
1450 cdvd.Result[1] = itob(cdvd.RTC.second); //Seconds
1451 cdvd.Result[2] = itob(cdvd.RTC.minute); //Minutes
1452 cdvd.Result[3] = itob(cdvd.RTC.hour); //Hours
1453 cdvd.Result[4] = 0; //Nothing
1454 cdvd.Result[5] = itob(cdvd.RTC.day); //Day
1455 cdvd.Result[6] = itob(cdvd.RTC.month); //Month
1456 cdvd.Result[7] = itob(cdvd.RTC.year); //Year
1457 /*Console.WriteLn("RTC Read Sec %x Min %x Hr %x Day %x Month %x Year %x", cdvd.Result[1], cdvd.Result[2],
1458 cdvd.Result[3], cdvd.Result[5], cdvd.Result[6], cdvd.Result[7]);
1459 Console.WriteLn("RTC Read Real Sec %d Min %d Hr %d Day %d Month %d Year %d", cdvd.RTC.second, cdvd.RTC.minute,
1460 cdvd.RTC.hour, cdvd.RTC.day, cdvd.RTC.month, cdvd.RTC.year);*/
1461 break;
1462
1463 case 0x09: // sceCdWriteRTC (7:1)
1464 SetResultSize(1);
1465 cdvd.Result[0] = 0;
1466 cdvd.RTC.pad = 0;
1467
1468 cdvd.RTC.second = btoi(cdvd.Param[cdvd.ParamP-7]);
1469 cdvd.RTC.minute = btoi(cdvd.Param[cdvd.ParamP-6]) % 60;
1470 cdvd.RTC.hour = btoi(cdvd.Param[cdvd.ParamP-5]) % 24;
1471 cdvd.RTC.day = btoi(cdvd.Param[cdvd.ParamP-3]);
1472 cdvd.RTC.month = btoi(cdvd.Param[cdvd.ParamP-2] & 0x7f);
1473 cdvd.RTC.year = btoi(cdvd.Param[cdvd.ParamP-1]);
1474 /*Console.WriteLn("RTC write incomming Sec %x Min %x Hr %x Day %x Month %x Year %x", cdvd.Param[cdvd.ParamP-7], cdvd.Param[cdvd.ParamP-6],
1475 cdvd.Param[cdvd.ParamP-5], cdvd.Param[cdvd.ParamP-3], cdvd.Param[cdvd.ParamP-2], cdvd.Param[cdvd.ParamP-1]);
1476 Console.WriteLn("RTC Write Sec %d Min %d Hr %d Day %d Month %d Year %d", cdvd.RTC.second, cdvd.RTC.minute,
1477 cdvd.RTC.hour, cdvd.RTC.day, cdvd.RTC.month, cdvd.RTC.year);*/
1478 //memcpy_fast((u8*)&cdvd.RTC, cdvd.Param, 7);
1479 break;
1480
1481 case 0x0A: // sceCdReadNVM (2:3)
1482 address = (cdvd.Param[0]<<8) | cdvd.Param[1];
1483
1484 if (address < 512)
1485 {
1486 SetResultSize(3);
1487 cdvd.Result[0] = cdvdReadNVM(&cdvd.Result[1], address*2, 2);
1488 // swap bytes around
1489 tmp = cdvd.Result[1];
1490 cdvd.Result[1] = cdvd.Result[2];
1491 cdvd.Result[2] = tmp;
1492 }
1493 else
1494 {
1495 SetResultSize(1);
1496 cdvd.Result[0] = 0xff;
1497 }
1498 break;
1499
1500 case 0x0B: // sceCdWriteNVM (4:1)
1501 SetResultSize(1);
1502 address = (cdvd.Param[0]<<8) | cdvd.Param[1];
1503
1504 if (address < 512)
1505 {
1506 // swap bytes around
1507 tmp = cdvd.Param[2];
1508 cdvd.Param[2] = cdvd.Param[3];
1509 cdvd.Param[3] = tmp;
1510 cdvd.Result[0] = cdvdWriteNVM(&cdvd.Param[2], address*2, 2);
1511 }
1512 else
1513 {
1514 cdvd.Result[0] = 0xff;
1515 }
1516 break;
1517
1518 // case 0x0C: // sceCdSetHDMode (1:1)
1519 // break;
1520
1521
1522 case 0x0F: // sceCdPowerOff (0:1)- Call74 from Xcdvdman
1523 SetResultSize(1);
1524 cdvd.Result[0] = 0;
1525 break;
1526
1527 case 0x12: // sceCdReadILinkId (0:9)
1528 SetResultSize(9);
1529 cdvd.Result[0] = cdvdReadILinkID(&cdvd.Result[1]);
1530 break;
1531
1532 case 0x13: // sceCdWriteILinkID (8:1)
1533 SetResultSize(1);
1534 cdvd.Result[0] = cdvdWriteILinkID(&cdvd.Param[1]);
1535 break;
1536
1537 case 0x14: // CdCtrlAudioDigitalOut (1:1)
1538 //parameter can be 2, 0, ...
1539 SetResultSize(1);
1540 cdvd.Result[0] = 0; //8 is a flag; not used
1541 break;
1542
1543 case 0x15: // sceCdForbidDVDP (0:1)
1544 //Console.WriteLn("sceCdForbidDVDP");
1545 SetResultSize(1);
1546 cdvd.Result[0] = 5;
1547 break;
1548
1549 case 0x16: // AutoAdjustCtrl - from cdvdman (1:1)
1550 SetResultSize(1);
1551 cdvd.Result[0] = 0;
1552 break;
1553
1554 case 0x17: // CdReadModelNumber (1:9) - from xcdvdman
1555 SetResultSize(9);
1556 cdvd.Result[0] = cdvdReadModelNumber(&cdvd.Result[1], cdvd.Param[0]);
1557 break;
1558
1559 case 0x18: // CdWriteModelNumber (9:1) - from xcdvdman
1560 SetResultSize(1);
1561 cdvd.Result[0] = cdvdWriteModelNumber(&cdvd.Param[1], cdvd.Param[0]);
1562 break;
1563
1564 // case 0x19: // sceCdForbidRead (0:1) - from xcdvdman
1565 // break;
1566
1567 case 0x1A: // sceCdBootCertify (4:1)//(4:16 in psx?)
1568 SetResultSize(1);//on input there are 4 bytes: 1;?10;J;C for 18000; 1;60;E;C for 39002 from ROMVER
1569 cdvd.Result[0] = 1;//i guess that means okay
1570 break;
1571
1572 case 0x1B: // sceCdCancelPOffRdy (0:1) - Call73 from Xcdvdman (1:1)
1573 SetResultSize(1);
1574 cdvd.Result[0] = 0;
1575 break;
1576
1577 case 0x1C: // sceCdBlueLEDCtl (1:1) - Call72 from Xcdvdman
1578 SetResultSize(1);
1579 cdvd.Result[0] = 0;
1580 break;
1581
1582 // case 0x1D: // cdvdman_call116 (0:5) - In V10 Bios
1583 // break;
1584
1585 case 0x1E: // sceRemote2Read (0:5) - // 00 14 AA BB CC -> remote key code
1586 SetResultSize(5);
1587 cdvd.Result[0] = 0x00;
1588 cdvd.Result[1] = 0x14;
1589 cdvd.Result[2] = 0x00;
1590 cdvd.Result[3] = 0x00;
1591 cdvd.Result[4] = 0x00;
1592 break;
1593
1594 // case 0x1F: // sceRemote2_7 (2:1) - cdvdman_call117
1595 // break;
1596
1597 case 0x20: // sceRemote2_6 (0:3) // 00 01 00
1598 SetResultSize(3);
1599 cdvd.Result[0] = 0x00;
1600 cdvd.Result[1] = 0x01;
1601 cdvd.Result[2] = 0x00;
1602 break;
1603
1604 // case 0x21: // sceCdWriteWakeUpTime (8:1)
1605 // break;
1606
1607 case 0x22: // sceCdReadWakeUpTime (0:10)
1608 SetResultSize(10);
1609 cdvd.Result[0] = 0;
1610 cdvd.Result[1] = 0;
1611 cdvd.Result[2] = 0;
1612 cdvd.Result[3] = 0;
1613 cdvd.Result[4] = 0;
1614 cdvd.Result[5] = 0;
1615 cdvd.Result[6] = 0;
1616 cdvd.Result[7] = 0;
1617 cdvd.Result[8] = 0;
1618 cdvd.Result[9] = 0;
1619 break;
1620
1621 case 0x24: // sceCdRCBypassCtrl (1:1) - In V10 Bios
1622 // FIXME: because PRId<0x23, the bit 0 of sio2 don't get updated 0xBF808284
1623 SetResultSize(1);
1624 cdvd.Result[0] = 0;
1625 break;
1626
1627 // case 0x25: // cdvdman_call120 (1:1) - In V10 Bios
1628 // break;
1629
1630 // case 0x26: // cdvdman_call128 (0,3) - In V10 Bios
1631 // break;
1632
1633 // case 0x27: // cdvdman_call148 (0:13) - In V10 Bios
1634 // break;
1635
1636 // case 0x28: // cdvdman_call150 (1:1) - In V10 Bios
1637 // break;
1638
1639 case 0x29: //sceCdNoticeGameStart (1:1)
1640 SetResultSize(1);
1641 cdvd.Result[0] = 0;
1642 break;
1643
1644 // case 0x2C: //sceCdXBSPowerCtl (2:2)
1645 // break;
1646
1647 // case 0x2D: //sceCdXLEDCtl (2:2)
1648 // break;
1649
1650 // case 0x2E: //sceCdBuzzerCtl (0:1)
1651 // break;
1652
1653 // case 0x2F: //cdvdman_call167 (16:1)
1654 // break;
1655
1656 // case 0x30: //cdvdman_call169 (1:9)
1657 // break;
1658
1659 case 0x31: //sceCdSetMediumRemoval (1:1)
1660 SetResultSize(1);
1661 cdvd.Result[0] = 0;
1662 break;
1663
1664 case 0x32: //sceCdGetMediumRemoval (0:2)
1665 SetResultSize(2);
1666 cdvd.Result[0] = 0;
1667 //cdvd.Result[0] = 0; // fixme: I'm pretty sure that the same variable shouldn't be set twice here. Perhaps cdvd.Result[1]?
1668 break;
1669
1670 // case 0x33: //sceCdXDVRPReset (1:1)
1671 // break;
1672
1673 case 0x36: //cdvdman_call189 [__sceCdReadRegionParams - made up name] (0:15) i think it is 16, not 15
1674 SetResultSize(15);
1675
1676 cdvdGetMechaVer(&cdvd.Result[1]);
1677 cdvd.Result[0] = cdvdReadRegionParams(&cdvd.Result[3]);//size==8
1678 Console.WriteLn("REGION PARAMS = %s %s", mg_zones[cdvd.Result[1]], &cdvd.Result[3]);
1679 cdvd.Result[1] = 1 << cdvd.Result[1]; //encryption zone; see offset 0x1C in encrypted headers
1680 //////////////////////////////////////////
1681 cdvd.Result[2] = 0; //??
1682 // cdvd.Result[3] == ROMVER[4] == *0xBFC7FF04
1683 // cdvd.Result[4] == OSDVER[4] == CAP Jjpn, Aeng, Eeng, Heng, Reng, Csch, Kkor?
1684 // cdvd.Result[5] == OSDVER[5] == small
1685 // cdvd.Result[6] == OSDVER[6] == small
1686 // cdvd.Result[7] == OSDVER[7] == small
1687 // cdvd.Result[8] == VERSTR[0x22] == *0xBFC7FF52
1688 // cdvd.Result[9] == DVDID J U O E A R C M
1689 // cdvd.Result[10]== 0; //??
1690 cdvd.Result[11] = 0; //??
1691 cdvd.Result[12] = 0; //??
1692 //////////////////////////////////////////
1693 cdvd.Result[13] = 0; //0xFF - 77001
1694 cdvd.Result[14] = 0; //??
1695 break;
1696
1697 case 0x37: //called from EECONF [sceCdReadMAC - made up name] (0:9)
1698 SetResultSize(9);
1699 cdvd.Result[0] = cdvdReadMAC(&cdvd.Result[1]);
1700 break;
1701
1702 case 0x38: //used to fix the MAC back after accidentally trashed it :D [sceCdWriteMAC - made up name] (8:1)
1703 SetResultSize(1);
1704 cdvd.Result[0] = cdvdWriteMAC(&cdvd.Param[0]);
1705 break;
1706
1707 case 0x3E: //[__sceCdWriteRegionParams - made up name] (15:1) [Florin: hum, i was expecting 14:1]
1708 SetResultSize(1);
1709 cdvd.Result[0] = cdvdWriteRegionParams(&cdvd.Param[2]);
1710 break;
1711
1712 case 0x40: // CdOpenConfig (3:1)
1713 SetResultSize(1);
1714 cdvd.CReadWrite = cdvd.Param[0];
1715 cdvd.COffset = cdvd.Param[1];
1716 cdvd.CNumBlocks = cdvd.Param[2];
1717 cdvd.CBlockIndex= 0;
1718 cdvd.Result[0] = 0;
1719 break;
1720
1721 case 0x41: // CdReadConfig (0:16)
1722 SetResultSize(16);
1723 cdvdReadConfig(&cdvd.Result[0]);
1724 break;
1725
1726 case 0x42: // CdWriteConfig (16:1)
1727 SetResultSize(1);
1728 cdvd.Result[0] = cdvdWriteConfig(&cdvd.Param[0]);
1729 break;
1730
1731 case 0x43: // CdCloseConfig (0:1)
1732 SetResultSize(1);
1733 cdvd.CReadWrite = 0;
1734 cdvd.COffset = 0;
1735 cdvd.CNumBlocks = 0;
1736 cdvd.CBlockIndex= 0;
1737 cdvd.Result[0] = 0;
1738 break;
1739
1740 case 0x80: // secrman: __mechacon_auth_0x80
1741 SetResultSize(1);//in:1
1742 cdvd.mg_datatype = 0;//data
1743 cdvd.Result[0] = 0;
1744 break;
1745
1746 case 0x81: // secrman: __mechacon_auth_0x81
1747 SetResultSize(1);//in:1
1748 cdvd.mg_datatype = 0;//data
1749 cdvd.Result[0] = 0;
1750 break;
1751
1752 case 0x82: // secrman: __mechacon_auth_0x82
1753 SetResultSize(1);//in:16
1754 cdvd.Result[0] = 0;
1755 break;
1756
1757 case 0x83: // secrman: __mechacon_auth_0x83
1758 SetResultSize(1);//in:8
1759 cdvd.Result[0] = 0;
1760 break;
1761
1762 case 0x84: // secrman: __mechacon_auth_0x84
1763 SetResultSize(1+8+4);//in:0
1764 cdvd.Result[0] = 0;
1765
1766 cdvd.Result[1] = 0x21;
1767 cdvd.Result[2] = 0xdc;
1768 cdvd.Result[3] = 0x31;
1769 cdvd.Result[4] = 0x96;
1770 cdvd.Result[5] = 0xce;
1771 cdvd.Result[6] = 0x72;
1772 cdvd.Result[7] = 0xe0;
1773 cdvd.Result[8] = 0xc8;
1774
1775 cdvd.Result[9] = 0x69;
1776 cdvd.Result[10] = 0xda;
1777 cdvd.Result[11] = 0x34;
1778 cdvd.Result[12] = 0x9b;
1779 break;
1780
1781 case 0x85: // secrman: __mechacon_auth_0x85
1782 SetResultSize(1+4+8);//in:0
1783 cdvd.Result[0] = 0;
1784
1785 cdvd.Result[1] = 0xeb;
1786 cdvd.Result[2] = 0x01;
1787 cdvd.Result[3] = 0xc7;
1788 cdvd.Result[4] = 0xa9;
1789
1790 cdvd.Result[ 5] = 0x3f;
1791 cdvd.Result[ 6] = 0x9c;
1792 cdvd.Result[ 7] = 0x5b;
1793 cdvd.Result[ 8] = 0x19;
1794 cdvd.Result[ 9] = 0x31;
1795 cdvd.Result[10] = 0xa0;
1796 cdvd.Result[11] = 0xb3;
1797 cdvd.Result[12] = 0xa3;
1798 break;
1799
1800 case 0x86: // secrman: __mechacon_auth_0x86
1801 SetResultSize(1);//in:16
1802 cdvd.Result[0] = 0;
1803 break;
1804
1805 case 0x87: // secrman: __mechacon_auth_0x87
1806 SetResultSize(1);//in:8
1807 cdvd.Result[0] = 0;
1808 break;
1809
1810 case 0x8D: // sceMgWriteData
1811 SetResultSize(1);//in:length<=16
1812 if (cdvd.mg_size + cdvd.ParamC > cdvd.mg_maxsize)
1813 {
1814 cdvd.Result[0] = 0x80;
1815 }
1816 else
1817 {
1818 memcpy_fast(cdvd.mg_buffer + cdvd.mg_size, cdvd.Param, cdvd.ParamC);
1819 cdvd.mg_size += cdvd.ParamC;
1820 cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error
1821 }
1822 break;
1823
1824 case 0x8E: // sceMgReadData
1825 SetResultSize( std::min(16, cdvd.mg_size) );
1826 memcpy_fast(cdvd.Result, cdvd.mg_buffer, cdvd.ResultC);
1827 cdvd.mg_size -= cdvd.ResultC;
1828 memcpy_fast(cdvd.mg_buffer, cdvd.mg_buffer+cdvd.ResultC, cdvd.mg_size);
1829 break;
1830
1831 case 0x88: // secrman: __mechacon_auth_0x88 //for now it is the same; so, fall;)
1832 case 0x8F: // secrman: __mechacon_auth_0x8F
1833 SetResultSize(1);//in:0
1834 if (cdvd.mg_datatype == 1) // header data
1835 {
1836 u64* psrc, *pdst;
1837 int bit_ofs, i;
1838
1839 if ((cdvd.mg_maxsize != cdvd.mg_size)||(cdvd.mg_size < 0x20) || (cdvd.mg_size != *(u16*)&cdvd.mg_buffer[0x14]))
1840 {
1841 fail_pol_cal();
1842 break;
1843 }
1844
1845 Console.Write("[MG] ELF_size=0x%X Hdr_size=0x%X unk=0x%X flags=0x%X count=%d zones=",
1846 *(u32*)&cdvd.mg_buffer[0x10], *(u16*)&cdvd.mg_buffer[0x14], *(u16*)&cdvd.mg_buffer[0x16],
1847 *(u16*)&cdvd.mg_buffer[0x18], *(u16*)&cdvd.mg_buffer[0x1A]);
1848 for (i=0; i<8; i++)
1849 {
1850 if (cdvd.mg_buffer[0x1C] & (1<<i)) Console.Write("%s ", mg_zones[i]);
1851 }
1852 Console.Newline();
1853
1854 bit_ofs = mg_BIToffset(cdvd.mg_buffer);
1855
1856 psrc = (u64*)&cdvd.mg_buffer[bit_ofs-0x20];
1857
1858 pdst = (u64*)cdvd.mg_kbit;
1859 pdst[0] = psrc[0];
1860 pdst[1] = psrc[1];
1861 //memcpy(cdvd.mg_kbit, &cdvd.mg_buffer[bit_ofs-0x20], 0x10);
1862
1863 pdst = (u64*)cdvd.mg_kcon;
1864 pdst[0] = psrc[2];
1865 pdst[1] = psrc[3];
1866 //memcpy(cdvd.mg_kcon, &cdvd.mg_buffer[bit_ofs-0x10], 0x10);
1867
1868 if ((cdvd.mg_buffer[bit_ofs+5] || cdvd.mg_buffer[bit_ofs+6] || cdvd.mg_buffer[bit_ofs+7]) ||
1869 (cdvd.mg_buffer[bit_ofs+4] * 16 + bit_ofs + 8 + 16 != *(u16*)&cdvd.mg_buffer[0x14]))
1870 {
1871 fail_pol_cal();
1872 break;
1873 }
1874 }
1875 cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error
1876 break;
1877
1878 case 0x90: // sceMgWriteHeaderStart
1879 SetResultSize(1);//in:5
1880 cdvd.mg_size = 0;
1881 cdvd.mg_datatype = 1;//header data
1882 Console.WriteLn("[MG] hcode=%d cnum=%d a2=%d length=0x%X",
1883 cdvd.Param[0], cdvd.Param[3], cdvd.Param[4], cdvd.mg_maxsize = cdvd.Param[1] | (((int)cdvd.Param[2])<<8));
1884
1885 cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error
1886 break;
1887
1888 case 0x91: // sceMgReadBITLength
1889 {
1890 SetResultSize(3);//in:0
1891 int bit_ofs = mg_BIToffset(cdvd.mg_buffer);
1892 memcpy_fast(cdvd.mg_buffer, &cdvd.mg_buffer[bit_ofs], 8+16*cdvd.mg_buffer[bit_ofs+4]);
1893
1894 cdvd.mg_maxsize = 0; // don't allow any write
1895 cdvd.mg_size = 8+16*cdvd.mg_buffer[4];//new offset, i just moved the data
1896 Console.WriteLn("[MG] BIT count=%d", cdvd.mg_buffer[4]);
1897
1898 cdvd.Result[0] = (cdvd.mg_datatype == 1) ? 0 : 0x80; // 0 complete ; 1 busy ; 0x80 error
1899 cdvd.Result[1] = (cdvd.mg_size >> 0) & 0xFF;
1900 cdvd.Result[2] = (cdvd.mg_size >> 8) & 0xFF;
1901 break;
1902 }
1903 case 0x92: // sceMgWriteDatainLength
1904 SetResultSize(1);//in:2
1905 cdvd.mg_size = 0;
1906 cdvd.mg_datatype = 0;//data (encrypted)
1907 cdvd.mg_maxsize = cdvd.Param[0] | (((int)cdvd.Param[1])<<8);
1908 cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error
1909 break;
1910
1911 case 0x93: // sceMgWriteDataoutLength
1912 SetResultSize(1);//in:2
1913 if (((cdvd.Param[0] | (((int)cdvd.Param[1])<<8)) == cdvd.mg_size) && (cdvd.mg_datatype == 0))
1914 {
1915 cdvd.mg_maxsize = 0; // don't allow any write
1916 cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error
1917 }
1918 else
1919 {
1920 cdvd.Result[0] = 0x80;
1921 }
1922 break;
1923
1924 case 0x94: // sceMgReadKbit - read first half of BIT key
1925 SetResultSize(1+8);//in:0
1926 cdvd.Result[0] = 0;
1927
1928 ((int*)(cdvd.Result+1))[0] = ((int*)cdvd.mg_kbit)[0];
1929 ((int*)(cdvd.Result+1))[1] = ((int*)cdvd.mg_kbit)[1];
1930 //memcpy(cdvd.Result+1, cdvd.mg_kbit, 8);
1931 break;
1932
1933 case 0x95: // sceMgReadKbit2 - read second half of BIT key
1934 SetResultSize(1+8);//in:0
1935 cdvd.Result[0] = 0;
1936 ((int*)(cdvd.Result+1))[0] = ((int*)(cdvd.mg_kbit+8))[0];
1937 ((int*)(cdvd.Result+1))[1] = ((int*)(cdvd.mg_kbit+8))[1];
1938 //memcpy(cdvd.Result+1, cdvd.mg_kbit+8, 8);
1939 break;
1940
1941 case 0x96: // sceMgReadKcon - read first half of content key
1942 SetResultSize(1+8);//in:0
1943 cdvd.Result[0] = 0;
1944 ((int*)(cdvd.Result+1))[0] = ((int*)cdvd.mg_kcon)[0];
1945 ((int*)(cdvd.Result+1))[1] = ((int*)cdvd.mg_kcon)[1];
1946 //memcpy(cdvd.Result+1, cdvd.mg_kcon, 8);
1947 break;
1948
1949 case 0x97: // sceMgReadKcon2 - read second half of content key
1950 SetResultSize(1+8);//in:0
1951 cdvd.Result[0] = 0;
1952 ((int*)(cdvd.Result+1))[0] = ((int*)(cdvd.mg_kcon+8))[0];
1953 ((int*)(cdvd.Result+1))[1] = ((int*)(cdvd.mg_kcon+8))[1];
1954 //memcpy(cdvd.Result+1, cdvd.mg_kcon+8, 8);
1955 break;
1956
1957 default:
1958 // fake a 'correct' command
1959 SetResultSize(1); //in:0
1960 cdvd.Result[0] = 0; // 0 complete ; 1 busy ; 0x80 error
1961 Console.WriteLn("SCMD Unknown %x", rt);
1962 break;
1963 } // end switch
1964
1965 //Console.WriteLn("SCMD - 0x%x\n", rt);
1966 cdvd.ParamP = 0;
1967 cdvd.ParamC = 0;
1968 }
1969
1970 static __forceinline void cdvdWrite17(u8 rt) { // SDATAIN
1971 CDVD_LOG("cdvdWrite17(SDataIn) %x", rt);
1972
1973 if (cdvd.ParamP < 32) {
1974 cdvd.Param[cdvd.ParamP++] = rt;
1975 cdvd.ParamC++;
1976 }
1977 }
1978
1979 static __forceinline void cdvdWrite18(u8 rt) { // SDATAOUT
1980 CDVD_LOG("cdvdWrite18(SDataOut) %x", rt);
1981 Console.WriteLn("*PCSX2* SDATAOUT");
1982 }
1983
1984 static __forceinline void cdvdWrite3A(u8 rt) { // DEC-SET
1985 CDVD_LOG("cdvdWrite3A(DecSet) %x", rt);
1986 cdvd.decSet = rt;
1987 Console.WriteLn("DecSet Write: %02X", cdvd.decSet);
1988 }
1989
1990 void cdvdWrite(u8 key, u8 rt)
1991 {
1992 switch (key)
1993 {
1994 case 0x04: cdvdWrite04(rt); break;
1995 case 0x05: cdvdWrite05(rt); break;
1996 case 0x06: cdvdWrite06(rt); break;
1997 case 0x07: cdvdWrite07(rt); break;
1998 case 0x08: cdvdWrite08(rt); break;
1999 case 0x0A: cdvdWrite0A(rt); break;
2000 case 0x0F: cdvdWrite0F(rt); break;
2001 case 0x14: cdvdWrite14(rt); break;
2002 case 0x16: cdvdWrite16(rt); break;
2003 case 0x17: cdvdWrite17(rt); break;
2004 case 0x18: cdvdWrite18(rt); break;
2005 case 0x3A: cdvdWrite3A(rt); break;
2006 default:
2007 Console.Warning("IOP Unknown 8bit write to addr 0x1f4020%x = 0x%x", key, rt);
2008 break;
2009 }
2010 }

  ViewVC Help
Powered by ViewVC 1.1.22