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 |
} |