1 |
/* PCSX2 - PS2 Emulator for PCs |
2 |
* Copyright (C) 2002-2010 PCSX2 Dev Team |
3 |
* |
4 |
* PCSX2 is free software: you can redistribute it and/or modify it under the terms |
5 |
* of the GNU Lesser General Public License as published by the Free Software Found- |
6 |
* ation, either version 3 of the License, or (at your option) any later version. |
7 |
* |
8 |
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
9 |
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
10 |
* PURPOSE. See the GNU General Public License for more details. |
11 |
* |
12 |
* You should have received a copy of the GNU General Public License along with PCSX2. |
13 |
* If not, see <http://www.gnu.org/licenses/>. |
14 |
*/ |
15 |
|
16 |
|
17 |
#include "PrecompiledHeader.h" |
18 |
#include "IopCommon.h" |
19 |
|
20 |
#include "CdRom.h" |
21 |
#include "CDVD.h" |
22 |
|
23 |
//THIS ALL IS FOR THE CDROM REGISTERS HANDLING |
24 |
|
25 |
enum cdrom_registers |
26 |
{ |
27 |
CdlSync = 0, |
28 |
CdlNop = 1, |
29 |
CdlSetloc = 2, |
30 |
CdlPlay = 3, |
31 |
CdlForward = 4, |
32 |
CdlBackward = 5, |
33 |
CdlReadN = 6, |
34 |
CdlStandby = 7, |
35 |
CdlStop = 8, |
36 |
CdlPause = 9, |
37 |
CdlInit = 10, |
38 |
CdlMute = 11, |
39 |
CdlDemute = 12, |
40 |
CdlSetfilter = 13, |
41 |
CdlSetmode = 14, |
42 |
CdlGetmode = 15, |
43 |
CdlGetlocL = 16, |
44 |
CdlGetlocP = 17, |
45 |
Cdl18 = 18, |
46 |
CdlGetTN = 19, |
47 |
CdlGetTD = 20, |
48 |
CdlSeekL = 21, |
49 |
CdlSeekP = 22, |
50 |
CdlTest = 25, |
51 |
CdlID = 26, |
52 |
CdlReadS = 27, |
53 |
CdlReset = 28, |
54 |
CdlReadToc = 30, |
55 |
|
56 |
AUTOPAUSE = 249, |
57 |
READ_ACK = 250, |
58 |
READ = 251, |
59 |
REPPLAY_ACK = 252, |
60 |
REPPLAY = 253, |
61 |
ASYNC = 254 |
62 |
/* don't set 255, it's reserved */ |
63 |
}; |
64 |
|
65 |
const char *CmdName[0x100]= { |
66 |
"CdlSync", "CdlNop", "CdlSetloc", "CdlPlay", |
67 |
"CdlForward", "CdlBackward", "CdlReadN", "CdlStandby", |
68 |
"CdlStop", "CdlPause", "CdlInit", "CdlMute", |
69 |
"CdlDemute", "CdlSetfilter", "CdlSetmode", "CdlGetmode", |
70 |
"CdlGetlocL", "CdlGetlocP", "Cdl18", "CdlGetTN", |
71 |
"CdlGetTD", "CdlSeekL", "CdlSeekP", NULL, |
72 |
NULL, "CdlTest", "CdlID", "CdlReadS", |
73 |
"CdlReset", NULL, "CDlReadToc", NULL |
74 |
}; |
75 |
|
76 |
cdrStruct cdr; |
77 |
s32 LoadCdBios; |
78 |
|
79 |
u8 Test04[] = { 0 }; |
80 |
u8 Test05[] = { 0 }; |
81 |
u8 Test20[] = { 0x98, 0x06, 0x10, 0xC3 }; |
82 |
u8 Test22[] = { 0x66, 0x6F, 0x72, 0x20, 0x45, 0x75, 0x72, 0x6F }; |
83 |
u8 Test23[] = { 0x43, 0x58, 0x44, 0x32, 0x39 ,0x34, 0x30, 0x51 }; |
84 |
|
85 |
// 1x = 75 sectors per second |
86 |
// PSXCLK = 1 sec in the ps |
87 |
// so (PSXCLK / 75) / BIAS = cdr read time (linuzappz) |
88 |
//#define cdReadTime ((PSXCLK / 75) / BIAS) |
89 |
u32 cdReadTime;// = ((PSXCLK / 75) / BIAS); |
90 |
|
91 |
#define CDR_INT(eCycle) PSX_INT(IopEvt_Cdrom, eCycle) |
92 |
#define CDREAD_INT(eCycle) PSX_INT(IopEvt_CdromRead, eCycle) |
93 |
|
94 |
|
95 |
static void AddIrqQueue(u8 irq, u32 ecycle); |
96 |
|
97 |
static __forceinline void StartReading(u32 type) { |
98 |
cdr.Reading = type; |
99 |
cdr.FirstSector = 1; |
100 |
cdr.Readed = 0xff; |
101 |
AddIrqQueue(READ_ACK, 0x800); |
102 |
} |
103 |
|
104 |
static __forceinline void StopReading() { |
105 |
if (cdr.Reading) { |
106 |
cdr.Reading = 0; |
107 |
psxRegs.interrupt &= ~(1<<IopEvt_CdromRead); |
108 |
} |
109 |
} |
110 |
|
111 |
static __forceinline void StopCdda() { |
112 |
if (cdr.Play) { |
113 |
cdr.StatP&=~0x80; |
114 |
cdr.Play = 0; |
115 |
} |
116 |
} |
117 |
|
118 |
static __forceinline void SetResultSize(u8 size) { |
119 |
cdr.ResultP = 0; |
120 |
cdr.ResultC = size; |
121 |
cdr.ResultReady = 1; |
122 |
} |
123 |
|
124 |
static void ReadTrack() { |
125 |
cdr.Prev[0] = itob(cdr.SetSector[0]); |
126 |
cdr.Prev[1] = itob(cdr.SetSector[1]); |
127 |
cdr.Prev[2] = itob(cdr.SetSector[2]); |
128 |
|
129 |
CDVD_LOG("KEY *** %x:%x:%x", cdr.Prev[0], cdr.Prev[1], cdr.Prev[2]); |
130 |
cdr.RErr = DoCDVDreadTrack(msf_to_lsn(cdr.SetSector), CDVD_MODE_2340); |
131 |
} |
132 |
|
133 |
// cdr.Stat: |
134 |
enum cdr_stat_values |
135 |
{ |
136 |
NoIntr = 0, |
137 |
DataReady, |
138 |
Complete, |
139 |
Acknowledge, |
140 |
DataEnd, |
141 |
DiskError |
142 |
}; |
143 |
|
144 |
static void AddIrqQueue(u8 irq, u32 ecycle) { |
145 |
cdr.Irq = irq; |
146 |
if (cdr.Stat) { |
147 |
cdr.eCycle = ecycle; |
148 |
} else { |
149 |
CDR_INT(ecycle); |
150 |
} |
151 |
} |
152 |
|
153 |
void cdrInterrupt() { |
154 |
cdvdTD trackInfo; |
155 |
int i; |
156 |
u8 Irq = cdr.Irq; |
157 |
|
158 |
if (cdr.Stat) { |
159 |
CDR_INT(0x800); |
160 |
return; |
161 |
} |
162 |
|
163 |
cdr.Irq = 0xff; |
164 |
cdr.Ctrl&=~0x80; |
165 |
|
166 |
switch (Irq) { |
167 |
case CdlSync: |
168 |
SetResultSize(1); |
169 |
cdr.StatP|= 0x2; |
170 |
cdr.Result[0] = cdr.StatP; |
171 |
cdr.Stat = Acknowledge; |
172 |
break; |
173 |
|
174 |
case CdlNop: |
175 |
SetResultSize(1); |
176 |
cdr.Result[0] = cdr.StatP; |
177 |
cdr.Stat = Acknowledge; |
178 |
break; |
179 |
|
180 |
case CdlSetloc: |
181 |
cdr.CmdProcess = 0; |
182 |
SetResultSize(1); |
183 |
cdr.StatP|= 0x2; |
184 |
cdr.Result[0] = cdr.StatP; |
185 |
cdr.Stat = Acknowledge; |
186 |
break; |
187 |
|
188 |
case CdlPlay: |
189 |
cdr.CmdProcess = 0; |
190 |
SetResultSize(1); |
191 |
cdr.Result[0] = cdr.StatP; |
192 |
cdr.Stat = Acknowledge; |
193 |
cdr.StatP|= 0x82; |
194 |
break; |
195 |
|
196 |
case CdlForward: |
197 |
cdr.CmdProcess = 0; |
198 |
SetResultSize(1); |
199 |
cdr.StatP|= 0x2; |
200 |
cdr.Result[0] = cdr.StatP; |
201 |
cdr.Stat = Complete; |
202 |
break; |
203 |
|
204 |
case CdlBackward: |
205 |
cdr.CmdProcess = 0; |
206 |
SetResultSize(1); |
207 |
cdr.StatP|= 0x2; |
208 |
cdr.Result[0] = cdr.StatP; |
209 |
cdr.Stat = Complete; |
210 |
break; |
211 |
|
212 |
case CdlStandby: |
213 |
cdr.CmdProcess = 0; |
214 |
SetResultSize(1); |
215 |
cdr.StatP|= 0x2; |
216 |
cdr.Result[0] = cdr.StatP; |
217 |
cdr.Stat = Complete; |
218 |
break; |
219 |
|
220 |
case CdlStop: |
221 |
cdr.CmdProcess = 0; |
222 |
SetResultSize(1); |
223 |
cdr.StatP&=~0x2; |
224 |
cdr.Result[0] = cdr.StatP; |
225 |
cdr.Stat = Complete; |
226 |
// cdr.Stat = Acknowledge; |
227 |
break; |
228 |
|
229 |
case CdlPause: |
230 |
SetResultSize(1); |
231 |
cdr.Result[0] = cdr.StatP; |
232 |
cdr.Stat = Acknowledge; |
233 |
AddIrqQueue(CdlPause + 0x20, 0x800); |
234 |
break; |
235 |
|
236 |
case CdlPause + 0x20: |
237 |
SetResultSize(1); |
238 |
cdr.StatP&=~0x20; |
239 |
cdr.StatP|= 0x2; |
240 |
cdr.Result[0] = cdr.StatP; |
241 |
cdr.Stat = Complete; |
242 |
break; |
243 |
|
244 |
case CdlInit: |
245 |
SetResultSize(1); |
246 |
cdr.StatP = 0x2; |
247 |
cdr.Result[0] = cdr.StatP; |
248 |
cdr.Stat = Acknowledge; |
249 |
AddIrqQueue(CdlInit + 0x20, 0x800); |
250 |
break; |
251 |
|
252 |
case CdlInit + 0x20: |
253 |
SetResultSize(1); |
254 |
cdr.Result[0] = cdr.StatP; |
255 |
cdr.Stat = Complete; |
256 |
cdr.Init = 1; |
257 |
break; |
258 |
|
259 |
case CdlMute: |
260 |
SetResultSize(1); |
261 |
cdr.StatP|= 0x2; |
262 |
cdr.Result[0] = cdr.StatP; |
263 |
cdr.Stat = Acknowledge; |
264 |
break; |
265 |
|
266 |
case CdlDemute: |
267 |
SetResultSize(1); |
268 |
cdr.StatP|= 0x2; |
269 |
cdr.Result[0] = cdr.StatP; |
270 |
cdr.Stat = Acknowledge; |
271 |
break; |
272 |
|
273 |
case CdlSetfilter: |
274 |
SetResultSize(1); |
275 |
cdr.StatP|= 0x2; |
276 |
cdr.Result[0] = cdr.StatP; |
277 |
cdr.Stat = Acknowledge; |
278 |
break; |
279 |
|
280 |
case CdlSetmode: |
281 |
SetResultSize(1); |
282 |
cdr.StatP|= 0x2; |
283 |
cdr.Result[0] = cdr.StatP; |
284 |
cdr.Stat = Acknowledge; |
285 |
break; |
286 |
|
287 |
case CdlGetmode: |
288 |
SetResultSize(6); |
289 |
cdr.StatP|= 0x2; |
290 |
cdr.Result[0] = cdr.StatP; |
291 |
cdr.Result[1] = cdr.Mode; |
292 |
cdr.Result[2] = cdr.File; |
293 |
cdr.Result[3] = cdr.Channel; |
294 |
cdr.Result[4] = 0; |
295 |
cdr.Result[5] = 0; |
296 |
cdr.Stat = Acknowledge; |
297 |
break; |
298 |
|
299 |
case CdlGetlocL: |
300 |
SetResultSize(8); |
301 |
for (i=0; i<8; i++) |
302 |
cdr.Result[i] = cdr.Transfer[i]; |
303 |
cdr.Stat = Acknowledge; |
304 |
break; |
305 |
|
306 |
case CdlGetlocP: |
307 |
SetResultSize(8); |
308 |
cdr.Result[0] = 1; |
309 |
cdr.Result[1] = 1; |
310 |
cdr.Result[2] = cdr.Prev[0]; |
311 |
cdr.Result[3] = itob((btoi(cdr.Prev[1])) - 2); |
312 |
cdr.Result[4] = cdr.Prev[2]; |
313 |
cdr.Result[5] = cdr.Prev[0]; |
314 |
cdr.Result[6] = cdr.Prev[1]; |
315 |
cdr.Result[7] = cdr.Prev[2]; |
316 |
cdr.Stat = Acknowledge; |
317 |
break; |
318 |
|
319 |
case CdlGetTN: |
320 |
cdr.CmdProcess = 0; |
321 |
SetResultSize(3); |
322 |
cdr.StatP|= 0x2; |
323 |
cdr.Result[0] = cdr.StatP; |
324 |
if (CDVD->getTN(&cdr.ResultTN) == -1) { |
325 |
cdr.Stat = DiskError; |
326 |
cdr.Result[0]|= 0x01; |
327 |
} else { |
328 |
cdr.Stat = Acknowledge; |
329 |
cdr.Result[1] = itob(cdr.ResultTN.strack); |
330 |
cdr.Result[2] = itob(cdr.ResultTN.etrack); |
331 |
} |
332 |
break; |
333 |
|
334 |
case CdlGetTD: |
335 |
cdr.CmdProcess = 0; |
336 |
cdr.Track = btoi(cdr.Param[0]); |
337 |
SetResultSize(4); |
338 |
cdr.StatP|= 0x2; |
339 |
if (CDVD->getTD(cdr.Track, &trackInfo) == -1) { |
340 |
cdr.Stat = DiskError; |
341 |
cdr.Result[0]|= 0x01; |
342 |
} else { |
343 |
lsn_to_msf(cdr.ResultTD, trackInfo.lsn); |
344 |
cdr.Stat = Acknowledge; |
345 |
cdr.Result[0] = cdr.StatP; |
346 |
cdr.Result[1] = cdr.ResultTD[2]; |
347 |
cdr.Result[2] = cdr.ResultTD[1]; |
348 |
cdr.Result[3] = cdr.ResultTD[0]; |
349 |
} |
350 |
break; |
351 |
|
352 |
case CdlSeekL: |
353 |
SetResultSize(1); |
354 |
cdr.StatP|= 0x2; |
355 |
cdr.Result[0] = cdr.StatP; |
356 |
cdr.Stat = Acknowledge; |
357 |
AddIrqQueue(CdlSeekL + 0x20, 0x800); |
358 |
break; |
359 |
|
360 |
case CdlSeekL + 0x20: |
361 |
SetResultSize(1); |
362 |
cdr.StatP|= 0x2; |
363 |
cdr.Result[0] = cdr.StatP; |
364 |
cdr.Stat = Complete; |
365 |
break; |
366 |
|
367 |
case CdlSeekP: |
368 |
SetResultSize(1); |
369 |
cdr.StatP|= 0x2; |
370 |
cdr.Result[0] = cdr.StatP; |
371 |
cdr.Stat = Acknowledge; |
372 |
AddIrqQueue(CdlSeekP + 0x20, 0x800); |
373 |
break; |
374 |
|
375 |
case CdlSeekP + 0x20: |
376 |
SetResultSize(1); |
377 |
cdr.StatP|= 0x2; |
378 |
cdr.Result[0] = cdr.StatP; |
379 |
cdr.Stat = Complete; |
380 |
break; |
381 |
|
382 |
case CdlTest: |
383 |
cdr.Stat = Acknowledge; |
384 |
switch (cdr.Param[0]) { |
385 |
case 0x20: // System Controller ROM Version |
386 |
SetResultSize(4); |
387 |
*(int*)cdr.Result = *(int*)Test20; |
388 |
break; |
389 |
|
390 |
case 0x22: |
391 |
SetResultSize(8); |
392 |
*(int*)cdr.Result = *(int*)Test22; |
393 |
break; |
394 |
|
395 |
case 0x23: |
396 |
case 0x24: |
397 |
SetResultSize(8); |
398 |
*(int*)cdr.Result = *(int*)Test23; |
399 |
break; |
400 |
} |
401 |
break; |
402 |
|
403 |
case CdlID: |
404 |
SetResultSize(1); |
405 |
cdr.StatP|= 0x2; |
406 |
cdr.Result[0] = cdr.StatP; |
407 |
cdr.Stat = Acknowledge; |
408 |
AddIrqQueue(CdlID + 0x20, 0x800); |
409 |
break; |
410 |
|
411 |
case CdlID + 0x20: |
412 |
SetResultSize(8); |
413 |
cdr.Result[0] = 0x00; // 0x08 and cdr.Result[1]|0x10 : audio cd, enters cd player |
414 |
cdr.Result[1] = 0x00; // 0x80 leads to the menu in the bios, else loads CD |
415 |
|
416 |
if (!LoadCdBios) cdr.Result[1] |= 0x80; |
417 |
cdr.Result[2] = 0x00; |
418 |
cdr.Result[3] = 0x00; |
419 |
strncpy((char *)&cdr.Result[4], "PCSX", 4); |
420 |
cdr.Stat = Complete; |
421 |
break; |
422 |
|
423 |
case CdlReset: |
424 |
SetResultSize(1); |
425 |
cdr.StatP = 0x2; |
426 |
cdr.Result[0] = cdr.StatP; |
427 |
cdr.Stat = Acknowledge; |
428 |
break; |
429 |
|
430 |
case CdlReadToc: |
431 |
SetResultSize(1); |
432 |
cdr.StatP|= 0x2; |
433 |
cdr.Result[0] = cdr.StatP; |
434 |
cdr.Stat = Acknowledge; |
435 |
AddIrqQueue(CdlReadToc + 0x20, 0x800); |
436 |
break; |
437 |
|
438 |
case CdlReadToc + 0x20: |
439 |
SetResultSize(1); |
440 |
cdr.StatP|= 0x2; |
441 |
cdr.Result[0] = cdr.StatP; |
442 |
cdr.Stat = Complete; |
443 |
break; |
444 |
|
445 |
case AUTOPAUSE: |
446 |
cdr.OCUP = 0; |
447 |
AddIrqQueue(CdlPause, 0x400); |
448 |
break; |
449 |
|
450 |
case READ_ACK: |
451 |
if (!cdr.Reading) return; |
452 |
|
453 |
SetResultSize(1); |
454 |
cdr.StatP|= 0x2; |
455 |
cdr.Result[0] = cdr.StatP; |
456 |
cdr.Stat = Acknowledge; |
457 |
|
458 |
ReadTrack(); |
459 |
|
460 |
CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); |
461 |
|
462 |
break; |
463 |
|
464 |
case REPPLAY_ACK: |
465 |
cdr.Stat = Acknowledge; |
466 |
cdr.Result[0] = cdr.StatP; |
467 |
SetResultSize(1); |
468 |
AddIrqQueue(REPPLAY, cdReadTime); |
469 |
break; |
470 |
|
471 |
case REPPLAY: |
472 |
//if ((cdr.Mode & 5) != 5) break; |
473 |
break; |
474 |
|
475 |
case 0xff: |
476 |
return; |
477 |
|
478 |
default: |
479 |
cdr.Stat = Complete; |
480 |
break; |
481 |
} |
482 |
|
483 |
if (cdr.Stat != NoIntr && cdr.Reg2 != 0x18) |
484 |
psxHu32(0x1070)|= 0x4; |
485 |
|
486 |
CDVD_LOG("Cdr Interrupt %x\n", Irq); |
487 |
} |
488 |
|
489 |
void cdrReadInterrupt() { |
490 |
|
491 |
if (!cdr.Reading) |
492 |
return; |
493 |
|
494 |
if (cdr.Stat) { |
495 |
CDREAD_INT(0x800); |
496 |
return; |
497 |
} |
498 |
|
499 |
CDVD_LOG("KEY END"); |
500 |
|
501 |
cdr.OCUP = 1; |
502 |
SetResultSize(1); |
503 |
cdr.StatP|= 0x22; |
504 |
cdr.Result[0] = cdr.StatP; |
505 |
|
506 |
if( cdr.RErr == 0 ) |
507 |
{ |
508 |
while( (cdr.RErr = DoCDVDgetBuffer(cdr.Transfer)), cdr.RErr == -2 ) |
509 |
{ |
510 |
// not finished yet ... block on the read until it finishes. |
511 |
Threading::Sleep( 0 ); |
512 |
Threading::SpinWait(); |
513 |
} |
514 |
} |
515 |
|
516 |
if (cdr.RErr == -1) |
517 |
{ |
518 |
CDVD_LOG(" err\n"); |
519 |
memzero(cdr.Transfer); |
520 |
cdr.Stat = DiskError; |
521 |
cdr.Result[0] |= 0x01; |
522 |
ReadTrack(); |
523 |
CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); |
524 |
return; |
525 |
} |
526 |
|
527 |
cdr.Stat = DataReady; |
528 |
|
529 |
CDVD_LOG(" %x:%x:%x", cdr.Transfer[0], cdr.Transfer[1], cdr.Transfer[2]); |
530 |
|
531 |
cdr.SetSector[2]++; |
532 |
|
533 |
if (cdr.SetSector[2] == 75) { |
534 |
cdr.SetSector[2] = 0; |
535 |
cdr.SetSector[1]++; |
536 |
if (cdr.SetSector[1] == 60) { |
537 |
cdr.SetSector[1] = 0; |
538 |
cdr.SetSector[0]++; |
539 |
} |
540 |
} |
541 |
|
542 |
cdr.Readed = 0; |
543 |
|
544 |
if ((cdr.Transfer[4+2] & 0x80) && (cdr.Mode & 0x2)) { // EOF |
545 |
CDVD_LOG("AutoPausing Read"); |
546 |
AddIrqQueue(CdlPause, 0x800); |
547 |
} |
548 |
else { |
549 |
ReadTrack(); |
550 |
CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime); |
551 |
} |
552 |
|
553 |
psxHu32(0x1070)|= 0x4; |
554 |
return; |
555 |
} |
556 |
|
557 |
/* |
558 |
cdrRead0: |
559 |
bit 0 - 0 REG1 command send / 1 REG1 data read |
560 |
bit 1 - 0 data transfer finish / 1 data transfer ready/in progress |
561 |
bit 2 - unknown |
562 |
bit 3 - unknown |
563 |
bit 4 - unknown |
564 |
bit 5 - 1 result ready |
565 |
bit 6 - 1 dma ready |
566 |
bit 7 - 1 command being processed |
567 |
*/ |
568 |
|
569 |
u8 cdrRead0(void) { |
570 |
if (cdr.ResultReady) |
571 |
cdr.Ctrl |= 0x20; |
572 |
else |
573 |
cdr.Ctrl &= ~0x20; |
574 |
|
575 |
if (cdr.OCUP) |
576 |
cdr.Ctrl |= 0x40; |
577 |
else |
578 |
cdr.Ctrl &= ~0x40; |
579 |
|
580 |
// what means the 0x10 and the 0x08 bits? i only saw it used by the bios |
581 |
cdr.Ctrl|=0x18; |
582 |
|
583 |
CDVD_LOG("CD0 Read: %x", cdr.Ctrl); |
584 |
return psxHu8(0x1800) = cdr.Ctrl; |
585 |
} |
586 |
|
587 |
/* |
588 |
cdrWrite0: |
589 |
0 - to send a command / 1 - to get the result |
590 |
*/ |
591 |
|
592 |
void cdrWrite0(u8 rt) { |
593 |
CDVD_LOG("CD0 write: %x", rt); |
594 |
|
595 |
cdr.Ctrl = rt | (cdr.Ctrl & ~0x3); |
596 |
|
597 |
if (rt == 0) { |
598 |
cdr.ParamP = 0; |
599 |
cdr.ParamC = 0; |
600 |
cdr.ResultReady = 0; |
601 |
} |
602 |
} |
603 |
|
604 |
u8 cdrRead1(void) { |
605 |
if (cdr.ResultReady && cdr.Ctrl & 0x1) { |
606 |
psxHu8(0x1801) = cdr.Result[cdr.ResultP++]; |
607 |
if (cdr.ResultP == cdr.ResultC) cdr.ResultReady = 0; |
608 |
} |
609 |
else |
610 |
psxHu8(0x1801) = 0; |
611 |
|
612 |
CDVD_LOG("CD1 Read: %x", psxHu8(0x1801)); |
613 |
return psxHu8(0x1801); |
614 |
} |
615 |
|
616 |
void cdrWrite1(u8 rt) { |
617 |
int i; |
618 |
|
619 |
CDVD_LOG("CD1 write: %x (%s)", rt, CmdName[rt]); |
620 |
cdr.Cmd = rt; |
621 |
cdr.OCUP = 0; |
622 |
|
623 |
#ifdef CDRCMD_DEBUG |
624 |
SysPrintf("CD1 write: %x (%s)", rt, CmdName[rt]); |
625 |
if (cdr.ParamC) { |
626 |
SysPrintf(" Param[%d] = {", cdr.ParamC); |
627 |
for (i=0;i<cdr.ParamC;i++) SysPrintf(" %x,", cdr.Param[i]); |
628 |
SysPrintf("}\n"); |
629 |
} else SysPrintf("\n"); |
630 |
#endif |
631 |
|
632 |
if (cdr.Ctrl & 0x1) return; |
633 |
|
634 |
switch(cdr.Cmd) { |
635 |
case CdlSync: |
636 |
cdr.Ctrl|= 0x80; |
637 |
cdr.Stat = NoIntr; |
638 |
AddIrqQueue(cdr.Cmd, 0x800); |
639 |
break; |
640 |
|
641 |
case CdlNop: |
642 |
cdr.Ctrl|= 0x80; |
643 |
cdr.Stat = NoIntr; |
644 |
AddIrqQueue(cdr.Cmd, 0x800); |
645 |
break; |
646 |
|
647 |
case CdlSetloc: |
648 |
StopReading(); |
649 |
for (i=0; i<3; i++) cdr.SetSector[i] = btoi(cdr.Param[i]); |
650 |
cdr.SetSector[3] = 0; |
651 |
if ((cdr.SetSector[0] | cdr.SetSector[1] | cdr.SetSector[2]) == 0) { |
652 |
*(u32 *)cdr.SetSector = *(u32 *)cdr.SetSectorSeek; |
653 |
} |
654 |
cdr.Ctrl|= 0x80; |
655 |
cdr.Stat = NoIntr; |
656 |
AddIrqQueue(cdr.Cmd, 0x800); |
657 |
break; |
658 |
|
659 |
case CdlPlay: |
660 |
cdr.Play = 1; |
661 |
cdr.Ctrl|= 0x80; |
662 |
cdr.Stat = NoIntr; |
663 |
AddIrqQueue(cdr.Cmd, 0x800); |
664 |
break; |
665 |
|
666 |
case CdlForward: |
667 |
if (cdr.CurTrack < 0xaa) cdr.CurTrack++; |
668 |
cdr.Ctrl|= 0x80; |
669 |
cdr.Stat = NoIntr; |
670 |
AddIrqQueue(cdr.Cmd, 0x800); |
671 |
break; |
672 |
|
673 |
case CdlBackward: |
674 |
if (cdr.CurTrack > 1) cdr.CurTrack--; |
675 |
cdr.Ctrl|= 0x80; |
676 |
cdr.Stat = NoIntr; |
677 |
AddIrqQueue(cdr.Cmd, 0x800); |
678 |
break; |
679 |
|
680 |
case CdlReadN: |
681 |
cdr.Irq = 0; |
682 |
StopReading(); |
683 |
cdr.Ctrl|= 0x80; |
684 |
cdr.Stat = NoIntr; |
685 |
StartReading(1); |
686 |
break; |
687 |
|
688 |
case CdlStandby: |
689 |
StopCdda(); |
690 |
StopReading(); |
691 |
cdr.Ctrl|= 0x80; |
692 |
cdr.Stat = NoIntr; |
693 |
AddIrqQueue(cdr.Cmd, 0x800); |
694 |
break; |
695 |
|
696 |
case CdlStop: |
697 |
StopCdda(); |
698 |
StopReading(); |
699 |
cdr.Ctrl|= 0x80; |
700 |
cdr.Stat = NoIntr; |
701 |
AddIrqQueue(cdr.Cmd, 0x800); |
702 |
break; |
703 |
|
704 |
case CdlPause: |
705 |
StopCdda(); |
706 |
StopReading(); |
707 |
cdr.Ctrl|= 0x80; |
708 |
cdr.Stat = NoIntr; |
709 |
AddIrqQueue(cdr.Cmd, 0x40000); |
710 |
break; |
711 |
|
712 |
case CdlReset: |
713 |
case CdlInit: |
714 |
StopCdda(); |
715 |
StopReading(); |
716 |
cdr.Ctrl|= 0x80; |
717 |
cdr.Stat = NoIntr; |
718 |
AddIrqQueue(cdr.Cmd, 0x800); |
719 |
break; |
720 |
|
721 |
case CdlMute: |
722 |
cdr.Muted = 0; |
723 |
cdr.Ctrl|= 0x80; |
724 |
cdr.Stat = NoIntr; |
725 |
AddIrqQueue(cdr.Cmd, 0x800); |
726 |
break; |
727 |
|
728 |
case CdlDemute: |
729 |
cdr.Muted = 1; |
730 |
cdr.Ctrl|= 0x80; |
731 |
cdr.Stat = NoIntr; |
732 |
AddIrqQueue(cdr.Cmd, 0x800); |
733 |
break; |
734 |
|
735 |
case CdlSetfilter: |
736 |
cdr.File = cdr.Param[0]; |
737 |
cdr.Channel = cdr.Param[1]; |
738 |
cdr.Ctrl|= 0x80; |
739 |
cdr.Stat = NoIntr; |
740 |
AddIrqQueue(cdr.Cmd, 0x800); |
741 |
break; |
742 |
|
743 |
case CdlSetmode: |
744 |
CDVD_LOG("Setmode %x", cdr.Param[0]); |
745 |
|
746 |
cdr.Mode = cdr.Param[0]; |
747 |
cdr.Ctrl|= 0x80; |
748 |
cdr.Stat = NoIntr; |
749 |
AddIrqQueue(cdr.Cmd, 0x800); |
750 |
break; |
751 |
|
752 |
case CdlGetmode: |
753 |
cdr.Ctrl|= 0x80; |
754 |
cdr.Stat = NoIntr; |
755 |
AddIrqQueue(cdr.Cmd, 0x800); |
756 |
break; |
757 |
|
758 |
case CdlGetlocL: |
759 |
cdr.Ctrl|= 0x80; |
760 |
cdr.Stat = NoIntr; |
761 |
AddIrqQueue(cdr.Cmd, 0x800); |
762 |
break; |
763 |
|
764 |
case CdlGetlocP: |
765 |
cdr.Ctrl|= 0x80; |
766 |
cdr.Stat = NoIntr; |
767 |
AddIrqQueue(cdr.Cmd, 0x800); |
768 |
break; |
769 |
|
770 |
case CdlGetTN: |
771 |
cdr.Ctrl|= 0x80; |
772 |
cdr.Stat = NoIntr; |
773 |
AddIrqQueue(cdr.Cmd, 0x800); |
774 |
break; |
775 |
|
776 |
case CdlGetTD: |
777 |
cdr.Ctrl|= 0x80; |
778 |
cdr.Stat = NoIntr; |
779 |
AddIrqQueue(cdr.Cmd, 0x800); |
780 |
break; |
781 |
|
782 |
case CdlSeekL: |
783 |
((u32 *)cdr.SetSectorSeek)[0] = ((u32 *)cdr.SetSector)[0]; |
784 |
cdr.Ctrl|= 0x80; |
785 |
cdr.Stat = NoIntr; |
786 |
AddIrqQueue(cdr.Cmd, 0x800); |
787 |
break; |
788 |
|
789 |
case CdlSeekP: |
790 |
((u32 *)cdr.SetSectorSeek)[0] = ((u32 *)cdr.SetSector)[0]; |
791 |
cdr.Ctrl|= 0x80; |
792 |
cdr.Stat = NoIntr; |
793 |
AddIrqQueue(cdr.Cmd, 0x800); |
794 |
break; |
795 |
|
796 |
case CdlTest: |
797 |
cdr.Ctrl|= 0x80; |
798 |
cdr.Stat = NoIntr; |
799 |
AddIrqQueue(cdr.Cmd, 0x800); |
800 |
break; |
801 |
|
802 |
case CdlID: |
803 |
cdr.Ctrl|= 0x80; |
804 |
cdr.Stat = NoIntr; |
805 |
AddIrqQueue(cdr.Cmd, 0x800); |
806 |
break; |
807 |
|
808 |
case CdlReadS: |
809 |
cdr.Irq = 0; |
810 |
StopReading(); |
811 |
cdr.Ctrl|= 0x80; |
812 |
cdr.Stat = NoIntr; |
813 |
StartReading(2); |
814 |
break; |
815 |
|
816 |
case CdlReadToc: |
817 |
cdr.Ctrl|= 0x80; |
818 |
cdr.Stat = NoIntr; |
819 |
AddIrqQueue(cdr.Cmd, 0x800); |
820 |
break; |
821 |
|
822 |
default: |
823 |
CDVD_LOG("Unknown Cmd: %x\n", cdr.Cmd); |
824 |
return; |
825 |
} |
826 |
if (cdr.Stat != NoIntr) |
827 |
iopIntcIrq( 2 ); |
828 |
} |
829 |
|
830 |
u8 cdrRead2(void) { |
831 |
u8 ret; |
832 |
|
833 |
if (cdr.Readed == 0) { |
834 |
ret = 0; |
835 |
} else { |
836 |
ret = *cdr.pTransfer++; |
837 |
} |
838 |
|
839 |
CDVD_LOG("CD2 Read: %x", ret); |
840 |
return ret; |
841 |
} |
842 |
|
843 |
void cdrWrite2(u8 rt) { |
844 |
CDVD_LOG("CD2 write: %x", rt); |
845 |
|
846 |
if (cdr.Ctrl & 0x1) { |
847 |
switch (rt) { |
848 |
case 0x07: |
849 |
cdr.ParamP = 0; |
850 |
cdr.ParamC = 0; |
851 |
cdr.ResultReady = 0; |
852 |
cdr.Ctrl = 0; |
853 |
break; |
854 |
|
855 |
default: |
856 |
cdr.Reg2 = rt; |
857 |
break; |
858 |
} |
859 |
} |
860 |
else |
861 |
{ |
862 |
if (!(cdr.Ctrl & 0x1) && cdr.ParamP < 8) { |
863 |
cdr.Param[cdr.ParamP++] = rt; |
864 |
cdr.ParamC++; |
865 |
} |
866 |
} |
867 |
} |
868 |
|
869 |
u8 cdrRead3(void) { |
870 |
if (cdr.Stat) { |
871 |
if (cdr.Ctrl & 0x1) |
872 |
psxHu8(0x1803) = cdr.Stat | 0xE0; |
873 |
else |
874 |
psxHu8(0x1803) = 0xff; |
875 |
} else psxHu8(0x1803) = 0; |
876 |
|
877 |
CDVD_LOG("CD3 Read: %x", psxHu8(0x1803)); |
878 |
return psxHu8(0x1803); |
879 |
} |
880 |
|
881 |
void cdrWrite3(u8 rt) { |
882 |
CDVD_LOG("CD3 write: %x", rt); |
883 |
|
884 |
if (rt == 0x07 && cdr.Ctrl & 0x1) { |
885 |
cdr.Stat = 0; |
886 |
|
887 |
if (cdr.Irq == 0xff) { cdr.Irq = 0; return; } |
888 |
if (cdr.Irq) { |
889 |
CDR_INT(cdr.eCycle); |
890 |
} |
891 |
return; |
892 |
} |
893 |
|
894 |
if (rt == 0x80 && !(cdr.Ctrl & 0x1) && cdr.Readed == 0) { |
895 |
cdr.Readed = 1; |
896 |
cdr.pTransfer = cdr.Transfer; |
897 |
|
898 |
switch (cdr.Mode&0x30) { |
899 |
case 0x10: |
900 |
case 0x00: cdr.pTransfer+=12; break; |
901 |
default: break; |
902 |
} |
903 |
} |
904 |
} |
905 |
|
906 |
void psxDma3(u32 madr, u32 bcr, u32 chcr) { |
907 |
u32 cdsize; |
908 |
|
909 |
CDVD_LOG("*** DMA 3 *** %lx addr = %lx size = %lx", chcr, madr, bcr); |
910 |
|
911 |
switch (chcr) { |
912 |
case 0x11000000: |
913 |
case 0x11400100: |
914 |
if (cdr.Readed == 0) { |
915 |
CDVD_LOG("*** DMA 3 *** NOT READY"); |
916 |
return; |
917 |
} |
918 |
|
919 |
cdsize = (bcr & 0xffff) * 4; |
920 |
memcpy_fast(iopPhysMem(madr), cdr.pTransfer, cdsize); |
921 |
psxCpu->Clear(madr, cdsize/4); |
922 |
cdr.pTransfer+=cdsize; |
923 |
|
924 |
break; |
925 |
case 0x41000200: |
926 |
//SysPrintf("unhandled cdrom dma3: madr: %x, bcr: %x, chcr %x\n", madr, bcr, chcr); |
927 |
return; |
928 |
|
929 |
default: |
930 |
CDVD_LOG("Unknown cddma %lx", chcr); |
931 |
break; |
932 |
} |
933 |
HW_DMA3_CHCR &= ~0x01000000; |
934 |
psxDmaInterrupt(3); |
935 |
} |
936 |
|
937 |
#ifdef ENABLE_NEW_IOPDMA |
938 |
s32 CALLBACK cdvdDmaRead(s32 channel, u32* data, u32 bytesLeft, u32* bytesProcessed) |
939 |
{ |
940 |
#ifdef ENABLE_NEW_IOPDMA_CDVD |
941 |
// hacked up from the code above |
942 |
|
943 |
if (cdr.Readed == 0) |
944 |
{ |
945 |
//CDVD_LOG("*** DMA 3 *** NOT READY"); |
946 |
wordsProcessed = 0; |
947 |
return 10000; |
948 |
} |
949 |
|
950 |
memcpy_fast(data, cdr.pTransfer, wordsLeft); |
951 |
//psxCpu->Clear(madr, cdsize/4); |
952 |
cdr.pTransfer+=wordsLeft; |
953 |
*wordsProcessed = wordsLeft; |
954 |
|
955 |
Console.WriteLn(Color_Black,"New IOP DMA handled CDVD DMA: channel %d, data %p, remaining %08x, processed %08x.", channel,data,wordsLeft, *wordsProcessed); |
956 |
#endif |
957 |
return 0; |
958 |
} |
959 |
|
960 |
void CALLBACK cdvdDmaInterrupt(s32 channel) |
961 |
{ |
962 |
#ifdef ENABLE_NEW_IOPDMA_CDVD |
963 |
cdrInterrupt(); |
964 |
#endif |
965 |
} |
966 |
|
967 |
#endif |
968 |
|
969 |
void cdrReset() { |
970 |
memzero(cdr); |
971 |
cdr.CurTrack=1; |
972 |
cdr.File=1; cdr.Channel=1; |
973 |
cdReadTime = (PSXCLK / 1757) * BIAS; |
974 |
} |
975 |
|
976 |
void SaveStateBase::cdrFreeze() |
977 |
{ |
978 |
FreezeTag( "cdrom" ); |
979 |
Freeze(cdr); |
980 |
} |
981 |
|