1 /******************************************************************************/
2 /* Mednafen Sony PS1 Emulation Module */
3 /******************************************************************************/
4 /* cdc.cpp:
5 ** Copyright (C) 2011-2018 Mednafen Team
6 **
7 ** This program is free software; you can redistribute it and/or
8 ** modify it under the terms of the GNU General Public License
9 ** as published by the Free Software Foundation; either version 2
10 ** of the License, or (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software Foundation, Inc.,
19 ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 */
21
22 // TODO: Test seekl to CD-DA, and seekl to beyond end of disc.
23
24 // TODO: Rewrite command processing to use switch() state machine madness, to handle some commands(like 0x0A) whose timing
25 // characteristics cannot be handled well with the current way. Be sure to test interruptability(with a new command) of the commands, too.
26
27 #pragma GCC optimize ("unroll-loops")
28
29 /*
30 Games to test after changing code affecting CD reading and buffering:
31 Bedlam (massive graphics corruption)
32 Rise 2 (massive graphics corruption)
33
34 Captain Commando (boss graphics corruption on first stage)
35 Gran Turismo (missing music; GetLocL must be valid and sector data must be ready simultaneous with clearing of status seek bit and setting of reading bit)
36 Harukanaru Toki no Naka de - Banjou Yuugi (needs GetLocL to reflect dancing around target seek position after seek completes; otherwise hangs on voice acting)
37 Incredible Crisis (needs GetLocL to be valid after a SeekL; otherwise hangs without music near start of "Etsuko and the Golden Pig")
38 Tomb Raider(needs GetLocP to reflect dancing around target seek position after seek completes; otherwise, CD-DA tracks at M:S:F=x:x:0 fail to play and game hangs)
39 Vib Ribbon, with extra audio CD
40 Mortal Kombat Trilogy, music resumption after pause.
41
42 Nightmare Creatures hangs during startup for some CD timing alignments/windows, and it spams command 0x0A without properly waiting for it to complete.
43 */
44
45 // TODO: async command counter and async command phase?
46 /*
47
48 TODO:
49 Implement missing commands.
50
51 SPU CD-DA and CD-XA streaming semantics.
52 */
53
54 /*
55 After eject(doesn't appear to occur when drive is in STOP state):
56 * Does not appear to occur in STOP state.
57 * Does not appear to occur in PAUSE state.
58 * DOES appear to occur in STANDBY state. (TODO: retest)
59
60 % Result 0: 16
61 % Result 1: 08
62 % IRQ Result: e5
63 % 19 e0
64
65 Command abortion tests(NOP tested):
66 Does not appear to occur when in STOP or PAUSE states(STOP or PAUSE command just executed).
67
68 DOES occur after a ReadTOC completes, if ReadTOC is not followed by a STOP or PAUSE. Odd.
69 */
70
71 #include "psx.h"
72 #include "cdc.h"
73 #include "spu.h"
74
75 using namespace CDUtility;
76
77 namespace MDFN_IEN_PSX
78 {
79
PS_CDC()80 PS_CDC::PS_CDC() : DMABuffer(4096)
81 {
82 IsPSXDisc = false;
83 Cur_CDIF = NULL;
84
85 DriveStatus = DS_STOPPED;
86 PendingCommandPhase = 0;
87 }
88
~PS_CDC()89 PS_CDC::~PS_CDC()
90 {
91
92 }
93
SetDisc(bool tray_open,CDInterface * cdif,const char * disc_id)94 void PS_CDC::SetDisc(bool tray_open, CDInterface* cdif, const char *disc_id)
95 {
96 if(tray_open)
97 cdif = NULL;
98
99 Cur_CDIF = cdif;
100 IsPSXDisc = false;
101 memset(DiscID, 0, sizeof(DiscID));
102
103 if(Cur_CDIF)
104 {
105 HeaderBufValid = false;
106 DiscStartupDelay = (int64)1000 * 33868800 / 1000;
107 DiscChanged = true;
108
109 Cur_CDIF->ReadTOC(&toc);
110
111 if(disc_id)
112 {
113 strncpy((char *)DiscID, disc_id, 4);
114 IsPSXDisc = true;
115 }
116 }
117 }
118
CalcNextEvent(void)119 int32 PS_CDC::CalcNextEvent(void)
120 {
121 int32 next_event = SPUCounter;
122
123 if(PSRCounter > 0 && next_event > PSRCounter)
124 next_event = PSRCounter;
125
126 if(PendingCommandCounter > 0 && next_event > PendingCommandCounter)
127 next_event = PendingCommandCounter;
128
129 if(!(IRQBuffer & 0xF))
130 {
131 if(CDCReadyReceiveCounter > 0 && next_event > CDCReadyReceiveCounter)
132 next_event = CDCReadyReceiveCounter;
133 }
134
135 if(DiscStartupDelay > 0 && next_event > DiscStartupDelay)
136 next_event = DiscStartupDelay;
137
138 //fprintf(stderr, "%d %d %d %d --- %d\n", PSRCounter, PendingCommandCounter, CDCReadyReceiveCounter, DiscStartupDelay, next_event);
139
140 return(next_event);
141 }
142
SoftReset(void)143 void PS_CDC::SoftReset(void)
144 {
145 ClearAudioBuffers();
146
147 // Not sure about initial volume state
148 Pending_DecodeVolume[0][0] = 0x80;
149 Pending_DecodeVolume[0][1] = 0x00;
150 Pending_DecodeVolume[1][0] = 0x00;
151 Pending_DecodeVolume[1][1] = 0x80;
152 memcpy(DecodeVolume, Pending_DecodeVolume, sizeof(DecodeVolume));
153
154 RegSelector = 0;
155 memset(ArgsBuf, 0, sizeof(ArgsBuf));
156 ArgsWP = ArgsRP = 0;
157
158 memset(ResultsBuffer, 0, sizeof(ResultsBuffer));
159 ResultsWP = 0;
160 ResultsRP = 0;
161 ResultsIn = 0;
162
163 CDCReadyReceiveCounter = 0;
164
165 IRQBuffer = 0;
166 IRQOutTestMask = 0;
167 RecalcIRQ();
168
169 DMABuffer.Flush();
170 SB_In = 0;
171 SectorPipe_Pos = SectorPipe_In = 0;
172 SectorsRead = 0;
173
174 memset(SubQBuf, 0, sizeof(SubQBuf));
175 memset(SubQBuf_Safe, 0, sizeof(SubQBuf_Safe));
176 SubQChecksumOK = false;
177
178 memset(HeaderBuf, 0, sizeof(HeaderBuf));
179
180
181 FilterFile = 0;
182 FilterChan = 0;
183
184 PendingCommand = 0;
185 PendingCommandPhase = 0;
186 PendingCommandCounter = 0;
187
188 Mode = 0x20;
189
190 HeaderBufValid = false;
191 SeekFinished = -1;
192 DriveStatus = DS_STOPPED;
193 ClearAIP();
194 StatusAfterSeek = DS_STOPPED;
195 SeekRetryCounter = 0;
196
197 Forward = false;
198 Backward = false;
199 Muted = false;
200
201 PlayTrackMatch = 0;
202
203 PSRCounter = 0;
204
205 CurSector = 0;
206
207 ClearAIP();
208
209 SeekTarget = 0;
210
211 CommandLoc = 0;
212 CommandLoc_Dirty = true;
213
214 DiscChanged = true;
215 }
216
Power(void)217 void PS_CDC::Power(void)
218 {
219 SPU->Power();
220
221 SoftReset();
222
223 HoldLogicalPos = false;
224
225 DiscStartupDelay = 0;
226
227 SPUCounter = SPU->UpdateFromCDC(0);
228 lastts = 0;
229 }
230
StateAction(StateMem * sm,const unsigned load,const bool data_only)231 void PS_CDC::StateAction(StateMem *sm, const unsigned load, const bool data_only)
232 {
233 SFORMAT StateRegs[] =
234 {
235 SFVAR(DiscChanged),
236 SFVAR(DiscStartupDelay),
237
238 SFVARN(AudioBuffer.Samples, "&AudioBuffer.Samples[0][0]"),
239 SFVAR(AudioBuffer.Size),
240 SFVAR(AudioBuffer.Freq),
241 SFVAR(AudioBuffer.ReadPos),
242
243 SFVARN(Pending_DecodeVolume, "&Pending_DecodeVolume[0][0]"),
244 SFVARN(DecodeVolume, "&DecodeVolume[0][0]"),
245
246 SFVARN(ADPCM_ResampBuf, "&ADPCM_ResampBuf[0][0]"),
247 SFVAR(ADPCM_ResampCurPhase),
248 SFVAR(ADPCM_ResampCurPos),
249
250
251
252 SFVAR(RegSelector),
253 SFVAR(ArgsBuf),
254 SFVAR(ArgsWP),
255 SFVAR(ArgsRP),
256
257 SFVAR(ArgsReceiveLatch),
258 SFVAR(ArgsReceiveBuf),
259 SFVAR(ArgsReceiveIn),
260
261 SFVAR(ResultsBuffer),
262 SFVAR(ResultsIn),
263 SFVAR(ResultsWP),
264 SFVAR(ResultsRP),
265
266 //
267 //
268 //
269 SFPTR8(&DMABuffer.data[0], DMABuffer.data.size()),
270 SFVAR(DMABuffer.read_pos),
271 SFVAR(DMABuffer.write_pos),
272 SFVAR(DMABuffer.in_count),
273 //
274 //
275 //
276
277 SFVAR(SB),
278 SFVAR(SB_In),
279
280 SFVARN(SectorPipe, "&SectorPipe[0][0]"),
281 SFVAR(SectorPipe_Pos),
282 SFVAR(SectorPipe_In),
283
284 SFVAR(SubQBuf),
285 SFVAR(SubQBuf_Safe),
286
287 SFVAR(SubQChecksumOK),
288
289 SFVAR(HeaderBufValid),
290 SFVAR(HeaderBuf),
291
292 SFVAR(IRQBuffer),
293 SFVAR(IRQOutTestMask),
294 SFVAR(CDCReadyReceiveCounter),
295
296
297 SFVAR(FilterFile),
298 SFVAR(FilterChan),
299
300 SFVAR(PendingCommand),
301 SFVAR(PendingCommandPhase),
302 SFVAR(PendingCommandCounter),
303
304 SFVAR(SPUCounter),
305
306 SFVAR(Mode),
307 SFVAR(DriveStatus),
308 SFVAR(StatusAfterSeek),
309 SFVAR(Forward),
310 SFVAR(Backward),
311 SFVAR(Muted),
312
313 SFVAR(PlayTrackMatch),
314
315 SFVAR(PSRCounter),
316
317 SFVAR(HoldLogicalPos),
318
319 SFVAR(CurSector),
320 SFVAR(SectorsRead),
321
322 SFVAR(AsyncIRQPending),
323 SFVAR(AsyncResultsPending),
324 SFVAR(AsyncResultsPendingCount),
325
326 SFVAR(SeekTarget),
327 SFVAR(SeekRetryCounter),
328 SFVAR(SeekFinished),
329
330 // FIXME: Save TOC stuff?
331 #if 0
332 CDUtility::TOC toc;
333 bool IsPSXDisc;
334 uint8 DiscID[4];
335 #endif
336
337 SFVAR(CommandLoc),
338 SFVAR(CommandLoc_Dirty),
339 SFVARN(xa_previous, "&xa_previous[0][0]"),
340
341 SFVAR(xa_cur_set),
342 SFVAR(xa_cur_file),
343 SFVAR(xa_cur_chan),
344
345 SFVAR(ReportLastF),
346 SFVAR(ReportStartupDelay),
347
348 SFEND
349 };
350
351 MDFNSS_StateAction(sm, load, data_only, StateRegs, "CDC");
352
353 if(load)
354 {
355 DMABuffer.SaveStatePostLoad();
356 SectorPipe_Pos %= SectorPipe_Count;
357
358 if(AudioBuffer.Size > sizeof(AudioBuffer.Samples[0]) / sizeof(AudioBuffer.Samples[0][0]))
359 AudioBuffer.Size = sizeof(AudioBuffer.Samples[0]) / sizeof(AudioBuffer.Samples[0][0]);
360
361 if(AudioBuffer.ReadPos > AudioBuffer.Size)
362 AudioBuffer.ReadPos = AudioBuffer.Size;
363
364 ResultsRP &= 0xF;
365 ResultsWP &= 0xF;
366 ResultsIn &= 0x1F;
367
368 ADPCM_ResampCurPos &= 0x1F;
369 ADPCM_ResampCurPhase %= 7;
370 }
371 }
372
ResetTS(void)373 void PS_CDC::ResetTS(void)
374 {
375 lastts = 0;
376 }
377
RecalcIRQ(void)378 void PS_CDC::RecalcIRQ(void)
379 {
380 IRQ_Assert(IRQ_CD, (bool)(IRQBuffer & (IRQOutTestMask & 0x1F)));
381 }
382
383 //static int32 doom_ts;
WriteIRQ(uint8 V)384 void PS_CDC::WriteIRQ(uint8 V)
385 {
386 assert(CDCReadyReceiveCounter <= 0);
387 assert(!(IRQBuffer & 0xF));
388
389 //PSX_WARNING("[CDC] ***IRQTHINGY: 0x%02x -- %u", V, doom_ts);
390
391 CDCReadyReceiveCounter = 2000; //1024;
392
393 IRQBuffer = (IRQBuffer & 0x10) | V;
394 RecalcIRQ();
395 }
396
BeginResults(void)397 void PS_CDC::BeginResults(void)
398 {
399 //if(ResultsIn)
400 // {
401 // printf("Cleared %d results. IRQBuffer=0x%02x\n", ResultsIn, IRQBuffer);
402 //}
403
404 ResultsIn = 0;
405 ResultsWP = 0;
406 ResultsRP = 0;
407
408 memset(ResultsBuffer, 0x00, sizeof(ResultsBuffer));
409 }
410
WriteResult(uint8 V)411 void PS_CDC::WriteResult(uint8 V)
412 {
413 ResultsBuffer[ResultsWP] = V;
414 ResultsWP = (ResultsWP + 1) & 0xF;
415 ResultsIn = (ResultsIn + 1) & 0x1F;
416
417 if(!ResultsIn)
418 PSX_WARNING("[CDC] Results buffer overflow!");
419 }
420
ReadResult(void)421 uint8 PS_CDC::ReadResult(void)
422 {
423 uint8 ret = ResultsBuffer[ResultsRP];
424
425 if(!ResultsIn)
426 PSX_WARNING("[CDC] Results buffer underflow!");
427
428 ResultsRP = (ResultsRP + 1) & 0xF;
429 ResultsIn = (ResultsIn - 1) & 0x1F;
430
431 return ret;
432 }
433
MakeStatus(bool cmd_error)434 uint8 PS_CDC::MakeStatus(bool cmd_error)
435 {
436 uint8 ret = 0;
437
438 // Are these bit positions right?
439
440 if(DriveStatus == DS_PLAYING)
441 ret |= 0x80;
442
443 if(DriveStatus == DS_READING)
444 ret |= 0x20;
445
446 if(DriveStatus == DS_SEEKING || DriveStatus == DS_SEEKING_LOGICAL || DriveStatus == DS_SEEKING_LOGICAL2)
447 ret |= 0x40;
448
449 if(!Cur_CDIF || DiscChanged)
450 ret |= 0x10;
451
452 if(DriveStatus != DS_STOPPED)
453 ret |= 0x02;
454
455 if(cmd_error)
456 ret |= 0x01;
457
458 DiscChanged = false; // FIXME: Only do it on NOP command execution?
459
460 return(ret);
461 }
462
DecodeSubQ(uint8 * subpw)463 bool PS_CDC::DecodeSubQ(uint8 *subpw)
464 {
465 uint8 tmp_q[0xC];
466
467 memset(tmp_q, 0, 0xC);
468
469 for(int i = 0; i < 96; i++)
470 tmp_q[i >> 3] |= ((subpw[i] & 0x40) >> 6) << (7 - (i & 7));
471
472 if((tmp_q[0] & 0xF) == 1)
473 {
474 memcpy(SubQBuf, tmp_q, 0xC);
475 SubQChecksumOK = subq_check_checksum(tmp_q);
476
477 if(SubQChecksumOK)
478 {
479 memcpy(SubQBuf_Safe, tmp_q, 0xC);
480 return(true);
481 }
482 }
483
484 return(false);
485 }
486
487 static const int16 CDADPCMImpulse[7][25] =
488 {
489 { 0, -5, 17, -35, 70, -23, -68, 347, -839, 2062, -4681, 15367, 21472, -5882, 2810, -1352, 635, -235, 26, 43, -35, 16, -8, 2, 0, }, /* 0 */
490 { 0, -2, 10, -34, 65, -84, 52, 9, -266, 1024, -2680, 9036, 26516, -6016, 3021, -1571, 848, -365, 107, 10, -16, 17, -8, 3, -1, }, /* 1 */
491 { -2, 0, 3, -19, 60, -75, 162, -227, 306, -67, -615, 3229, 29883, -4532, 2488, -1471, 882, -424, 166, -27, 5, 6, -8, 3, -1, }, /* 2 */
492 { -1, 3, -2, -5, 31, -74, 179, -402, 689, -926, 1272, -1446, 31033, -1446, 1272, -926, 689, -402, 179, -74, 31, -5, -2, 3, -1, }, /* 3 */
493 { -1, 3, -8, 6, 5, -27, 166, -424, 882, -1471, 2488, -4532, 29883, 3229, -615, -67, 306, -227, 162, -75, 60, -19, 3, 0, -2, }, /* 4 */
494 { -1, 3, -8, 17, -16, 10, 107, -365, 848, -1571, 3021, -6016, 26516, 9036, -2680, 1024, -266, 9, 52, -84, 65, -34, 10, -2, 0, }, /* 5 */
495 { 0, 2, -8, 16, -35, 43, 26, -235, 635, -1352, 2810, -5882, 21472, 15367, -4681, 2062, -839, 347, -68, -23, 70, -35, 17, -5, 0, }, /* 6 */
496 };
497
ReadAudioBuffer(int32 samples[2])498 void PS_CDC::ReadAudioBuffer(int32 samples[2])
499 {
500 samples[0] = AudioBuffer.Samples[0][AudioBuffer.ReadPos];
501 samples[1] = AudioBuffer.Samples[1][AudioBuffer.ReadPos];
502
503 AudioBuffer.ReadPos++;
504 }
505
ApplyVolume(int32 samples[2])506 INLINE void PS_CDC::ApplyVolume(int32 samples[2])
507 {
508 //
509 // Take care not to alter samples[] before we're done calculating the new output samples!
510 //
511 int32 left_out = ((samples[0] * DecodeVolume[0][0]) >> 7) + ((samples[1] * DecodeVolume[1][0]) >> 7);
512 int32 right_out = ((samples[0] * DecodeVolume[0][1]) >> 7) + ((samples[1] * DecodeVolume[1][1]) >> 7);
513
514 clamp(&left_out, -32768, 32767);
515 clamp(&right_out, -32768, 32767);
516
517 if(Muted)
518 {
519 left_out = 0;
520 right_out = 0;
521 }
522
523 samples[0] = left_out;
524 samples[1] = right_out;
525 }
526
527 //
528 // This function must always set samples[0] and samples[1], even if just to 0; range of samples[n] shall be restricted to -32768 through 32767.
529 //
GetCDAudio(int32 samples[2])530 void PS_CDC::GetCDAudio(int32 samples[2])
531 {
532 const unsigned freq = (AudioBuffer.ReadPos < AudioBuffer.Size) ? AudioBuffer.Freq : 0;
533
534 samples[0] = 0;
535 samples[1] = 0;
536
537 if(!freq)
538 return;
539
540 if(freq == 7 || freq == 14)
541 {
542 ReadAudioBuffer(samples);
543 if(freq == 14)
544 ReadAudioBuffer(samples);
545 }
546 else
547 {
548 int32 out_tmp[2] = { 0, 0 };
549
550 for(unsigned i = 0; i < 2; i++)
551 {
552 const int16* imp = CDADPCMImpulse[ADPCM_ResampCurPhase];
553 int16* wf = &ADPCM_ResampBuf[i][(ADPCM_ResampCurPos + 32 - 25) & 0x1F];
554
555 for(unsigned s = 0; s < 25; s++)
556 {
557 out_tmp[i] += imp[s] * wf[s];
558 }
559
560 out_tmp[i] >>= 15;
561 clamp(&out_tmp[i], -32768, 32767);
562 samples[i] = out_tmp[i];
563 }
564
565 ADPCM_ResampCurPhase += freq;
566
567 if(ADPCM_ResampCurPhase >= 7)
568 {
569 int32 raw[2] = { 0, 0 };
570
571 ADPCM_ResampCurPhase -= 7;
572 ReadAudioBuffer(raw);
573
574 for(unsigned i = 0; i < 2; i++)
575 {
576 ADPCM_ResampBuf[i][ADPCM_ResampCurPos + 0] =
577 ADPCM_ResampBuf[i][ADPCM_ResampCurPos + 32] = raw[i];
578 }
579 ADPCM_ResampCurPos = (ADPCM_ResampCurPos + 1) & 0x1F;
580 }
581 }
582
583 //
584 // Algorithmically, volume is applied after resampling for CD-XA ADPCM playback, per PS1 tests(though when "mute" is applied wasn't tested).
585 //
586 ApplyVolume(samples);
587 }
588
589
590 struct XA_Subheader
591 {
592 uint8 file;
593 uint8 channel;
594 uint8 submode;
595 uint8 coding;
596
597 uint8 file_dup;
598 uint8 channel_dup;
599 uint8 submode_dup;
600 uint8 coding_dup;
601 };
602 static_assert(sizeof(XA_Subheader) == 8, "XA_Subheader wrong size!");
603
604 struct XA_SoundGroup
605 {
606 uint8 params[16];
607 uint8 samples[112];
608 };
609 static_assert(sizeof(XA_SoundGroup) == 128, "XA_SoundGroup wrong size!");
610
611 #define XA_SUBMODE_EOF 0x80
612 #define XA_SUBMODE_REALTIME 0x40
613 #define XA_SUBMODE_FORM 0x20
614 #define XA_SUBMODE_TRIGGER 0x10
615 #define XA_SUBMODE_DATA 0x08
616 #define XA_SUBMODE_AUDIO 0x04
617 #define XA_SUBMODE_VIDEO 0x02
618 #define XA_SUBMODE_EOR 0x01
619
620 #define XA_CODING_EMPHASIS 0x40
621
622 //#define XA_CODING_BPS_MASK 0x30
623 //#define XA_CODING_BPS_4BIT 0x00
624 //#define XA_CODING_BPS_8BIT 0x10
625 //#define XA_CODING_SR_MASK 0x0C
626 //#define XA_CODING_SR_378 0x00
627 //#define XA_CODING_SR_
628
629 #define XA_CODING_8BIT 0x10
630 #define XA_CODING_189 0x04
631 #define XA_CODING_STEREO 0x01
632
633 // Special regression prevention test cases:
634 // Um Jammer Lammy (start doing poorly)
635 // Yarudora Series Vol.1 - Double Cast (non-FMV speech)
636
XA_Test(const uint8 * sdata)637 bool PS_CDC::XA_Test(const uint8 *sdata)
638 {
639 const XA_Subheader *sh = (const XA_Subheader *)&sdata[12 + 4];
640
641 if(!(Mode & MODE_STRSND))
642 return false;
643
644 if(!(sh->submode & XA_SUBMODE_AUDIO))
645 return false;
646
647 //printf("Test File: 0x%02x 0x%02x - Channel: 0x%02x 0x%02x - Submode: 0x%02x 0x%02x - Coding: 0x%02x 0x%02x - \n", sh->file, sh->file_dup, sh->channel, sh->channel_dup, sh->submode, sh->submode_dup, sh->coding, sh->coding_dup);
648
649 if((Mode & MODE_SF) && (sh->file != FilterFile || sh->channel != FilterChan))
650 return false;
651
652 if(!xa_cur_set || (Mode & MODE_SF))
653 {
654 xa_cur_set = true;
655 xa_cur_file = sh->file;
656 xa_cur_chan = sh->channel;
657 }
658 else if(sh->file != xa_cur_file || sh->channel != xa_cur_chan)
659 return false;
660
661 if(sh->submode & XA_SUBMODE_EOF)
662 {
663 //puts("YAY");
664 xa_cur_set = false;
665 xa_cur_file = 0;
666 xa_cur_chan = 0;
667 }
668
669 return true;
670 }
671
ClearAudioBuffers(void)672 void PS_CDC::ClearAudioBuffers(void)
673 {
674 memset(&AudioBuffer, 0, sizeof(AudioBuffer));
675 memset(xa_previous, 0, sizeof(xa_previous));
676
677 xa_cur_set = false;
678 xa_cur_file = 0;
679 xa_cur_chan = 0;
680
681 memset(ADPCM_ResampBuf, 0, sizeof(ADPCM_ResampBuf));
682 ADPCM_ResampCurPhase = 0;
683 ADPCM_ResampCurPos = 0;
684 }
685
686 //
687 // output should be readable at -2 and -1
DecodeXAADPCM(const uint8 * input,int16 * output,const unsigned shift,const unsigned weight)688 static void DecodeXAADPCM(const uint8 *input, int16 *output, const unsigned shift, const unsigned weight)
689 {
690 // Weights copied over from SPU channel ADPCM playback code, may not be entirely the same for CD-XA ADPCM, we need to run tests.
691 static const int32 Weights[16][2] =
692 {
693 // s-1 s-2
694 { 0, 0 },
695 { 60, 0 },
696 { 115, -52 },
697 { 98, -55 },
698 { 122, -60 },
699 };
700
701 for(int i = 0; i < 28; i++)
702 {
703 int32 sample;
704
705 sample = (int16)(input[i] << 8);
706 sample >>= shift;
707
708 sample += ((output[i - 1] * Weights[weight][0]) >> 6) + ((output[i - 2] * Weights[weight][1]) >> 6);
709
710 if(sample < -32768)
711 sample = -32768;
712
713 if(sample > 32767)
714 sample = 32767;
715
716 output[i] = sample;
717 }
718 }
719
XA_ProcessSector(const uint8 * sdata,CD_Audio_Buffer * ab)720 void PS_CDC::XA_ProcessSector(const uint8 *sdata, CD_Audio_Buffer *ab)
721 {
722 const XA_Subheader *sh = (const XA_Subheader *)&sdata[12 + 4];
723 const unsigned unit_index_shift = (sh->coding & XA_CODING_8BIT) ? 0 : 1;
724
725 //printf("File: 0x%02x 0x%02x - Channel: 0x%02x 0x%02x - Submode: 0x%02x 0x%02x - Coding: 0x%02x 0x%02x - \n", sh->file, sh->file_dup, sh->channel, sh->channel_dup, sh->submode, sh->submode_dup, sh->coding, sh->coding_dup);
726 ab->ReadPos = 0;
727 ab->Size = 18 * (4 << unit_index_shift) * 28;
728
729 if(sh->coding & XA_CODING_STEREO)
730 ab->Size >>= 1;
731
732 ab->Freq = (sh->coding & XA_CODING_189) ? 3 : 6;
733
734 //fprintf(stderr, "Coding: %02x %02x\n", sh->coding, sh->coding_dup);
735
736 for(unsigned group = 0; group < 18; group++)
737 {
738 const XA_SoundGroup *sg = (const XA_SoundGroup *)&sdata[12 + 4 + 8 + group * 128];
739
740 for(unsigned unit = 0; unit < (4U << unit_index_shift); unit++)
741 {
742 const uint8 param = sg->params[(unit & 3) | ((unit & 4) << 1)];
743 const uint8 param_copy = sg->params[4 | (unit & 3) | ((unit & 4) << 1)];
744 uint8 ibuffer[28];
745 int16 obuffer[2 + 28];
746
747 if(param != param_copy)
748 {
749 PSX_WARNING("[CDC] CD-XA param != param_copy --- %d %02x %02x\n", unit, param, param_copy);
750 }
751
752 for(unsigned i = 0; i < 28; i++)
753 {
754 uint8 tmp = sg->samples[i * 4 + (unit >> unit_index_shift)];
755
756 if(unit_index_shift)
757 {
758 tmp <<= (unit & 1) ? 0 : 4;
759 tmp &= 0xf0;
760 }
761
762 ibuffer[i] = tmp;
763 }
764
765 const bool ocn = (bool)(unit & 1) && (sh->coding & XA_CODING_STEREO);
766
767 obuffer[0] = xa_previous[ocn][0];
768 obuffer[1] = xa_previous[ocn][1];
769
770 DecodeXAADPCM(ibuffer, &obuffer[2], param & 0x0F, param >> 4);
771
772 xa_previous[ocn][0] = obuffer[28];
773 xa_previous[ocn][1] = obuffer[29];
774
775 if(param != param_copy)
776 memset(obuffer, 0, sizeof(obuffer));
777
778 if(sh->coding & XA_CODING_STEREO)
779 {
780 for(unsigned s = 0; s < 28; s++)
781 {
782 ab->Samples[ocn][group * (2 << unit_index_shift) * 28 + (unit >> 1) * 28 + s] = obuffer[2 + s];
783 }
784 }
785 else
786 {
787 for(unsigned s = 0; s < 28; s++)
788 {
789 ab->Samples[0][group * (4 << unit_index_shift) * 28 + unit * 28 + s] = obuffer[2 + s];
790 ab->Samples[1][group * (4 << unit_index_shift) * 28 + unit * 28 + s] = obuffer[2 + s];
791 }
792 }
793 }
794 }
795
796 #if 0
797 // Test
798 for(unsigned i = 0; i < ab->Size; i++)
799 {
800 static unsigned counter = 0;
801
802 ab->Samples[0][i] = (counter & 2) ? -0x6000 : 0x6000;
803 ab->Samples[1][i] = rand();
804 counter++;
805 }
806 #endif
807 }
808
ClearAIP(void)809 void PS_CDC::ClearAIP(void)
810 {
811 AsyncResultsPendingCount = 0;
812 AsyncIRQPending = 0;
813 }
814
CheckAIP(void)815 void PS_CDC::CheckAIP(void)
816 {
817 if(AsyncIRQPending && CDCReadyReceiveCounter <= 0)
818 {
819 BeginResults();
820
821 for(unsigned i = 0; i < AsyncResultsPendingCount; i++)
822 WriteResult(AsyncResultsPending[i]);
823
824 WriteIRQ(AsyncIRQPending);
825
826 ClearAIP();
827 }
828 }
829
SetAIP(unsigned irq,unsigned result_count,uint8 * r)830 void PS_CDC::SetAIP(unsigned irq, unsigned result_count, uint8 *r)
831 {
832 if(AsyncIRQPending)
833 {
834 PSX_WARNING("***WARNING*** Previous notification skipped: CurSector=%d, old_notification=0x%02x", CurSector, AsyncIRQPending);
835 }
836 ClearAIP();
837
838 AsyncResultsPendingCount = result_count;
839
840 for(unsigned i = 0; i < result_count; i++)
841 AsyncResultsPending[i] = r[i];
842
843 AsyncIRQPending = irq;
844
845 CheckAIP();
846 }
847
SetAIP(unsigned irq,uint8 result0)848 void PS_CDC::SetAIP(unsigned irq, uint8 result0)
849 {
850 uint8 tr[1] = { result0 };
851 SetAIP(irq, 1, tr);
852 }
853
SetAIP(unsigned irq,uint8 result0,uint8 result1)854 void PS_CDC::SetAIP(unsigned irq, uint8 result0, uint8 result1)
855 {
856 uint8 tr[2] = { result0, result1 };
857 SetAIP(irq, 2, tr);
858 }
859
860
EnbufferizeCDDASector(const uint8 * buf)861 void PS_CDC::EnbufferizeCDDASector(const uint8 *buf)
862 {
863 CD_Audio_Buffer *ab = &AudioBuffer;
864
865 ab->Freq = 7 * ((Mode & MODE_SPEED) ? 2 : 1);
866 ab->Size = 588;
867
868 if(SubQBuf_Safe[0] & 0x40)
869 {
870 for(int i = 0; i < 588; i++)
871 {
872 ab->Samples[0][i] = 0;
873 ab->Samples[1][i] = 0;
874 }
875 }
876 else
877 {
878 for(int i = 0; i < 588; i++)
879 {
880 ab->Samples[0][i] = (int16)MDFN_de16lsb(&buf[i * sizeof(int16) * 2 + 0]);
881 ab->Samples[1][i] = (int16)MDFN_de16lsb(&buf[i * sizeof(int16) * 2 + 2]);
882 }
883 }
884
885 ab->ReadPos = 0;
886 }
887
HandlePlayRead(void)888 void PS_CDC::HandlePlayRead(void)
889 {
890 uint8 read_buf[2352 + 96];
891
892 //PSX_WARNING("Read sector: %d", CurSector);
893
894 if(CurSector >= ((int32)toc.tracks[100].lba + 300) && CurSector >= (75 * 60 * 75 - 150))
895 {
896 PSX_WARNING("[CDC] Read/Play position waaay too far out(%u), forcing STOP", CurSector);
897 SeekFinished = -1;
898 DriveStatus = DS_STOPPED;
899 SectorPipe_Pos = SectorPipe_In = 0;
900 SectorsRead = 0;
901 return;
902 }
903
904 if(CurSector >= (int32)toc.tracks[100].lba)
905 {
906 PSX_WARNING("[CDC] In leadout area: %u", CurSector);
907 }
908
909 Cur_CDIF->ReadRawSector(read_buf, CurSector); // FIXME: error out on error.
910 DecodeSubQ(read_buf + 2352);
911
912 if(SubQBuf_Safe[1] == 0xAA && (DriveStatus == DS_PLAYING || (DriveStatus == DS_READING && !(SubQBuf_Safe[0] & 0x40) && (Mode & MODE_CDDA))))
913 {
914 HeaderBufValid = false;
915
916 PSX_WARNING("[CDC] CD-DA leadout reached: %u", CurSector);
917
918 // Status in this end-of-disc context here should be generated after we're in the pause state.
919 SeekTarget = CurSector;
920 DriveStatus = DS_PAUSED;
921 SectorPipe_Pos = SectorPipe_In = 0;
922 SectorsRead = 0;
923 SetAIP(CDCIRQ_DATA_END, MakeStatus());
924
925 return;
926 }
927
928 if(DriveStatus == DS_PLAYING)
929 {
930 if(Mode & MODE_AUTOPAUSE)
931 {
932 // Note: Some game(s) start playing in the pregap of a track(so don't replace this with a simple subq index == 0 check for autopause).
933 // Pitball enables autopause a while after playing starts.
934 //
935 if(PlayTrackMatch == -1 && SubQChecksumOK)
936 PlayTrackMatch = SubQBuf_Safe[0x1];
937
938 if(PlayTrackMatch != -1 && SubQBuf_Safe[0x1] != PlayTrackMatch)
939 {
940 // Status needs to be taken before we're paused(IE it should still report playing).
941 SetAIP(CDCIRQ_DATA_END, MakeStatus());
942
943 SeekTarget = CurSector;
944 DriveStatus = DS_PAUSED;
945 SectorPipe_Pos = SectorPipe_In = 0;
946 SectorsRead = 0;
947 PSRCounter = 0;
948 return;
949 }
950 }
951
952 if((Mode & MODE_REPORT) && ReportStartupDelay <= 0 && (((SubQBuf_Safe[0x9] >> 4) != ReportLastF) || Forward || Backward) && SubQChecksumOK)
953 {
954 uint8 tr[8];
955 uint16 abs_lev_max = 0;
956 bool abs_lev_chselect = SubQBuf_Safe[0x8] & 0x01;
957
958 for(int i = 0; i < 588; i++)
959 abs_lev_max = std::max<uint16>(abs_lev_max, std::min<int>(abs((int16)MDFN_de16lsb(&read_buf[i * 4 + (abs_lev_chselect * 2)])), 32767));
960 abs_lev_max |= abs_lev_chselect << 15;
961
962 tr[0] = MakeStatus();
963 tr[1] = SubQBuf_Safe[0x1]; // Track
964 tr[2] = SubQBuf_Safe[0x2]; // Index
965
966 if(SubQBuf_Safe[0x9] & 0x10)
967 {
968 tr[3] = SubQBuf_Safe[0x3]; // R M
969 tr[4] = SubQBuf_Safe[0x4] | 0x80; // R S
970 tr[5] = SubQBuf_Safe[0x5]; // R F
971 }
972 else
973 {
974 tr[3] = SubQBuf_Safe[0x7]; // A M
975 tr[4] = SubQBuf_Safe[0x8]; // A S
976 tr[5] = SubQBuf_Safe[0x9]; // A F
977 }
978
979 tr[6] = abs_lev_max >> 0;
980 tr[7] = abs_lev_max >> 8;
981
982 SetAIP(CDCIRQ_DATA_READY, 8, tr);
983 }
984 ReportLastF = SubQBuf_Safe[0x9] >> 4;
985 }
986
987 if(SectorPipe_In >= SectorPipe_Count)
988 {
989 uint8* buf = SectorPipe[SectorPipe_Pos];
990 SectorPipe_In--;
991
992 if(SubQBuf_Safe[0] & 0x40) // Data sector
993 {
994 if(DriveStatus == DS_SEEKING_LOGICAL2 || DriveStatus == DS_READING || (HoldLogicalPos && (DriveStatus == DS_PAUSED || DriveStatus == DS_STANDBY)))
995 {
996 memcpy(HeaderBuf, buf + 12, 12);
997 HeaderBufValid = true;
998
999 if(DriveStatus == DS_SEEKING_LOGICAL2)
1000 {
1001 if(AMSF_to_LBA(BCD_to_U8(HeaderBuf[0]), BCD_to_U8(HeaderBuf[1]), BCD_to_U8(HeaderBuf[2])) == SeekTarget)
1002 {
1003 //puts("Logical2 seek finished");
1004 DriveStatus = StatusAfterSeek;
1005 SeekFinished = true;
1006 ReportStartupDelay = 24000000;
1007 }
1008 else
1009 {
1010 if(!SeekRetryCounter)
1011 {
1012 HoldLogicalPos = false;
1013 DriveStatus = DS_STANDBY;
1014 SeekFinished = -1;
1015 }
1016 else
1017 SeekRetryCounter--;
1018 }
1019 }
1020 }
1021 //
1022 //
1023 //
1024 //printf("%d, %02x:%02x:%02x --- %d %d\n", DriveStatus, HeaderBuf[0], HeaderBuf[1], HeaderBuf[2], SeekTarget, AMSF_to_LBA(BCD_to_U8(HeaderBuf[0]), BCD_to_U8(HeaderBuf[1]), BCD_to_U8(HeaderBuf[2])));
1025
1026 if(DriveStatus == DS_READING)
1027 {
1028 if((Mode & MODE_STRSND) && (buf[12 + 3] == 0x2) && ((buf[12 + 6] & 0x64) == 0x64))
1029 {
1030 if(XA_Test(buf))
1031 {
1032 if(AudioBuffer.ReadPos < AudioBuffer.Size)
1033 {
1034 PSX_WARNING("[CDC] CD-XA ADPCM sector skipped - readpos=0x%04x, size=0x%04x", AudioBuffer.ReadPos, AudioBuffer.Size);
1035 }
1036 else
1037 {
1038 XA_ProcessSector(buf, &AudioBuffer);
1039 }
1040 }
1041 }
1042 else
1043 {
1044 // maybe if(!(Mode & 0x30)) too?
1045 if(!(buf[12 + 6] & 0x20))
1046 {
1047 if(!edc_lec_check_and_correct(buf, true))
1048 {
1049 MDFN_Notify(MDFN_NOTICE_WARNING, _("Uncorrectable error(s) in sector %d."), CurSector);
1050 }
1051 }
1052
1053 if(!(Mode & 0x30) && (buf[12 + 6] & 0x20))
1054 PSX_WARNING("[CDC] BORK: %d", CurSector);
1055
1056 int32 offs = (Mode & 0x20) ? 0 : 12;
1057 int32 size = (Mode & 0x20) ? 2340 : 2048;
1058
1059 if(Mode & 0x10)
1060 {
1061 offs = 12;
1062 size = 2328;
1063 }
1064
1065 memcpy(SB, buf + 12 + offs, size);
1066 SB_In = size;
1067 SetAIP(CDCIRQ_DATA_READY, MakeStatus());
1068 }
1069 }
1070 }
1071 else // CD-DA sector
1072 {
1073 if(DriveStatus == DS_SEEKING_LOGICAL2)
1074 {
1075 if(Mode & MODE_CDDA)
1076 {
1077 DriveStatus = StatusAfterSeek;
1078 SeekFinished = true;
1079 ReportStartupDelay = 24000000;
1080 }
1081 else
1082 {
1083 if(!SeekRetryCounter)
1084 {
1085 HoldLogicalPos = false;
1086 DriveStatus = DS_STANDBY;
1087 SeekFinished = -1;
1088 }
1089 else
1090 SeekRetryCounter--;
1091 }
1092 }
1093 //
1094 //
1095 //
1096 if((DriveStatus == DS_READING && (Mode & MODE_CDDA)) || DriveStatus == DS_PLAYING)
1097 {
1098 if(AudioBuffer.ReadPos < AudioBuffer.Size)
1099 {
1100 PSX_WARNING("[CDC] BUG CDDA buffer full");
1101 }
1102 else
1103 {
1104 EnbufferizeCDDASector(buf);
1105 }
1106 }
1107 }
1108 }
1109
1110 memcpy(SectorPipe[SectorPipe_Pos], read_buf, 2352);
1111 SectorPipe_Pos = (SectorPipe_Pos + 1) % SectorPipe_Count;
1112 SectorPipe_In++;
1113
1114 PSRCounter += 33868800 / (75 * ((Mode & MODE_SPEED) ? 2 : 1));
1115
1116 if(DriveStatus == DS_PLAYING)
1117 {
1118 // FIXME: What's the real fast-forward and backward speed?
1119 if(Forward)
1120 CurSector += 12;
1121 else if(Backward)
1122 {
1123 CurSector -= 12;
1124
1125 if(CurSector < 0) // FIXME: How does a real PS handle this condition?
1126 CurSector = 0;
1127 }
1128 else
1129 CurSector++;
1130 }
1131 else
1132 CurSector++;
1133
1134 if(DriveStatus == DS_PAUSED || DriveStatus == DS_STANDBY) // || DriveStatus == DS_SEEKING_LOGICAL2)
1135 {
1136 if(CurSector >= (SeekTarget + 2))
1137 CurSector = std::max<int32>(-150, CurSector - 9);
1138 }
1139 else
1140 SectorsRead++;
1141 }
1142
Update(const pscpu_timestamp_t timestamp)1143 pscpu_timestamp_t PS_CDC::Update(const pscpu_timestamp_t timestamp)
1144 {
1145 int32 clocks = timestamp - lastts;
1146
1147 if(!Cur_CDIF)
1148 {
1149 if(DriveStatus != DS_STOPPED || (PendingCommandCounter > 0 && PendingCommandPhase >= 2))
1150 {
1151 SetAIP(CDCIRQ_DISC_ERROR, (MakeStatus() & ~0xE0) | 0x04, 0x08);
1152
1153 SectorPipe_Pos = SectorPipe_In = 0;
1154 SectorsRead = 0;
1155 HeaderBufValid = false;
1156 SeekFinished = -1;
1157
1158 DriveStatus = DS_STOPPED;
1159 PSRCounter = 0;
1160
1161 if(PendingCommandPhase >= 2)
1162 {
1163 PendingCommand = 0x00;
1164 PendingCommandCounter = 0;
1165 PendingCommandPhase = 0;
1166 }
1167 }
1168
1169 DiscStartupDelay = 0;
1170 }
1171 //
1172 //
1173 //
1174 while(clocks > 0)
1175 {
1176 int32 chunk_clocks = clocks;
1177
1178 if(PSRCounter > 0 && chunk_clocks > PSRCounter)
1179 chunk_clocks = PSRCounter;
1180
1181 if(PendingCommandCounter > 0 && chunk_clocks > PendingCommandCounter)
1182 chunk_clocks = PendingCommandCounter;
1183
1184 if(chunk_clocks > SPUCounter)
1185 chunk_clocks = SPUCounter;
1186
1187 if(DiscStartupDelay > 0)
1188 {
1189 if(chunk_clocks > DiscStartupDelay)
1190 chunk_clocks = DiscStartupDelay;
1191
1192 DiscStartupDelay -= chunk_clocks;
1193
1194 if(DiscStartupDelay <= 0)
1195 {
1196 SeekTarget = CurSector;
1197 HoldLogicalPos = false;
1198 DriveStatus = DS_PAUSED; // or is it supposed to be DS_STANDBY?
1199 }
1200 }
1201
1202 //MDFN_DispMessage("%02x %d -- %d %d -- %02x", IRQBuffer, CDCReadyReceiveCounter, PSRCounter, PendingCommandCounter, PendingCommand);
1203
1204 if(!(IRQBuffer & 0xF))
1205 {
1206 if(CDCReadyReceiveCounter > 0 && chunk_clocks > CDCReadyReceiveCounter)
1207 chunk_clocks = CDCReadyReceiveCounter;
1208
1209 if(CDCReadyReceiveCounter > 0)
1210 CDCReadyReceiveCounter -= chunk_clocks;
1211 }
1212
1213 CheckAIP();
1214
1215 if(PSRCounter > 0)
1216 {
1217 PSRCounter -= chunk_clocks;
1218
1219 if(ReportStartupDelay > 0)
1220 ReportStartupDelay -= chunk_clocks;
1221
1222 if(PSRCounter <= 0)
1223 {
1224 if(DriveStatus == DS_SEEKING)
1225 {
1226 CurSector = SeekTarget;
1227
1228 HoldLogicalPos = false;
1229 DriveStatus = StatusAfterSeek;
1230 SeekFinished = true;
1231 ReportStartupDelay = 24000000;
1232
1233 PSRCounter = 33868800 / (75 * ((Mode & MODE_SPEED) ? 2 : 1));
1234 }
1235 else if(DriveStatus == DS_SEEKING_LOGICAL)
1236 {
1237 CurSector = SeekTarget;
1238
1239 HoldLogicalPos = true;
1240 DriveStatus = DS_SEEKING_LOGICAL2;
1241 }
1242 //
1243 //
1244 //
1245 if(DriveStatus == DS_PAUSED || DriveStatus == DS_STANDBY || DriveStatus == DS_READING || DriveStatus == DS_PLAYING || DriveStatus == DS_SEEKING_LOGICAL2)
1246 {
1247 HandlePlayRead();
1248 }
1249 }
1250 }
1251
1252 if(PendingCommandCounter > 0)
1253 {
1254 PendingCommandCounter -= chunk_clocks;
1255
1256 if(PendingCommandCounter <= 0 && CDCReadyReceiveCounter > 0)
1257 {
1258 PendingCommandCounter = CDCReadyReceiveCounter; //256;
1259 }
1260 //else if(PendingCommandCounter <= 0 && PSRCounter > 0 && PSRCounter < 2000)
1261 //{
1262 // PendingCommandCounter = PSRCounter + 1;
1263 //}
1264 else if(PendingCommandCounter <= 0)
1265 {
1266 int32 next_time = 0;
1267
1268 if(PendingCommandPhase == -1)
1269 {
1270 if(ArgsRP != ArgsWP)
1271 {
1272 ArgsReceiveLatch = ArgsBuf[ArgsRP & 0x0F];
1273 ArgsRP = (ArgsRP + 1) & 0x1F;
1274 PendingCommandPhase += 1;
1275 next_time = 1815;
1276 }
1277 else
1278 {
1279 PendingCommandPhase += 2;
1280 next_time = 8500;
1281 }
1282 }
1283 else if(PendingCommandPhase == 0) // Command phase 0
1284 {
1285 if(ArgsReceiveIn < 32)
1286 ArgsReceiveBuf[ArgsReceiveIn++] = ArgsReceiveLatch;
1287
1288 if(ArgsRP != ArgsWP)
1289 {
1290 ArgsReceiveLatch = ArgsBuf[ArgsRP & 0x0F];
1291 ArgsRP = (ArgsRP + 1) & 0x1F;
1292 next_time = 1815;
1293 }
1294 else
1295 {
1296 PendingCommandPhase++;
1297 next_time = 8500;
1298 }
1299 }
1300 else if(PendingCommandPhase >= 2) // Command phase 2+
1301 {
1302 BeginResults();
1303
1304 const CDC_CTEntry *command = &Commands[PendingCommand];
1305
1306 next_time = (this->*(command->func2))();
1307 }
1308 else // Command phase 1
1309 {
1310 if(PendingCommand >= 0x20 || !Commands[PendingCommand].func)
1311 {
1312 BeginResults();
1313
1314 PSX_WARNING("[CDC] Unknown command: 0x%02x", PendingCommand);
1315
1316 WriteResult(MakeStatus(true));
1317 WriteResult(ERRCODE_BAD_COMMAND);
1318 WriteIRQ(CDCIRQ_DISC_ERROR);
1319 }
1320 else if(ArgsReceiveIn < Commands[PendingCommand].args_min || ArgsReceiveIn > Commands[PendingCommand].args_max)
1321 {
1322 BeginResults();
1323
1324 PSX_DBG(PSX_DBG_WARNING, "[CDC] Bad number(%d) of args(first check) for command 0x%02x", ArgsReceiveIn, PendingCommand);
1325 for(unsigned int i = 0; i < ArgsReceiveIn; i++)
1326 PSX_DBG(PSX_DBG_WARNING, " 0x%02x", ArgsReceiveBuf[i]);
1327 PSX_DBG(PSX_DBG_WARNING, "\n");
1328
1329 WriteResult(MakeStatus(true));
1330 WriteResult(ERRCODE_BAD_NUMARGS);
1331 WriteIRQ(CDCIRQ_DISC_ERROR);
1332 }
1333 else
1334 {
1335 BeginResults();
1336
1337 const CDC_CTEntry *command = &Commands[PendingCommand];
1338
1339 PSX_DBG(PSX_DBG_SPARSE, "[CDC] Command: %s --- ", command->name);
1340 for(unsigned int i = 0; i < ArgsReceiveIn; i++)
1341 PSX_DBG(PSX_DBG_SPARSE, " 0x%02x", ArgsReceiveBuf[i]);
1342 PSX_DBG(PSX_DBG_SPARSE, "\n");
1343
1344 next_time = (this->*(command->func))(ArgsReceiveIn, ArgsReceiveBuf);
1345 PendingCommandPhase = 2;
1346 }
1347 ArgsReceiveIn = 0;
1348 } // end command phase 1
1349
1350 if(!next_time)
1351 PendingCommandCounter = 0;
1352 else
1353 PendingCommandCounter += next_time;
1354 }
1355 }
1356
1357 SPUCounter = SPU->UpdateFromCDC(chunk_clocks);
1358
1359 clocks -= chunk_clocks;
1360 } // end while(clocks > 0)
1361
1362 lastts = timestamp;
1363
1364 return(timestamp + CalcNextEvent());
1365 }
1366
Write(const pscpu_timestamp_t timestamp,uint32 A,uint8 V)1367 void PS_CDC::Write(const pscpu_timestamp_t timestamp, uint32 A, uint8 V)
1368 {
1369 A &= 0x3;
1370
1371 //printf("Write: %08x %02x\n", A, V);
1372
1373 if(A == 0x00)
1374 {
1375 RegSelector = V & 0x3;
1376 }
1377 else
1378 {
1379 const unsigned reg_index = ((RegSelector & 0x3) * 3) + (A - 1);
1380
1381 Update(timestamp);
1382 //PSX_WARNING("[CDC] Write to register 0x%02x: 0x%02x @ %d --- 0x%02x 0x%02x\n", reg_index, V, timestamp, DMABuffer.CanRead(), IRQBuffer);
1383
1384 switch(reg_index)
1385 {
1386 default:
1387 PSX_WARNING("[CDC] Unknown write to register 0x%02x: 0x%02x\n", reg_index, V);
1388 break;
1389
1390 case 0x00:
1391 if(PendingCommandCounter > 0)
1392 {
1393 PSX_WARNING("[CDC] WARNING: Interrupting command 0x%02x, phase=%d, timeleft=%d with command=0x%02x", PendingCommand, PendingCommandPhase,
1394 PendingCommandCounter, V);
1395 }
1396
1397 if(IRQBuffer & 0xF)
1398 {
1399 PSX_WARNING("[CDC] Attempting to start command(0x%02x) while IRQBuffer(0x%02x) is not clear.", V, IRQBuffer);
1400 }
1401
1402 if(ResultsIn > 0)
1403 {
1404 PSX_WARNING("[CDC] Attempting to start command(0x%02x) while command results(count=%d) still in buffer.", V, ResultsIn);
1405 }
1406
1407 PendingCommandCounter = 10500 + PSX_GetRandU32(0, 3000) + 1815;
1408 PendingCommand = V;
1409 PendingCommandPhase = -1;
1410 ArgsReceiveIn = 0;
1411 break;
1412
1413 case 0x01:
1414 ArgsBuf[ArgsWP & 0xF] = V;
1415 ArgsWP = (ArgsWP + 1) & 0x1F;
1416
1417 if(!((ArgsWP - ArgsRP) & 0x0F))
1418 {
1419 PSX_WARNING("[CDC] Argument buffer overflow");
1420 }
1421 break;
1422
1423 case 0x02:
1424 if(V & 0x80)
1425 {
1426 if(!DMABuffer.CanRead())
1427 {
1428 if(!SB_In)
1429 {
1430 PSX_WARNING("[CDC] Data read begin when no data to read!");
1431
1432 DMABuffer.Write(SB, 2340);
1433
1434 while(DMABuffer.CanWrite())
1435 DMABuffer.WriteByte(0x00);
1436 }
1437 else
1438 {
1439 DMABuffer.Write(SB, SB_In);
1440 SB_In = 0;
1441 }
1442 }
1443 else
1444 {
1445 //PSX_WARNING("[CDC] Attempt to start data transfer via 0x80->1803 when %d bytes still in buffer", DMABuffer.CanRead());
1446 }
1447 }
1448 else if(V & 0x40) // Something CD-DA related(along with & 0x20 ???)?
1449 {
1450 for(unsigned i = 0; i < 4 && DMABuffer.CanRead(); i++)
1451 DMABuffer.ReadByte();
1452 }
1453 else
1454 {
1455 DMABuffer.Flush();
1456 }
1457
1458 if(V & 0x20)
1459 {
1460 PSX_WARNING("[CDC] Mystery IRQ trigger bit set.");
1461 IRQBuffer |= 0x10;
1462 RecalcIRQ();
1463 }
1464 break;
1465
1466 case 0x04:
1467 IRQOutTestMask = V;
1468 RecalcIRQ();
1469 break;
1470
1471 case 0x05:
1472 if((IRQBuffer &~ V) != IRQBuffer && ResultsIn)
1473 {
1474 // To debug icky race-condition related problems in "Psychic Detective", and to see if any games suffer from the same potential issue
1475 // (to know what to test when we emulate CPU more accurately in regards to pipeline stalls and timing, which could throw off our kludge
1476 // for this issue)
1477 PSX_WARNING("[CDC] Acknowledged IRQ(wrote 0x%02x, before_IRQBuffer=0x%02x) while %u bytes in results buffer.", V, IRQBuffer, ResultsIn);
1478 }
1479
1480 IRQBuffer &= ~V;
1481 RecalcIRQ();
1482
1483 if(V & 0x80) // Forced CD hardware reset of some kind(interface, controller, and drive?) Seems to take a while(relatively speaking) to complete.
1484 {
1485 PSX_WARNING("[CDC] Soft Reset");
1486 SoftReset();
1487 }
1488
1489 if(V & 0x40) // Does it clear more than arguments buffer? Doesn't appear to clear results buffer.
1490 {
1491 ArgsWP = ArgsRP = 0;
1492 }
1493 break;
1494
1495 case 0x07:
1496 Pending_DecodeVolume[0][0] = V;
1497 break;
1498
1499 case 0x08:
1500 Pending_DecodeVolume[0][1] = V;
1501 break;
1502
1503 case 0x09:
1504 Pending_DecodeVolume[1][1] = V;
1505 break;
1506
1507 case 0x0A:
1508 Pending_DecodeVolume[1][0] = V;
1509 break;
1510
1511 case 0x0B:
1512 if(V & 0x20)
1513 {
1514 memcpy(DecodeVolume, Pending_DecodeVolume, sizeof(DecodeVolume));
1515
1516 for(int i = 0; i < 2; i++)
1517 {
1518 for(int o = 0; o < 2; o++)
1519 {
1520 //fprintf(stderr, "Input Channel %d, Output Channel %d -- Volume=%d\n", i, o, DecodeVolume[i][o]);
1521 }
1522 }
1523 }
1524 break;
1525 }
1526 PSX_SetEventNT(PSX_EVENT_CDC, timestamp + CalcNextEvent());
1527 }
1528 }
1529
Read(const pscpu_timestamp_t timestamp,uint32 A)1530 uint8 PS_CDC::Read(const pscpu_timestamp_t timestamp, uint32 A)
1531 {
1532 uint8 ret = 0;
1533
1534 A &= 0x03;
1535
1536 //printf("Read %08x\n", A);
1537
1538 if(A == 0x00)
1539 {
1540 ret = RegSelector & 0x3;
1541
1542 if(ArgsWP == ArgsRP)
1543 ret |= 0x08; // Args FIFO empty.
1544
1545 if(!((ArgsWP - ArgsRP) & 0x10))
1546 ret |= 0x10; // Args FIFO has room.
1547
1548 if(ResultsIn)
1549 ret |= 0x20;
1550
1551 if(DMABuffer.CanRead())
1552 ret |= 0x40;
1553
1554 if(PendingCommandCounter > 0 && PendingCommandPhase <= 1)
1555 ret |= 0x80;
1556 }
1557 else
1558 {
1559 switch(A & 0x3)
1560 {
1561 case 0x01:
1562 ret = ReadResult();
1563 break;
1564
1565 case 0x02:
1566 //PSX_WARNING("[CDC] DMA Buffer manual read");
1567 if(DMABuffer.CanRead())
1568 ret = DMABuffer.ReadByte();
1569 else
1570 {
1571 PSX_WARNING("[CDC] CD data transfer port read, but no data present!");
1572 }
1573 break;
1574
1575 case 0x03:
1576 if(RegSelector & 0x1)
1577 {
1578 ret = 0xE0 | IRQBuffer;
1579 }
1580 else
1581 {
1582 ret = 0xFF;
1583 }
1584 break;
1585 }
1586 }
1587
1588 return(ret);
1589 }
1590
1591
DMACanRead(void)1592 bool PS_CDC::DMACanRead(void)
1593 {
1594 return(DMABuffer.CanRead());
1595 }
1596
DMARead(void)1597 uint32 PS_CDC::DMARead(void)
1598 {
1599 uint32 data = 0;
1600
1601 for(int i = 0; i < 4; i++)
1602 {
1603 if(DMABuffer.CanRead())
1604 data |= DMABuffer.ReadByte() << (i * 8);
1605 else
1606 {
1607 PSX_WARNING("[CDC] DMA read buffer underflow!");
1608 }
1609 }
1610
1611 return(data);
1612 }
1613
CommandCheckDiscPresent(void)1614 bool PS_CDC::CommandCheckDiscPresent(void)
1615 {
1616 if(!Cur_CDIF || DiscStartupDelay > 0)
1617 {
1618 WriteResult(MakeStatus(true));
1619 WriteResult(ERRCODE_NOT_READY);
1620
1621 WriteIRQ(CDCIRQ_DISC_ERROR);
1622
1623 return(false);
1624 }
1625
1626 return(true);
1627 }
1628
Command_Nop(const int arg_count,const uint8 * args)1629 int32 PS_CDC::Command_Nop(const int arg_count, const uint8 *args)
1630 {
1631 WriteResult(MakeStatus());
1632 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
1633
1634 return(0);
1635 }
1636
Command_Setloc(const int arg_count,const uint8 * args)1637 int32 PS_CDC::Command_Setloc(const int arg_count, const uint8 *args)
1638 {
1639 uint8 m, s, f;
1640
1641 if((args[0] & 0x0F) > 0x09 || args[0] > 0x99 ||
1642 (args[1] & 0x0F) > 0x09 || args[1] > 0x59 ||
1643 (args[2] & 0x0F) > 0x09 || args[2] > 0x74)
1644 {
1645 WriteResult(MakeStatus(true));
1646 WriteResult(ERRCODE_BAD_ARGVAL);
1647 WriteIRQ(CDCIRQ_DISC_ERROR);
1648 return(0);
1649 }
1650
1651 m = BCD_to_U8(args[0]);
1652 s = BCD_to_U8(args[1]);
1653 f = BCD_to_U8(args[2]);
1654
1655 CommandLoc = f + 75 * s + 75 * 60 * m - 150;
1656 CommandLoc_Dirty = true;
1657
1658 WriteResult(MakeStatus());
1659 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
1660
1661 return(0);
1662 }
1663
CalcSeekTime(int32 initial,int32 target,bool motor_on,bool paused)1664 int32 PS_CDC::CalcSeekTime(int32 initial, int32 target, bool motor_on, bool paused)
1665 {
1666 int32 ret = 0;
1667
1668 if(!motor_on)
1669 {
1670 initial = 0;
1671 ret += 33868800;
1672 }
1673
1674 const int32 abs_diff = abs(initial - target);
1675
1676 ret += std::max<int64>((int64)abs_diff * 33868800 * 1000 / (72 * 60 * 75) / 1000, 20000);
1677
1678 if(abs_diff >= 2250)
1679 ret += (int64)33868800 * 300 / 1000;
1680 else if(paused)
1681 {
1682 // The delay to restart from a Pause state is...very....WEIRD. The time it takes is related to the amount of time that has passed since the pause, and
1683 // where on the disc the laser head is, with generally more time passed = longer to resume, except that there's a window of time where it takes a
1684 // ridiculous amount of time when not much time has passed.
1685 //
1686 // What we have here will be EXTREMELY simplified.
1687
1688 //
1689 //
1690
1691 //if(time_passed >= 67737)
1692 //{
1693 //}
1694 //else
1695 {
1696 // Take twice as long for 1x mode.
1697 ret += 1237952 * ((Mode & MODE_SPEED) ? 1 : 2);
1698 }
1699 }
1700 else if(abs_diff >= 3 && abs_diff < 12)
1701 ret += 33868800 / (75 * ((Mode & MODE_SPEED) ? 2 : 1)) * 4;
1702
1703 //else if(target < initial)
1704 // ret += 1000000;
1705
1706 ret += PSX_GetRandU32(0, 25000);
1707
1708 PSX_DBG(PSX_DBG_SPARSE, "[CDC] CalcSeekTime() %d->%d = %d\n", initial, target, ret);
1709
1710 return(ret);
1711 }
1712
1713 #if 0
1714 void PS_CDC::BeginSeek(uint32 target, int after_seek)
1715 {
1716 SeekTarget = target;
1717 StatusAfterSeek = after_seek;
1718
1719 PSRCounter = CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED);
1720 }
1721 #endif
1722
1723 // Remove this function when we have better seek emulation; it's here because the Rockman complete works games(at least 2 and 4) apparently have finicky fubared CD
1724 // access code.
PreSeekHack(int32 target)1725 void PS_CDC::PreSeekHack(int32 target)
1726 {
1727 uint8 pwbuf[96];
1728 int max_try = 32;
1729
1730 CurSector = target; // If removing/changing this, take into account how it will affect ReadN/ReadS/Play/etc command calls that interrupt a seek.
1731 SeekRetryCounter = 128;
1732
1733 // If removing this SubQ reading bit, think about how it will interact with a Read command of data(or audio :b) sectors when Mode bit0 is 1.
1734 do
1735 {
1736 Cur_CDIF->ReadRawSectorPWOnly(pwbuf, target++, true);
1737 } while(!DecodeSubQ(pwbuf) && --max_try > 0);
1738 }
1739
1740 /*
1741 Play command with a track argument that's not a valid BCD quantity causes interesting half-buggy behavior on an actual PS1(unlike some of the other commands,
1742 an error doesn't seem to be generated for a bad BCD argument).
1743 */
Command_Play(const int arg_count,const uint8 * args)1744 int32 PS_CDC::Command_Play(const int arg_count, const uint8 *args)
1745 {
1746 if(!CommandCheckDiscPresent())
1747 return(0);
1748
1749 ClearAIP();
1750
1751 WriteResult(MakeStatus());
1752 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
1753
1754 Forward = Backward = false;
1755
1756 if(arg_count && args[0])
1757 {
1758 int track = BCD_to_U8(args[0]);
1759
1760 if(track < toc.first_track)
1761 {
1762 PSX_WARNING("[CDC] Attempt to play track before first track.");
1763 track = toc.first_track;
1764 }
1765 else if(track > toc.last_track)
1766 {
1767 PSX_WARNING("[CDC] Attempt to play track after last track.");
1768 track = toc.last_track;
1769 }
1770
1771 ClearAudioBuffers();
1772 SectorPipe_Pos = SectorPipe_In = 0;
1773 SectorsRead = 0;
1774
1775 PlayTrackMatch = track;
1776
1777 PSX_WARNING("[CDC] Play track: %d", track);
1778
1779 SeekTarget = toc.tracks[track].lba;
1780 PSRCounter = CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED);
1781 HeaderBufValid = false;
1782 PreSeekHack(SeekTarget);
1783
1784 SeekFinished = false;
1785 DriveStatus = DS_SEEKING;
1786 StatusAfterSeek = DS_PLAYING;
1787 }
1788 else if(CommandLoc_Dirty || DriveStatus != DS_PLAYING)
1789 {
1790 ClearAudioBuffers();
1791 SectorPipe_Pos = SectorPipe_In = 0;
1792 SectorsRead = 0;
1793
1794 if(CommandLoc_Dirty)
1795 SeekTarget = CommandLoc;
1796 else
1797 SeekTarget = CurSector;
1798
1799 PlayTrackMatch = -1;
1800
1801 PSRCounter = CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED);
1802 HeaderBufValid = false;
1803 PreSeekHack(SeekTarget);
1804
1805 SeekFinished = false;
1806 DriveStatus = DS_SEEKING;
1807 StatusAfterSeek = DS_PLAYING;
1808 }
1809
1810 CommandLoc_Dirty = false;
1811 return(0);
1812 }
1813
Command_Forward(const int arg_count,const uint8 * args)1814 int32 PS_CDC::Command_Forward(const int arg_count, const uint8 *args)
1815 {
1816 if(!CommandCheckDiscPresent())
1817 return(0);
1818
1819 WriteResult(MakeStatus());
1820 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
1821
1822 Backward = false;
1823 Forward = true;
1824
1825 return(0);
1826 }
1827
Command_Backward(const int arg_count,const uint8 * args)1828 int32 PS_CDC::Command_Backward(const int arg_count, const uint8 *args)
1829 {
1830 if(!CommandCheckDiscPresent())
1831 return(0);
1832
1833 WriteResult(MakeStatus());
1834 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
1835
1836 Backward = true;
1837 Forward = false;
1838
1839 return(0);
1840 }
1841
1842
ReadBase(void)1843 void PS_CDC::ReadBase(void)
1844 {
1845 if(!CommandCheckDiscPresent())
1846 return;
1847
1848 if(!IsPSXDisc)
1849 {
1850 WriteResult(MakeStatus(true));
1851 WriteResult(ERRCODE_BAD_COMMAND);
1852
1853 WriteIRQ(CDCIRQ_DISC_ERROR);
1854 return;
1855 }
1856
1857 WriteResult(MakeStatus());
1858 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
1859
1860 if((DriveStatus == DS_SEEKING_LOGICAL || DriveStatus == DS_SEEKING_LOGICAL2) && SeekTarget == CommandLoc && StatusAfterSeek == DS_READING)
1861 {
1862 CommandLoc_Dirty = false;
1863 return;
1864 }
1865
1866 if(CommandLoc_Dirty || DriveStatus != DS_READING)
1867 {
1868 // Don't flush the DMABuffer here; see CTR course selection screen.
1869 ClearAIP();
1870 ClearAudioBuffers();
1871 SB_In = 0;
1872 SectorPipe_Pos = SectorPipe_In = 0;
1873 SectorsRead = 0;
1874
1875 // TODO: separate motor start from seek phase?
1876
1877 if(CommandLoc_Dirty)
1878 SeekTarget = CommandLoc;
1879 else if(DriveStatus != DS_PAUSED && DriveStatus != DS_STANDBY)
1880 SeekTarget = CurSector;
1881
1882 PSRCounter = 33868800 / (75 * ((Mode & MODE_SPEED) ? 2 : 1)) + CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED);
1883 HeaderBufValid = false;
1884 PreSeekHack(SeekTarget);
1885
1886 SeekFinished = false;
1887 DriveStatus = DS_SEEKING_LOGICAL;
1888 StatusAfterSeek = DS_READING;
1889 }
1890
1891 CommandLoc_Dirty = false;
1892 }
1893
Command_ReadN(const int arg_count,const uint8 * args)1894 int32 PS_CDC::Command_ReadN(const int arg_count, const uint8 *args)
1895 {
1896 ReadBase();
1897 return 0;
1898 }
1899
Command_ReadS(const int arg_count,const uint8 * args)1900 int32 PS_CDC::Command_ReadS(const int arg_count, const uint8 *args)
1901 {
1902 ReadBase();
1903 return 0;
1904 }
1905
Command_Stop(const int arg_count,const uint8 * args)1906 int32 PS_CDC::Command_Stop(const int arg_count, const uint8 *args)
1907 {
1908 if(!CommandCheckDiscPresent())
1909 return(0);
1910
1911 WriteResult(MakeStatus());
1912 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
1913
1914 if(DriveStatus == DS_STOPPED)
1915 {
1916 return(5000);
1917 }
1918 else
1919 {
1920 ClearAudioBuffers();
1921 ClearAIP();
1922 SectorPipe_Pos = SectorPipe_In = 0;
1923 SectorsRead = 0;
1924
1925 DriveStatus = DS_STOPPED;
1926 HeaderBufValid = false;
1927
1928 return(33868); // FIXME, should be much higher.
1929 }
1930 }
1931
Command_Stop_Part2(void)1932 int32 PS_CDC::Command_Stop_Part2(void)
1933 {
1934 PSRCounter = 0;
1935
1936 WriteResult(MakeStatus());
1937 WriteIRQ(CDCIRQ_COMPLETE);
1938
1939 return(0);
1940 }
1941
Command_Standby(const int arg_count,const uint8 * args)1942 int32 PS_CDC::Command_Standby(const int arg_count, const uint8 *args)
1943 {
1944 if(!CommandCheckDiscPresent())
1945 return(0);
1946
1947 if(DriveStatus != DS_STOPPED)
1948 {
1949 WriteResult(MakeStatus(true));
1950 WriteResult(0x20);
1951 WriteIRQ(CDCIRQ_DISC_ERROR);
1952 return(0);
1953 }
1954
1955 WriteResult(MakeStatus());
1956 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
1957
1958 ClearAudioBuffers();
1959 ClearAIP();
1960 SectorPipe_Pos = SectorPipe_In = 0;
1961 SectorsRead = 0;
1962
1963 SeekTarget = CurSector; // FIXME? CurSector = 0?
1964 HoldLogicalPos = false;
1965 DriveStatus = DS_STANDBY;
1966
1967 return((int64)33868800 * 100 / 1000); // No idea, FIXME.
1968 }
1969
Command_Standby_Part2(void)1970 int32 PS_CDC::Command_Standby_Part2(void)
1971 {
1972 PSRCounter = 0;
1973
1974 WriteResult(MakeStatus());
1975 WriteIRQ(CDCIRQ_COMPLETE);
1976
1977 return(0);
1978 }
1979
Command_Pause(const int arg_count,const uint8 * args)1980 int32 PS_CDC::Command_Pause(const int arg_count, const uint8 *args)
1981 {
1982 if(!CommandCheckDiscPresent())
1983 return 0;
1984
1985 WriteResult(MakeStatus());
1986 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
1987
1988 if(DriveStatus == DS_PAUSED || DriveStatus == DS_STOPPED)
1989 {
1990 return 5000;
1991 }
1992 else
1993 {
1994 CurSector -= std::min<uint32>(4, SectorsRead); // See: Bedlam, Rise 2
1995 SectorsRead = 0;
1996
1997 // "Viewpoint" flips out and crashes if reading isn't stopped (almost?) immediately.
1998 //ClearAudioBuffers();
1999 SectorPipe_Pos = SectorPipe_In = 0;
2000 ClearAIP();
2001 SeekTarget = CurSector;
2002 DriveStatus = DS_PAUSED;
2003 PSRCounter = 33868800 / (75 * ((Mode & MODE_SPEED) ? 2 : 1));
2004
2005 // An approximation.
2006 return (1124584 + ((int64)CurSector * 42596 / (75 * 60))) * ((Mode & MODE_SPEED) ? 1 : 2) + PSX_GetRandU32(0, 100000);
2007 }
2008 }
2009
Command_Pause_Part2(void)2010 int32 PS_CDC::Command_Pause_Part2(void)
2011 {
2012 WriteResult(MakeStatus());
2013 WriteIRQ(CDCIRQ_COMPLETE);
2014
2015 return 0;
2016 }
2017
Command_Reset(const int arg_count,const uint8 * args)2018 int32 PS_CDC::Command_Reset(const int arg_count, const uint8 *args)
2019 {
2020 WriteResult(MakeStatus());
2021 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2022
2023 Muted = false; // Does it get reset here?
2024 Mode = 0x20; // Confirmed(and see "This Is Football 2").
2025 CommandLoc = 0;
2026 //
2027 //
2028 //
2029 // printf("DriveStatus: %d %d %d\n", DriveStatus, StatusAfterSeek, SeekTarget);
2030 if(Cur_CDIF && DiscStartupDelay <= 0)
2031 {
2032 if((DriveStatus == DS_SEEKING_LOGICAL || DriveStatus == DS_SEEKING) && StatusAfterSeek == DS_PAUSED && SeekTarget == 0)
2033 {
2034 //puts("HRMPH");
2035 return 256;
2036 }
2037 else
2038 {
2039 ClearAudioBuffers();
2040
2041 SB_In = 0;
2042 SectorPipe_Pos = SectorPipe_In = 0;
2043 SectorsRead = 0;
2044
2045 SeekTarget = 0;
2046 PSRCounter = std::max<int32>(PSX_GetRandU32(0, 3250000), CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED));
2047 PreSeekHack(SeekTarget);
2048 SeekFinished = false;
2049 DriveStatus = HoldLogicalPos ? DS_SEEKING_LOGICAL : DS_SEEKING;
2050 StatusAfterSeek = DS_PAUSED;
2051 ClearAIP();
2052
2053 return 4100000;
2054 }
2055 }
2056 else
2057 {
2058 SeekFinished = true;
2059 return 70000;
2060 }
2061 }
2062
Command_Mute(const int arg_count,const uint8 * args)2063 int32 PS_CDC::Command_Mute(const int arg_count, const uint8 *args)
2064 {
2065 Muted = true;
2066
2067 WriteResult(MakeStatus());
2068 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2069
2070 return(0);
2071 }
2072
Command_Demute(const int arg_count,const uint8 * args)2073 int32 PS_CDC::Command_Demute(const int arg_count, const uint8 *args)
2074 {
2075 Muted = false;
2076
2077 WriteResult(MakeStatus());
2078 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2079
2080 return(0);
2081 }
2082
Command_Setfilter(const int arg_count,const uint8 * args)2083 int32 PS_CDC::Command_Setfilter(const int arg_count, const uint8 *args)
2084 {
2085 FilterFile = args[0];
2086 FilterChan = args[1];
2087
2088 //PSX_WARNING("[CDC] Setfilter: %02x %02x", args[0], args[1]);
2089
2090 WriteResult(MakeStatus());
2091 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2092
2093 return(0);
2094 }
2095
Command_Setmode(const int arg_count,const uint8 * args)2096 int32 PS_CDC::Command_Setmode(const int arg_count, const uint8 *args)
2097 {
2098 Mode = args[0];
2099
2100 WriteResult(MakeStatus());
2101 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2102
2103 return(0);
2104 }
2105
Command_Getparam(const int arg_count,const uint8 * args)2106 int32 PS_CDC::Command_Getparam(const int arg_count, const uint8 *args)
2107 {
2108 WriteResult(MakeStatus());
2109 WriteResult(Mode);
2110 WriteResult(0x00);
2111 WriteResult(FilterFile);
2112 WriteResult(FilterChan);
2113
2114 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2115
2116
2117 return(0);
2118 }
2119
Command_GetlocL(const int arg_count,const uint8 * args)2120 int32 PS_CDC::Command_GetlocL(const int arg_count, const uint8 *args)
2121 {
2122 if(!CommandCheckDiscPresent())
2123 return(0);
2124
2125 if(!HeaderBufValid)
2126 {
2127 WriteResult(MakeStatus(true));
2128 WriteResult(0x80);
2129 WriteIRQ(CDCIRQ_DISC_ERROR);
2130 return(0);
2131 }
2132
2133 for(unsigned i = 0; i < 8; i++)
2134 {
2135 //printf("%d %d: %02x\n", DriveStatus, i, HeaderBuf[i]);
2136 WriteResult(HeaderBuf[i]);
2137 }
2138
2139 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2140
2141 return(0);
2142 }
2143
Command_GetlocP(const int arg_count,const uint8 * args)2144 int32 PS_CDC::Command_GetlocP(const int arg_count, const uint8 *args)
2145 {
2146 if(!CommandCheckDiscPresent())
2147 return(0);
2148
2149 //printf("%2x:%2x %2x:%2x:%2x %2x:%2x:%2x\n", SubQBuf_Safe[0x1], SubQBuf_Safe[0x2], SubQBuf_Safe[0x3], SubQBuf_Safe[0x4], SubQBuf_Safe[0x5], SubQBuf_Safe[0x7], SubQBuf_Safe[0x8], SubQBuf_Safe[0x9]);
2150
2151 WriteResult(SubQBuf_Safe[0x1]); // Track
2152 WriteResult(SubQBuf_Safe[0x2]); // Index
2153 WriteResult(SubQBuf_Safe[0x3]); // R M
2154 WriteResult(SubQBuf_Safe[0x4]); // R S
2155 WriteResult(SubQBuf_Safe[0x5]); // R F
2156 WriteResult(SubQBuf_Safe[0x7]); // A M
2157 WriteResult(SubQBuf_Safe[0x8]); // A S
2158 WriteResult(SubQBuf_Safe[0x9]); // A F
2159
2160 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2161
2162 return(0);
2163 }
2164
Command_ReadT(const int arg_count,const uint8 * args)2165 int32 PS_CDC::Command_ReadT(const int arg_count, const uint8 *args)
2166 {
2167 WriteResult(MakeStatus());
2168 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2169
2170 return(44100 * 768 / 1000);
2171 }
2172
Command_ReadT_Part2(void)2173 int32 PS_CDC::Command_ReadT_Part2(void)
2174 {
2175 WriteResult(MakeStatus());
2176 WriteIRQ(CDCIRQ_COMPLETE);
2177
2178 return(0);
2179 }
2180
Command_GetTN(const int arg_count,const uint8 * args)2181 int32 PS_CDC::Command_GetTN(const int arg_count, const uint8 *args)
2182 {
2183 if(!CommandCheckDiscPresent())
2184 return(0);
2185
2186 WriteResult(MakeStatus());
2187 WriteResult(U8_to_BCD(toc.first_track));
2188 WriteResult(U8_to_BCD(toc.last_track));
2189
2190 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2191
2192 return(0);
2193 }
2194
Command_GetTD(const int arg_count,const uint8 * args)2195 int32 PS_CDC::Command_GetTD(const int arg_count, const uint8 *args)
2196 {
2197 if(!CommandCheckDiscPresent())
2198 return(0);
2199
2200 int track;
2201 uint8 m, s, f;
2202
2203 if(!args[0])
2204 track = 100;
2205 else
2206 {
2207 track = BCD_to_U8(args[0]);
2208
2209 if(!BCD_is_valid(args[0]) || track < toc.first_track || track > toc.last_track) // Error
2210 {
2211 WriteResult(MakeStatus(true));
2212 WriteResult(ERRCODE_BAD_ARGVAL);
2213 WriteIRQ(CDCIRQ_DISC_ERROR);
2214 return(0);
2215 }
2216 }
2217
2218 LBA_to_AMSF(toc.tracks[track].lba, &m, &s, &f);
2219
2220 WriteResult(MakeStatus());
2221 WriteResult(U8_to_BCD(m));
2222 WriteResult(U8_to_BCD(s));
2223 //WriteResult(U8_to_BCD(f));
2224
2225 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2226
2227 return(0);
2228 }
2229
Command_SeekL(const int arg_count,const uint8 * args)2230 int32 PS_CDC::Command_SeekL(const int arg_count, const uint8 *args)
2231 {
2232 if(!CommandCheckDiscPresent())
2233 return(0);
2234
2235 WriteResult(MakeStatus());
2236 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2237
2238 SeekTarget = CommandLoc;
2239
2240 #if 1
2241 SectorsRead = 0;
2242 SectorPipe_Pos = SectorPipe_In = 0;
2243 #endif
2244 PSRCounter = CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED);
2245 //HeaderBufValid = false;
2246 PreSeekHack(SeekTarget);
2247 SeekFinished = false;
2248 DriveStatus = DS_SEEKING_LOGICAL;
2249 StatusAfterSeek = DS_STANDBY;
2250 ClearAIP();
2251
2252 return(PSRCounter);
2253 }
2254
Command_SeekP(const int arg_count,const uint8 * args)2255 int32 PS_CDC::Command_SeekP(const int arg_count, const uint8 *args)
2256 {
2257 if(!CommandCheckDiscPresent())
2258 return(0);
2259
2260 WriteResult(MakeStatus());
2261 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2262
2263 SeekTarget = CommandLoc;
2264
2265 PSRCounter = CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED);
2266 HeaderBufValid = false;
2267 PreSeekHack(SeekTarget);
2268 SeekFinished = false;
2269 DriveStatus = DS_SEEKING;
2270 StatusAfterSeek = DS_STANDBY;
2271 ClearAIP();
2272
2273 return(PSRCounter);
2274 }
2275
2276 // Used with Command_Reset(), too.
Command_Seek_PartN(void)2277 int32 PS_CDC::Command_Seek_PartN(void)
2278 {
2279 if(DriveStatus != DS_SEEKING && DriveStatus != DS_SEEKING_LOGICAL && DriveStatus != DS_SEEKING_LOGICAL2)
2280 {
2281 if(SeekFinished)
2282 {
2283 BeginResults();
2284
2285 if(SeekFinished < 0)
2286 {
2287 WriteResult(MakeStatus() | 0x04);
2288 WriteResult(0x04);
2289 WriteIRQ(CDCIRQ_DISC_ERROR);
2290 }
2291 else
2292 {
2293 WriteResult(MakeStatus());
2294 WriteIRQ(CDCIRQ_COMPLETE);
2295 }
2296 }
2297 else
2298 {
2299 PSX_WARNING("[CDC] DriveStatus no longer seeking, but SeekFinished is still 0.");
2300 }
2301
2302 return 0;
2303 }
2304 else
2305 {
2306 return std::max<int32>(PSRCounter, 256);
2307 }
2308 }
2309
Command_Test(const int arg_count,const uint8 * args)2310 int32 PS_CDC::Command_Test(const int arg_count, const uint8 *args)
2311 {
2312 //PSX_WARNING("[CDC] Test command sub-operation: 0x%02x", args[0]);
2313
2314 switch(args[0])
2315 {
2316 default:
2317 PSX_WARNING("[CDC] Unknown Test command sub-operation: 0x%02x", args[0]);
2318 WriteResult(MakeStatus(true));
2319 WriteResult(0x10);
2320 WriteIRQ(CDCIRQ_DISC_ERROR);
2321 break;
2322
2323 case 0x00:
2324 case 0x01:
2325 case 0x02:
2326 case 0x03:
2327 case 0x10:
2328 case 0x11:
2329 case 0x12:
2330 case 0x13:
2331 case 0x14:
2332 case 0x15:
2333 case 0x16:
2334 case 0x17:
2335 case 0x18:
2336 case 0x19:
2337 case 0x1A:
2338 PSX_WARNING("[CDC] Unknown Test command sub-operation: 0x%02x", args[0]);
2339 WriteResult(MakeStatus());
2340 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2341 break;
2342
2343 #if 0
2344 case 0x50: // *Need to retest this test command, it takes additional arguments??? Or in any case, it generates a different error code(0x20) than most other Test
2345 // sub-commands that generate an error code(0x10).
2346 break;
2347
2348 // Same with 0x60, 0x71-0x76
2349
2350 #endif
2351
2352 case 0x51: // *Need to retest this test command
2353 PSX_WARNING("[CDC] Unknown Test command sub-operation: 0x%02x", args[0]);
2354 WriteResult(0x01);
2355 WriteResult(0x00);
2356 WriteResult(0x00);
2357 break;
2358
2359 case 0x75: // *Need to retest this test command
2360 PSX_WARNING("[CDC] Unknown Test command sub-operation: 0x%02x", args[0]);
2361 WriteResult(0x00);
2362 WriteResult(0xC0);
2363 WriteResult(0x00);
2364 WriteResult(0x00);
2365 break;
2366
2367 //
2368 // SCEx counters not reset by command 0x0A.
2369 //
2370
2371 case 0x04: // Reset SCEx counters
2372 WriteResult(MakeStatus());
2373 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2374 break;
2375
2376 case 0x05: // Read SCEx counters
2377 WriteResult(0x00); // Number of TOC/leadin reads? (apparently increases by 1 or 2 per ReadTOC, even on non-PSX music CD)
2378 WriteResult(0x00); // Number of SCEx strings received? (Stays at zero on music CD)
2379 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2380 break;
2381
2382 case 0x20:
2383 {
2384 WriteResult(0x97);
2385 WriteResult(0x01);
2386 WriteResult(0x10);
2387 WriteResult(0xC2);
2388
2389 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2390 }
2391 break;
2392
2393 case 0x21: // *Need to retest this test command.
2394 {
2395 WriteResult(0x01);
2396 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2397 }
2398 break;
2399
2400 case 0x22:
2401 {
2402 static const uint8 td[7] = { 0x66, 0x6f, 0x72, 0x20, 0x55, 0x2f, 0x43 };
2403
2404 for(unsigned i = 0; i < 7; i++)
2405 WriteResult(td[i]);
2406
2407 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2408 }
2409 break;
2410
2411 case 0x23:
2412 case 0x24:
2413 {
2414 static const uint8 td[8] = { 0x43, 0x58, 0x44, 0x32, 0x35, 0x34, 0x35, 0x51 };
2415
2416 for(unsigned i = 0; i < 8; i++)
2417 WriteResult(td[i]);
2418
2419 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2420 }
2421 break;
2422
2423 case 0x25:
2424 {
2425 static const uint8 td[8] = { 0x43, 0x58, 0x44, 0x31, 0x38, 0x31, 0x35, 0x51 };
2426
2427 for(unsigned i = 0; i < 8; i++)
2428 WriteResult(td[i]);
2429
2430 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2431 }
2432 break;
2433 }
2434 return(0);
2435 }
2436
Command_ID(const int arg_count,const uint8 * args)2437 int32 PS_CDC::Command_ID(const int arg_count, const uint8 *args)
2438 {
2439 if(!CommandCheckDiscPresent())
2440 return(0);
2441
2442 WriteResult(MakeStatus());
2443 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2444
2445 return(33868);
2446 }
2447
Command_ID_Part2(void)2448 int32 PS_CDC::Command_ID_Part2(void)
2449 {
2450 if(IsPSXDisc)
2451 {
2452 WriteResult(MakeStatus());
2453 WriteResult(0x00);
2454 WriteResult(0x20);
2455 WriteResult(0x00);
2456 }
2457 else
2458 {
2459 WriteResult(MakeStatus() | 0x08);
2460 WriteResult(0x90);
2461 WriteResult(toc.disc_type);
2462 WriteResult(0x00);
2463 }
2464
2465 if(IsPSXDisc)
2466 {
2467 WriteResult(DiscID[0]);
2468 WriteResult(DiscID[1]);
2469 WriteResult(DiscID[2]);
2470 WriteResult(DiscID[3]);
2471 }
2472 else
2473 {
2474 WriteResult(0xff);
2475 WriteResult(0);
2476 WriteResult(0);
2477 WriteResult(0);
2478 }
2479
2480 if(IsPSXDisc)
2481 WriteIRQ(CDCIRQ_COMPLETE);
2482 else
2483 WriteIRQ(CDCIRQ_DISC_ERROR);
2484
2485 return(0);
2486 }
2487
Command_Init(const int arg_count,const uint8 * args)2488 int32 PS_CDC::Command_Init(const int arg_count, const uint8 *args)
2489 {
2490 return(0);
2491 }
2492
Command_ReadTOC(const int arg_count,const uint8 * args)2493 int32 PS_CDC::Command_ReadTOC(const int arg_count, const uint8 *args)
2494 {
2495 int32 ret_time;
2496
2497 HeaderBufValid = false;
2498 WriteResult(MakeStatus());
2499 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2500
2501 // ReadTOC doesn't error out if the tray is open, and it completes rather quickly in that case.
2502 //
2503 if(!CommandCheckDiscPresent())
2504 return(26000);
2505
2506
2507
2508 // A gross approximation.
2509 // The penalty for the drive being stopped seems to be rather high(higher than what CalcSeekTime() currently introduces), although
2510 // that should be investigated further.
2511 //
2512 // ...and not to mention the time taken varies from disc to disc even!
2513 ret_time = 30000000 + CalcSeekTime(CurSector, 0, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED);
2514
2515 SeekTarget = 0;
2516 HoldLogicalPos = false;
2517 DriveStatus = DS_PAUSED; // Ends up in a pause state when the command is finished. Maybe we should add DS_READTOC or something...
2518 ClearAIP();
2519
2520 return ret_time;
2521 }
2522
Command_ReadTOC_Part2(void)2523 int32 PS_CDC::Command_ReadTOC_Part2(void)
2524 {
2525 //if(!CommandCheckDiscPresent())
2526 // DriveStatus = DS_PAUSED;
2527
2528 WriteResult(MakeStatus());
2529 WriteIRQ(CDCIRQ_COMPLETE);
2530
2531 return(0);
2532 }
2533
Command_0x1d(const int arg_count,const uint8 * args)2534 int32 PS_CDC::Command_0x1d(const int arg_count, const uint8 *args)
2535 {
2536 WriteResult(MakeStatus());
2537 WriteIRQ(CDCIRQ_ACKNOWLEDGE);
2538 return(0);
2539 }
2540
2541 const PS_CDC::CDC_CTEntry PS_CDC::Commands[0x20] =
2542 {
2543 { /* 0x00, */ 0, 0, NULL, NULL, NULL },
2544 { /* 0x01, */ 0, 0, "Nop", &PS_CDC::Command_Nop, NULL },
2545 { /* 0x02, */ 3, 3, "Setloc", &PS_CDC::Command_Setloc, NULL },
2546 { /* 0x03, */ 0, 1, "Play", &PS_CDC::Command_Play, NULL },
2547 { /* 0x04, */ 0, 0, "Forward", &PS_CDC::Command_Forward, NULL },
2548 { /* 0x05, */ 0, 0, "Backward", &PS_CDC::Command_Backward, NULL },
2549 { /* 0x06, */ 0, 0, "ReadN", &PS_CDC::Command_ReadN, NULL },
2550 { /* 0x07, */ 0, 0, "Standby", &PS_CDC::Command_Standby, &PS_CDC::Command_Standby_Part2 },
2551 { /* 0x08, */ 0, 0, "Stop", &PS_CDC::Command_Stop, &PS_CDC::Command_Stop_Part2 },
2552 { /* 0x09, */ 0, 0, "Pause", &PS_CDC::Command_Pause, &PS_CDC::Command_Pause_Part2 },
2553 { /* 0x0A, */ 0, 0, "Reset", &PS_CDC::Command_Reset, &PS_CDC::Command_Seek_PartN },
2554 { /* 0x0B, */ 0, 0, "Mute", &PS_CDC::Command_Mute, NULL },
2555 { /* 0x0C, */ 0, 0, "Demute", &PS_CDC::Command_Demute, NULL },
2556 { /* 0x0D, */ 2, 2, "Setfilter", &PS_CDC::Command_Setfilter, NULL },
2557 { /* 0x0E, */ 1, 1, "Setmode", &PS_CDC::Command_Setmode, NULL },
2558 { /* 0x0F, */ 0, 0, "Getparam", &PS_CDC::Command_Getparam, NULL },
2559 { /* 0x10, */ 0, 0, "GetlocL", &PS_CDC::Command_GetlocL, NULL },
2560 { /* 0x11, */ 0, 0, "GetlocP", &PS_CDC::Command_GetlocP, NULL },
2561 { /* 0x12, */ 1, 1, "ReadT", &PS_CDC::Command_ReadT, &PS_CDC::Command_ReadT_Part2 },
2562 { /* 0x13, */ 0, 0, "GetTN", &PS_CDC::Command_GetTN, NULL },
2563 { /* 0x14, */ 1, 1, "GetTD", &PS_CDC::Command_GetTD, NULL },
2564 { /* 0x15, */ 0, 0, "SeekL", &PS_CDC::Command_SeekL, &PS_CDC::Command_Seek_PartN },
2565 { /* 0x16, */ 0, 0, "SeekP", &PS_CDC::Command_SeekP, &PS_CDC::Command_Seek_PartN },
2566
2567 { /* 0x17, */ 0, 0, NULL, NULL, NULL },
2568 { /* 0x18, */ 0, 0, NULL, NULL, NULL },
2569
2570 { /* 0x19, */ 1, 1/* ??? */, "Test", &PS_CDC::Command_Test, NULL },
2571 { /* 0x1A, */ 0, 0, "ID", &PS_CDC::Command_ID, &PS_CDC::Command_ID_Part2 },
2572 { /* 0x1B, */ 0, 0, "ReadS", &PS_CDC::Command_ReadS, NULL },
2573 { /* 0x1C, */ 0, 0, "Init", &PS_CDC::Command_Init, NULL },
2574 { /* 0x1D, */ 2, 2, "Unknown 0x1D", &PS_CDC::Command_0x1d, NULL },
2575 { /* 0x1E, */ 0, 0, "ReadTOC", &PS_CDC::Command_ReadTOC, &PS_CDC::Command_ReadTOC_Part2 },
2576 { /* 0x1F, */ 0, 0, NULL, NULL, NULL },
2577 };
2578
2579
2580 }
2581