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