1 /*
2  * Redistribution and use in source and binary forms, with or without modification,
3  * are permitted provided that the following conditions are met:
4  *
5  *  1. Redistributions of source code must retain the above copyright notice,
6  * this list of conditions and the following disclaimer.
7  * 2. Redistributions in binary form must reproduce the above copyright notice,
8  * this list of conditions and the following disclaimer in the documentation
9  * and/or other materials provided with the distribution.
10  * 3. The name of the author may not be used to endorse or promote products
11  * derived from this software without specific prior written permission.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
14  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
16  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
17  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
18  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
19  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
21  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
22  * OF SUCH DAMAGE.
23  */
24 
25 #include "pce.h"
26 #include "utils.h"
27 
28 UChar pce_cd_cmdcnt;
29 
30 UInt32 pce_cd_sectoraddy;
31 
32 UChar pce_cd_sectoraddress[3];
33 
34 UChar pce_cd_temp_dirinfo[4];
35 
36 UChar pce_cd_temp_play[4];
37 
38 UChar pce_cd_temp_stop[4];
39 
40 UChar pce_cd_dirinfo[4];
41 
42 extern UChar pce_cd_adpcm_trans_done;
43 
44 UChar cd_port_180b = 0;
45 
46 UChar cd_fade;
47 // the byte set by the fade function
48 
49 static void
pce_cd_set_sector_address(void)50 pce_cd_set_sector_address (void)
51 {
52   pce_cd_sectoraddy = pce_cd_sectoraddress[0] << 16;
53   pce_cd_sectoraddy += pce_cd_sectoraddress[1] << 8;
54   pce_cd_sectoraddy += pce_cd_sectoraddress[2];
55 }
56 
57 static void
pce_cd_handle_command(void)58 pce_cd_handle_command (void)
59 {
60 
61   if (pce_cd_cmdcnt)
62     {
63 #ifdef CD_DEBUG
64       fprintf (stderr, "Command arg received: 0x%02x.\n", io.cd_port_1801);
65 #endif
66 
67       if (--pce_cd_cmdcnt)
68 	io.cd_port_1800 = 0xd0;
69       else
70 	io.cd_port_1800 = 0xc8;
71 
72       switch (pce_cd_curcmd)
73 	{
74 	case 0x08:
75 	  if (!pce_cd_cmdcnt)
76 	    {
77 #ifdef CD_DEBUG
78 	      fprintf (stderr, "Read command: %d sectors.\n", io.cd_port_1801);
79 	      fprintf (stderr, "Starting at %02x:%02x:%02x.\n",
80 		       pce_cd_sectoraddress[0], pce_cd_sectoraddress[1],
81 		       pce_cd_sectoraddress[2]);
82 	      fprintf (stderr, "MODE : %x\n", Rd6502 (0x20FF));
83 #endif
84 
85 	      cd_sectorcnt = io.cd_port_1801;
86 
87               if (cd_sectorcnt == 0)
88                 {
89                   fprintf(stderr, "cd_sectorcnt == 0 !!!");
90                   Log("cd_sectorcnt == 0 !!!");
91                 }
92 
93 	      pce_cd_set_sector_address ();
94 	      pce_cd_read_sector ();
95 
96 
97 	      /* TEST */
98 	      // cd_port_1800 = 0xD0; // Xanadu 2 doesn't block but still crash
99 	      /* TEST */
100 
101 #ifdef CD_DEBUG
102 	      fprintf (stderr, "Result of reading : $1800 = 0X%02X\n\n\n",
103 		       io.cd_port_1800);
104 #endif
105 
106 /* TEST ZEO
107     if (Rd6502(0x20ff)==0xfe)
108      cd_port_1800 = 0x98;
109     else
110      cd_port_1800 = 0xc8;
111  * ******** */
112 
113 	    }
114 	  else
115 	    pce_cd_sectoraddress[3 - pce_cd_cmdcnt] = io.cd_port_1801;
116 
117 	  break;
118 	case 0xd8:
119 
120 	  pce_cd_temp_play[pce_cd_cmdcnt] = io.cd_port_1801;
121 
122 	  if (!pce_cd_cmdcnt)
123 	    {
124 	      io.cd_port_1800 = 0xd8;
125 	    }
126 	  break;
127 	case 0xd9:
128 
129 	  pce_cd_temp_stop[pce_cd_cmdcnt] = io.cd_port_1801;
130 
131 	  if (!pce_cd_cmdcnt)
132 	    {
133 	      io.cd_port_1800 = 0xd8;
134 /*
135                if (pce_cd_temp_stop[3] == 1)
136                  osd_cd_play_audio_track(bcdbin[pce_cd_temp_play[2]]);
137                else
138 */
139 	      if ((pce_cd_temp_play[0] |
140 		   pce_cd_temp_play[1] |
141 		   pce_cd_temp_stop[0] | pce_cd_temp_stop[1]) == 0)
142 		{
143 		  if (CD_emulation == 5)
144 		    HCD_play_track (bcdbin[pce_cd_temp_play[2]], 1);
145 		  else
146 		    osd_cd_play_audio_track (bcdbin[pce_cd_temp_play[2]]);
147 		}
148 	      else
149 		{
150 		  if (CD_emulation == 5)
151 		    HCD_play_sectors (Time2Frame (bcdbin[pce_cd_temp_play[2]],
152 						  bcdbin[pce_cd_temp_play[1]],
153 						  bcdbin[pce_cd_temp_play[0]]),
154 				      Time2Frame (bcdbin[pce_cd_temp_stop[2]],
155 						  bcdbin[pce_cd_temp_stop[1]],
156 						  bcdbin[pce_cd_temp_stop[0]]),
157 				      pce_cd_temp_stop[3] == 1);
158 		  else
159 		    osd_cd_play_audio_range (bcdbin[pce_cd_temp_play[2]],
160 					     bcdbin[pce_cd_temp_play[1]],
161 					     bcdbin[pce_cd_temp_play[0]],
162 					     bcdbin[pce_cd_temp_stop[2]],
163 					     bcdbin[pce_cd_temp_stop[1]],
164 					     bcdbin[pce_cd_temp_stop[0]]);
165 		}
166 	      Log ("play from %d:%d:%d:(%d) to %d:%d:%d:(%d)\nloop = %d\n",
167 		   bcdbin[pce_cd_temp_play[2]],
168 		   bcdbin[pce_cd_temp_play[1]],
169 		   bcdbin[pce_cd_temp_play[0]],
170 		   pce_cd_temp_play[3],
171 		   bcdbin[pce_cd_temp_stop[2]],
172 		   bcdbin[pce_cd_temp_stop[1]],
173 		   bcdbin[pce_cd_temp_stop[0]],
174 		   pce_cd_temp_stop[3], pce_cd_temp_stop[3] == 1);
175 
176 	    }
177 	  break;
178 	case 0xde:
179 
180 #ifdef CD_DEBUG
181 	  Log (" Arg for 0xde command is %X, command count is %d\n",
182 	       io.cd_port_1801, pce_cd_cmdcnt);
183 #endif
184 
185 	  if (pce_cd_cmdcnt)
186 	    pce_cd_temp_dirinfo[pce_cd_cmdcnt] = io.cd_port_1801;
187 	  else
188 	    {
189 	      // We have received two arguments in pce_cd_temp_dirinfo
190 	      // We can use only one
191 	      // There's an argument indicating the kind of info we want
192 	      // and an optional argument for track number
193 
194 	      pce_cd_temp_dirinfo[0] = io.cd_port_1801;
195 
196 #ifdef CD_DEBUG
197 	      Log
198 		(" I'll answer to 0xde command request\nArguments are %x, %x, %x, %x\n",
199 		 pce_cd_temp_dirinfo[0], pce_cd_temp_dirinfo[1],
200 		 pce_cd_temp_dirinfo[2], pce_cd_temp_dirinfo[3]);
201 #endif
202 
203 	      switch (pce_cd_temp_dirinfo[1])
204 		{
205 		case 0:
206 		  // We want info on number of first and last track
207 
208 		  switch (CD_emulation)
209 		    {
210 		    case 2:
211 		    case 3:
212 		    case 4:
213 		      pce_cd_dirinfo[0] = binbcd[01];	// Number of first track  (BCD)
214 		      pce_cd_dirinfo[1] = binbcd[nb_max_track];	// Number of last track (BCD)
215 		      break;
216 		    case 1:
217 		      {
218 			int first_track, last_track;
219 			osd_cd_nb_tracks (&first_track, &last_track);
220 			pce_cd_dirinfo[0] = binbcd[first_track];
221 			pce_cd_dirinfo[1] = binbcd[last_track];
222 		      }
223 		      break;
224 		    case 5:
225 		      Log ("HCD: first track %d, last track %d\n",
226 			   HCD_first_track, HCD_last_track);
227 		      pce_cd_dirinfo[0] = binbcd[HCD_first_track];
228 		      pce_cd_dirinfo[1] = binbcd[HCD_last_track];
229 		      break;
230 		    }		// switch CD emulation
231 
232 		  cd_read_buffer = pce_cd_dirinfo;
233 		  pce_cd_read_datacnt = 2;
234 
235 #ifdef CD_DEBUG
236 		  Log (" Data resulting of 0xde request is %x and %x\n",
237 		       cd_read_buffer[0], cd_read_buffer[1]);
238 #endif
239 		  break;
240 
241 		case 2:
242 
243 		  // We want info on the track whose number is pce_cd_temp_dirinfo[0]
244 
245 		  switch (CD_emulation)
246 		    {
247 		    case 2:
248 		    case 3:
249 		    case 4:
250 		    case 5:
251 
252 		      pce_cd_dirinfo[0] =
253 			CD_track[bcdbin[pce_cd_temp_dirinfo[0]]].beg_min;
254 		      pce_cd_dirinfo[1] =
255 			CD_track[bcdbin[pce_cd_temp_dirinfo[0]]].beg_sec;
256 		      pce_cd_dirinfo[2] =
257 			CD_track[bcdbin[pce_cd_temp_dirinfo[0]]].beg_fra;
258 		      pce_cd_dirinfo[3] =
259 			CD_track[bcdbin[pce_cd_temp_dirinfo[0]]].type;
260 
261 #ifdef CD_DEBUG
262 		      Log ("Type of track %d is %d\n",
263 			   bcdbin[pce_cd_temp_dirinfo[0]],
264 			   CD_track[bcdbin[pce_cd_temp_dirinfo[0]]].type);
265 #endif
266 		      break;
267 		    case 1:
268 		      {
269 			int Min, Sec, Fra, Ctrl;
270 			osd_cd_track_info (bcdbin[pce_cd_temp_dirinfo[0]],
271 					   &Min, &Sec, &Fra, &Ctrl);
272 
273 			pce_cd_dirinfo[0] = binbcd[Min];
274 			pce_cd_dirinfo[1] = binbcd[Sec];
275 			pce_cd_dirinfo[2] = binbcd[Fra];
276 			pce_cd_dirinfo[3] = Ctrl;
277 
278 			Log
279 			  ("The control byte of the audio track #%d is 0x%02X\n",
280 			   bcdbin[pce_cd_temp_dirinfo[0]], pce_cd_dirinfo[3]);
281 
282 			break;
283 
284 		      }		// case CD emulation = 1
285 
286 		    }		// switch CD emulation
287 
288 		  pce_cd_read_datacnt = 3;
289 		  cd_read_buffer = pce_cd_dirinfo;
290 
291 		  break;
292 
293 		case 1:
294 
295 		  switch (CD_emulation)
296 		    {
297 		    case 1:
298 		      {
299 
300 			int min, sec, fra;
301 
302 			osd_cd_length (&min, &sec, &fra);
303 
304 			pce_cd_dirinfo[0] = binbcd[min];
305 			pce_cd_dirinfo[1] = binbcd[sec];
306 			pce_cd_dirinfo[2] = binbcd[fra];
307 
308 			break;
309 		      }		// case Cd emulation = 1
310 		    default:
311 		      pce_cd_dirinfo[0] = 0x25;
312 		      pce_cd_dirinfo[1] = 0x06;
313 		      pce_cd_dirinfo[2] = 0x00;
314 		    }		// switch CD emulation
315 
316 		  pce_cd_read_datacnt = 3;
317 		  cd_read_buffer = pce_cd_dirinfo;
318 
319 		  break;
320 
321 		}		// switch command of request 0xde
322 
323 	    }			// end if of request 0xde (receiving command or executing them)
324 
325 	}			// switch of request
326 
327     }				// end if of command arg or new request
328   else
329     {
330 
331       // it's a command ID we're receiving
332 
333 #ifdef CD_DEBUG
334       fprintf (stderr, "Command byte received: 0x%02x.\n", io.cd_port_1801);
335 #endif
336 
337       switch (io.cd_port_1801)
338 	{
339 	case 0x00:
340 	  io.cd_port_1800 = 0xD8;
341 	  break;
342 	case 0x08:
343 	  pce_cd_curcmd = io.cd_port_1801;
344 	  pce_cd_cmdcnt = 4;
345 	  break;
346 	case 0xD8:
347 	  pce_cd_curcmd = io.cd_port_1801;
348 	  pce_cd_cmdcnt = 4;
349 	  break;
350 	case 0xD9:
351 	  pce_cd_curcmd = io.cd_port_1801;
352 	  pce_cd_cmdcnt = 4;
353 	  break;
354 	case 0xDA:
355 	  pce_cd_curcmd = io.cd_port_1801;
356 	  pce_cd_cmdcnt = 0;
357 
358 	  if (CD_emulation == 1)
359 	    osd_cd_stop_audio ();
360 	  else if (CD_emulation == 5)
361 	    HCD_pause_playing ();
362 
363 	  break;
364 	case 0xDE:
365 	  /* Get CD directory info */
366 	  /* First arg is command? */
367 	  /* Second arg is track? */
368 	  io.cd_port_1800 = 0xd0;
369 	  pce_cd_cmdcnt = 2;
370 	  pce_cd_read_datacnt = 3;	/* 4 bytes */
371 	  pce_cd_curcmd = io.cd_port_1801;
372 	  break;
373 	}
374 
375 /*
376         if (cd_port_1801 == 0x00) {
377             cd_port_1800 = 0xd8;
378         } else if (cd_port_1801 == 0x08) {
379             pce_cd_curcmd = cd_port_1801;
380             pce_cd_cmdcnt = 4;
381         } else if (cd_port_1801 == 0xd8) {
382             pce_cd_cmdcnt = 4;
383             pce_cd_curcmd = cd_port_1801;
384         } else if (cd_port_1801 == 0xd9) {
385             pce_cd_cmdcnt = 4;
386             pce_cd_curcmd = cd_port_1801;
387         } else if (cd_port_1801 == 0xde) {
388             // Get CD directory info
389             // First arg is command?
390             // Second arg is track?
391             cd_port_1800 = 0xd0;
392             pce_cd_cmdcnt = 2;
393             pce_cd_read_datacnt = 3; // 4 bytes
394             pce_cd_curcmd = cd_port_1801;
395         }
396 */
397 
398     }
399 }
400 
pce_cd_handle_read_1800(UInt16 A)401 UChar pce_cd_handle_read_1800(UInt16 A)
402 {
403   switch (A & 15)
404     {
405     case 0:
406       return io.cd_port_1800;
407     case 1:
408       {
409         UChar retval;
410 
411         if (cd_read_buffer)
412           {
413             retval = *cd_read_buffer++;
414             if (pce_cd_read_datacnt == 2048)
415               {
416                 pce_cd_read_datacnt--;
417 
418 #ifndef FINAL_RELEASE
419                 fprintf (stderr, "Data count fudge\n");
420 #endif
421 
422               }
423             if (!pce_cd_read_datacnt)
424               cd_read_buffer = 0;
425           }
426         else
427           retval = 0;
428         return retval;
429       }
430 
431     case 2:
432       return io.cd_port_1802;
433 
434     case 3:
435 
436       {
437 
438         static UChar tmp_res = 0x02;
439 
440         tmp_res = 0x02 - tmp_res;
441 
442         io.backup = DISABLE;
443 
444         /* TEST */// return 0x20;
445 
446         return tmp_res | 0x20;
447 
448       }
449 
450       /* TEST */
451     case 4:
452       return io.cd_port_1804;
453 
454       /* TEST */
455     case 5:
456       return 0x50;
457 
458       /* TEST */
459     case 6:
460       return 0x05;
461 
462     case 0x0A:
463 #ifndef FINAL_RELEASE
464       Log ("HARD : Read %x from ADPCM[%04X] to VRAM : 0X%04X\n", PCM[io.adpcm_rptr], io.adpcm_rptr, io.VDC[MAWR].W * 2);
465 #endif
466 
467       if (!io.adpcm_firstread)
468         return PCM[io.adpcm_rptr++];
469       else
470         {
471           io.adpcm_firstread--;
472           return NODATA;
473         }
474 
475     case 0x0B:	/* TEST */
476       return 0x00;
477     case 0x0C:	/* TEST */
478       return 0x01;	// 0x89
479     case 0x0D:	/* TEST */
480       return 0x00;
481 
482     case 8:
483       if (pce_cd_read_datacnt)
484         {
485           UChar retval;
486 
487           if (cd_read_buffer)
488             retval = *cd_read_buffer++;
489           else
490             retval = 0;
491 
492           if (!--pce_cd_read_datacnt)
493             {
494               cd_read_buffer = 0;
495               if (!--cd_sectorcnt)
496                 {
497 #ifndef FINAL_RELEASE
498                   fprintf (stderr,
499                            "Sector data count over.\n");
500 #endif
501                   io.cd_port_1800 |= 0x10;
502                   pce_cd_curcmd = 0;
503                 }
504               else
505                 {
506 #ifndef FINAL_RELEASE
507                   fprintf (stderr,
508                            "Sector data count %d.\n",
509                            cd_sectorcnt);
510 #endif
511                   pce_cd_read_sector ();
512                 }
513             }
514           return retval;
515         }
516       break;
517     }
518   // FIXME: what to return here?
519   return 0;
520 }
521 
522 
pce_cd_handle_write_1800(UInt16 A,UChar V)523 void pce_cd_handle_write_1800(UInt16 A, UChar V)
524 {
525   switch (A & 15)
526     {
527 
528     case 7:
529       io.backup = ENABLE;
530       return;
531 
532     case 0:
533       if (V == 0x81)
534         io.cd_port_1800 = 0xD0;
535       return;
536     case 1:
537       io.cd_port_1801 = V;
538       if (!pce_cd_cmdcnt)
539         switch (V)
540           {
541           case 0:
542             /*
543               #ifndef FINAL_RELEASE
544               fprintf(stderr,"RESET? command at 1801\n");
545               #endif
546             */
547             return;
548           case 3:
549             /*
550               #ifndef FINAL_RELEASE
551               fprintf(stderr,"GET SYSTEM STATUS? command at 1801\n");
552               #endif
553             */
554             return;
555           case 8:
556             /*
557               #ifndef FINAL_RELEASE
558               fprintf(stderr,"READ SECTOR command at 1801\n");
559               #endif*/
560             return;
561           case 0x81:
562             /*
563               #ifndef FINAL_RELEASE
564               fprintf(stderr,"ANOTHER RESET? command at 1801\n");
565               #endif
566             */
567             io.cd_port_1800 = 0x40;
568             return;
569           case 0xD8:
570           case 0xD9:
571             /*
572               #ifndef FINAL_RELEASE
573               fprintf(stderr,"PLAY AUDIO? command at 1801\n");
574               #endif
575             */
576             return;
577 
578           case 0xDA:
579             /*
580               #ifndef FINAL_RELEASE
581               fprintf(stderr,"PAUSE AUDIO PLAYING? command at 1801\n");
582               #endif
583             */
584             return;
585 
586           case 0xDD:
587             /*
588               #ifndef FINAL_RELEASE
589               fprintf(stderr,"READ Q CHANNEL? command at 1801\n");
590               #endif
591             */
592             return;
593           case 0xDE:
594             /*
595               #ifndef FINAL_RELEASE
596               fprintf(stderr,"GET DIRECTORY INFO? command at 1801\n");
597               #endif
598             */
599             return;
600 
601           default:
602             /*
603               #ifndef FINAL_RELEASE
604               if (!pce_cd_cmdcnt)
605               fprintf(stderr,"ERROR, unknown command %x at 1801\n",V);
606               #endif
607             */
608             return;
609           }
610 
611       return;
612 
613     case 2:
614 #ifndef FINAL_RELEASE
615       // fprintf(stderr,"trying to access port 1802 in write\n");
616 #endif
617 
618       if ((!(io.cd_port_1802 & 0x80)) && (V & 0x80))
619         {
620           io.cd_port_1800 &= ~0x40;
621         }
622       else if ((io.cd_port_1802 & 0x80) && (!(V & 0x80)))
623         {
624           io.cd_port_1800 |= 0x40;
625 
626 #ifndef FINAL_RELEASE
627           Log ("ADPCM trans = %d\n", pce_cd_adpcm_trans_done);
628 #endif
629           if (pce_cd_adpcm_trans_done)
630             {
631 
632 #ifndef FINAL_RELEASE
633               Log ("ack the DMA transfert of ADPCM data\n");
634 #endif
635 
636               io.cd_port_1800 |= 0x10;
637               pce_cd_curcmd = 0x00;
638               pce_cd_adpcm_trans_done = 0;
639 
640             }
641 
642           if (io.cd_port_1800 & 0x08)
643             {
644               /*              deb_printf("pce_cd: data byte acknowledged.\n"); */
645               if (io.cd_port_1800 & 0x20)
646                 {
647                   io.cd_port_1800 &= ~0x80;
648                 }
649               else if (!pce_cd_read_datacnt)
650                 {
651                   if (pce_cd_curcmd == 0x08)
652                     {
653                       if (!--cd_sectorcnt)
654                         {
655 #ifndef FINAL_RELEASE
656                           fprintf (stderr, "sector data count over.\n");
657 #endif
658                           io.cd_port_1800 |= 0x10;	/* wrong */
659                           pce_cd_curcmd = 0x00;
660                         }
661                       else
662                         {
663 #ifndef FINAL_RELEASE
664                           fprintf (stderr, "sector data count %d.\n",
665                                    cd_sectorcnt);
666 #endif
667                           pce_cd_read_sector ();
668                         }
669                     }
670                   else
671                     {
672                       if (io.cd_port_1800 & 0x10)
673                         {
674                           io.cd_port_1800 |= 0x20;
675                         }
676                       else
677                         {
678                           io.cd_port_1800 |= 0x10;
679                         }
680                     }
681                 }
682               else
683                 {
684                   pce_cd_read_datacnt--;
685                 }
686             }
687           else
688             {
689               pce_cd_handle_command ();
690             }
691         }
692 
693       io.cd_port_1802 = V;
694       return;
695     case 4:
696       if (V & 2)
697         {			// Reset asked
698           // do nothing for now
699 #ifndef FINAL_RELEASE
700           fprintf (stderr, "Reset mode for CD asked\n");
701 #endif
702 
703           switch (CD_emulation)
704             {
705             case 1:
706               if (osd_cd_init (ISO_filename) != 0)
707                 {
708                   Log ("CD rom drive couldn't be initialised\n");
709                   exit (4);
710                 }
711               break;
712             case 2:
713             case 3:
714             case 4:
715               fill_cd_info ();
716               break;
717 
718             case 5:
719               fill_HCD_info(ISO_filename);
720               break;
721             }
722 
723           Wr6502 (0x222D, 1);
724           // This byte is set to 1 if a disc if present
725 
726           //cd_port_1800 &= ~0x40;
727           io.cd_port_1804 = V;
728         }
729       else
730         {			// Normal utilisation
731 #ifndef FINAL_RELEASE
732           fprintf (stderr, "Normal mode for CD asked\n");
733 #endif
734           io.cd_port_1804 = V;
735           // cd_port_1800 |= 0x40; // Maybe the previous reset is enough
736           // cd_port_1800 |= 0xD0;
737           // Indicates that the Hardware is ready after such a reset
738         }
739       return;
740 
741     case 8:
742       io.adpcm_ptr.B.l = V;
743       return;
744     case 9:
745       io.adpcm_ptr.B.h = V;
746       return;
747 
748     case 0x0A:
749       PCM[io.adpcm_wptr++] = V;
750 #ifndef FINAL_RELEASE
751       fprintf (stderr, "Wrote %02X to ADPCM buffer[%04X]\n", V,
752                io.adpcm_wptr - 1);
753       Log ("wrote to ADPCM, %02X at PCM[0X%04X]\n", V, io.adpcm_wptr - 1);
754 #endif
755       return;
756     case 0x0B:		// DMA enable ?
757 
758       if ((V & 2) && (!(cd_port_180b & 2)))
759         {
760           issue_ADPCM_dma ();
761           cd_port_180b = V;
762           return;
763         }
764 
765 
766       /* TEST */
767       if (!V)
768         {
769           io.cd_port_1800 &= ~0xF8;
770           io.cd_port_1800 |= 0xD8;
771         }
772 
773       cd_port_180b = V;
774 
775       return;
776 
777     case 0x0D:
778 
779       if ((V & 0x03) == 0x03)
780         {
781           io.adpcm_dmaptr = io.adpcm_ptr.W;	// set DMA pointer
782 #ifndef FINAL_RELEASE
783           fprintf (stderr, "Set DMA pointer to %x\n", io.adpcm_dmaptr);
784 #endif
785         }
786 
787       if (V & 0x04)
788         {
789           io.adpcm_wptr = io.adpcm_ptr.W;	// set write pointer
790 #ifndef FINAL_RELEASE
791           fprintf (stderr, "Set write pointer to %x\n", io.adpcm_wptr);
792 #endif
793         }
794 
795       if (V & 0x08)		// set read pointer
796         {
797           io.adpcm_rptr = io.adpcm_ptr.W;
798           io.adpcm_firstread = 2;
799 
800 #ifndef FINAL_RELEASE
801           fprintf (stderr, "Set read pointer to %x\n", io.adpcm_rptr);
802 #endif
803 
804         }
805 
806       /* TEST
807          else { io.adpcm_rptr = io.adpcm_ptr.W; io.adpcm_firstread = TRUE; }
808       */
809       /* TEST */
810       //if (V&0x08) io.
811 
812       if (V & 0x80)
813         {			// ADPCM reset
814 #ifndef FINAL_RELEASE
815           fprintf (stderr, "Reset mode for ADPCM\n");
816 #endif
817         }
818       else
819         {			// Normal ADPCM utilisation
820 #ifndef FINAL_RELEASE
821           fprintf (stderr, "Normal mode for ADPCM\n");
822 #endif
823         }
824 
825 
826 
827       return;
828 
829     case 0xe:		// Set ADPCM playback rate
830       io.adpcm_rate = 32 / (16 - (V & 15));
831 
832 #ifndef FINAL_RELEASE
833       fprintf (stderr, "ADPCM rate set to %d kHz\n", io.adpcm_rate);
834 #endif
835       return;
836 
837     case 0xf:		// don't know how to use it
838 #ifndef FINAL_RELEASE
839       fprintf (stderr, "Fade setting to %d\n", V);
840 #endif
841 
842       cd_fade = V;
843       return;
844     }			// A&15 switch, i.e. CD ports
845 }
846