Previous 199869 Revisions Next

r19246 Sunday 2nd December, 2012 at 02:56:09 UTC by David Haywood
megacd/neocd: precursor to proper cleanups (nw)

(rather ugly for now, the code *should* be collapsible to a single set of functions but we're not there yet, not even close, lots of push and pull of system specific bits needed before everything is in the right place)
[src/mame]mame.mak
[src/mame/includes]megadriv.h
[src/mame/machine]megacd.c megacd.h megacdcd.c* megacdcd.h*
[src/mess]mess.mak
[src/mess/drivers]ng_aes.c

trunk/src/mame/machine/megacd.c
r19245r19246
11
22#include "includes/megadriv.h"
33#include "megacd.lh"
4#include "sound/cdda.h"
54#include "sound/rf5c68.h"
65
6
7
78// the main MD emulation needs to know the state of these because it appears in the MD regs / affect DMA operations
89int sega_cd_connected = 0x00;
910
r19245r19246
6465   segacd_irq3_timer->adjust(SEGACD_IRQ3_TIMER_SPEED);
6566}
6667
67TIMER_DEVICE_CALLBACK_MEMBER( sega_segacd_device::scd_dma_timer_callback )
68{
69   // todo: accurate timing of this!
7068
71   #define RATE 256
72   CDC_Do_DMA(machine(), RATE);
73
74   // timed reset of flags
75   scd_mode_dmna_ret_flags |= 0x0021;
76
77   scd_dma_timer->adjust(attotime::from_hz(megadriv_framerate) / megadrive_total_scanlines);
78
79}
80
81TIMER_DEVICE_CALLBACK_MEMBER( sega_segacd_device::segacd_access_timer_callback )
82{
83   CheckCommand(machine());
84}
85
8669TIMER_DEVICE_CALLBACK_MEMBER( sega_segacd_device::segacd_gfx_conversion_timer_callback )
8770{
8871   //printf("segacd_gfx_conversion_timer_callback\n");
r19245r19246
11497   AM_RANGE(0xff8000 ,0xff8001) AM_READWRITE(segacd_sub_led_ready_r, segacd_sub_led_ready_w)
11598   AM_RANGE(0xff8002 ,0xff8003) AM_READWRITE(segacd_sub_memory_mode_r, segacd_sub_memory_mode_w)
11699
117   AM_RANGE(0xff8004 ,0xff8005) AM_READWRITE(segacd_cdc_mode_address_r, segacd_cdc_mode_address_w)
118   AM_RANGE(0xff8006 ,0xff8007) AM_READWRITE(segacd_cdc_data_r, segacd_cdc_data_w)
119   AM_RANGE(0xff8008, 0xff8009) AM_READ(cdc_data_sub_r)
120   AM_RANGE(0xff800a, 0xff800b) AM_READWRITE(cdc_dmaaddr_r,cdc_dmaaddr_w) // CDC DMA Address
100   AM_RANGE(0xff8004 ,0xff8005) AM_DEVREADWRITE("tempcdc",lc89510_temp_device, segacd_cdc_mode_address_r, segacd_cdc_mode_address_w)
101   AM_RANGE(0xff8006 ,0xff8007) AM_DEVREADWRITE("tempcdc",lc89510_temp_device,segacd_cdc_data_r, segacd_cdc_data_w)
102   AM_RANGE(0xff8008, 0xff8009) AM_DEVREAD("tempcdc",lc89510_temp_device, cdc_data_sub_r)
103   AM_RANGE(0xff800a, 0xff800b) AM_DEVREADWRITE("tempcdc",lc89510_temp_device,cdc_dmaaddr_r,cdc_dmaaddr_w) // CDC DMA Address
121104   AM_RANGE(0xff800c, 0xff800d) AM_READWRITE(segacd_stopwatch_timer_r, segacd_stopwatch_timer_w)// Stopwatch timer
122105   AM_RANGE(0xff800e ,0xff800f) AM_READWRITE(segacd_comms_flags_r, segacd_comms_flags_subcpu_w)
123106   AM_RANGE(0xff8010 ,0xff801f) AM_READWRITE(segacd_comms_sub_part1_r, segacd_comms_sub_part1_w)
124107   AM_RANGE(0xff8020 ,0xff802f) AM_READWRITE(segacd_comms_sub_part2_r, segacd_comms_sub_part2_w)
125108   AM_RANGE(0xff8030, 0xff8031) AM_READWRITE(segacd_irq3timer_r, segacd_irq3timer_w) // Timer W/INT3
126   AM_RANGE(0xff8032, 0xff8033) AM_READWRITE(segacd_irq_mask_r,segacd_irq_mask_w)
127   AM_RANGE(0xff8034, 0xff8035) AM_READWRITE(segacd_cdfader_r,segacd_cdfader_w) // CD Fader
128   AM_RANGE(0xff8036, 0xff8037) AM_READWRITE(segacd_cdd_ctrl_r,segacd_cdd_ctrl_w)
129   AM_RANGE(0xff8038, 0xff8041) AM_READ8(segacd_cdd_rx_r,0xffff)
130   AM_RANGE(0xff8042, 0xff804b) AM_WRITE8(segacd_cdd_tx_w,0xffff)
109   AM_RANGE(0xff8032, 0xff8033) AM_DEVREADWRITE("tempcdc",lc89510_temp_device,segacd_irq_mask_r,segacd_irq_mask_w)
110   AM_RANGE(0xff8034, 0xff8035) AM_DEVREADWRITE("tempcdc",lc89510_temp_device,segacd_cdfader_r,segacd_cdfader_w) // CD Fader
111   AM_RANGE(0xff8036, 0xff8037) AM_DEVREADWRITE("tempcdc",lc89510_temp_device,segacd_cdd_ctrl_r,segacd_cdd_ctrl_w)
112   AM_RANGE(0xff8038, 0xff8041) AM_DEVREAD8("tempcdc",lc89510_temp_device,segacd_cdd_rx_r,0xffff)
113   AM_RANGE(0xff8042, 0xff804b) AM_DEVWRITE8("tempcdc",lc89510_temp_device,segacd_cdd_tx_w,0xffff)
131114   AM_RANGE(0xff804c, 0xff804d) AM_READWRITE(segacd_font_color_r, segacd_font_color_w)
132115   AM_RANGE(0xff804e, 0xff804f) AM_RAM AM_SHARE("segacd_font")
133116   AM_RANGE(0xff8050, 0xff8057) AM_READ(segacd_font_converted_r)
r19245r19246
150133
151134   MCFG_CPU_ADD("segacd_68k", M68000, SEGACD_CLOCK ) /* 12.5 MHz */
152135   MCFG_CPU_PROGRAM_MAP(segacd_map)
153
136   
154137   MCFG_DEVICE_ADD("cdc", LC89510, 0) // cd controller
155138
139   // temporary until things are cleaned up
140   MCFG_DEVICE_ADD("tempcdc", LC89510_TEMP, 0) // cd controller
141   MCFG_SEGACD_HACK_SET_CDC_DO_DMA( sega_segacd_device, SegaCD_CDC_Do_DMA ) // hack
142
156143   MCFG_TIMER_ADD_NONE("sw_timer") //stopwatch timer
157   MCFG_TIMER_DRIVER_ADD_PERIODIC("hock_timer", sega_segacd_device, segacd_access_timer_callback, attotime::from_hz(75))
158144   MCFG_TIMER_DRIVER_ADD("irq3_timer", sega_segacd_device, segacd_irq3_timer_callback)
159145   MCFG_TIMER_DRIVER_ADD("stamp_timer", sega_segacd_device, segacd_gfx_conversion_timer_callback)
160146   MCFG_TIMER_DRIVER_ADD("scd_dma_timer", sega_segacd_device, scd_dma_timer_callback)
161147
148   
162149
163
164150   MCFG_DEFAULT_LAYOUT( layout_megacd )
165151
166   MCFG_SOUND_ADD( "cdda", CDDA, 0 )
167   MCFG_SOUND_ROUTE( 0, ":lspeaker", 0.50 ) // TODO: accurate volume balance
168   MCFG_SOUND_ROUTE( 1, ":rspeaker", 0.50 )
169152
153
170154   MCFG_SOUND_ADD("rfsnd", RF5C68, SEGACD_CLOCK) // RF5C164!
171155   MCFG_SOUND_ROUTE( 0, ":lspeaker", 0.50 )
172156   MCFG_SOUND_ROUTE( 1, ":rspeaker", 0.50 )
r19245r19246
189173
190174
191175
192inline int sega_segacd_device::to_bcd(int val, bool byte)
193{
194   if (val > 99) val = 99;
195176
196   if (byte) return (((val) / 10) << 4) + ((val) % 10);
197   else return (((val) / 10) << 8) + ((val) % 10);
198}
199177
200178
201179
202180
203
204
205
206181inline void sega_segacd_device::write_pixel(running_machine& machine, UINT8 pix, int pixeloffset )
207182{
208183
r19245r19246
324299
325300
326301
327void sega_segacd_device::set_data_audio_mode(void)
328{
329   if (CURRENT_TRACK_IS_DATA)
330   {
331      SET_CDD_DATA_MODE
332   }
333   else
334   {
335      SET_CDD_AUDIO_MODE
336      //fatalerror("CDDA unsupported\n");
337   }
338}
339302
340void sega_segacd_device::CDD_DoChecksum(void)
341{
342   int checksum =
343      CDD_RX[0] +
344      CDD_RX[1] +
345      CDD_RX[2] +
346      CDD_RX[3] +
347      CDD_RX[4] +
348      CDD_RX[5] +
349      CDD_RX[6] +
350      CDD_RX[7] +
351      CDD_RX[9];
352
353   checksum &= 0xf;
354   checksum ^= 0xf;
355
356   CDD_RX[8] = checksum;
357}
358
359void sega_segacd_device::CDD_Export(void)
360{
361   CDD_RX[0] = (CDD_STATUS  & 0x00ff)>>0;
362   CDD_RX[1] = (CDD_STATUS  & 0xff00)>>8;
363   CDD_RX[2] = (CDD_MIN  & 0x00ff)>>0;
364   CDD_RX[3] = (CDD_MIN  & 0xff00)>>8;
365   CDD_RX[4] = (CDD_SEC & 0x00ff)>>0;
366   CDD_RX[5] = (CDD_SEC & 0xff00)>>8;
367   CDD_RX[6] = (CDD_FRAME   & 0x00ff)>>0;
368   CDD_RX[7] = (CDD_FRAME   & 0xff00)>>8;
369   /* 8 = checksum */
370   CDD_RX[9] = (CDD_EXT     & 0x00ff)>>0;
371
372   CDD_DoChecksum();
373
374   CDD_CONTROL &= ~4; // Clear HOCK bit
375
376}
377
378
379
380void sega_segacd_device::CDC_UpdateHEAD(void)
381{
382   if (CDC_CTRLB1 & 0x01)
383   {
384      CDC_HEADB0 = CDC_HEADB1 = CDC_HEADB2 = CDC_HEADB3 = 0x00;
385   }
386   else
387   {
388      UINT32 msf = lba_to_msf_alt(SCD_CURLBA+150);
389      CDC_HEADB0 = to_bcd (((msf & 0x00ff0000)>>16), true);
390      CDC_HEADB1 = to_bcd (((msf & 0x0000ff00)>>8), true);
391      CDC_HEADB2 = to_bcd (((msf & 0x000000ff)>>0), true);
392      CDC_HEADB3 = 0x01;
393   }
394}
395
396
397void sega_segacd_device::scd_ctrl_checks(running_machine& machine)
398{
399   CDC_STATB0 = 0x80;
400
401   (CDC_CTRLB0 & 0x10) ? (CDC_STATB2 = CDC_CTRLB1 & 0x08) : (CDC_STATB2 = CDC_CTRLB1 & 0x0C);
402   (CDC_CTRLB0 & 0x02) ? (CDC_STATB3 = 0x20) : (CDC_STATB3 = 0x00);
403
404   if (CDC_IFCTRL & 0x20)
405   {
406      CHECK_SCD_LV5_INTERRUPT
407      CDC_IFSTAT &= ~0x20;
408      CDC_DECODE = 0;
409   }
410}
411
412void sega_segacd_device::scd_advance_current_readpos(void)
413{
414   SCD_CURLBA++;
415
416   CDC_WA += SECTOR_SIZE;
417   CDC_PT += SECTOR_SIZE;
418
419   CDC_WA &= 0x7fff;
420   CDC_PT &= 0x7fff;
421}
422
423int sega_segacd_device::Read_LBA_To_Buffer(running_machine& machine)
424{
425   bool data_track = false;
426   if (CDD_CONTROL & 0x0100) data_track = true;
427
428   if (data_track)
429      cdrom_read_data(segacd.cd, SCD_CURLBA, SCD_BUFFER, CD_TRACK_MODE1);
430
431   CDC_UpdateHEAD();
432
433   if (!data_track)
434   {
435      scd_advance_current_readpos();
436   }
437
438   if (CDC_CTRLB0 & 0x80)
439   {
440      if (CDC_CTRLB0 & 0x04)
441      {
442         if (data_track)
443         {
444            scd_advance_current_readpos();
445
446            memcpy(&CDC_BUFFER[CDC_PT + 4], SCD_BUFFER, 2048);
447            CDC_BUFFER[CDC_PT+0] = CDC_HEADB0;
448            CDC_BUFFER[CDC_PT+1] = CDC_HEADB1;
449            CDC_BUFFER[CDC_PT+2] = CDC_HEADB2;
450            CDC_BUFFER[CDC_PT+3] = CDC_HEADB3;
451         }
452         else
453         {
454            memcpy(&CDC_BUFFER[CDC_PT], SCD_BUFFER, SECTOR_SIZE);
455         }
456      }
457
458      scd_ctrl_checks(machine);
459   }
460
461
462   return 0;
463}
464
465void sega_segacd_device::CheckCommand(running_machine& machine)
466{
467   if (CDD_DONE)
468   {
469      CDD_DONE = 0;
470      CDD_Export();
471      CHECK_SCD_LV4_INTERRUPT
472   }
473
474   if (SCD_READ_ENABLED)
475   {
476      set_data_audio_mode();
477      Read_LBA_To_Buffer(machine);
478   }
479}
480
481
482void sega_segacd_device::CDD_GetStatus(void)
483{
484   UINT16 s = (CDD_STATUS & 0x0f00);
485
486   if ((s == 0x0200) || (s == 0x0700) || (s == 0x0e00))
487      CDD_STATUS = (SCD_STATUS & 0xff00) | (CDD_STATUS & 0x00ff);
488}
489
490
491void sega_segacd_device::CDD_Stop(running_machine &machine)
492{
493   CLEAR_CDD_RESULT
494   STOP_CDC_READ
495   SCD_STATUS = CDD_STOPPED;
496   CDD_STATUS = 0x0000;
497   SET_CDD_DATA_MODE
498   cdda_stop_audio( machine.device( ":segacd:cdda" ) ); //stop any pending CD-DA
499}
500
501
502void sega_segacd_device::CDD_GetPos(void)
503{
504   CLEAR_CDD_RESULT
505   UINT32 msf;
506   CDD_STATUS &= 0xFF;
507   if(segacd.cd == NULL) // no cd is there, bail out
508      return;
509   CDD_STATUS |= SCD_STATUS;
510   msf = lba_to_msf_alt(SCD_CURLBA+150);
511   CDD_MIN = to_bcd(((msf & 0x00ff0000)>>16),false);
512   CDD_SEC = to_bcd(((msf & 0x0000ff00)>>8),false);
513   CDD_FRAME = to_bcd(((msf & 0x000000ff)>>0),false);
514}
515
516void sega_segacd_device::CDD_GetTrackPos(void)
517{
518   CLEAR_CDD_RESULT
519   int elapsedlba;
520   UINT32 msf;
521   CDD_STATUS &= 0xFF;
522   //  UINT32 end_msf = ;
523   if(segacd.cd == NULL) // no cd is there, bail out
524      return;
525   CDD_STATUS |= SCD_STATUS;
526   elapsedlba = SCD_CURLBA - segacd.toc->tracks[ cdrom_get_track(segacd.cd, SCD_CURLBA) ].physframeofs;
527   msf = lba_to_msf_alt (elapsedlba);
528   //popmessage("%08x %08x",SCD_CURLBA,segacd.toc->tracks[ cdrom_get_track(segacd.cd, SCD_CURLBA) + 1 ].physframeofs);
529   CDD_MIN = to_bcd(((msf & 0x00ff0000)>>16),false);
530   CDD_SEC = to_bcd(((msf & 0x0000ff00)>>8),false);
531   CDD_FRAME = to_bcd(((msf & 0x000000ff)>>0),false);
532}
533
534void sega_segacd_device::CDD_GetTrack(void)
535{
536   CLEAR_CDD_RESULT
537   CDD_STATUS &= 0xFF;
538   if(segacd.cd == NULL) // no cd is there, bail out
539      return;
540   CDD_STATUS |= SCD_STATUS;
541   SCD_CURTRK = cdrom_get_track(segacd.cd, SCD_CURLBA)+1;
542   CDD_MIN = to_bcd(SCD_CURTRK, false);
543}
544
545void sega_segacd_device::CDD_Length(void)
546{
547   CLEAR_CDD_RESULT
548   CDD_STATUS &= 0xFF;
549   if(segacd.cd == NULL) // no cd is there, bail out
550      return;
551   CDD_STATUS |= SCD_STATUS;
552
553   UINT32 startlba = (segacd.toc->tracks[cdrom_get_last_track(segacd.cd)].physframeofs);
554   UINT32 startmsf = lba_to_msf_alt( startlba );
555
556   CDD_MIN = to_bcd((startmsf&0x00ff0000)>>16,false);
557   CDD_SEC = to_bcd((startmsf&0x0000ff00)>>8,false);
558   CDD_FRAME = to_bcd((startmsf&0x000000ff)>>0,false);
559}
560
561
562void sega_segacd_device::CDD_FirstLast(void)
563{
564   CLEAR_CDD_RESULT
565   CDD_STATUS &= 0xFF;
566   if(segacd.cd == NULL) // no cd is there, bail out
567      return;
568   CDD_STATUS |= SCD_STATUS;
569   CDD_MIN = 1; // first
570   CDD_SEC = to_bcd(cdrom_get_last_track(segacd.cd),false); // last
571}
572
573void sega_segacd_device::CDD_GetTrackAdr(void)
574{
575   CLEAR_CDD_RESULT
576
577   int track = (CDD_TX[4] & 0xF) + (CDD_TX[5] & 0xF) * 10;
578   int last_track = cdrom_get_last_track(segacd.cd);
579
580   CDD_STATUS &= 0xFF;
581   if(segacd.cd == NULL) // no cd is there, bail out
582      return;
583   CDD_STATUS |= SCD_STATUS;
584
585   if (track > last_track)
586      track = last_track;
587
588   if (track < 1)
589      track = 1;
590
591   UINT32 startlba = (segacd.toc->tracks[track-1].physframeofs);
592   UINT32 startmsf = lba_to_msf_alt( startlba+150 );
593
594   CDD_MIN = to_bcd((startmsf&0x00ff0000)>>16,false);
595   CDD_SEC = to_bcd((startmsf&0x0000ff00)>>8,false);
596   CDD_FRAME = to_bcd((startmsf&0x000000ff)>>0,false);
597   CDD_EXT = track % 10;
598
599   if (segacd.toc->tracks[track - 1].trktype != CD_TRACK_AUDIO)
600      CDD_FRAME |= 0x0800;
601}
602
603UINT32 sega_segacd_device::getmsf_from_regs(void)
604{
605   UINT32 msf = 0;
606
607   msf  = ((CDD_TX[2] & 0xF) + (CDD_TX[3] & 0xF) * 10) << 16;
608   msf |= ((CDD_TX[4] & 0xF) + (CDD_TX[5] & 0xF) * 10) << 8;
609   msf |= ((CDD_TX[6] & 0xF) + (CDD_TX[7] & 0xF) * 10) << 0;
610
611   return msf;
612}
613
614void sega_segacd_device::CDD_Play(running_machine &machine)
615{
616   CLEAR_CDD_RESULT
617   UINT32 msf = getmsf_from_regs();
618   SCD_CURLBA = msf_to_lba(msf)-150;
619   UINT32 end_msf = segacd.toc->tracks[ cdrom_get_track(segacd.cd, SCD_CURLBA) + 1 ].physframeofs;
620   SCD_CURTRK = cdrom_get_track(segacd.cd, SCD_CURLBA)+1;
621   CDC_UpdateHEAD();
622   SCD_STATUS = CDD_PLAYINGCDDA;
623   CDD_STATUS = 0x0102;
624   set_data_audio_mode();
625   printf("%d Track played\n",SCD_CURTRK);
626   CDD_MIN = to_bcd(SCD_CURTRK, false);
627   if(!(CURRENT_TRACK_IS_DATA))
628      cdda_start_audio( machine.device( ":segacd:cdda" ), SCD_CURLBA, end_msf - SCD_CURLBA );
629   SET_CDC_READ
630}
631
632
633void sega_segacd_device::CDD_Seek(void)
634{
635   CLEAR_CDD_RESULT
636   UINT32 msf = getmsf_from_regs();
637   SCD_CURLBA = msf_to_lba(msf)-150;
638   SCD_CURTRK = cdrom_get_track(segacd.cd, SCD_CURLBA)+1;
639   CDC_UpdateHEAD();
640   STOP_CDC_READ
641   SCD_STATUS = CDD_READY;
642   CDD_STATUS = 0x0200;
643   set_data_audio_mode();
644}
645
646
647void sega_segacd_device::CDD_Pause(running_machine &machine)
648{
649   CLEAR_CDD_RESULT
650   STOP_CDC_READ
651   SCD_STATUS = CDD_READY;
652   CDD_STATUS = SCD_STATUS;
653   SET_CDD_DATA_MODE
654
655   //segacd.current_frame = cdda_get_audio_lba( machine.device( ":segacd:cdda" ) );
656   //if(!(CURRENT_TRACK_IS_DATA))
657   cdda_pause_audio( machine.device( ":segacd:cdda" ), 1 );
658}
659
660void sega_segacd_device::CDD_Resume(running_machine &machine)
661{
662   CLEAR_CDD_RESULT
663   STOP_CDC_READ
664   SCD_CURTRK = cdrom_get_track(segacd.cd, SCD_CURLBA)+1;
665   SCD_STATUS = CDD_PLAYINGCDDA;
666   CDD_STATUS = 0x0102;
667   set_data_audio_mode();
668   CDD_MIN = to_bcd (SCD_CURTRK, false);
669   SET_CDC_READ
670   //if(!(CURRENT_TRACK_IS_DATA))
671   cdda_pause_audio( machine.device( ":segacd:cdda" ), 0 );
672}
673
674
675void sega_segacd_device::CDD_FF(running_machine &machine)
676{
677   fatalerror("Fast Forward unsupported\n");
678}
679
680
681void sega_segacd_device::CDD_RW(running_machine &machine)
682{
683   fatalerror("Fast Rewind unsupported\n");
684}
685
686
687void sega_segacd_device::CDD_Open(void)
688{
689   fatalerror("Close Tray unsupported\n");
690   /* TODO: re-read CD-ROM buffer here (Mega CD has multi disc games iirc?) */
691}
692
693
694void sega_segacd_device::CDD_Close(void)
695{
696   fatalerror("Open Tray unsupported\n");
697   /* TODO: clear CD-ROM buffer here */
698}
699
700
701void sega_segacd_device::CDD_Init(void)
702{
703   CLEAR_CDD_RESULT
704   STOP_CDC_READ
705   SCD_STATUS = CDD_READY;
706   CDD_STATUS = SCD_STATUS;
707   CDD_SEC = 1;
708   CDD_FRAME = 1;
709}
710
711
712void sega_segacd_device::CDD_Default(void)
713{
714   CLEAR_CDD_RESULT
715   CDD_STATUS = SCD_STATUS;
716}
717
718
719void sega_segacd_device::CDD_Reset(void)
720{
721   CLEAR_CDD_RESULT
722   CDD_CONTROL = CDD_STATUS = 0;
723
724   for (int i = 0; i < 10; i++)
725      CDD_RX[i] = CDD_TX[i] = 0;
726
727   CDD_DoChecksum();
728
729   SCD_CURTRK = SCD_CURLBA = 0;
730   SCD_STATUS = CDD_READY;
731}
732
733void sega_segacd_device::CDC_Reset(void)
734{
735   memset(CDC_BUFFER, 0x00, ((16 * 1024 * 2) + SECTOR_SIZE));
736   CDC_UpdateHEAD();
737
738   CDC_DMA_ADDRC = CDC_DMACNT = CDC_PT = CDC_SBOUT = CDC_IFCTRL = CDC_CTRLB0 = CDC_CTRLB1 =
739      CDC_CTRLB2 = CDC_HEADB1 = CDC_HEADB2 = CDC_HEADB3 = CDC_STATB0 = CDC_STATB1 = CDC_STATB2 = CDC_DECODE = 0;
740
741   CDC_IFSTAT = 0xFF;
742   CDC_WA = SECTOR_SIZE * 2;
743   CDC_HEADB0 = 0x01;
744   CDC_STATB3 = 0x80;
745}
746
747
748void sega_segacd_device::lc89510_Reset(void)
749{
750   CDD_Reset();
751   CDC_Reset();
752
753   CDC_REG0 = CDC_REG1 = CDC_DMA_ADDR = SCD_STATUS_CDC = CDD_DONE = 0;
754}
755
756void sega_segacd_device::CDC_End_Transfer(running_machine& machine)
757{
758   STOP_CDC_DMA
759   CDC_REG0 |= 0x8000;
760   CDC_REG0 &= ~0x4000;
761   CDC_IFSTAT |= 0x08;
762
763   if (CDC_IFCTRL & 0x40)
764   {
765      CDC_IFSTAT &= ~0x40;
766      CHECK_SCD_LV5_INTERRUPT
767   }
768}
769
770void sega_segacd_device::CDC_Do_DMA(running_machine& machine, int rate)
771{
772   address_space& space = machine.device(":segacd:segacd_68k")->memory().space(AS_PROGRAM);
773
774   UINT32 dstoffset, length;
775   UINT8 *dest;
776   UINT16 destination = CDC_REG0 & 0x0700;
777
778   if (!(SCD_DMA_ENABLED))
779      return;
780
781   if ((destination == READ_MAIN) || (destination==READ_SUB))
782   {
783      CDC_REG0 |= 0x4000;
784      return;
785   }
786
787   if (CDC_DMACNT <= (rate * 2))
788   {
789      length = (CDC_DMACNT + 1) >> 1;
790      CDC_End_Transfer(machine);
791   }
792   else
793      length = rate;
794
795
796   int dmacount = length;
797
798   bool PCM_DMA = false;
799
800   if (destination==DMA_PCM)
801   {
802      dstoffset = (CDC_DMA_ADDR & 0x03FF) << 2;
803      PCM_DMA = true;
804   }
805   else
806   {
807      dstoffset = (CDC_DMA_ADDR & 0xFFFF) << 3;
808   }
809
810   int srcoffset = 0;
811
812   while (dmacount--)
813   {
814      UINT16 data = (CDC_BUFFER[CDC_DMA_ADDRC+srcoffset]<<8) | CDC_BUFFER[CDC_DMA_ADDRC+srcoffset+1];
815
816      if (destination==DMA_PRG)
817      {
818         dest = (UINT8 *) segacd_4meg_prgram;
819      }
820      else if (destination==DMA_WRAM)
821      {
822         dest = (UINT8*)segacd_dataram;
823      }
824      else if (destination==DMA_PCM)
825      {
826         dest = 0;//fatalerror("PCM RAM DMA unimplemented!\n");
827      }
828      else
829      {
830         fatalerror("Unknown DMA Destination!!\n");
831      }
832
833      if (PCM_DMA)
834      {
835         space.write_byte(0xff2000+(((dstoffset*2)+1)&0x1fff),data >> 8);
836         space.write_byte(0xff2000+(((dstoffset*2)+3)&0x1fff),data & 0xff);
837      //  printf("PCM_DMA writing %04x %04x\n",0xff2000+(dstoffset*2), data);
838      }
839      else
840      {
841         if (dest)
842         {
843            if (destination==DMA_WRAM)
844            {
845
846               if ((scd_rammode&2)==RAM_MODE_2MEG)
847               {
848                  dstoffset &= 0x3ffff;
849
850                  dest[dstoffset+1] = data >>8;
851                  dest[dstoffset+0] = data&0xff;
852
853                  segacd_mark_tiles_dirty(space.machine(), dstoffset/2);
854               }
855               else
856               {
857                  dstoffset &= 0x1ffff;
858
859                  if (!(scd_rammode & 1))
860                  {
861                     segacd_1meg_mode_word_write(space.machine(),(dstoffset+0x20000)/2, data, 0xffff, 0);
862                  }
863                  else
864                  {
865                     segacd_1meg_mode_word_write(space.machine(),(dstoffset+0x00000)/2, data, 0xffff, 0);
866                  }
867               }
868
869            }
870            else
871            {
872               // main ram
873               dest[dstoffset+1] = data >>8;
874               dest[dstoffset+0] = data&0xff;
875            }
876
877         }
878      }
879
880      srcoffset += 2;
881      dstoffset += 2;
882   }
883
884   if (PCM_DMA)
885   {
886      CDC_DMA_ADDR += length >> 1;
887   }
888   else
889   {
890      CDC_DMA_ADDR += length >> 2;
891   }
892
893   CDC_DMA_ADDRC += length*2;
894
895   if (SCD_DMA_ENABLED)
896      CDC_DMACNT -= length*2;
897   else
898      CDC_DMACNT = 0;
899}
900
901
902
903
904UINT16 sega_segacd_device::CDC_Host_r(running_machine& machine, UINT16 type)
905{
906   UINT16 destination = CDC_REG0 & 0x0700;
907
908   if (SCD_DMA_ENABLED)
909   {
910      if (destination == type)
911      {
912         CDC_DMACNT -= 2;
913
914         if (CDC_DMACNT <= 0)
915         {
916            if (type==READ_SUB) CDC_DMACNT = 0;
917
918            CDC_End_Transfer(machine);
919         }
920
921         UINT16 data = (CDC_BUFFER[CDC_DMA_ADDRC]<<8) | CDC_BUFFER[CDC_DMA_ADDRC+1];
922         CDC_DMA_ADDRC += 2;
923
924         return data;
925      }
926   }
927
928   return 0;
929}
930
931
932UINT8 sega_segacd_device::CDC_Reg_r(void)
933{
934   int reg = CDC_REG0 & 0xF;
935   UINT8 ret = 0;
936   UINT16 decoderegs = 0x73F2;
937
938   if ((decoderegs>>reg)&1)
939      CDC_DECODE |= (1 << reg);
940
941   //if (reg!=REG_R_STAT3)
942      CDC_REG0 = (CDC_REG0 & 0xFFF0) | ((reg+1)&0xf);
943
944
945   switch (reg)
946   {
947      case REG_R_COMIN:  ret = 0/*COMIN*/;            break;
948      case REG_R_IFSTAT: ret = CDC_IFSTAT;           break;
949      case REG_R_DBCL:   ret = CDC_DMACNT & 0xff;       break;
950      case REG_R_DBCH:   ret = (CDC_DMACNT >>8) & 0xff; break;
951      case REG_R_HEAD0:  ret = CDC_HEADB0;           break;
952      case REG_R_HEAD1:  ret = CDC_HEADB1;           break;
953      case REG_R_HEAD2:  ret = CDC_HEADB2;           break;
954      case REG_R_HEAD3:  ret = CDC_HEADB3;           break;
955      case REG_R_PTL:      ret = CDC_PT & 0xff;        break;
956      case REG_R_PTH:      ret = (CDC_PT >>8) & 0xff;  break;
957      case REG_R_WAL:    ret = CDC_WA & 0xff;        break;
958      case REG_R_WAH:    ret = (CDC_WA >>8) & 0xff;  break;
959      case REG_R_STAT0:  ret = CDC_STATB0;           break;
960      case REG_R_STAT1:  ret = CDC_STATB1;           break;
961      case REG_R_STAT2:  ret = CDC_STATB2;           break;
962      case REG_R_STAT3:  ret = CDC_STATB3;
963
964         CDC_IFSTAT |= 0x20;
965
966         // ??
967         if ((CDC_CTRLB0 & 0x80) && (CDC_IFCTRL & 0x20))
968         {
969            if ((CDC_DECODE & decoderegs) == decoderegs)
970            CDC_STATB3 = 0x80;
971         }
972         break;
973   }
974
975   return ret;
976}
977
978void sega_segacd_device::CDC_Reg_w(UINT8 data)
979{
980   int reg = CDC_REG0 & 0xF;
981
982   int changers0[0x10] = { 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0};
983
984   if (changers0[reg])
985      CDC_REG0 = (CDC_REG0 & 0xFFF0) | (reg+1);
986
987   switch (reg)
988   {
989   case REG_W_SBOUT:
990         CDC_SBOUT = data;
991         break;
992
993   case REG_W_IFCTRL:
994         CDC_IFCTRL = data;
995
996         if (!(CDC_IFCTRL & 0x02))
997         {
998            CDC_DMACNT = 0;
999            STOP_CDC_DMA;
1000            CDC_IFSTAT |= 0x08;
1001         }
1002         break;
1003
1004   case REG_W_DBCL: CDC_DMACNT = (CDC_DMACNT &~ 0x00ff) | (data & 0x00ff) << 0; break;
1005   case REG_W_DBCH: CDC_DMACNT = (CDC_DMACNT &~ 0xff00) | (data & 0x00ff) << 8; break;
1006   case REG_W_DACL: CDC_DMA_ADDRC = (CDC_DMA_ADDRC &~ 0x00ff) | (data & 0x00ff) << 0; break;
1007   case REG_W_DACH: CDC_DMA_ADDRC = (CDC_DMA_ADDRC &~ 0xff00) | (data & 0x00ff) << 8; break;
1008
1009   case REG_W_DTTRG:
1010         if (CDC_IFCTRL & 0x02)
1011         {
1012            CDC_IFSTAT &= ~0x08;
1013            SET_CDC_DMA;
1014            CDC_REG0 &= ~0x8000;
1015         }
1016         break;
1017
1018   case REG_W_DTACK: CDC_IFSTAT |= 0x40; break;
1019   case REG_W_WAL: CDC_WA = (CDC_WA &~ 0x00ff) | (data & 0x00ff) << 0; break;
1020   case REG_W_WAH:   CDC_WA = (CDC_WA &~ 0xff00) | (data & 0x00ff) << 8;   break;
1021   case REG_W_CTRL0: CDC_CTRLB0 = data; break;
1022   case REG_W_CTRL1: CDC_CTRLB1 = data; break;
1023   case REG_W_PTL: CDC_PT = (CDC_PT &~ 0x00ff) | (data & 0x00ff) << 0; break;
1024   case REG_W_PTH: CDC_PT = (CDC_PT &~ 0xff00) | (data & 0x00ff) << 8;   break;
1025   case REG_W_CTRL2: CDC_CTRLB2 = data; break;
1026   case REG_W_RESET: CDC_Reset();       break;
1027   }
1028}
1029
1030void sega_segacd_device::CDD_Process(running_machine& machine, int reason)
1031{
1032   CDD_Export();
1033   CHECK_SCD_LV4_INTERRUPT
1034}
1035
1036void sega_segacd_device::CDD_Handle_TOC_Commands(void)
1037{
1038   int subcmd = CDD_TX[2];
1039   CDD_STATUS = (CDD_STATUS & 0xFF00) | subcmd;
1040
1041   switch (subcmd)
1042   {
1043      case TOCCMD_CURPOS:      CDD_GetPos();     break;
1044      case TOCCMD_TRKPOS:      CDD_GetTrackPos(); break;
1045      case TOCCMD_CURTRK:    CDD_GetTrack();   break;
1046      case TOCCMD_LENGTH:    CDD_Length();      break;
1047      case TOCCMD_FIRSTLAST: CDD_FirstLast();   break;
1048      case TOCCMD_TRACKADDR: CDD_GetTrackAdr(); break;
1049      default:               CDD_GetStatus();   break;
1050   }
1051}
1052
1053static const char *const CDD_import_cmdnames[] =
1054{
1055   "Get Status",         // 0
1056   "Stop ALL",            // 1
1057   "Handle TOC",         // 2
1058   "Play",               // 3
1059   "Seek",               // 4
1060   "<undefined>",         // 5
1061   "Pause",            // 6
1062   "Resume",            // 7
1063   "FF",               // 8
1064   "RWD",               // 9
1065   "INIT",               // A
1066   "<undefined>",         // B
1067   "Close Tray",         // C
1068   "Open Tray",         // D
1069   "<undefined>",         // E
1070   "<undefined>"         // F
1071};
1072
1073void sega_segacd_device::CDD_Import(running_machine& machine)
1074{
1075   if(CDD_TX[1] != 2 && CDD_TX[1] != 0)
1076      printf("%s\n",CDD_import_cmdnames[CDD_TX[1]]);
1077
1078   switch (CDD_TX[1])
1079   {
1080      case CMD_STATUS:   CDD_GetStatus();          break;
1081      case CMD_STOPALL:   CDD_Stop(machine);         break;
1082      case CMD_GETTOC:   CDD_Handle_TOC_Commands(); break;
1083      case CMD_READ:      CDD_Play(machine);         break;
1084      case CMD_SEEK:      CDD_Seek();                  break;
1085      case CMD_STOP:      CDD_Pause(machine);          break;
1086      case CMD_RESUME:   CDD_Resume(machine);       break;
1087      case CMD_FF:      CDD_FF(machine);           break;
1088      case CMD_RW:      CDD_RW(machine);           break;
1089      case CMD_INIT:      CDD_Init();                  break;
1090      case CMD_CLOSE:      CDD_Open();                break;
1091      case CMD_OPEN:      CDD_Close();              break;
1092      default:         CDD_Default();              break;
1093   }
1094
1095   CDD_DONE = 1;
1096}
1097
1098
1099
1100
1101303WRITE16_MEMBER( sega_segacd_device::scd_a12000_halt_reset_w )
1102304{
1103305
r19245r19246
1455657   COMBINE_DATA(&segacd_comms_part2[offset]);
1456658}
1457659
1458/**************************************************************
1459 CDC Stuff ********
1460**************************************************************/
1461660
1462
1463
1464WRITE16_MEMBER( sega_segacd_device::segacd_cdc_mode_address_w )
1465{
1466   COMBINE_DATA(&CDC_REG0);
1467}
1468
1469READ16_MEMBER( sega_segacd_device::segacd_cdc_mode_address_r )
1470{
1471   return CDC_REG0;
1472}
1473
1474WRITE16_MEMBER( sega_segacd_device::segacd_cdc_data_w )
1475{
1476   COMBINE_DATA(&CDC_REG1);
1477
1478   if (ACCESSING_BITS_0_7)
1479      CDC_Reg_w(data);
1480}
1481
1482READ16_MEMBER( sega_segacd_device::segacd_cdc_data_r )
1483{
1484   UINT16 retdat = 0x0000;
1485
1486   if (ACCESSING_BITS_0_7)
1487      retdat |= CDC_Reg_r();
1488
1489   return retdat;
1490}
1491
1492
1493
1494
1495
1496661READ16_MEMBER( sega_segacd_device::segacd_main_dataram_part1_r )
1497662{
1498663   if ((scd_rammode&2)==RAM_MODE_2MEG)
r19245r19246
19151080}
19161081
19171082
1918READ16_MEMBER( sega_segacd_device::cdc_data_sub_r )
1919{
1920   return CDC_Host_r(space.machine(), READ_SUB);
1921}
19221083
1923READ16_MEMBER( sega_segacd_device::cdc_data_main_r )
1924{
1925   return CDC_Host_r(space.machine(), READ_MAIN);
1926}
1927
1928
1929
19301084WRITE16_MEMBER( sega_segacd_device::segacd_stopwatch_timer_w )
19311085{
19321086   if(data == 0)
r19245r19246
21271281
21281282
21291283
2130READ16_MEMBER( sega_segacd_device::segacd_irq_mask_r )
2131{
2132
2133   return segacd_irq_mask;
2134}
2135
2136WRITE16_MEMBER( sega_segacd_device::segacd_irq_mask_w )
2137{
2138   if (ACCESSING_BITS_0_7)
2139   {
2140      UINT16 control = CDD_CONTROL;
2141
2142   //  printf("segacd_irq_mask_w %04x %04x (CDD control is %04x)\n",data, mem_mask, control);
2143
2144      if (data & 0x10)
2145      {
2146         if (control & 0x04)
2147         {
2148            if (!(segacd_irq_mask & 0x10))
2149            {
2150               segacd_irq_mask = data & 0x7e;
2151               CDD_Process(space.machine(), 0);
2152               return;
2153            }
2154         }
2155      }
2156
2157      segacd_irq_mask = data & 0x7e;
2158   }
2159   else
2160   {
2161
2162      printf("segacd_irq_mask_w only MSB written\n");
2163
2164   }
2165}
2166
2167READ16_MEMBER( sega_segacd_device::segacd_cdd_ctrl_r )
2168{
2169
2170   return CDD_CONTROL;
2171}
2172
2173
2174WRITE16_MEMBER( sega_segacd_device::segacd_cdd_ctrl_w )
2175{
2176   if (ACCESSING_BITS_0_7)
2177   {
2178      UINT16 control = CDD_CONTROL;
2179
2180
2181      //printf("segacd_cdd_ctrl_w %04x %04x (control %04x irq %04x\n", data, mem_mask, control, segacd_irq_mask);
2182
2183      data &=0x4; // only HOCK bit is writable
2184
2185      if (data & 0x4)
2186      {
2187         if (!(control & 0x4))
2188         {
2189            if (segacd_irq_mask&0x10)
2190            {
2191               CDD_Process(space.machine(), 1);
2192            }
2193         }
2194      }
2195
2196      CDD_CONTROL |= data;
2197   }
2198   else
2199   {
2200      printf("segacd_cdd_ctrl_w only MSB written\n");
2201   }
2202}
2203
2204
2205
2206READ8_MEMBER( sega_segacd_device::segacd_cdd_rx_r )
2207{
2208   return CDD_RX[offset^1];
2209}
2210
2211WRITE8_MEMBER( sega_segacd_device::segacd_cdd_tx_w )
2212{
2213   CDD_TX[offset^1] = data;
2214
2215   if(offset == 9)
2216   {
2217      CDD_Import(space.machine());
2218   }
2219}
2220
2221
2222
22231284READ16_MEMBER( sega_segacd_device::segacd_stampsize_r )
22241285{
22251286   UINT16 retdata = 0x0000;
r19245r19246
24841545
24851546
24861547
2487READ16_MEMBER( sega_segacd_device::cdc_dmaaddr_r )
2488{
2489   return CDC_DMA_ADDR;
2490}
24911548
2492WRITE16_MEMBER( sega_segacd_device::cdc_dmaaddr_w )
2493{
2494   COMBINE_DATA(&CDC_DMA_ADDR);
2495}
2496
2497READ16_MEMBER( sega_segacd_device::segacd_cdfader_r )
2498{
2499   return 0;
2500}
2501
2502WRITE16_MEMBER( sega_segacd_device::segacd_cdfader_w )
2503{
2504   static double cdfader_vol;
2505   if(data & 0x800f)
2506      printf("CD Fader register write %04x\n",data);
2507
2508   cdfader_vol = (double)((data & 0x3ff0) >> 4);
2509
2510   if(data & 0x4000)
2511      cdfader_vol = 100.0;
2512   else
2513      cdfader_vol = (cdfader_vol / 1024.0) * 100.0;
2514
2515   //printf("%f\n",cdfader_vol);
2516
2517   cdda_set_volume(space.machine().device(":segacd:cdda"), cdfader_vol);
2518}
2519
25201549READ16_MEMBER( sega_segacd_device::segacd_backupram_r )
25211550{
25221551   if(ACCESSING_BITS_8_15 && !(space.debugger_access()))
r19245r19246
25751604   _segacd_68k_cpu = machine().device<cpu_device>(":segacd:segacd_68k");
25761605   sega_cd_connected = 1;
25771606
2578   scd_dma_timer = machine().device<timer_device>(":segacd:scd_dma_timer");
25791607   segacd_gfx_conversion_timer = machine().device<timer_device>(":segacd:stamp_timer");
25801608   segacd_irq3_timer = machine().device<timer_device>(":segacd:irq3_timer");
1609   scd_dma_timer = machine().device<timer_device>(":segacd:scd_dma_timer");
25811610
25821611   address_space& space = machine().device("maincpu")->memory().space(AS_PROGRAM);
25831612
r19245r19246
26571686
26581687   segacd_hint_register = 0xffff; // -1
26591688
2660   /* init cd-rom device */
26611689
2662   lc89510_Reset();
26631690
2664   {
2665      cdrom_image_device *cddevice = machine().device<cdrom_image_device>("cdrom");
2666      if ( cddevice )
2667      {
2668         segacd.cd = cddevice->get_cdrom_file();
2669         if ( segacd.cd )
2670         {
2671            segacd.toc = cdrom_get_toc( segacd.cd );
2672            cdda_set_cdrom( machine().device(":segacd:cdda"), segacd.cd );
2673            cdda_stop_audio( machine().device( ":segacd:cdda" ) ); //stop any pending CD-DA
2674         }
2675      }
2676   }
2677
2678
2679   if (segacd.cd)
2680      printf("cd found\n");
2681
26821691   scd_rammode = 0;
26831692   scd_mode_dmna_ret_flags = 0x5421;
26841693
1694   lc89510_temp = machine().device<lc89510_temp_device>(":segacd:tempcdc");
1695   lc89510_temp->reset_cd();
1696   scd_dma_timer->adjust(attotime::zero);
26851697
26861698   stopwatch_timer = machine().device<timer_device>(":segacd:sw_timer");
26871699
2688   scd_dma_timer->adjust(attotime::zero);
26891700
26901701
26911702   // HACK!!!! timegal, anettfut, roadaven end up with the SubCPU waiting in a loop for *something*
r19245r19246
27261737}
27271738
27281739
1740// todo: tidy up
1741TIMER_DEVICE_CALLBACK_MEMBER( sega_segacd_device::scd_dma_timer_callback )
1742{
1743   // todo: accurate timing of this!
1744
1745   #define RATE 256
1746   lc89510_temp->CDC_Do_DMA(machine(), RATE);
1747
1748   // timed reset of flags
1749   scd_mode_dmna_ret_flags |= 0x0021;
1750
1751   scd_dma_timer->adjust(attotime::from_hz(megadriv_framerate) / megadrive_total_scanlines);
1752
1753}
1754
1755// todo: tidy up, too many CDC internals here
1756void sega_segacd_device::SegaCD_CDC_Do_DMA(int &dmacount, UINT8 *CDC_BUFFER, UINT16 &CDC_DMA_ADDR, UINT16 &CDC_DMA_ADDRC, UINT16 &destination )
1757{
1758   int length = dmacount;
1759   UINT8 *dest;
1760   int srcoffset = 0;
1761   int dstoffset = 0;
1762   address_space& space = machine().device(":segacd:segacd_68k")->memory().space(AS_PROGRAM);
1763
1764   bool PCM_DMA = false;
1765
1766   if (destination==DMA_PCM)
1767   {
1768      dstoffset = (CDC_DMA_ADDR & 0x03FF) << 2;
1769      PCM_DMA = true;
1770   }
1771   else
1772   {
1773      dstoffset = (CDC_DMA_ADDR & 0xFFFF) << 3;
1774   }
1775
1776
1777   while (dmacount--)
1778   {
1779      UINT16 data = (CDC_BUFFER[CDC_DMA_ADDRC+srcoffset]<<8) | CDC_BUFFER[CDC_DMA_ADDRC+srcoffset+1];
1780
1781      if (destination==DMA_PRG)
1782      {
1783         dest = (UINT8 *) segacd_4meg_prgram;
1784      }
1785      else if (destination==DMA_WRAM)
1786      {
1787         dest = (UINT8*)segacd_dataram;
1788      }
1789      else if (destination==DMA_PCM)
1790      {
1791         dest = 0;//fatalerror("PCM RAM DMA unimplemented!\n");
1792      }
1793      else
1794      {
1795         fatalerror("Unknown DMA Destination!!\n");
1796      }
1797
1798      if (PCM_DMA)
1799      {
1800         space.write_byte(0xff2000+(((dstoffset*2)+1)&0x1fff),data >> 8);
1801         space.write_byte(0xff2000+(((dstoffset*2)+3)&0x1fff),data & 0xff);
1802      //  printf("PCM_DMA writing %04x %04x\n",0xff2000+(dstoffset*2), data);
1803      }
1804      else
1805      {
1806         if (dest)
1807         {
1808            if (destination==DMA_WRAM)
1809            {
1810
1811               if ((scd_rammode&2)==RAM_MODE_2MEG)
1812               {
1813                  dstoffset &= 0x3ffff;
1814
1815                  dest[dstoffset+1] = data >>8;
1816                  dest[dstoffset+0] = data&0xff;
1817
1818                  segacd_mark_tiles_dirty(space.machine(), dstoffset/2);
1819               }
1820               else
1821               {
1822                  dstoffset &= 0x1ffff;
1823
1824                  if (!(scd_rammode & 1))
1825                  {
1826                     segacd_1meg_mode_word_write(space.machine(),(dstoffset+0x20000)/2, data, 0xffff, 0);
1827                  }
1828                  else
1829                  {
1830                     segacd_1meg_mode_word_write(space.machine(),(dstoffset+0x00000)/2, data, 0xffff, 0);
1831                  }
1832               }
1833
1834            }
1835            else
1836            {
1837               // main ram
1838               dest[dstoffset+1] = data >>8;
1839               dest[dstoffset+0] = data&0xff;
1840            }
1841
1842         }
1843      }
1844
1845      srcoffset += 2;
1846      dstoffset += 2;
1847   }
1848
1849
1850   if (PCM_DMA)
1851   {
1852      CDC_DMA_ADDR += length >> 1;
1853   }
1854   else
1855   {
1856      CDC_DMA_ADDR += length >> 2;
1857   }
1858}
1859
trunk/src/mame/machine/megacd.h
r19245r19246
11/* Sega CD / Mega CD */
22
33#include "machine/lc89510.h"
4#include "machine/megacdcd.h"
45
56
7#define RAM_MODE_2MEG (0)
8#define RAM_MODE_1MEG (2)
69
7
8#define READ_MAIN (0x0200)
9#define READ_SUB  (0x0300)
1010#define DMA_PCM  (0x0400)
1111#define DMA_PRG  (0x0500)
1212#define DMA_WRAM (0x0700)
1313
14#define REG_W_SBOUT  (0x0)
15#define REG_W_IFCTRL (0x1)
16#define REG_W_DBCL   (0x2)
17#define REG_W_DBCH   (0x3)
18#define REG_W_DACL   (0x4)
19#define REG_W_DACH   (0x5)
20#define REG_W_DTTRG  (0x6)
21#define REG_W_DTACK  (0x7)
22#define REG_W_WAL    (0x8)
23#define REG_W_WAH    (0x9)
24#define REG_W_CTRL0  (0xA)
25#define REG_W_CTRL1  (0xB)
26#define REG_W_PTL    (0xC)
27#define REG_W_PTH    (0xD)
28#define REG_W_CTRL2  (0xE)
29#define REG_W_RESET  (0xF)
30
31#define REG_R_COMIN  (0x0)
32#define REG_R_IFSTAT (0x1)
33#define REG_R_DBCL   (0x2)
34#define REG_R_DBCH   (0x3)
35#define REG_R_HEAD0  (0x4)
36#define REG_R_HEAD1  (0x5)
37#define REG_R_HEAD2  (0x6)
38#define REG_R_HEAD3  (0x7)
39#define REG_R_PTL    (0x8)
40#define REG_R_PTH    (0x9)
41#define REG_R_WAL    (0xa)
42#define REG_R_WAH    (0xb)
43#define REG_R_STAT0  (0xc)
44#define REG_R_STAT1  (0xd)
45#define REG_R_STAT2  (0xe)
46#define REG_R_STAT3  (0xf)
47
48#define CMD_STATUS   (0x0)
49#define CMD_STOPALL  (0x1)
50#define CMD_GETTOC   (0x2)
51#define CMD_READ     (0x3)
52#define CMD_SEEK     (0x4)
53//                   (0x5)
54#define CMD_STOP     (0x6)
55#define CMD_RESUME   (0x7)
56#define CMD_FF       (0x8)
57#define CMD_RW       (0x9)
58#define CMD_INIT     (0xa)
59//                   (0xb)
60#define CMD_CLOSE    (0xc)
61#define CMD_OPEN     (0xd)
62//                   (0xe)
63//                   (0xf)
64
65
66#define TOCCMD_CURPOS    (0x0)
67#define TOCCMD_TRKPOS    (0x1)
68#define TOCCMD_CURTRK    (0x2)
69#define TOCCMD_LENGTH    (0x3)
70#define TOCCMD_FIRSTLAST (0x4)
71#define TOCCMD_TRACKADDR (0x5)
72
73struct segacd_t
74{
75   cdrom_file   *cd;
76   const cdrom_toc   *toc;
77   UINT32 current_frame;
78};
79
80
81
82#define SECTOR_SIZE (2352)
83
84#define SET_CDD_DATA_MODE \
85   CDD_CONTROL |= 0x0100; \
86
87#define SET_CDD_AUDIO_MODE \
88   CDD_CONTROL &= ~0x0100; \
89
90#define STOP_CDC_READ \
91   SCD_STATUS_CDC &= ~0x01; \
92
93#define SET_CDC_READ \
94   SCD_STATUS_CDC |= 0x01; \
95
96#define SET_CDC_DMA \
97   SCD_STATUS_CDC |= 0x08; \
98
99#define STOP_CDC_DMA \
100   SCD_STATUS_CDC &= ~0x08; \
101
102#define SCD_READ_ENABLED \
103   (SCD_STATUS_CDC & 1)
104
105#define SCD_DMA_ENABLED \
106   (SCD_STATUS_CDC & 0x08)
107
108#define CLEAR_CDD_RESULT \
109   CDD_MIN = CDD_SEC = CDD_FRAME = CDD_EXT = 0; \
110
111#define CHECK_SCD_LV5_INTERRUPT \
112   if (segacd_irq_mask & 0x20) \
14// irq3 timer
15#define CHECK_SCD_LV3_INTERRUPT \
16   if (lc89510_temp->get_segacd_irq_mask() & 0x08) \
11317   { \
114      machine.device(":segacd:segacd_68k")->execute().set_input_line(5, HOLD_LINE); \
18      machine().device(":segacd:segacd_68k")->execute().set_input_line(3, HOLD_LINE); \
11519   } \
11620
117#define CHECK_SCD_LV4_INTERRUPT \
118   if (segacd_irq_mask & 0x10) \
119   { \
120      machine.device(":segacd:segacd_68k")->execute().set_input_line(4, HOLD_LINE); \
121   } \
122
123
124
12521// from master
12622#define CHECK_SCD_LV2_INTERRUPT \
127   if (segacd_irq_mask & 0x04) \
23   if (lc89510_temp->get_segacd_irq_mask() & 0x04) \
12824   { \
12925      machine.device(":segacd:segacd_68k")->execute().set_input_line(2, HOLD_LINE); \
13026   } \
13127
13228
133// irq3 timer
134#define CHECK_SCD_LV3_INTERRUPT \
135   if (segacd_irq_mask & 0x08) \
136   { \
137      machine().device(":segacd:segacd_68k")->execute().set_input_line(3, HOLD_LINE); \
138   } \
139
14029// gfx convert
14130#define CHECK_SCD_LV1_INTERRUPT \
142   if (segacd_irq_mask & 0x02) \
31   if (lc89510_temp->get_segacd_irq_mask() & 0x02) \
14332   { \
14433      machine().device(":segacd:segacd_68k")->execute().set_input_line(1, HOLD_LINE); \
14534   } \
14635
147#define CURRENT_TRACK_IS_DATA \
148   (segacd.toc->tracks[SCD_CURTRK - 1].trktype != CD_TRACK_AUDIO) \
14936
150
151#define RAM_MODE_2MEG (0)
152#define RAM_MODE_1MEG (2)
153
154
155#define CDD_PLAYINGCDDA   0x0100
156#define CDD_READY      0x0400
157#define CDD_STOPPED      0x0900
158
15937#define SEGACD_IRQ3_TIMER_SPEED (attotime::from_nsec(segacd_irq3_timer_reg*30720))
16038
16139
r19245r19246
328206
329207extern UINT16 a12000_halt_reset_reg;
330208
209
210
211
212
213
214
331215class sega_segacd_device : public device_t
332216{
333217public:
334218   sega_segacd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock, device_type type);
335219
336220   cpu_device *_segacd_68k_cpu;
221   lc89510_temp_device *lc89510_temp;
337222
338
339   UINT16 segacd_irq_mask;
340223   UINT16 *segacd_backupram;
341224   timer_device *stopwatch_timer;
342225   UINT8 segacd_font_color;
r19245r19246
347230   timer_device *segacd_gfx_conversion_timer;
348231   timer_device *segacd_irq3_timer;
349232   //timer_device *segacd_hock_timer;
350   timer_device* scd_dma_timer;
351233
352234   UINT16* segacd_4meg_prgram;  // pointer to SubCPU PrgRAM
353235   UINT16* segacd_dataram;
r19245r19246
380262   int segacd_ready;// = 1; // actually set 100ms after startup?
381263   UINT16 segacd_irq3_timer_reg;
382264
383   segacd_t segacd;
384265
385   UINT8    SCD_BUFFER[2560];
386   UINT32   SCD_STATUS;
387   UINT32   SCD_STATUS_CDC;
388   INT32    SCD_CURLBA;
389   UINT8    SCD_CURTRK;
390
391   UINT16 CDC_DECODE;
392   INT16 CDC_DMACNT; // can go negative
393   UINT16 CDC_DMA_ADDRC;
394   UINT16 CDC_PT;
395   UINT16 CDC_WA;
396   UINT16 CDC_REG0;
397   UINT16 CDC_REG1;
398   UINT16 CDC_DMA_ADDR;
399   UINT16 CDC_IFSTAT;
400   UINT8 CDC_HEADB0;
401   UINT8 CDC_HEADB1;
402   UINT8 CDC_HEADB2;
403   UINT8 CDC_HEADB3;
404   UINT8 CDC_STATB0;
405   UINT8 CDC_STATB1;
406   UINT8 CDC_STATB2;
407   UINT8 CDC_STATB3;
408   UINT16 CDC_SBOUT;
409   UINT16 CDC_IFCTRL;
410   UINT8 CDC_CTRLB0;
411   UINT8 CDC_CTRLB1;
412   UINT8 CDC_CTRLB2;
413   UINT8 CDC_BUFFER[(32 * 1024 * 2) + SECTOR_SIZE];
414
415   UINT32 CDD_STATUS;
416   UINT32 CDD_MIN;
417   UINT32 CDD_SEC;
418
419   UINT8 CDD_RX[10];
420   UINT8 CDD_TX[10];
421   UINT32 CDD_FRAME;
422   UINT32 CDD_EXT;
423   UINT16 CDD_CONTROL;
424   INT16  CDD_DONE;
425
426266   TIMER_DEVICE_CALLBACK_MEMBER( segacd_irq3_timer_callback );
427   TIMER_DEVICE_CALLBACK_MEMBER( scd_dma_timer_callback );
428   TIMER_DEVICE_CALLBACK_MEMBER( segacd_access_timer_callback );
429267   TIMER_DEVICE_CALLBACK_MEMBER( segacd_gfx_conversion_timer_callback );
430268
431269   UINT16 handle_segacd_sub_int_callback(int irqline);
432270
433   inline int to_bcd(int val, bool byte);
434271   inline void write_pixel(running_machine& machine, UINT8 pix, int pixeloffset );
435272   UINT16 segacd_1meg_mode_word_read(int offset, UINT16 mem_mask);
436273   void segacd_1meg_mode_word_write(running_machine& machine, int offset, UINT16 data, UINT16 mem_mask, int use_pm);
437   void set_data_audio_mode(void);
438   void CDD_DoChecksum(void);
439   void CDD_Export(void);
440   void CDC_UpdateHEAD(void);
441   void scd_ctrl_checks(running_machine& machine);
442   void scd_advance_current_readpos(void);
443   int Read_LBA_To_Buffer(running_machine& machine);
444   void CheckCommand(running_machine& machine);
445   void CDD_GetStatus(void);
446   void CDD_Stop(running_machine &machine);
447   void CDD_GetPos(void);
448   void CDD_GetTrackPos(void);
449   void CDD_GetTrack(void);
450   void CDD_Length(void);
451   void CDD_FirstLast(void);
452   void CDD_GetTrackAdr(void);
453   UINT32 getmsf_from_regs(void);
454   void CDD_Play(running_machine &machine);
455   void CDD_Seek(void);
456   void CDD_Pause(running_machine &machine);
457   void CDD_Resume(running_machine &machine);
458   void CDD_FF(running_machine &machine);
459   void CDD_RW(running_machine &machine);
460   void CDD_Open(void);
461   void CDD_Close(void);
462   void CDD_Init(void);
463   void CDD_Default(void);
464   void CDD_Reset(void);
465   void CDC_Reset(void);
466   void lc89510_Reset(void);
467   void CDC_End_Transfer(running_machine& machine);
468   void CDC_Do_DMA(running_machine& machine, int rate);
469   UINT16 CDC_Host_r(running_machine& machine, UINT16 type);
470   UINT8 CDC_Reg_r(void);
471   void CDC_Reg_w(UINT8 data);
472   void CDD_Process(running_machine& machine, int reason);
473   void CDD_Handle_TOC_Commands(void);
474   void CDD_Import(running_machine& machine);
475274
275
276
277
476278   void segacd_mark_tiles_dirty(running_machine& machine, int offset);
477279   int segacd_get_active_stampmap_tilemap(void);
478280
r19245r19246
516318   READ16_MEMBER( segacd_comms_sub_part2_r );
517319   WRITE16_MEMBER( segacd_comms_sub_part2_w );
518320
519   WRITE16_MEMBER( segacd_cdc_mode_address_w );
520   READ16_MEMBER( segacd_cdc_mode_address_r );
521   WRITE16_MEMBER( segacd_cdc_data_w );
522   READ16_MEMBER( segacd_cdc_data_r );
523321
322
524323   READ16_MEMBER( segacd_main_dataram_part1_r );
525324   WRITE16_MEMBER( segacd_main_dataram_part1_w );
526325
r19245r19246
528327   READ16_MEMBER( scd_a12006_hint_register_r );
529328   WRITE16_MEMBER( scd_a12006_hint_register_w );
530329
531   READ16_MEMBER( cdc_data_sub_r );
532   READ16_MEMBER( cdc_data_main_r );
330
533331   WRITE16_MEMBER( segacd_stopwatch_timer_w );
534332   READ16_MEMBER( segacd_stopwatch_timer_r );
535333   READ16_MEMBER( segacd_sub_led_ready_r );
r19245r19246
538336   WRITE16_MEMBER( segacd_sub_dataram_part1_w );
539337   READ16_MEMBER( segacd_sub_dataram_part2_r );
540338   WRITE16_MEMBER( segacd_sub_dataram_part2_w );
541   READ16_MEMBER( segacd_irq_mask_r );
542   WRITE16_MEMBER( segacd_irq_mask_w );
543   READ16_MEMBER( segacd_cdd_ctrl_r );
544   WRITE16_MEMBER( segacd_cdd_ctrl_w );
545   READ8_MEMBER( segacd_cdd_rx_r );
546   WRITE8_MEMBER( segacd_cdd_tx_w );
339
340
547341   READ16_MEMBER( segacd_stampsize_r );
548342   WRITE16_MEMBER( segacd_stampsize_w );
549343
r19245r19246
564358   WRITE16_MEMBER( segacd_imagebuffer_hdot_size_w );
565359   READ16_MEMBER( segacd_irq3timer_r );
566360   WRITE16_MEMBER( segacd_irq3timer_w );
567   READ16_MEMBER( cdc_dmaaddr_r );
568   WRITE16_MEMBER( cdc_dmaaddr_w );
569   READ16_MEMBER( segacd_cdfader_r );
570   WRITE16_MEMBER( segacd_cdfader_w );
571361   READ16_MEMBER( segacd_backupram_r );
572362   WRITE16_MEMBER( segacd_backupram_w );
573363   READ16_MEMBER( segacd_font_color_r );
574364   WRITE16_MEMBER( segacd_font_color_w );
575365   READ16_MEMBER( segacd_font_converted_r );
366   TIMER_DEVICE_CALLBACK_MEMBER( scd_dma_timer_callback );
576367
368   void SegaCD_CDC_Do_DMA( int &dmacount, UINT8 *CDC_BUFFER, UINT16 &CDC_DMA_ADDR, UINT16 &CDC_DMA_ADDRC, UINT16 &destination );
369   timer_device* scd_dma_timer;
370
577371protected:
578372   virtual void device_start();
579373   virtual void device_reset();
r19245r19246
615409extern const device_type SEGA_SEGACD_US;
616410extern const device_type SEGA_SEGACD_JAPAN;
617411extern const device_type SEGA_SEGACD_EUROPE;
412
413
trunk/src/mame/machine/megacdcd.c
r0r19246
1/* CD controller code from megacd.c, used by Sega Cd / Mega CD */
2
3/* todo: cleanup(!!), make more generic, unifiy implementation with NeoCD, turn into a device and move to the proper lc89510.c file
4  currently this is a bit of a mix of system specific bits, incomplete implementations etc. as well as a rather kludgy combination
5  of the CDC and drive emulation. */
6
7
8#include "emu.h"
9#include "machine/megacdcd.h"
10
11const device_type LC89510_TEMP = &device_creator<lc89510_temp_device>;
12
13lc89510_temp_device::lc89510_temp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
14   : device_t(mconfig, LC89510_TEMP, "lc89510_temp_device", tag, owner, clock)
15{
16   segacd_dma_callback =  segacd_dma_delegate(FUNC(lc89510_temp_device::Fake_CDC_Do_DMA), this);
17   is_neoCD = false;
18
19   nff0002 = 0;
20   nIRQAcknowledge = ~0;
21   for (int i=0;i<10;i++)
22      CDD_TX[i] = 0;
23   for (int i=0;i<10;i++)
24      CDD_RX[i] = 0;
25   NeoCDCommsWordCount = 0;
26   NeoCDAssyStatus = 0;
27   NeoCDTrack = 0;
28   NeoCDSectorMin = 0;
29   NeoCDSectorSec = 0;
30   NeoCDSectorFrm = 0;
31   SCD_CURLBA = 0;
32   for (int i=0;i<2352;i++)
33      NeoCDSectorData[i] = 0;
34   bNeoCDLoadSector = false;
35   NeoCDDMAAddress1 = 0;
36   NeoCDDMAAddress2 = 0;
37   NeoCDDMAValue1   = 0;
38   NeoCDDMAValue2   = 0;
39   NeoCDDMACount    = 0;
40   NeoCDDMAMode = 0;
41   CDC_REG0 = 0;
42   nNeoCDIRQVectorAck = 0;
43   nNeoCDIRQVector = 0;
44}
45
46
47void lc89510_temp_device::set_CDC_Do_DMA(device_t &device,segacd_dma_delegate new_segacd_dma_callback)
48{
49   lc89510_temp_device &dev = downcast<lc89510_temp_device &>(device);
50   dev.segacd_dma_callback = new_segacd_dma_callback;
51}
52
53void lc89510_temp_device::set_is_neoCD(device_t &device, bool is_neoCD)
54{
55   lc89510_temp_device &dev = downcast<lc89510_temp_device &>(device);
56   dev.is_neoCD = is_neoCD;
57}
58
59// HACK for DMA handling, this gets replaced
60void lc89510_temp_device::Fake_CDC_Do_DMA(int &dmacount, UINT8 *CDC_BUFFER, UINT16 &CDC_DMA_ADDR, UINT16 &CDC_DMA_ADDRC, UINT16 &destination )
61{
62   fatalerror("Fake_CDC_Do_DMA\n");
63}
64
65void lc89510_temp_device::device_start()
66{
67   segacd_dma_callback.bind_relative_to(*owner());
68   m_cdda = (cdda_device*)subdevice("cdda");
69}
70
71void lc89510_temp_device::device_reset()
72{
73
74}
75
76
77inline int lc89510_temp_device::to_bcd(int val, bool byte)
78{
79   if (val > 99) val = 99;
80
81   if (byte) return (((val) / 10) << 4) + ((val) % 10);
82   else return (((val) / 10) << 8) + ((val) % 10);
83}
84
85
86
87void lc89510_temp_device::set_data_audio_mode(void)
88{
89   if (CURRENT_TRACK_IS_DATA)
90   {
91      SET_CDD_DATA_MODE
92   }
93   else
94   {
95      SET_CDD_AUDIO_MODE
96      //fatalerror("CDDA unsupported\n");
97   }
98}
99
100void lc89510_temp_device::CDD_DoChecksum(void)
101{
102   int checksum =
103      CDD_RX[0] +
104      CDD_RX[1] +
105      CDD_RX[2] +
106      CDD_RX[3] +
107      CDD_RX[4] +
108      CDD_RX[5] +
109      CDD_RX[6] +
110      CDD_RX[7] +
111      CDD_RX[8];
112
113   checksum &= 0xf;
114   checksum ^= 0xf;
115
116   CDD_RX[9] = checksum;
117}
118
119void lc89510_temp_device::CDD_Export(void)
120{
121   CDD_RX[0] = (CDD_STATUS  & 0xff00)>>8;
122   CDD_RX[1] = (CDD_STATUS  & 0x00ff)>>0;
123   CDD_RX[2] = (CDD_MIN  & 0xff00)>>8;
124   CDD_RX[3] = (CDD_MIN  & 0x00ff)>>0;
125   CDD_RX[4] = (CDD_SEC & 0xff00)>>8;
126   CDD_RX[5] = (CDD_SEC & 0x00ff)>>0;
127   CDD_RX[6] = (CDD_FRAME   & 0xff00)>>8;
128   CDD_RX[7] = (CDD_FRAME   & 0x00ff)>>0;
129   CDD_RX[8] = (CDD_EXT     & 0x00ff)>>0;
130   /* 9 = checksum */
131
132   CDD_DoChecksum();
133
134   CDD_CONTROL &= ~4; // Clear HOCK bit
135
136}
137
138
139
140
141
142void lc89510_temp_device::CheckCommand(running_machine& machine)
143{
144   if (CDD_DONE)
145   {
146      CDD_DONE = 0;
147      CDD_Export();
148      CHECK_SCD_LV4_INTERRUPT
149   }
150
151   if (SCD_READ_ENABLED)
152   {
153      set_data_audio_mode();
154      Read_LBA_To_Buffer(machine);
155   }
156}
157
158
159void lc89510_temp_device::CDD_GetStatus(void)
160{
161   UINT16 s = (CDD_STATUS & 0x0f00);
162
163   if ((s == 0x0200) || (s == 0x0700) || (s == 0x0e00))
164      CDD_STATUS = (SCD_STATUS & 0xff00) | (CDD_STATUS & 0x00ff);
165}
166
167
168void lc89510_temp_device::CDD_Stop(running_machine &machine)
169{
170   CLEAR_CDD_RESULT
171   STOP_CDC_READ
172   SCD_STATUS = CDD_STOPPED;
173   CDD_STATUS = 0x0000;
174   SET_CDD_DATA_MODE
175   cdda_stop_audio( m_cdda ); //stop any pending CD-DA
176}
177
178
179void lc89510_temp_device::CDD_GetPos(void)
180{
181   CLEAR_CDD_RESULT
182   UINT32 msf;
183   CDD_STATUS &= 0xFF;
184   if(segacd.cd == NULL) // no cd is there, bail out
185      return;
186   CDD_STATUS |= SCD_STATUS;
187   msf = lba_to_msf_alt(SCD_CURLBA+150);
188   CDD_MIN = to_bcd(((msf & 0x00ff0000)>>16),false);
189   CDD_SEC = to_bcd(((msf & 0x0000ff00)>>8),false);
190   CDD_FRAME = to_bcd(((msf & 0x000000ff)>>0),false);
191}
192
193void lc89510_temp_device::CDD_GetTrackPos(void)
194{
195   CLEAR_CDD_RESULT
196   int elapsedlba;
197   UINT32 msf;
198   CDD_STATUS &= 0xFF;
199   //  UINT32 end_msf = ;
200   if(segacd.cd == NULL) // no cd is there, bail out
201      return;
202   CDD_STATUS |= SCD_STATUS;
203   elapsedlba = SCD_CURLBA - segacd.toc->tracks[ cdrom_get_track(segacd.cd, SCD_CURLBA) ].physframeofs;
204   msf = lba_to_msf_alt (elapsedlba);
205   //popmessage("%08x %08x",SCD_CURLBA,segacd.toc->tracks[ cdrom_get_track(segacd.cd, SCD_CURLBA) + 1 ].physframeofs);
206   CDD_MIN = to_bcd(((msf & 0x00ff0000)>>16),false);
207   CDD_SEC = to_bcd(((msf & 0x0000ff00)>>8),false);
208   CDD_FRAME = to_bcd(((msf & 0x000000ff)>>0),false);
209}
210
211void lc89510_temp_device::CDD_GetTrack(void)
212{
213   CLEAR_CDD_RESULT
214   CDD_STATUS &= 0xFF;
215   if(segacd.cd == NULL) // no cd is there, bail out
216      return;
217   CDD_STATUS |= SCD_STATUS;
218   SCD_CURTRK = cdrom_get_track(segacd.cd, SCD_CURLBA)+1;
219   CDD_MIN = to_bcd(SCD_CURTRK, false);
220}
221
222void lc89510_temp_device::CDD_Length(void)
223{
224   CLEAR_CDD_RESULT
225   CDD_STATUS &= 0xFF;
226   if(segacd.cd == NULL) // no cd is there, bail out
227      return;
228   CDD_STATUS |= SCD_STATUS;
229
230   UINT32 startlba = (segacd.toc->tracks[cdrom_get_last_track(segacd.cd)].physframeofs);
231   UINT32 startmsf = lba_to_msf_alt( startlba );
232
233   CDD_MIN = to_bcd((startmsf&0x00ff0000)>>16,false);
234   CDD_SEC = to_bcd((startmsf&0x0000ff00)>>8,false);
235   CDD_FRAME = to_bcd((startmsf&0x000000ff)>>0,false);
236}
237
238
239void lc89510_temp_device::CDD_FirstLast(void)
240{
241   CLEAR_CDD_RESULT
242   CDD_STATUS &= 0xFF;
243   if(segacd.cd == NULL) // no cd is there, bail out
244      return;
245   CDD_STATUS |= SCD_STATUS;
246   CDD_MIN = 1; // first
247   CDD_SEC = to_bcd(cdrom_get_last_track(segacd.cd),false); // last
248}
249
250void lc89510_temp_device::CDD_GetTrackAdr(void)
251{
252   CLEAR_CDD_RESULT
253
254   int track = (CDD_TX[5] & 0xF) + (CDD_TX[4] & 0xF) * 10;
255   int last_track = cdrom_get_last_track(segacd.cd);
256
257   CDD_STATUS &= 0xFF;
258   if(segacd.cd == NULL) // no cd is there, bail out
259      return;
260   CDD_STATUS |= SCD_STATUS;
261
262   if (track > last_track)
263      track = last_track;
264
265   if (track < 1)
266      track = 1;
267
268   UINT32 startlba = (segacd.toc->tracks[track-1].physframeofs);
269   UINT32 startmsf = lba_to_msf_alt( startlba+150 );
270
271   CDD_MIN = to_bcd((startmsf&0x00ff0000)>>16,false);
272   CDD_SEC = to_bcd((startmsf&0x0000ff00)>>8,false);
273   CDD_FRAME = to_bcd((startmsf&0x000000ff)>>0,false);
274   CDD_EXT = track % 10;
275
276   if (segacd.toc->tracks[track - 1].trktype != CD_TRACK_AUDIO)
277      CDD_FRAME |= 0x0800;
278}
279
280UINT32 lc89510_temp_device::getmsf_from_regs(void)
281{
282   UINT32 msf = 0;
283
284   msf  = ((CDD_TX[3] & 0xF) + (CDD_TX[2] & 0xF) * 10) << 16;
285   msf |= ((CDD_TX[5] & 0xF) + (CDD_TX[4] & 0xF) * 10) << 8;
286   msf |= ((CDD_TX[7] & 0xF) + (CDD_TX[6] & 0xF) * 10) << 0;
287
288   return msf;
289}
290
291void lc89510_temp_device::CDD_Play(running_machine &machine)
292{
293   CLEAR_CDD_RESULT
294   UINT32 msf = getmsf_from_regs();
295   SCD_CURLBA = msf_to_lba(msf)-150;
296   UINT32 end_msf = segacd.toc->tracks[ cdrom_get_track(segacd.cd, SCD_CURLBA) + 1 ].physframeofs;
297   SCD_CURTRK = cdrom_get_track(segacd.cd, SCD_CURLBA)+1;
298   CDC_UpdateHEAD();
299   SCD_STATUS = CDD_PLAYINGCDDA;
300   CDD_STATUS = 0x0102;
301   set_data_audio_mode();
302   printf("%d Track played\n",SCD_CURTRK);
303   CDD_MIN = to_bcd(SCD_CURTRK, false);
304   if(!(CURRENT_TRACK_IS_DATA))
305      cdda_start_audio( m_cdda, SCD_CURLBA, end_msf - SCD_CURLBA );
306   SET_CDC_READ
307}
308
309
310void lc89510_temp_device::CDD_Seek(void)
311{
312   CLEAR_CDD_RESULT
313   UINT32 msf = getmsf_from_regs();
314   SCD_CURLBA = msf_to_lba(msf)-150;
315   SCD_CURTRK = cdrom_get_track(segacd.cd, SCD_CURLBA)+1;
316   CDC_UpdateHEAD();
317   STOP_CDC_READ
318   SCD_STATUS = CDD_READY;
319   CDD_STATUS = 0x0200;
320   set_data_audio_mode();
321}
322
323
324void lc89510_temp_device::CDD_Pause(running_machine &machine)
325{
326   CLEAR_CDD_RESULT
327   STOP_CDC_READ
328   SCD_STATUS = CDD_READY;
329   CDD_STATUS = SCD_STATUS;
330   SET_CDD_DATA_MODE
331
332   //segacd.current_frame = cdda_get_audio_lba( machine.device( "cdda" ) );
333   //if(!(CURRENT_TRACK_IS_DATA))
334   cdda_pause_audio( m_cdda, 1 );
335}
336
337void lc89510_temp_device::CDD_Resume(running_machine &machine)
338{
339   CLEAR_CDD_RESULT
340   STOP_CDC_READ
341   SCD_CURTRK = cdrom_get_track(segacd.cd, SCD_CURLBA)+1;
342   SCD_STATUS = CDD_PLAYINGCDDA;
343   CDD_STATUS = 0x0102;
344   set_data_audio_mode();
345   CDD_MIN = to_bcd (SCD_CURTRK, false);
346   SET_CDC_READ
347   //if(!(CURRENT_TRACK_IS_DATA))
348   cdda_pause_audio( m_cdda, 0 );
349}
350
351
352void lc89510_temp_device::CDD_FF(running_machine &machine)
353{
354   fatalerror("Fast Forward unsupported\n");
355}
356
357
358void lc89510_temp_device::CDD_RW(running_machine &machine)
359{
360   fatalerror("Fast Rewind unsupported\n");
361}
362
363
364void lc89510_temp_device::CDD_Open(void)
365{
366   fatalerror("Close Tray unsupported\n");
367   /* TODO: re-read CD-ROM buffer here (Mega CD has multi disc games iirc?) */
368}
369
370
371void lc89510_temp_device::CDD_Close(void)
372{
373   fatalerror("Open Tray unsupported\n");
374   /* TODO: clear CD-ROM buffer here */
375}
376
377
378void lc89510_temp_device::CDD_Init(void)
379{
380   CLEAR_CDD_RESULT
381   STOP_CDC_READ
382   SCD_STATUS = CDD_READY;
383   CDD_STATUS = SCD_STATUS;
384   CDD_SEC = 1;
385   CDD_FRAME = 1;
386}
387
388
389void lc89510_temp_device::CDD_Default(void)
390{
391   CLEAR_CDD_RESULT
392   CDD_STATUS = SCD_STATUS;
393}
394
395
396void lc89510_temp_device::CDD_Reset(void)
397{
398   CLEAR_CDD_RESULT
399   CDD_CONTROL = CDD_STATUS = 0;
400
401   for (int i = 0; i < 10; i++)
402      CDD_RX[i] = CDD_TX[i] = 0;
403
404   CDD_DoChecksum();
405
406   SCD_CURTRK = SCD_CURLBA = 0;
407   SCD_STATUS = CDD_READY;
408}
409
410void lc89510_temp_device::CDC_Reset(void)
411{
412   memset(CDC_BUFFER, 0x00, ((16 * 1024 * 2) + SECTOR_SIZE));
413   CDC_UpdateHEAD();
414
415   CDC_DMA_ADDRC = CDC_DMACNT = CDC_PT = CDC_SBOUT = CDC_IFCTRL = CDC_CTRLB0 = CDC_CTRLB1 =
416      CDC_CTRLB2 = CDC_HEADB1 = CDC_HEADB2 = CDC_HEADB3 = CDC_STATB0 = CDC_STATB1 = CDC_STATB2 = CDC_DECODE = 0;
417
418   CDC_IFSTAT = 0xFF;
419   CDC_WA = SECTOR_SIZE * 2;
420   CDC_HEADB0 = 0x01;
421   CDC_STATB3 = 0x80;
422}
423
424
425void lc89510_temp_device::lc89510_Reset(void)
426{
427   CDD_Reset();
428   CDC_Reset();
429
430   CDC_REG0 = CDC_REG1 = CDC_DMA_ADDR = SCD_STATUS_CDC = CDD_DONE = 0;
431}
432
433void lc89510_temp_device::CDC_End_Transfer(running_machine& machine)
434{
435   STOP_CDC_DMA
436   CDC_REG0 |= 0x8000;
437   CDC_REG0 &= ~0x4000;
438   CDC_IFSTAT |= 0x08;
439
440   if (CDC_IFCTRL & 0x40)
441   {
442      CDC_IFSTAT &= ~0x40;
443      CHECK_SCD_LV5_INTERRUPT
444   }
445}
446
447
448void lc89510_temp_device::CDC_Do_DMA(running_machine& machine, int rate)
449{
450   UINT32 length;
451
452   UINT16 destination = CDC_REG0 & 0x0700;
453
454   if (!(SCD_DMA_ENABLED))
455      return;
456
457   if ((destination == READ_MAIN) || (destination==READ_SUB))
458   {
459      CDC_REG0 |= 0x4000;
460      return;
461   }
462
463   if (CDC_DMACNT <= (rate * 2))
464   {
465      length = (CDC_DMACNT + 1) >> 1;
466      CDC_End_Transfer(machine);
467   }
468   else
469      length = rate;
470
471
472   int dmacount = length;
473
474   // HACK
475   segacd_dma_callback(dmacount, CDC_BUFFER, CDC_DMA_ADDR, CDC_DMA_ADDRC, destination );
476   
477
478   CDC_DMA_ADDRC += length*2;
479
480   if (SCD_DMA_ENABLED)
481      CDC_DMACNT -= length*2;
482   else
483      CDC_DMACNT = 0;
484}
485
486
487
488
489UINT16 lc89510_temp_device::CDC_Host_r(running_machine& machine, UINT16 type)
490{
491   UINT16 destination = CDC_REG0 & 0x0700;
492
493   if (SCD_DMA_ENABLED)
494   {
495      if (destination == type)
496      {
497         CDC_DMACNT -= 2;
498
499         if (CDC_DMACNT <= 0)
500         {
501            if (type==READ_SUB) CDC_DMACNT = 0;
502
503            CDC_End_Transfer(machine);
504         }
505
506         UINT16 data = (CDC_BUFFER[CDC_DMA_ADDRC]<<8) | CDC_BUFFER[CDC_DMA_ADDRC+1];
507         CDC_DMA_ADDRC += 2;
508
509         return data;
510      }
511   }
512
513   return 0;
514}
515
516
517UINT8 lc89510_temp_device::CDC_Reg_r(void)
518{
519   int reg = CDC_REG0 & 0xF;
520   UINT8 ret = 0;
521   UINT16 decoderegs = 0x73F2;
522
523   if ((decoderegs>>reg)&1)
524      CDC_DECODE |= (1 << reg);
525
526   //if (reg!=REG_R_STAT3)
527      CDC_REG0 = (CDC_REG0 & 0xFFF0) | ((reg+1)&0xf);
528
529
530   switch (reg)
531   {
532      case REG_R_COMIN:  ret = 0/*COMIN*/;            break;
533      case REG_R_IFSTAT: ret = CDC_IFSTAT;           break;
534      case REG_R_DBCL:   ret = CDC_DMACNT & 0xff;       break;
535      case REG_R_DBCH:   ret = (CDC_DMACNT >>8) & 0xff; break;
536      case REG_R_HEAD0:  ret = CDC_HEADB0;           break;
537      case REG_R_HEAD1:  ret = CDC_HEADB1;           break;
538      case REG_R_HEAD2:  ret = CDC_HEADB2;           break;
539      case REG_R_HEAD3:  ret = CDC_HEADB3;           break;
540      case REG_R_PTL:      ret = CDC_PT & 0xff;        break;
541      case REG_R_PTH:      ret = (CDC_PT >>8) & 0xff;  break;
542      case REG_R_WAL:    ret = CDC_WA & 0xff;        break;
543      case REG_R_WAH:    ret = (CDC_WA >>8) & 0xff;  break;
544      case REG_R_STAT0:  ret = CDC_STATB0;           break;
545      case REG_R_STAT1:  ret = CDC_STATB1;           break;
546      case REG_R_STAT2:  ret = CDC_STATB2;           break;
547      case REG_R_STAT3:  ret = CDC_STATB3;
548
549         CDC_IFSTAT |= 0x20;
550
551         // ??
552         if ((CDC_CTRLB0 & 0x80) && (CDC_IFCTRL & 0x20))
553         {
554            if ((CDC_DECODE & decoderegs) == decoderegs)
555            CDC_STATB3 = 0x80;
556         }
557         break;
558   }
559
560   return ret;
561}
562
563void lc89510_temp_device::CDC_Reg_w(UINT8 data)
564{
565   int reg = CDC_REG0 & 0xF;
566
567   int changers0[0x10] = { 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0};
568
569   if (changers0[reg])
570      CDC_REG0 = (CDC_REG0 & 0xFFF0) | (reg+1);
571
572   switch (reg)
573   {
574   case REG_W_SBOUT:
575         CDC_SBOUT = data;
576         break;
577
578   case REG_W_IFCTRL:
579         CDC_IFCTRL = data;
580
581         if (!(CDC_IFCTRL & 0x02))
582         {
583            CDC_DMACNT = 0;
584            STOP_CDC_DMA;
585            CDC_IFSTAT |= 0x08;
586         }
587         break;
588
589   case REG_W_DBCL: CDC_DMACNT = (CDC_DMACNT &~ 0x00ff) | (data & 0x00ff) << 0; break;
590   case REG_W_DBCH: CDC_DMACNT = (CDC_DMACNT &~ 0xff00) | (data & 0x00ff) << 8; break;
591   case REG_W_DACL: CDC_DMA_ADDRC = (CDC_DMA_ADDRC &~ 0x00ff) | (data & 0x00ff) << 0; break;
592   case REG_W_DACH: CDC_DMA_ADDRC = (CDC_DMA_ADDRC &~ 0xff00) | (data & 0x00ff) << 8; break;
593
594   case REG_W_DTTRG:
595         if (CDC_IFCTRL & 0x02)
596         {
597            CDC_IFSTAT &= ~0x08;
598            SET_CDC_DMA;
599            CDC_REG0 &= ~0x8000;
600         }
601         break;
602
603   case REG_W_DTACK: CDC_IFSTAT |= 0x40; break;
604   case REG_W_WAL: CDC_WA = (CDC_WA &~ 0x00ff) | (data & 0x00ff) << 0; break;
605   case REG_W_WAH:   CDC_WA = (CDC_WA &~ 0xff00) | (data & 0x00ff) << 8;   break;
606   case REG_W_CTRL0: CDC_CTRLB0 = data; break;
607   case REG_W_CTRL1: CDC_CTRLB1 = data; break;
608   case REG_W_PTL: CDC_PT = (CDC_PT &~ 0x00ff) | (data & 0x00ff) << 0; break;
609   case REG_W_PTH: CDC_PT = (CDC_PT &~ 0xff00) | (data & 0x00ff) << 8;   break;
610   case REG_W_CTRL2: CDC_CTRLB2 = data; break;
611   case REG_W_RESET: CDC_Reset();       break;
612   }
613}
614
615void lc89510_temp_device::CDD_Process(running_machine& machine, int reason)
616{
617   CDD_Export();
618   CHECK_SCD_LV4_INTERRUPT
619}
620
621void lc89510_temp_device::CDD_Handle_TOC_Commands(void)
622{
623   int subcmd = CDD_TX[3];
624   CDD_STATUS = (CDD_STATUS & 0xFF00) | subcmd;
625
626   switch (subcmd)
627   {
628      case TOCCMD_CURPOS:      CDD_GetPos();     break;
629      case TOCCMD_TRKPOS:      CDD_GetTrackPos(); break;
630      case TOCCMD_CURTRK:    CDD_GetTrack();   break;
631      case TOCCMD_LENGTH:    CDD_Length();      break;
632      case TOCCMD_FIRSTLAST: CDD_FirstLast();   break;
633      case TOCCMD_TRACKADDR: CDD_GetTrackAdr(); break;
634      default:               CDD_GetStatus();   break;
635   }
636}
637
638static const char *const CDD_import_cmdnames[] =
639{
640   "Get Status",         // 0
641   "Stop ALL",            // 1
642   "Handle TOC",         // 2
643   "Play",               // 3
644   "Seek",               // 4
645   "<undefined>",         // 5
646   "Pause",            // 6
647   "Resume",            // 7
648   "FF",               // 8
649   "RWD",               // 9
650   "INIT",               // A
651   "<undefined>",         // B
652   "Close Tray",         // C
653   "Open Tray",         // D
654   "<undefined>",         // E
655   "<undefined>"         // F
656};
657
658void lc89510_temp_device::CDD_Import(running_machine& machine)
659{
660   if(CDD_TX[0] != 2 && CDD_TX[0] != 0)
661      printf("%s\n",CDD_import_cmdnames[CDD_TX[0]]);
662
663   switch (CDD_TX[0])
664   {
665      case CMD_STATUS:   CDD_GetStatus();          break;
666      case CMD_STOPALL:   CDD_Stop(machine);         break;
667      case CMD_GETTOC:   CDD_Handle_TOC_Commands(); break;
668      case CMD_READ:      CDD_Play(machine);         break;
669      case CMD_SEEK:      CDD_Seek();                  break;
670      case CMD_STOP:      CDD_Pause(machine);          break;
671      case CMD_RESUME:   CDD_Resume(machine);       break;
672      case CMD_FF:      CDD_FF(machine);           break;
673      case CMD_RW:      CDD_RW(machine);           break;
674      case CMD_INIT:      CDD_Init();                  break;
675      case CMD_CLOSE:      CDD_Open();                break;
676      case CMD_OPEN:      CDD_Close();              break;
677      default:         CDD_Default();              break;
678   }
679
680   CDD_DONE = 1;
681}
682
683
684/**************************************************************
685 CDC Stuff ********
686**************************************************************/
687
688
689
690WRITE16_MEMBER( lc89510_temp_device::segacd_cdc_mode_address_w )
691{
692   COMBINE_DATA(&CDC_REG0);
693}
694
695READ16_MEMBER( lc89510_temp_device::segacd_cdc_mode_address_r )
696{
697   return CDC_REG0;
698}
699
700WRITE16_MEMBER( lc89510_temp_device::segacd_cdc_data_w )
701{
702   COMBINE_DATA(&CDC_REG1);
703
704   if (ACCESSING_BITS_0_7)
705      CDC_Reg_w(data);
706}
707
708READ16_MEMBER( lc89510_temp_device::segacd_cdc_data_r )
709{
710   UINT16 retdat = 0x0000;
711
712   if (ACCESSING_BITS_0_7)
713      retdat |= CDC_Reg_r();
714
715   return retdat;
716}
717
718
719READ16_MEMBER( lc89510_temp_device::cdc_data_sub_r )
720{
721   return CDC_Host_r(space.machine(), READ_SUB);
722}
723
724READ16_MEMBER( lc89510_temp_device::cdc_data_main_r )
725{
726   return CDC_Host_r(space.machine(), READ_MAIN);
727}
728
729
730
731
732READ16_MEMBER( lc89510_temp_device::segacd_irq_mask_r )
733{
734
735   return segacd_irq_mask;
736}
737
738WRITE16_MEMBER( lc89510_temp_device::segacd_irq_mask_w )
739{
740   if (ACCESSING_BITS_0_7)
741   {
742      UINT16 control = CDD_CONTROL;
743
744   //  printf("segacd_irq_mask_w %04x %04x (CDD control is %04x)\n",data, mem_mask, control);
745
746      if (data & 0x10)
747      {
748         if (control & 0x04)
749         {
750            if (!(segacd_irq_mask & 0x10))
751            {
752               segacd_irq_mask = data & 0x7e;
753               CDD_Process(space.machine(), 0);
754               return;
755            }
756         }
757      }
758
759      segacd_irq_mask = data & 0x7e;
760   }
761   else
762   {
763
764      printf("segacd_irq_mask_w only MSB written\n");
765
766   }
767}
768
769READ16_MEMBER( lc89510_temp_device::segacd_cdd_ctrl_r )
770{
771
772   return CDD_CONTROL;
773}
774
775
776WRITE16_MEMBER( lc89510_temp_device::segacd_cdd_ctrl_w )
777{
778   if (ACCESSING_BITS_0_7)
779   {
780      UINT16 control = CDD_CONTROL;
781
782
783      //printf("segacd_cdd_ctrl_w %04x %04x (control %04x irq %04x\n", data, mem_mask, control, segacd_irq_mask);
784
785      data &=0x4; // only HOCK bit is writable
786
787      if (data & 0x4)
788      {
789         if (!(control & 0x4))
790         {
791            if (segacd_irq_mask&0x10)
792            {
793               CDD_Process(space.machine(), 1);
794            }
795         }
796      }
797
798      CDD_CONTROL |= data;
799   }
800   else
801   {
802      printf("segacd_cdd_ctrl_w only MSB written\n");
803   }
804}
805
806
807// mapped as serial
808UINT8 lc89510_temp_device::neocd_cdd_rx_r()
809{
810   UINT8 ret = 0;
811
812   if (NeoCDCommsWordCount >= 0 && NeoCDCommsWordCount < 10) {
813      ret = CDD_RX[NeoCDCommsWordCount] & 0x0F;
814   }
815
816   if (bNeoCDCommsClock) {
817      ret |= 0x10;
818   }
819   
820   return ret;
821}
822
823// mapped like 'ram'
824READ8_MEMBER( lc89510_temp_device::segacd_cdd_rx_r )
825{
826   return CDD_RX[offset];
827}
828
829// mapped as serial
830void lc89510_temp_device::neocd_cdd_tx_w(UINT8 data)
831{
832   //printf("neocd_cdd_tx_w %d, %02x\n", NeoCDCommsWordCount, data);
833
834   if (NeoCDCommsWordCount >= 0 && NeoCDCommsWordCount < 10) {
835      CDD_TX[NeoCDCommsWordCount] = data & 0x0F;
836   }
837}
838
839WRITE8_MEMBER( lc89510_temp_device::segacd_cdd_tx_w )
840{
841   CDD_TX[offset] = data;
842
843   if(offset == 9)
844   {
845      CDD_Import(space.machine());
846   }
847}
848
849
850
851
852READ16_MEMBER( lc89510_temp_device::cdc_dmaaddr_r )
853{
854   return CDC_DMA_ADDR;
855}
856
857WRITE16_MEMBER( lc89510_temp_device::cdc_dmaaddr_w )
858{
859   COMBINE_DATA(&CDC_DMA_ADDR);
860}
861
862READ16_MEMBER( lc89510_temp_device::segacd_cdfader_r )
863{
864   return 0;
865}
866
867WRITE16_MEMBER( lc89510_temp_device::segacd_cdfader_w )
868{
869   static double cdfader_vol;
870   if(data & 0x800f)
871      printf("CD Fader register write %04x\n",data);
872
873   cdfader_vol = (double)((data & 0x3ff0) >> 4);
874
875   if(data & 0x4000)
876      cdfader_vol = 100.0;
877   else
878      cdfader_vol = (cdfader_vol / 1024.0) * 100.0;
879
880   //printf("%f\n",cdfader_vol);
881
882   cdda_set_volume( m_cdda, cdfader_vol);
883}
884
885void lc89510_temp_device::reset_cd(void)
886{
887   /* init cd-rom device */
888
889   lc89510_Reset();
890
891   {
892      cdrom_image_device *cddevice = machine().device<cdrom_image_device>("cdrom");
893      if ( cddevice )
894      {
895         segacd.cd = cddevice->get_cdrom_file();
896         if ( segacd.cd )
897         {
898            segacd.toc = cdrom_get_toc( segacd.cd );
899            cdda_set_cdrom( m_cdda, segacd.cd );
900            cdda_stop_audio(m_cdda ); //stop any pending CD-DA
901         }
902      }
903   }
904
905
906
907   if (segacd.cd)
908      printf("cd found\n");
909}
910
911
912
913
914TIMER_DEVICE_CALLBACK_MEMBER( lc89510_temp_device::segacd_access_timer_callback )
915{
916   if (!is_neoCD)
917   {
918      CheckCommand(machine());
919   }
920   else
921   {
922      if (nff0002 & 0x0050) {
923         nIRQAcknowledge &= ~0x10;
924         NeoCDIRQUpdate(0);
925
926         if (nff0002 & 0x0500) {
927            Read_LBA_To_Buffer_NeoCD();
928         }
929      }
930   }
931}
932
933
934
935
936static MACHINE_CONFIG_FRAGMENT( lc89510_temp_fragment )
937   MCFG_TIMER_DRIVER_ADD_PERIODIC("hock_timer", lc89510_temp_device, segacd_access_timer_callback, attotime::from_hz(75))
938
939   MCFG_SOUND_ADD( "cdda", CDDA, 0 )
940   MCFG_SOUND_ROUTE( 0, ":lspeaker", 0.50 ) // TODO: accurate volume balance
941   MCFG_SOUND_ROUTE( 1, ":rspeaker", 0.50 )
942MACHINE_CONFIG_END
943
944machine_config_constructor lc89510_temp_device::device_mconfig_additions() const
945{
946   return MACHINE_CONFIG_NAME( lc89510_temp_fragment );
947}
948
949/* Neo CD */
950
951
952enum CDEmuStatusValue { idle = 0, reading, playing, paused, seeking, fastforward, fastreverse };
953CDEmuStatusValue CDEmuStatus;
954
955static inline CDEmuStatusValue CDEmuGetStatus()
956{
957//   printf("CDEmuGetStatus\n");
958   return CDEmuStatus;
959}
960
961UINT8* lc89510_temp_device::CDEmuReadQChannel(int SCD_CURLBA)
962{
963//   printf("CDEmuReadQChannel\n");
964   static unsigned char QChannelData[8];
965
966   if(segacd.cd == NULL) // no cd is there, bail out
967      return QChannelData;
968
969//  SCD_CURLBA
970   switch (CDEmuStatus) {
971      case reading:
972      case playing: {
973
974         UINT32 msf;
975         msf = lba_to_msf_alt(SCD_CURLBA+150);
976
977
978
979         QChannelData[0] = cdrom_get_track(segacd.cd, SCD_CURLBA);
980
981         QChannelData[1] = (msf >> 16)&0xff;
982         QChannelData[2] = (msf >> 8)&0xff;
983         QChannelData[3] = (msf >> 0)&0xff;
984
985         int elapsedlba;
986         elapsedlba = SCD_CURLBA - segacd.toc->tracks[ cdrom_get_track(segacd.cd, SCD_CURLBA) ].physframeofs;
987         msf = lba_to_msf_alt (elapsedlba);
988
989         QChannelData[4] = (msf >> 16)&0xff;
990         QChannelData[5] = (msf >> 8)&0xff;
991         QChannelData[6] = (msf >> 0)&0xff;
992
993         if (QChannelData[0]==1)
994            QChannelData[7] = 0x4;
995         else
996            QChannelData[7] = 0x0;
997
998         break;
999      }
1000      case paused: {
1001         break;
1002      }
1003      default: {
1004         memset(QChannelData, 0, sizeof(QChannelData));
1005      }
1006   }
1007
1008   return QChannelData;
1009}
1010
1011UINT8* lc89510_temp_device::CDEmuReadTOC(INT32 track)
1012{
1013//   printf("CDEmuReadTOC\n");
1014
1015   static unsigned char TOCEntry[4];
1016
1017   if(segacd.cd == NULL)
1018      return TOCEntry;
1019
1020
1021   if (track == -1) {
1022      printf("get first/last track nums\n");
1023      TOCEntry[0] = 1;
1024      TOCEntry[1] = cdrom_get_last_track(segacd.cd);
1025      TOCEntry[2] = 0;
1026      TOCEntry[3] = 0;
1027
1028      return TOCEntry;
1029   }
1030   else if (track == -2) {
1031      printf("get disc length\n");
1032
1033      UINT32 startlba = (segacd.toc->tracks[cdrom_get_last_track(segacd.cd)].physframeofs);
1034      UINT32 startmsf = lba_to_msf_alt( startlba );
1035
1036
1037      TOCEntry[0] = (startmsf >> 16)&0xff;
1038      TOCEntry[1] = (startmsf >> 8)&0xff;
1039      TOCEntry[2] = (startmsf >> 0)&0xff;
1040
1041      TOCEntry[3] = 0;
1042
1043      return TOCEntry;
1044   }
1045   else
1046   {
1047      printf("get track address\n");
1048
1049      int last_track = cdrom_get_last_track(segacd.cd);
1050
1051      if (track > last_track)
1052         track = last_track;
1053
1054      if (track < 1)
1055         track = 1;
1056
1057      UINT32 startlba = (segacd.toc->tracks[track-1].physframeofs);
1058      UINT32 startmsf = lba_to_msf_alt( startlba+150 );
1059
1060      TOCEntry[0] = (startmsf >> 16)&0xff;
1061      TOCEntry[1] = (startmsf >> 8)&0xff;
1062      TOCEntry[2] = (startmsf >> 0)&0xff;
1063      TOCEntry[3] =  track % 10;;
1064   }
1065
1066   return TOCEntry;
1067
1068}
1069
1070static void CDEmuStartRead()
1071{
1072   printf("CDEmuStartRead\n");
1073   CDEmuStatus = seeking;
1074}
1075
1076static void CDEmuPause()
1077{
1078   printf("CDEmuPause\n");
1079   CDEmuStatus = paused;
1080}
1081
1082static INT32 CDEmuStop()
1083{
1084   printf("CDEmuStop\n");
1085   return 1;
1086}
1087
1088static INT32 CDEmuPlay(UINT8 M, UINT8 S, UINT8 F)
1089{
1090   printf("CDEmuPlay\n");
1091   return 1;
1092}
1093
1094INT32 lc89510_temp_device::CDEmuLoadSector(INT32 LBA, char* pBuffer)
1095{
1096//   printf("CDEmuLoadSector %d\n", LBA);
1097   //LBA += 150;
1098
1099   cdrom_read_data(segacd.cd, LBA, pBuffer, CD_TRACK_MODE1);
1100
1101   return LBA+1;// - 150;
1102}
1103
1104
1105
1106void lc89510_temp_device::NeoCDLBAToMSF(const INT32 LBA)
1107{
1108   NeoCDSectorMin = (LBA + CD_FRAMES_PREGAP)                    / CD_FRAMES_MINUTE;
1109   NeoCDSectorSec = (LBA + CD_FRAMES_PREGAP) % CD_FRAMES_MINUTE / CD_FRAMES_SECOND;
1110   NeoCDSectorFrm = (LBA + CD_FRAMES_PREGAP) % CD_FRAMES_SECOND;
1111}
1112
1113
1114void lc89510_temp_device::NeoCDCommsReset()
1115{
1116   bNeoCDCommsSend  = false;
1117   bNeoCDCommsClock = true;
1118
1119   memset(CDD_TX, 0, sizeof(CDD_TX));
1120   memset(CDD_RX,  0, sizeof(CDD_RX));
1121
1122   NeoCDCommsWordCount = 0;
1123
1124   NeoCDAssyStatus = 9;
1125
1126   memset(NeoCDSectorData, 0, sizeof(NeoCDSectorData));
1127
1128   bNeoCDLoadSector = false;
1129
1130   nff0016 = 0;
1131}
1132
1133static INT32 SekIdle(INT32 nCycles)
1134{
1135   return nCycles;
1136}
1137
1138void lc89510_temp_device::NeoCDDoDMA()
1139{
1140
1141   // The LC8953 chip has a programmable DMA controller, which is not properly emulated.
1142   // Since the software only uses it in a limited way, we can apply a simple heuristic
1143   // to determnine the requested operation.
1144
1145   // Additionally, we don't know how many cycles DMA operations take.
1146   // Here, only bus access is used to get a rough approximation --
1147   // each read/write takes a single cycle, setup and everything else is ignored.
1148
1149//  bprintf(PRINT_IMPORTANT, _T("  - DMA controller transfer started (PC: 0x%06X)\n"), SekGetPC(-1));
1150
1151   switch (NeoCDDMAMode) {
1152
1153      case 0xCFFD: {
1154//          bprintf(PRINT_NORMAL, _T("    adr : 0x%08X - 0x%08X <- address, skip odd bytes\n"), NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 8);
1155
1156         //  - DMA controller 0x7E -> 0xCFFD (PC: 0xC07CE2)
1157         //  - DMA controller program[00] -> 0xFCF5 (PC: 0xC07CE8)
1158         //  - DMA controller program[02] -> 0xE8DA (PC: 0xC07CEE)
1159         //  - DMA controller program[04] -> 0x92DA (PC: 0xC07CF4)
1160         //  - DMA controller program[06] -> 0x92DB (PC: 0xC07CFA)
1161         //  - DMA controller program[08] -> 0x96DB (PC: 0xC07D00)
1162         //  - DMA controller program[10] -> 0x96F6 (PC: 0xC07D06)
1163         //  - DMA controller program[12] -> 0x2E02 (PC: 0xC07D0C)
1164         //  - DMA controller program[14] -> 0xFDFF (PC: 0xC07D12)
1165
1166         SekIdle(NeoCDDMACount * 4);
1167
1168         while (NeoCDDMACount--) {
1169            SekWriteWord(NeoCDDMAAddress1 + 0, NeoCDDMAAddress1 >> 24);
1170            SekWriteWord(NeoCDDMAAddress1 + 2, NeoCDDMAAddress1 >> 16);
1171            SekWriteWord(NeoCDDMAAddress1 + 4, NeoCDDMAAddress1 >>  8);
1172            SekWriteWord(NeoCDDMAAddress1 + 6, NeoCDDMAAddress1 >>  0);
1173            NeoCDDMAAddress1 += 8;
1174         }
1175
1176         break;
1177      }
1178
1179      case 0xE2DD: {
1180//          bprintf(PRINT_NORMAL, _T("    copy: 0x%08X - 0x%08X <- 0x%08X - 0x%08X, skip odd bytes\n"), NeoCDDMAAddress2, NeoCDDMAAddress2 + NeoCDDMACount * 2, NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 4);
1181
1182         //  - DMA controller 0x7E -> 0xE2DD (PC: 0xC0A190)
1183         //  - DMA controller program[00] -> 0xFCF5 (PC: 0xC0A192)
1184         //  - DMA controller program[02] -> 0x82BE (PC: 0xC0A194)
1185         //  - DMA controller program[04] -> 0x93DA (PC: 0xC0A196)
1186         //  - DMA controller program[06] -> 0xBE93 (PC: 0xC0A198)
1187         //  - DMA controller program[08] -> 0xDABE (PC: 0xC0A19A)
1188         //  - DMA controller program[10] -> 0xF62D (PC: 0xC0A19C)
1189         //  - DMA controller program[12] -> 0x02FD (PC: 0xC0A19E)
1190         //  - DMA controller program[14] -> 0xFFFF (PC: 0xC0A1A0)
1191
1192         SekIdle(NeoCDDMACount * 1);
1193
1194         while (NeoCDDMACount--) {
1195            SekWriteWord(NeoCDDMAAddress2 + 0, SekReadByte(NeoCDDMAAddress1 + 0));
1196            SekWriteWord(NeoCDDMAAddress2 + 2, SekReadByte(NeoCDDMAAddress1 + 1));
1197            NeoCDDMAAddress1 += 2;
1198            NeoCDDMAAddress2 += 4;
1199         }
1200
1201         break;
1202      }
1203
1204      case 0xFC2D: {
1205//          bprintf(PRINT_NORMAL, _T("    copy: 0x%08X - 0x%08X <- LC8951 external buffer, skip odd bytes\n"), NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 4);
1206
1207         //  - DMA controller 0x7E -> 0xFC2D (PC: 0xC0A190)
1208         //  - DMA controller program[00] -> 0xFCF5 (PC: 0xC0A192)
1209         //  - DMA controller program[02] -> 0x8492 (PC: 0xC0A194)
1210         //  - DMA controller program[04] -> 0xDA92 (PC: 0xC0A196)
1211         //  - DMA controller program[06] -> 0xDAF6 (PC: 0xC0A198)
1212         //  - DMA controller program[08] -> 0x2A02 (PC: 0xC0A19A)
1213         //  - DMA controller program[10] -> 0xFDFF (PC: 0xC0A19C)
1214         //  - DMA controller program[12] -> 0x48E7 (PC: 0xC0A19E)
1215         //  - DMA controller program[14] -> 0xFFFE (PC: 0xC0A1A0)
1216
1217         char* data = LC8915InitTransfer();
1218         if (data == NULL) {
1219            break;
1220         }
1221
1222         SekIdle(NeoCDDMACount * 4);
1223
1224         while (NeoCDDMACount--) {
1225            SekWriteByte(NeoCDDMAAddress1 + 0, data[0]);
1226            SekWriteByte(NeoCDDMAAddress1 + 2, data[1]);
1227            NeoCDDMAAddress1 += 4;
1228            data += 2;
1229         }
1230
1231         LC8915EndTransfer();
1232
1233         break;
1234      }
1235
1236      case 0xFE3D:
1237
1238         //  - DMA controller 0x7E -> 0xFE3D (PC: 0xC0A190)
1239         //  - DMA controller program[00] -> 0xFCF5 (PC: 0xC0A192)
1240         //  - DMA controller program[02] -> 0x82BF (PC: 0xC0A194)
1241         //  - DMA controller program[04] -> 0x93BF (PC: 0xC0A196)
1242         //  - DMA controller program[06] -> 0xF629 (PC: 0xC0A198)
1243         //  - DMA controller program[08] -> 0x02FD (PC: 0xC0A19A)
1244         //  - DMA controller program[10] -> 0xFFFF (PC: 0xC0A19C)
1245         //  - DMA controller program[12] -> 0xF17D (PC: 0xC0A19E)
1246         //  - DMA controller program[14] -> 0xFCF5 (PC: 0xC0A1A0)
1247
1248      case 0xFE6D: {
1249//          bprintf(PRINT_NORMAL, _T("    copy: 0x%08X - 0x%08X <- 0x%08X - 0x%08X\n"), NeoCDDMAAddress2, NeoCDDMAAddress2 + NeoCDDMACount * 2, NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 2);
1250
1251         //  - DMA controller 0x7E -> 0xFE6D (PC: 0xC0FD7A)
1252         //  - DMA controller program[00] -> 0xFCF5 (PC: 0xC0FD7C)
1253         //  - DMA controller program[02] -> 0x82BF (PC: 0xC0FD7E)
1254         //  - DMA controller program[04] -> 0xF693 (PC: 0xC0FD80)
1255         //  - DMA controller program[06] -> 0xBF29 (PC: 0xC0FD82)
1256         //  - DMA controller program[08] -> 0x02FD (PC: 0xC0FD84)
1257         //  - DMA controller program[10] -> 0xFFFF (PC: 0xC0FD86)
1258         //  - DMA controller program[12] -> 0xC515 (PC: 0xC0FD88)
1259         //  - DMA controller program[14] -> 0xFCF5 (PC: 0xC0FD8A)
1260
1261         SekIdle(NeoCDDMACount * 1);
1262
1263         while (NeoCDDMACount--) {
1264            SekWriteWord(NeoCDDMAAddress2, SekReadWord(NeoCDDMAAddress1));
1265            NeoCDDMAAddress1 += 2;
1266            NeoCDDMAAddress2 += 2;
1267         }
1268
1269if (NeoCDDMAAddress2 == 0x0800)  {
1270// MapVectorTable(false);
1271//  bprintf(PRINT_ERROR, _T("    RAM vectors mapped (PC = 0x%08X\n"), SekGetPC(0));
1272//  extern INT32 bRunPause;
1273//  bRunPause = 1;
1274}
1275         break;
1276      }
1277
1278      case 0xFEF5: {
1279//          bprintf(PRINT_NORMAL, _T("    adr : 0x%08X - 0x%08X <- address\n"), NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 4);
1280
1281         //  - DMA controller 0x7E -> 0xFEF5 (PC: 0xC07CE2)
1282         //  - DMA controller program[00] -> 0xFCF5 (PC: 0xC07CE8)
1283         //  - DMA controller program[02] -> 0x92E8 (PC: 0xC07CEE)
1284         //  - DMA controller program[04] -> 0xBE96 (PC: 0xC07CF4)
1285         //  - DMA controller program[06] -> 0xF629 (PC: 0xC07CFA)
1286         //  - DMA controller program[08] -> 0x02FD (PC: 0xC07D00)
1287         //  - DMA controller program[10] -> 0xFFFF (PC: 0xC07D06)
1288         //  - DMA controller program[12] -> 0xFC3D (PC: 0xC07D0C)
1289         //  - DMA controller program[14] -> 0xFCF5 (PC: 0xC07D12)
1290
1291         SekIdle(NeoCDDMACount * 2);
1292
1293         while (NeoCDDMACount--) {
1294            SekWriteWord(NeoCDDMAAddress1 + 0, NeoCDDMAAddress1 >> 16);
1295            SekWriteWord(NeoCDDMAAddress1 + 2, NeoCDDMAAddress1 >>  0);
1296            NeoCDDMAAddress1 += 4;
1297         }
1298
1299         break;
1300      }
1301
1302      case 0xFFC5: {
1303//          bprintf(PRINT_NORMAL, _T("    copy: 0x%08X - 0x%08X <- LC8951 external buffer\n"), NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 2);
1304
1305         //  - DMA controller 0x7E -> 0xFFC5 (PC: 0xC0A190)
1306         //  - DMA controller program[00] -> 0xFCF5 (PC: 0xC0A192)
1307         //  - DMA controller program[02] -> 0xA6F6 (PC: 0xC0A194)
1308         //  - DMA controller program[04] -> 0x2602 (PC: 0xC0A196)
1309         //  - DMA controller program[06] -> 0xFDFF (PC: 0xC0A198)
1310         //  - DMA controller program[08] -> 0xFC2D (PC: 0xC0A19A)
1311         //  - DMA controller program[10] -> 0xFCF5 (PC: 0xC0A19C)
1312         //  - DMA controller program[12] -> 0x8492 (PC: 0xC0A19E)
1313         //  - DMA controller program[14] -> 0xDA92 (PC: 0xC0A1A0)
1314
1315         char* data = LC8915InitTransfer();
1316         if (data == NULL) {
1317            break;
1318         }
1319
1320         SekIdle(NeoCDDMACount * 4);
1321
1322         while (NeoCDDMACount--) {
1323            SekWriteByte(NeoCDDMAAddress1 + 0, data[0]);
1324            SekWriteByte(NeoCDDMAAddress1 + 1, data[1]);
1325            NeoCDDMAAddress1 += 2;
1326            data += 2;
1327         }
1328
1329         LC8915EndTransfer();
1330
1331         break;
1332      }
1333
1334      case 0xFFCD:
1335
1336         //  - DMA controller 0x7E -> 0xFFCD (PC: 0xC0A190)
1337         //  - DMA controller program[00] -> 0xFCF5 (PC: 0xC0A192)
1338         //  - DMA controller program[02] -> 0x92F6 (PC: 0xC0A194)
1339         //  - DMA controller program[04] -> 0x2602 (PC: 0xC0A196)
1340         //  - DMA controller program[06] -> 0xFDFF (PC: 0xC0A198)
1341         //  - DMA controller program[08] -> 0x7006 (PC: 0xC0A19A)
1342         //  - DMA controller program[10] -> 0x6100 (PC: 0xC0A19C)
1343         //  - DMA controller program[12] -> 0x2412 (PC: 0xC0A19E)
1344         //  - DMA controller program[14] -> 0x13FC (PC: 0xC0A1A0)
1345
1346      case 0xFFDD: {
1347//          bprintf(PRINT_NORMAL, _T("    Fill: 0x%08X - 0x%08X <- 0x%04X\n"), NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 2, NeoCDDMAValue1);
1348
1349         //  - DMA controller 0x7E -> 0xFFDD (PC: 0xC07CE2)
1350         //  - DMA controller program[00] -> 0xFCF5 (PC: 0xC07CE8)
1351         //  - DMA controller program[02] -> 0x92F6 (PC: 0xC07CEE)
1352         //  - DMA controller program[04] -> 0x2602 (PC: 0xC07CF4)
1353         //  - DMA controller program[06] -> 0xFDFF (PC: 0xC07CFA)
1354         //  - DMA controller program[08] -> 0xFFFF (PC: 0xC07D00)
1355         //  - DMA controller program[10] -> 0xFCF5 (PC: 0xC07D06)
1356         //  - DMA controller program[12] -> 0x8AF0 (PC: 0xC07D0C)
1357         //  - DMA controller program[14] -> 0x1609 (PC: 0xC07D12)
1358
1359         SekIdle(NeoCDDMACount * 1);
1360
1361         while (NeoCDDMACount--) {
1362            SekWriteWord(NeoCDDMAAddress1, NeoCDDMAValue1);
1363            NeoCDDMAAddress1 += 2;
1364         }
1365
1366         break;
1367      }
1368      default: {
1369         //bprintf(PRINT_ERROR, _T("    Unknown transfer type 0x%04X (PC: 0x%06X)\n"), NeoCDDMAMode, SekGetPC(-1));
1370         //bprintf(PRINT_NORMAL, _T("    ??? : 0x%08X  0x%08X 0x%04X 0x%04X 0x%08X\n"), NeoCDDMAAddress1, NeoCDDMAAddress2, NeoCDDMAValue1, NeoCDDMAValue2, NeoCDDMACount);
1371
1372//extern INT32 bRunPause;
1373//bRunPause = 1;
1374
1375      }
1376   }
1377}
1378
1379
1380void lc89510_temp_device::NeoCDProcessCommand()
1381{
1382   memset(CDD_RX,  0, sizeof(CDD_RX));
1383
1384   if (CDD_TX[0]) {
1385      CDD_RX[1] = 15;
1386   }
1387
1388   switch (CDD_TX[0]) {
1389      case CMD_STATUS: // CDD_GetStatus();
1390         break;
1391      case CMD_STOPALL: // CDD_Stop(machine);
1392//                              //bprintf(PRINT_ERROR, _T("    CD comms received command %i\n"), CDD_TX[0]);
1393         CDEmuStop();
1394
1395         NeoCDAssyStatus = 0x0E;
1396         bNeoCDLoadSector = false;
1397         break;
1398      case CMD_GETTOC: // CDD_Handle_TOC_Commands();
1399//                              //bprintf(PRINT_ERROR, _T("    CD comms received command %i\n"), CDD_TX[0]);
1400         CDD_RX[1] = CDD_TX[3];
1401          switch (CDD_TX[3]) {
1402
1403
1404
1405            case TOCCMD_CURPOS: { //  CDD_GetPos();
1406               UINT8* ChannelData = CDEmuReadQChannel(SCD_CURLBA);
1407
1408               CDD_RX[2] = ChannelData[1] / 10;
1409               CDD_RX[3] = ChannelData[1] % 10;
1410
1411               CDD_RX[4] = ChannelData[2] / 10;
1412               CDD_RX[5] = ChannelData[2] % 10;
1413
1414               CDD_RX[6] = ChannelData[3] / 10;
1415               CDD_RX[7] = ChannelData[3] % 10;
1416
1417               CDD_RX[8] = ChannelData[7];
1418
1419// //bprintf(PRINT_ERROR, _T("    %02i %02i:%02i:%02i %02i:%02i:%02i %02i\n"), ChannelData[0], ChannelData[1], ChannelData[2], ChannelData[3], ChannelData[4], ChannelData[5], ChannelData[6], ChannelData[7]);
1420
1421               break;
1422            }
1423            case TOCCMD_TRKPOS: { //  CDD_GetTrackPos();
1424               UINT8* ChannelData = CDEmuReadQChannel(SCD_CURLBA);
1425
1426               CDD_RX[2] = ChannelData[4] / 10;
1427               CDD_RX[3] = ChannelData[4] % 10;
1428
1429               CDD_RX[4] = ChannelData[5] / 10;
1430               CDD_RX[5] = ChannelData[5] % 10;
1431
1432               CDD_RX[6] = ChannelData[6] / 10;
1433               CDD_RX[7] = ChannelData[6] % 10;
1434
1435               CDD_RX[8] = ChannelData[7];
1436
1437               break;
1438            }
1439            case TOCCMD_CURTRK: { //  CDD_GetTrack();
1440
1441               UINT8* ChannelData = CDEmuReadQChannel(SCD_CURLBA);
1442
1443               CDD_RX[2] = ChannelData[0] / 10;
1444               CDD_RX[3] = ChannelData[0] % 10;
1445
1446
1447               CDD_RX[8] = ChannelData[7];
1448
1449               break;
1450            }
1451            case TOCCMD_LENGTH: { //  CDD_Length();
1452               UINT8* TOCEntry = CDEmuReadTOC(-2);
1453
1454               CDD_RX[2] = TOCEntry[0] / 10;
1455               CDD_RX[3] = TOCEntry[0] % 10;
1456
1457               CDD_RX[4] = TOCEntry[1] / 10;
1458               CDD_RX[5] = TOCEntry[1] % 10;
1459
1460               CDD_RX[6] = TOCEntry[2] / 10;
1461               CDD_RX[7] = TOCEntry[2] % 10;
1462
1463               break;
1464            }
1465            case TOCCMD_FIRSTLAST: { //  CDD_FirstLast();
1466               UINT8* TOCEntry = CDEmuReadTOC(-1);
1467
1468               CDD_RX[2] = TOCEntry[0] / 10;
1469               CDD_RX[3] = TOCEntry[0] % 10;
1470
1471               CDD_RX[4] = TOCEntry[1] / 10;
1472               CDD_RX[5] = TOCEntry[1] % 10;
1473
1474               break;
1475            }
1476            case TOCCMD_TRACKADDR:   { //  CDD_GetTrackAdr();
1477               NeoCDTrack = CDD_TX[4] * 10 + CDD_TX[5];
1478
1479               UINT8* TOCEntry = CDEmuReadTOC(NeoCDTrack);
1480
1481               CDD_RX[2] = TOCEntry[0] / 10;
1482               CDD_RX[3] = TOCEntry[0] % 10;
1483
1484               CDD_RX[4] = TOCEntry[1] / 10;
1485               CDD_RX[5] = TOCEntry[1] % 10;
1486
1487               CDD_RX[6] = TOCEntry[2] / 10;
1488               CDD_RX[7] = TOCEntry[2] % 10;
1489
1490               // bit 3 of the 1st minutes digit indicates a data track
1491               if (TOCEntry[3] & 4) {
1492                  CDD_RX[6] |= 8;
1493               }
1494
1495               CDD_RX[8] = NeoCDTrack % 10;
1496
1497               break;
1498            }
1499
1500            case 6: {
1501
1502               UINT8* ChannelData = CDEmuReadQChannel(SCD_CURLBA);
1503
1504               CDD_RX[8] = ChannelData[7];
1505
1506               break;
1507            }
1508
1509            case 7: {
1510
1511               // must be 02, 0E, 0F, or 05
1512               CDD_RX[2] = 0;
1513               CDD_RX[3] = 5;
1514
1515               CDD_RX[4] = 0;
1516               CDD_RX[5] = 0;
1517
1518               CDD_RX[6] = 0;
1519               CDD_RX[7] = 0;
1520               break;
1521            }
1522          }
1523         break;
1524
1525
1526      case CMD_READ: { // CDD_Play(machine);
1527
1528         if (LC8951RegistersW[REG_W_CTRL0] & 4) {
1529
1530            if (CDEmuGetStatus() == playing) {
1531               //bprintf(PRINT_ERROR, _T("*** Switching CD mode to CD-ROM while in audio mode!(PC: 0x%06X)\n"), SekGetPC(-1));
1532            }
1533
1534            SCD_CURLBA  = CDD_TX[2] * (10 * CD_FRAMES_MINUTE);
1535            SCD_CURLBA += CDD_TX[3] * ( 1 * CD_FRAMES_MINUTE);
1536            SCD_CURLBA += CDD_TX[4] * (10 * CD_FRAMES_SECOND);
1537            SCD_CURLBA += CDD_TX[5] * ( 1 * CD_FRAMES_SECOND);
1538            SCD_CURLBA += CDD_TX[6] * (10                   );
1539            SCD_CURLBA += CDD_TX[7] * ( 1                   );
1540
1541            SCD_CURLBA -= CD_FRAMES_PREGAP;
1542
1543            CDEmuStartRead();
1544//              LC8951RegistersR[REG_R_IFSTAT] |= 0x20;
1545         } else {
1546
1547            if (CDEmuGetStatus() == reading) {
1548               //bprintf(PRINT_ERROR, _T("*** Switching CD mode to audio while in CD-ROM mode!(PC: 0x%06X)\n"), SekGetPC(-1));
1549            }
1550
1551            CDEmuPlay((CDD_TX[2] * 10) + CDD_TX[3], (CDD_TX[4] * 10) + CDD_TX[5], (CDD_TX[6] * 10) + CDD_TX[7]);
1552         }
1553
1554         NeoCDAssyStatus = 1;
1555         bNeoCDLoadSector = true;
1556
1557         break;
1558      }
1559      case CMD_SEEK: // CDD_Seek();   
1560//          //bprintf(PRINT_ERROR, _T("    CD comms received command %i\n"), CDD_TX[0]);
1561         CDEmuPause();
1562         break;
1563      case 5:
1564//          //bprintf(PRINT_ERROR, _T("    CD comms received command %i\n"), CDD_TX[0]);
1565//          NeoCDAssyStatus = 9;
1566//          bNeoCDLoadSector = false;
1567         break;
1568
1569      case CMD_STOP: // CDD_Pause(machine);
1570//          //bprintf(PRINT_ERROR, _T("    CD comms received command %i\n"), CDD_TX[0]);
1571         NeoCDAssyStatus = 4;
1572         bNeoCDLoadSector = false;
1573         break;
1574      case CMD_RESUME: //    CDD_Resume(machine);
1575//          //bprintf(PRINT_ERROR, _T("    CD comms received command %i\n"), CDD_TX[0]);
1576         NeoCDAssyStatus = 1;
1577         bNeoCDLoadSector = true;
1578         break;
1579         
1580      case CMD_FF: // CDD_FF(machine);   
1581      case CMD_RW: // CDD_RW(machine);   
1582      case CMD_INIT: // CDD_Init();     
1583      case 11:
1584      case CMD_CLOSE: // CDD_Close();   
1585      case CMD_OPEN: // CDD_Open();     
1586      case 14:
1587      case 15:
1588//          //bprintf(PRINT_ERROR, _T("    CD comms received command %i\n"), CDD_TX[0]);
1589         NeoCDAssyStatus = 9;
1590         bNeoCDLoadSector = false;
1591         break;
1592   }
1593}
1594
1595void lc89510_temp_device::NeoCDCommsControl(UINT8 clock, UINT8 send)
1596{
1597   if (clock && !bNeoCDCommsClock) {
1598      NeoCDCommsWordCount++;
1599      if (NeoCDCommsWordCount >= 10) {
1600         NeoCDCommsWordCount = 0;
1601
1602         if (send) {
1603
1604            // command receive complete
1605
1606            if (CDD_TX[0]) {
1607               INT32  sum = 0;
1608
1609                  printf("has command %02x\n", CDD_TX[0]);
1610
1611//                  bprintf(PRINT_NORMAL, _T("  - CD mechanism command receive completed : 0x"));
1612               for (INT32 i = 0; i < 9; i++) {
1613//                      bprintf(PRINT_NORMAL, _T("%X"), CDD_TX[i]);
1614                  sum += CDD_TX[i];
1615               }
1616               sum = ~(sum + 5) & 0x0F;
1617//                  bprintf(PRINT_NORMAL, _T(" (CS 0x%X, %s)\n"), CDD_TX[9], (sum == CDD_TX[9]) ? _T("OK") : _T("NG"));
1618               if (sum == CDD_TX[9]) {
1619
1620                  printf("request to process command %02x\n", CDD_TX[0]);
1621
1622                  NeoCDProcessCommand();
1623
1624                  if (CDD_TX[0]) {
1625
1626                     if (NeoCDAssyStatus == 1) {
1627                        if (CDEmuGetStatus() == idle) {
1628                           NeoCDAssyStatus = 0x0E;
1629                           bNeoCDLoadSector = false;
1630                        }
1631                     }
1632
1633                     CDD_RX[0] = NeoCDAssyStatus;
1634
1635                     // compute checksum
1636
1637                     sum = 0;
1638
1639                     for (INT32 i = 0; i < 9; i++) {
1640                        sum += CDD_RX[i];
1641                     }
1642                     CDD_RX[9] = ~(sum + 5) & 0x0F;
1643                  }
1644               }
1645            }
1646         } else {
1647
1648            // status send complete
1649
1650//              if (CDD_RX[0] || CDD_RX[1]) {
1651//                  INT32  sum = 0;
1652//
1653//                  bprintf(PRINT_NORMAL, _T("  - CD mechanism status send completed : 0x"));
1654//                  for (INT32 i = 0; i < 9; i++) {
1655//                      bprintf(PRINT_NORMAL, _T("%X"), CDD_RX[i]);
1656//                      sum += CDD_RX[i];
1657//                  }
1658//                  sum = ~(sum + 5) & 0x0F;
1659//                  bprintf(PRINT_NORMAL, _T(" (CS 0x%X, %s)\n"), CDD_RX[9], (sum == CDD_RX[9]) ? _T("OK") : _T("NG"));
1660//              }
1661
1662//              if (NeoCDAssyStatus == 0xE) {
1663//                  NeoCDAssyStatus = 9;
1664//              }
1665         }
1666
1667      }
1668      bNeoCDCommsSend = send;
1669   }
1670   bNeoCDCommsClock = clock;
1671}
1672
1673
1674void lc89510_temp_device::CDC_UpdateHEAD(void) // segacd
1675{
1676   if (CDC_CTRLB1 & 0x01)
1677   {
1678      CDC_HEADB0 = CDC_HEADB1 = CDC_HEADB2 = CDC_HEADB3 = 0x00;
1679   }
1680   else
1681   {
1682      UINT32 msf = lba_to_msf_alt(SCD_CURLBA+150);
1683      CDC_HEADB0 = to_bcd (((msf & 0x00ff0000)>>16), true);
1684      CDC_HEADB1 = to_bcd (((msf & 0x0000ff00)>>8), true);
1685      CDC_HEADB2 = to_bcd (((msf & 0x000000ff)>>0), true);
1686      CDC_HEADB3 = 0x01;
1687   }
1688}
1689
1690void lc89510_temp_device::LC8951UpdateHeader() // neocd
1691{
1692   NeoCDLBAToMSF(SCD_CURLBA);
1693
1694   if (LC8951RegistersW[REG_W_CTRL1] & 1) {
1695
1696      // HEAD registers have sub-header
1697
1698      LC8951RegistersR[REG_R_HEAD0] = 0;                                       // HEAD0
1699      LC8951RegistersR[REG_R_HEAD1] = 0;                                       // HEAD1
1700      LC8951RegistersR[REG_R_HEAD2] = 0;                                       // HEAD2
1701      LC8951RegistersR[REG_R_HEAD3] = 0;                                       // HEAD3
1702
1703   } else {
1704
1705      // HEAD registers have header
1706
1707      LC8951RegistersR[REG_R_HEAD0] = ((NeoCDSectorMin / 10) << 4) | (NeoCDSectorMin % 10);   // HEAD0
1708      LC8951RegistersR[REG_R_HEAD1] = ((NeoCDSectorSec / 10) << 4) | (NeoCDSectorSec % 10);   // HEAD1
1709      LC8951RegistersR[REG_R_HEAD2] = ((NeoCDSectorFrm / 10) << 4) | (NeoCDSectorFrm % 10);   // HEAD2
1710      LC8951RegistersR[REG_R_HEAD3] = 1;                                       // HEAD3
1711   }
1712}
1713
1714char* lc89510_temp_device::LC8915InitTransfer()
1715{
1716   if (!LC8951RegistersW[REG_W_DTTRG]) {
1717      //bprintf(PRINT_ERROR, _T("    LC8951 DTTRG status invalid\n"));
1718      return NULL;
1719   }
1720   if (!(LC8951RegistersW[REG_W_IFCTRL] & 0x02)) {
1721      //bprintf(PRINT_ERROR, _T("    LC8951 DOUTEN status invalid\n"));
1722      return NULL;
1723   }
1724   if (((LC8951RegistersW[REG_W_DACH] << 8) | LC8951RegistersW[REG_W_DACL]) + (NeoCDDMACount << 1) > 2352) {
1725      //bprintf(PRINT_ERROR, _T("    DMA transfer exceeds current sector in LC8951 external buffer\n"));
1726      return NULL;
1727   }
1728
1729   return NeoCDSectorData + ((LC8951RegistersW[REG_W_DACH] << 8) | LC8951RegistersW[REG_W_DACL]);
1730}
1731
1732void lc89510_temp_device::LC8915EndTransfer()
1733{
1734   LC8951RegistersW[REG_W_DTTRG]  = 0x00;                                    // reset DTTRG
1735
1736   LC8951RegistersR[REG_R_IFSTAT] |= 0x48;                                    //   set DTEI & DTBSY
1737   if (LC8951RegistersW[REG_W_IFCTRL] & 0x40) {
1738
1739      // trigger DTE interrupt
1740
1741      // the Neo Geo CD doesn't use the DTE interrupt
1742      // nIRQAcknowledge &= ~0x20;
1743      // NeoCDIRQUpdate(0);
1744
1745   }
1746}
1747
1748void lc89510_temp_device::LC8951Reset()
1749{
1750   memset(LC8951RegistersR, 0, sizeof(LC8951RegistersR));
1751   memset(LC8951RegistersW, 0, sizeof(LC8951RegistersW));
1752   LC8951RegistersR[REG_R_IFSTAT] = 0xFF;
1753   LC8951RegistersR[REG_R_STAT3] = 0x80;
1754
1755   LC8951UpdateHeader();
1756}
1757
1758void lc89510_temp_device::set_DMA_regs(int offset, UINT16 wordValue)
1759{
1760   switch (offset)
1761   {
1762      case 0x0064:
1763         NeoCDDMAAddress1 &= 0x0000FFFF;
1764         NeoCDDMAAddress1 |= wordValue << 16;
1765         break;
1766      case 0x0066:
1767         NeoCDDMAAddress1 &= 0xFFFF0000;
1768         NeoCDDMAAddress1 |= wordValue;
1769         break;
1770      case 0x0068:
1771         NeoCDDMAAddress2 &= 0x0000FFFF;
1772         NeoCDDMAAddress2 |= wordValue << 16;
1773         break;
1774      case 0x006A:
1775         NeoCDDMAAddress2 &= 0xFFFF0000;
1776         NeoCDDMAAddress2 |= wordValue;
1777         break;
1778      case 0x006C:
1779         NeoCDDMAValue1 = wordValue;
1780         break;
1781      case 0x006E:
1782         NeoCDDMAValue2 = wordValue;
1783         break;
1784      case 0x0070:
1785         NeoCDDMACount &= 0x0000FFFF;
1786         NeoCDDMACount |= wordValue << 16;
1787         break;
1788      case 0x0072:
1789         NeoCDDMACount &= 0xFFFF0000;
1790         NeoCDDMACount |= wordValue;
1791         break;
1792
1793      case 0x007E:
1794         NeoCDDMAMode = wordValue;
1795//          bprintf(PRINT_NORMAL, _T("  - DMA controller 0x%2X -> 0x%04X (PC: 0x%06X)\n"), sekAddress & 0xFF, wordValue, SekGetPC(-1));
1796         break;
1797
1798   }
1799}
1800
1801void lc89510_temp_device::reset_NeoCd(void)
1802{
1803   {
1804      cdrom_image_device *cddevice = machine().device<cdrom_image_device>("cdrom");
1805      if ( cddevice )
1806      {
1807         segacd.cd = cddevice->get_cdrom_file();
1808         if ( segacd.cd )
1809         {
1810            printf("found cd\n");
1811            segacd.toc = cdrom_get_toc( segacd.cd );
1812            cdda_set_cdrom( m_cdda, segacd.cd );
1813            cdda_stop_audio( m_cdda ); //stop any pending CD-DA
1814         }
1815      }
1816   }
1817}
1818
1819
1820/*
1821 *  CD-ROM / DMA control
1822 *
1823 *  DMA
1824
1825    FF0061  Write 0x40 means start DMA transfer
1826    FF0064  Source address (in copy mode), Target address (in filll mode)
1827    FF0068  Target address (in copy mode)
1828    FF006C  Fill word
1829    FF0070  Words count
1830    FF007E  \
1831    ......   | DMA programming words?   NeoGeoCD uses Sanyo Puppet LC8359 chip to
1832    FF008E  /                           interface with CD, and do DMA transfers
1833
1834    Memory access control
1835
1836    FF011C  DIP SWITCH (Region code)
1837    FF0105  Area Selector (5 = FIX, 0 = SPR, 4 = Z80, 1 = PCM)
1838    FF01A1  Sprite bank selector
1839    FF01A3  PCM bank selector
1840    FF0120  Prepare sprite area for transfer
1841    FF0122  Prepare PCM area for transfer
1842    FF0126  Prepare Z80 area for transfer
1843    FF0128  Prepare Fix area for transfer
1844    FF0140  Terminate work on Spr Area  (Sprites must be decoded here)
1845    FF0142  Terminate work on Pcm Area
1846    FF0146  Terminate work on Z80 Area  (Z80 needs to be reset)
1847    FF0148  Terminate work on Fix Area
1848
1849    CD-ROM:
1850    0xff0102 == 0xF0 start cd transfer
1851    int m=bcd(fast_r8(0x10f6c8));
1852    int s=bcd(fast_r8(0x10f6c9));
1853    int f=bcd(fast_r8(0x10f6ca));
1854    int seccount=fast_r16(0x10f688);
1855
1856    inisec=((m*60)+s)*75+f;
1857    inisec-=150;
1858    dstaddr=0x111204; // this must come from somewhere
1859
1860    the value @ 0x10f688 is decremented each time a sector is read until it's 0.
1861
1862 *
1863 */
1864
1865void lc89510_temp_device::Read_LBA_To_Buffer_NeoCD()
1866{
1867   if ((nff0002 & 0x0500)) {
1868      if (NeoCDAssyStatus == 1 && bNeoCDLoadSector) {
1869
1870//          if (LC8951RegistersW[REG_W_CTRL0] & 0x80) {
1871            SCD_CURLBA++;
1872            SCD_CURLBA = CDEmuLoadSector(SCD_CURLBA, NeoCDSectorData + 4) -1;
1873//          }
1874
1875         if (LC8951RegistersW[REG_W_CTRL0] & 0x80) {
1876            LC8951UpdateHeader();
1877
1878            LC8951RegistersR[REG_R_STAT0] = 0x80;                              // STAT0
1879            LC8951RegistersR[REG_R_STAT1] = 0;                                 // STAT1
1880            LC8951RegistersR[REG_R_STAT2] = 0x10;                              // STAT2
1881            LC8951RegistersR[REG_R_STAT3] = 0;                                 // STAT3
1882
1883//              bprintf(PRINT_IMPORTANT, _T("    Sector %08i (%02i:%02i:%02i) read\n"), SCD_CURLBA, NeoCDSectorMin, NeoCDSectorSec, NeoCDSectorFrm);
1884
1885// CDZ protection hack? (error correction on the CDC should correct this?)
1886#if 1
1887            if (NeoCDSectorData[4 + 64] == 'g' && !strncmp(NeoCDSectorData + 4, "Copyright by SNK", 16)) {
1888//                  printf(PRINT_ERROR, _T("    simulated CDZ protection error\n"));
1889//                  bprintf(PRINT_ERROR, _T("    %.70hs\n"), NeoCDSectorData + 4);
1890
1891               NeoCDSectorData[4 + 64] = 'f';
1892
1893               // LC8951RegistersR[REG_R_STATB0] = 0x00;                                 // STAT0
1894            }
1895#endif
1896
1897            nIRQAcknowledge &= ~0x20;
1898            NeoCDIRQUpdate(0);
1899
1900            LC8951RegistersR[REG_R_IFSTAT] &= ~0x20;
1901
1902//              bprintf(PRINT_IMPORTANT, _T("    DECI interrupt triggered\n"));
1903         }
1904      }
1905
1906      bNeoCDLoadSector = true;
1907//      bNeoCDLoadSector = false;
1908   }
1909}
1910
1911
1912
1913void lc89510_temp_device::scd_ctrl_checks(running_machine& machine)
1914{
1915   CDC_STATB0 = 0x80;
1916
1917   (CDC_CTRLB0 & 0x10) ? (CDC_STATB2 = CDC_CTRLB1 & 0x08) : (CDC_STATB2 = CDC_CTRLB1 & 0x0C);
1918   (CDC_CTRLB0 & 0x02) ? (CDC_STATB3 = 0x20) : (CDC_STATB3 = 0x00);
1919
1920   if (CDC_IFCTRL & 0x20)
1921   {
1922      CHECK_SCD_LV5_INTERRUPT
1923      CDC_IFSTAT &= ~0x20;
1924      CDC_DECODE = 0;
1925   }
1926}
1927
1928void lc89510_temp_device::scd_advance_current_readpos(void)
1929{
1930   SCD_CURLBA++;
1931
1932   CDC_WA += SECTOR_SIZE;
1933   CDC_PT += SECTOR_SIZE;
1934
1935   CDC_WA &= 0x7fff;
1936   CDC_PT &= 0x7fff;
1937}
1938
1939int lc89510_temp_device::Read_LBA_To_Buffer(running_machine& machine)
1940{
1941   bool data_track = false;
1942   if (CDD_CONTROL & 0x0100) data_track = true;
1943
1944   if (data_track)
1945      cdrom_read_data(segacd.cd, SCD_CURLBA, SCD_BUFFER, CD_TRACK_MODE1);
1946
1947   CDC_UpdateHEAD();
1948
1949   if (!data_track)
1950   {
1951      scd_advance_current_readpos();
1952   }
1953
1954   if (CDC_CTRLB0 & 0x80)
1955   {
1956      if (CDC_CTRLB0 & 0x04)
1957      {
1958         if (data_track)
1959         {
1960            scd_advance_current_readpos();
1961
1962            memcpy(&CDC_BUFFER[CDC_PT + 4], SCD_BUFFER, 2048);
1963            CDC_BUFFER[CDC_PT+0] = CDC_HEADB0;
1964            CDC_BUFFER[CDC_PT+1] = CDC_HEADB1;
1965            CDC_BUFFER[CDC_PT+2] = CDC_HEADB2;
1966            CDC_BUFFER[CDC_PT+3] = CDC_HEADB3;
1967         }
1968         else
1969         {
1970            memcpy(&CDC_BUFFER[CDC_PT], SCD_BUFFER, SECTOR_SIZE);
1971         }
1972      }
1973
1974      scd_ctrl_checks(machine);
1975   }
1976
1977
1978   return 0;
1979}
1980
1981
1982
1983
1984void lc89510_temp_device::SekWriteWord(UINT32 a, UINT16 d)
1985{
1986//  printf("write word %08x %04x\n", a, d);
1987   dma_space->write_word(a,d);
1988}
1989
1990void lc89510_temp_device::SekWriteByte(UINT32 a, UINT8 d)
1991{
1992//  printf("write byte %08x %02x\n", a, d);
1993   dma_space->write_byte(a,d);
1994}
1995
1996UINT32 lc89510_temp_device::SekReadByte(UINT32 a)
1997{
1998//  printf("read byte %08x\n", a);
1999   return dma_space->read_byte(a);
2000}
2001
2002
2003UINT32 lc89510_temp_device::SekReadWord(UINT32 a)
2004{
2005//  printf("read WORD %08x\n", a);
2006   return dma_space->read_word(a);
2007}
2008
2009
2010void lc89510_temp_device::NeoCDIRQUpdate(UINT8 byteValue)
2011{
2012   // do we also need to check the regular interrupts like FBA?
2013
2014   nIRQAcknowledge |= (byteValue & 0x38);
2015
2016   if ((nIRQAcknowledge & 0x08) == 0) {
2017      nNeoCDIRQVector = 0x17;
2018      nNeoCDIRQVectorAck = 1;
2019      machine().device("maincpu")->execute().set_input_line(4, HOLD_LINE);
2020      return;
2021   }
2022   if ((nIRQAcknowledge & 0x10) == 0) {
2023      nNeoCDIRQVector = 0x16;
2024      nNeoCDIRQVectorAck = 1;
2025      machine().device("maincpu")->execute().set_input_line(4, HOLD_LINE);
2026      return;
2027   }
2028   if ((nIRQAcknowledge & 0x20) == 0) {
2029      nNeoCDIRQVector = 0x15;
2030      nNeoCDIRQVectorAck = 1;
2031      machine().device("maincpu")->execute().set_input_line(4, HOLD_LINE);
2032      return;
2033   }
2034}
2035
2036void lc89510_temp_device::nff0002_set(UINT16 wordValue)
2037{
2038   nff0002 = wordValue;
2039}
2040
2041void lc89510_temp_device::nff0016_set(UINT16 wordValue)
2042{
2043   nff0016 = wordValue;
2044}
2045
2046UINT16 lc89510_temp_device::nff0016_r(void) { return nff0016; }
2047
2048UINT16 lc89510_temp_device::nLC8951_r(void)
2049{
2050   int regno = CDC_REG0 & 0xf;
2051   INT32 reg = LC8951RegistersR[regno];
2052
2053   switch (regno) {
2054      case 0x03:                                          // DBCH
2055         LC8951RegistersR[REG_R_DBCH] &=  0x0F;
2056         LC8951RegistersR[REG_R_DBCH] |=  (LC8951RegistersR[REG_R_IFSTAT] & 0x40) ? 0x00 : 0xF0;
2057         break;
2058      case 0x0D:                                          // STAT3
2059         LC8951RegistersR[REG_R_IFSTAT] |= 0x20;                        // reset DECI
2060         // bprintf(PRINT_ERROR, _T("  - DECI (PC: 0x%06X)\n"), SekGetPC(-1));
2061         break;
2062   }
2063
2064   CDC_REG0 = (regno + 1) & 0x0F;
2065   return reg;
2066}
2067
2068void lc89510_temp_device::nLC8951_w(UINT16 byteValue)
2069{
2070   int regno = CDC_REG0 & 0xf;
2071
2072   switch (regno) {
2073      case 3:                                             // DBCH
2074         LC8951RegistersW[REG_W_DBCH]  = byteValue & 0x0F;
2075         break;
2076      case 6:                                             // DTTRG
2077         LC8951RegistersW[REG_W_DTTRG]  = ~0x00;
2078         LC8951RegistersR[REG_R_IFSTAT] &= ~0x08;
2079         break;
2080      case 7:                                             // DTACK
2081         LC8951RegistersW[REG_W_DTACK]  = ~0x00;
2082         LC8951RegistersR[REG_R_IFSTAT] &= ~0x40;
2083         break;
2084//          case 10:
2085//              LC8951RegistersW[regno] = byteValue;
2086//              bprintf(PRINT_NORMAL, _T("  - CTRL0 -> %02X (PC: 0x%06X)\n"), LC8951RegistersW[regno], byteValue, SekGetPC(-1));
2087//              break;
2088      case 11:
2089         LC8951RegistersW[REG_W_CTRL1]  = byteValue;                     // CTRL1
2090         LC8951UpdateHeader();
2091         break;
2092      case 15:
2093         LC8951Reset();
2094         break;
2095      default:
2096         LC8951RegistersW[regno] = byteValue;
2097   }
2098   CDC_REG0 = (regno + 1) & 0x0F;
2099}
2100
2101
trunk/src/mame/machine/megacdcd.h
r0r19246
1
2#include "sound/cdda.h"
3#include "imagedev/chd_cd.h"
4
5
6typedef device_delegate<void (int&, UINT8*, UINT16&, UINT16&, UINT16&)> segacd_dma_delegate;
7
8
9
10#define READ_MAIN (0x0200)
11#define READ_SUB  (0x0300)
12
13#define REG_W_SBOUT  (0x0)
14#define REG_W_IFCTRL (0x1)
15#define REG_W_DBCL   (0x2)
16#define REG_W_DBCH   (0x3)
17#define REG_W_DACL   (0x4)
18#define REG_W_DACH   (0x5)
19#define REG_W_DTTRG  (0x6)
20#define REG_W_DTACK  (0x7)
21#define REG_W_WAL    (0x8)
22#define REG_W_WAH    (0x9)
23#define REG_W_CTRL0  (0xA)
24#define REG_W_CTRL1  (0xB)
25#define REG_W_PTL    (0xC)
26#define REG_W_PTH    (0xD)
27#define REG_W_CTRL2  (0xE)
28#define REG_W_RESET  (0xF)
29
30#define REG_R_COMIN  (0x0)
31#define REG_R_IFSTAT (0x1)
32#define REG_R_DBCL   (0x2)
33#define REG_R_DBCH   (0x3)
34#define REG_R_HEAD0  (0x4)
35#define REG_R_HEAD1  (0x5)
36#define REG_R_HEAD2  (0x6)
37#define REG_R_HEAD3  (0x7)
38#define REG_R_PTL    (0x8)
39#define REG_R_PTH    (0x9)
40#define REG_R_WAL    (0xa)
41#define REG_R_WAH    (0xb)
42#define REG_R_STAT0  (0xc)
43#define REG_R_STAT1  (0xd)
44#define REG_R_STAT2  (0xe)
45#define REG_R_STAT3  (0xf)
46
47#define CMD_STATUS   (0x0)
48#define CMD_STOPALL  (0x1)
49#define CMD_GETTOC   (0x2)
50#define CMD_READ     (0x3)
51#define CMD_SEEK     (0x4)
52//                   (0x5)
53#define CMD_STOP     (0x6)
54#define CMD_RESUME   (0x7)
55#define CMD_FF       (0x8)
56#define CMD_RW       (0x9)
57#define CMD_INIT     (0xa)
58//                   (0xb)
59#define CMD_CLOSE    (0xc)
60#define CMD_OPEN     (0xd)
61//                   (0xe)
62//                   (0xf)
63
64
65#define TOCCMD_CURPOS    (0x0)
66#define TOCCMD_TRKPOS    (0x1)
67#define TOCCMD_CURTRK    (0x2)
68#define TOCCMD_LENGTH    (0x3)
69#define TOCCMD_FIRSTLAST (0x4)
70#define TOCCMD_TRACKADDR (0x5)
71
72
73
74
75#define SECTOR_SIZE (2352)
76
77#define SET_CDD_DATA_MODE \
78   CDD_CONTROL |= 0x0100; \
79
80#define SET_CDD_AUDIO_MODE \
81   CDD_CONTROL &= ~0x0100; \
82
83#define STOP_CDC_READ \
84   SCD_STATUS_CDC &= ~0x01; \
85
86#define SET_CDC_READ \
87   SCD_STATUS_CDC |= 0x01; \
88
89#define SET_CDC_DMA \
90   SCD_STATUS_CDC |= 0x08; \
91
92#define STOP_CDC_DMA \
93   SCD_STATUS_CDC &= ~0x08; \
94
95#define SCD_READ_ENABLED \
96   (SCD_STATUS_CDC & 1)
97
98#define SCD_DMA_ENABLED \
99   (SCD_STATUS_CDC & 0x08)
100
101#define CLEAR_CDD_RESULT \
102   CDD_MIN = CDD_SEC = CDD_FRAME = CDD_EXT = 0; \
103
104#define CHECK_SCD_LV5_INTERRUPT \
105   if (segacd_irq_mask & 0x20) \
106   { \
107      machine.device(":segacd:segacd_68k")->execute().set_input_line(5, HOLD_LINE); \
108   } \
109
110#define CHECK_SCD_LV4_INTERRUPT \
111   if (segacd_irq_mask & 0x10) \
112   { \
113      machine.device(":segacd:segacd_68k")->execute().set_input_line(4, HOLD_LINE); \
114   } \
115
116
117
118
119
120#define CURRENT_TRACK_IS_DATA \
121   (segacd.toc->tracks[SCD_CURTRK - 1].trktype != CD_TRACK_AUDIO) \
122
123
124#define CDD_PLAYINGCDDA   0x0100
125#define CDD_READY      0x0400
126#define CDD_STOPPED      0x0900
127
128
129#define MCFG_SEGACD_HACK_SET_CDC_DO_DMA( _class, _method) \
130   lc89510_temp_device::set_CDC_Do_DMA(*device, segacd_dma_delegate(&_class::_method, #_class "::" #_method, NULL, (_class *)0)); \
131
132#define MCFG_SEGACD_HACK_SET_NEOCD \
133   lc89510_temp_device::set_is_neoCD(*device, true); \
134
135
136/* neocd */
137
138#define CD_FRAMES_MINUTE (60 * 75)
139#define CD_FRAMES_SECOND (     75)
140#define CD_FRAMES_PREGAP ( 2 * 75)
141
142#define SEK_IRQSTATUS_NONE (0x0000)
143#define SEK_IRQSTATUS_AUTO (0x2000)
144#define SEK_IRQSTATUS_ACK  (0x1000)
145
146class lc89510_temp_device : public device_t
147{
148public:
149   lc89510_temp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
150
151   // HACK for DMA handling
152   segacd_dma_delegate segacd_dma_callback;
153   void Fake_CDC_Do_DMA(int &dmacount, UINT8 *CDC_BUFFER, UINT16 &CDC_DMA_ADDR, UINT16 &CDC_DMA_ADDRC, UINT16 &destination );
154   static void set_CDC_Do_DMA(device_t &device,segacd_dma_delegate new_segacd_dma_callback);
155
156   static void set_is_neoCD(device_t &device, bool is_neoCD);
157
158
159   // HACK for neoCD handling
160   bool is_neoCD;
161
162
163   struct segacd_t
164   {
165      cdrom_file   *cd;
166      const cdrom_toc   *toc;
167      UINT32 current_frame;
168   };
169
170
171   segacd_t segacd;
172
173   UINT8    SCD_BUFFER[2560];
174   char NeoCDSectorData[2352];
175
176   UINT32   SCD_STATUS;
177   UINT32   SCD_STATUS_CDC;
178   INT32    SCD_CURLBA;
179   UINT8    SCD_CURTRK;
180
181
182   UINT16 CDC_DECODE;
183   INT16 CDC_DMACNT; // can go negative
184   UINT16 CDC_DMA_ADDRC;
185   UINT16 CDC_PT;
186   UINT16 CDC_WA;
187   UINT16 CDC_REG0;
188   UINT16 CDC_REG1;
189   UINT16 CDC_DMA_ADDR;
190   UINT16 CDC_IFSTAT;
191   UINT8 CDC_HEADB0;
192   UINT8 CDC_HEADB1;
193   UINT8 CDC_HEADB2;
194   UINT8 CDC_HEADB3;
195   UINT8 CDC_STATB0;
196   UINT8 CDC_STATB1;
197   UINT8 CDC_STATB2;
198   UINT8 CDC_STATB3;
199   UINT16 CDC_SBOUT;
200   UINT16 CDC_IFCTRL;
201   UINT8 CDC_CTRLB0;
202   UINT8 CDC_CTRLB1;
203   UINT8 CDC_CTRLB2;
204   UINT8 CDC_BUFFER[(32 * 1024 * 2) + SECTOR_SIZE];
205
206   UINT32 CDD_STATUS;
207   UINT32 CDD_MIN;
208   UINT32 CDD_SEC;
209
210   UINT8 CDD_RX[10];
211   UINT8 CDD_TX[10];
212   UINT32 CDD_FRAME;
213   UINT32 CDD_EXT;
214   UINT16 CDD_CONTROL;
215   INT16  CDD_DONE;
216
217   inline int to_bcd(int val, bool byte);
218   void set_data_audio_mode(void);
219   void CDD_DoChecksum(void);
220   void CDD_Export(void);
221   void CDC_UpdateHEAD(void);
222   void scd_ctrl_checks(running_machine& machine);
223   void scd_advance_current_readpos(void);
224   int Read_LBA_To_Buffer(running_machine& machine);
225   void CheckCommand(running_machine& machine);
226   void CDD_GetStatus(void);
227   void CDD_Stop(running_machine &machine);
228   void CDD_GetPos(void);
229   void CDD_GetTrackPos(void);
230   void CDD_GetTrack(void);
231   void CDD_Length(void);
232   void CDD_FirstLast(void);
233   void CDD_GetTrackAdr(void);
234   UINT32 getmsf_from_regs(void);
235   void CDD_Play(running_machine &machine);
236   void CDD_Seek(void);
237   void CDD_Pause(running_machine &machine);
238   void CDD_Resume(running_machine &machine);
239   void CDD_FF(running_machine &machine);
240   void CDD_RW(running_machine &machine);
241   void CDD_Open(void);
242   void CDD_Close(void);
243   void CDD_Init(void);
244   void CDD_Default(void);
245   void CDD_Reset(void);
246   void CDC_Reset(void);
247   void lc89510_Reset(void);
248   void CDC_End_Transfer(running_machine& machine);
249   void CDC_Do_DMA(running_machine& machine, int rate);
250   UINT16 CDC_Host_r(running_machine& machine, UINT16 type);
251   UINT8 CDC_Reg_r(void);
252   void CDC_Reg_w(UINT8 data);
253   void CDD_Process(running_machine& machine, int reason);
254   void CDD_Handle_TOC_Commands(void);
255   void CDD_Import(running_machine& machine);
256   READ16_MEMBER( segacd_irq_mask_r );
257   WRITE16_MEMBER( segacd_irq_mask_w );
258   READ16_MEMBER( segacd_cdd_ctrl_r );
259   WRITE16_MEMBER( segacd_cdd_ctrl_w );
260   READ8_MEMBER( segacd_cdd_rx_r );
261   WRITE8_MEMBER( segacd_cdd_tx_w );
262   READ16_MEMBER( cdc_dmaaddr_r );
263   WRITE16_MEMBER( cdc_dmaaddr_w );
264   READ16_MEMBER( segacd_cdfader_r );
265   WRITE16_MEMBER( segacd_cdfader_w );
266
267   void reset_cd(void);
268
269   WRITE16_MEMBER( segacd_cdc_mode_address_w );
270   READ16_MEMBER( segacd_cdc_mode_address_r );
271   WRITE16_MEMBER( segacd_cdc_data_w );
272   READ16_MEMBER( segacd_cdc_data_r );
273   READ16_MEMBER( cdc_data_sub_r );
274   READ16_MEMBER( cdc_data_main_r );
275
276   TIMER_DEVICE_CALLBACK_MEMBER( segacd_access_timer_callback );
277
278   UINT16 get_segacd_irq_mask(void) { return segacd_irq_mask; }
279   UINT16 segacd_irq_mask;
280   cdda_device* m_cdda;
281
282   /* NeoCD */
283   INT32 nIRQAcknowledge;
284   UINT16 nff0002;
285   UINT16 nff0016;
286
287
288   INT32 LC8951RegistersR[16];
289   INT32 LC8951RegistersW[16];
290
291
292
293   bool bNeoCDCommsClock, bNeoCDCommsSend;
294
295   INT32 NeoCDCommsWordCount;
296
297   INT32 NeoCDAssyStatus;
298
299   INT32 NeoCDTrack;
300
301   INT32 NeoCDSectorMin;
302   INT32 NeoCDSectorSec;
303   INT32 NeoCDSectorFrm;
304
305   bool bNeoCDLoadSector;
306
307   INT32 NeoCDDMAAddress1;
308   INT32 NeoCDDMAAddress2;
309   INT32 NeoCDDMAValue1;
310   INT32 NeoCDDMAValue2;
311   INT32 NeoCDDMACount;
312
313   INT32 NeoCDDMAMode;
314   int nNeoCDIRQVectorAck;
315   int get_nNeoCDIRQVectorAck(void) { return nNeoCDIRQVectorAck; }
316   void set_nNeoCDIRQVectorAck(int val) { nNeoCDIRQVectorAck = val; }
317   int nNeoCDIRQVector;
318   int get_nNeoCDIRQVector(void) { return nNeoCDIRQVector; }
319
320   void NeoCDIRQUpdate(UINT8 byteValue);
321   void Read_LBA_To_Buffer_NeoCD();
322   void NeoCDCommsControl(UINT8 clock, UINT8 send);
323   void NeoCDProcessCommand();
324   void LC8951UpdateHeader();
325   char* LC8915InitTransfer();
326   void LC8915EndTransfer();
327   void LC8951Reset();
328   void NeoCDLBAToMSF(const INT32 LBA);
329   void neocd_cdd_tx_w(UINT8 data);
330   UINT8 neocd_cdd_rx_r();
331   void NeoCDCommsReset();
332   void NeoCDDoDMA();
333   void SekWriteWord(UINT32 a, UINT16 d);
334   void SekWriteByte(UINT32 a, UINT8 d);
335   UINT32 SekReadByte(UINT32 a);
336   UINT32 SekReadWord(UINT32 a);
337
338   UINT8* CDEmuReadQChannel(int SCD_CURLBA);
339   UINT8* CDEmuReadTOC(INT32 track);
340   INT32 CDEmuLoadSector(INT32 LBA, char* pBuffer);
341   void set_DMA_regs(int offset, UINT16 wordValue);
342   void reset_NeoCd(void);
343   address_space* dma_space;
344
345   void nLC8951_w(UINT16 byteValue);
346   UINT16 nLC8951_r(void);
347   UINT16 nff0016_r(void);
348   void nff0016_set(UINT16 wordValue);
349   void nff0002_set(UINT16 wordValue);
350
351protected:
352   virtual void device_start();
353   virtual void device_reset();
354   virtual machine_config_constructor device_mconfig_additions() const;
355private:
356
357
358};
359
360extern const device_type LC89510_TEMP;
361
trunk/src/mame/mame.mak
r19245r19246
12431243   $(DRIVERS)/kopunch.o $(VIDEO)/kopunch.o \
12441244   $(MACHINE)/megadriv.o \
12451245   $(MACHINE)/megacd.o \
1246   $(MACHINE)/megacdcd.o \
12461247   $(MACHINE)/mega32x.o \
12471248   $(MACHINE)/megasvp.o \
12481249   $(MACHINE)/megavdp.o \
trunk/src/mame/includes/megadriv.h
r19245r19246
1010#include "sound/dac.h"
1111#include "sound/rf5c68.h"
1212#include "sound/sn76496.h"
13#include "imagedev/chd_cd.h"
13
1414#include "machine/nvram.h"
1515#include "cpu/ssp1601/ssp1601.h"
1616
trunk/src/mess/drivers/ng_aes.c
r19245r19246
3737#include "imagedev/cartslot.h"
3838#include "imagedev/chd_cd.h"
3939#include "sound/cdda.h"
40#include "machine/megacdcd.h"
4041
41struct neocd_t
42{
43   cdrom_file   *cd;
44   const cdrom_toc   *toc;
45};
4642
47static neocd_t neocd;
48
4943extern const char layout_neogeo[];
5044
5145static const char *audio_banks[4] =
r19245r19246
5448};
5549
5650
57#define CD_FRAMES_MINUTE (60 * 75)
58#define CD_FRAMES_SECOND (     75)
59#define CD_FRAMES_PREGAP ( 2 * 75)
6051
61#define SEK_IRQSTATUS_NONE (0x0000)
62#define SEK_IRQSTATUS_AUTO (0x2000)
63#define SEK_IRQSTATUS_ACK  (0x1000)
6452
6553static IRQ_CALLBACK(neocd_int_callback);
6654
6755/* Stubs for various functions called by the FBA code, replace with MAME specifics later */
68#define MAX_SLOT      (8)
56
6957UINT8 *NeoSpriteRAM, *NeoTextRAM;
70//UINT8* NeoSpriteROM[MAX_SLOT];
71//UINT8* NeoTextROM[MAX_SLOT];
72UINT8* YM2610ADPCMAROM[MAX_SLOT];
58//UINT8* NeoSpriteROM;
59//UINT8* NeoTextROM;
60UINT8* YM2610ADPCMAROM;
7361UINT8* NeoZ80ROMActive;
74UINT32 nNeoActiveSlot;
7562UINT8 NeoSystem = 6;
7663INT32 nNeoCDZ80ProgWriteWordCancelHack = 0;
7764
78enum CDEmuStatusValue { idle = 0, reading, playing, paused, seeking, fastforward, fastreverse };
79CDEmuStatusValue CDEmuStatus;
8065
81static inline CDEmuStatusValue CDEmuGetStatus()
82{
83   printf("CDEmuGetStatus\n");
84   return CDEmuStatus;
85}
8666
87static UINT8* CDEmuReadQChannel(int NeoCDSectorLBA)
88{
89   printf("CDEmuReadQChannel\n");
90   static unsigned char QChannelData[8];
9167
92   if(neocd.cd == NULL) // no cd is there, bail out
93      return QChannelData;
9468
95//  NeoCDSectorLBA
96   switch (CDEmuStatus) {
97      case reading:
98      case playing: {
9969
100         UINT32 msf;
101         msf = lba_to_msf_alt(NeoCDSectorLBA+150);
10270
103
104
105         QChannelData[0] = cdrom_get_track(neocd.cd, NeoCDSectorLBA);
106
107         QChannelData[1] = (msf >> 16)&0xff;
108         QChannelData[2] = (msf >> 8)&0xff;
109         QChannelData[3] = (msf >> 0)&0xff;
110
111         int elapsedlba;
112         elapsedlba = NeoCDSectorLBA - neocd.toc->tracks[ cdrom_get_track(neocd.cd, NeoCDSectorLBA) ].physframeofs;
113         msf = lba_to_msf_alt (elapsedlba);
114
115         QChannelData[4] = (msf >> 16)&0xff;
116         QChannelData[5] = (msf >> 8)&0xff;
117         QChannelData[6] = (msf >> 0)&0xff;
118
119         if (QChannelData[0]==1)
120            QChannelData[7] = 0x4;
121         else
122            QChannelData[7] = 0x0;
123
124         break;
125      }
126      case paused: {
127         break;
128      }
129      default: {
130         memset(QChannelData, 0, sizeof(QChannelData));
131      }
132   }
133
134   return QChannelData;
135}
136
137static UINT8* CDEmuReadTOC(INT32 track)
138{
139   printf("CDEmuReadTOC\n");
140
141   static unsigned char TOCEntry[4];
142
143   if(neocd.cd == NULL)
144      return TOCEntry;
145
146
147   if (track == -1) {
148      printf("get first/last track nums\n");
149      TOCEntry[0] = 1;
150      TOCEntry[1] = cdrom_get_last_track(neocd.cd);
151      TOCEntry[2] = 0;
152      TOCEntry[3] = 0;
153
154      return TOCEntry;
155   }
156   else if (track == -2) {
157      printf("get disc length\n");
158
159      UINT32 startlba = (neocd.toc->tracks[cdrom_get_last_track(neocd.cd)].physframeofs);
160      UINT32 startmsf = lba_to_msf_alt( startlba );
161
162
163      TOCEntry[0] = (startmsf >> 16)&0xff;
164      TOCEntry[1] = (startmsf >> 8)&0xff;
165      TOCEntry[2] = (startmsf >> 0)&0xff;
166
167      TOCEntry[3] = 0;
168
169      return TOCEntry;
170   }
171   else
172   {
173      printf("get track address\n");
174
175      int last_track = cdrom_get_last_track(neocd.cd);
176
177      if (track > last_track)
178         track = last_track;
179
180      if (track < 1)
181         track = 1;
182
183      UINT32 startlba = (neocd.toc->tracks[track-1].physframeofs);
184      UINT32 startmsf = lba_to_msf_alt( startlba+150 );
185
186      TOCEntry[0] = (startmsf >> 16)&0xff;
187      TOCEntry[1] = (startmsf >> 8)&0xff;
188      TOCEntry[2] = (startmsf >> 0)&0xff;
189      TOCEntry[3] =  track % 10;;
190   }
191
192   return TOCEntry;
193
194}
195
196static void CDEmuStartRead()
197{
198   printf("CDEmuStartRead\n");
199   CDEmuStatus = seeking;
200}
201
202static void CDEmuPause()
203{
204   printf("CDEmuPause\n");
205   CDEmuStatus = paused;
206}
207
208static INT32 CDEmuStop()
209{
210   printf("CDEmuStop\n");
211   return 1;
212}
213
214static INT32 CDEmuPlay(UINT8 M, UINT8 S, UINT8 F)
215{
216   printf("CDEmuPlay\n");
217   return 1;
218}
219
220static INT32 CDEmuLoadSector(INT32 LBA, char* pBuffer)
221{
222   printf("CDEmuLoadSector %d\n", LBA);
223   //LBA += 150;
224
225   cdrom_read_data(neocd.cd, LBA, pBuffer, CD_TRACK_MODE1);
226
227   return LBA+1;// - 150;
228}
229
230
231
232static INT32 SekIdle(INT32 nCycles)
233{
234   return nCycles;
235}
236
237static void NeoSetSpriteSlot(INT32 nSlot)
238{
239
240}
241
242static void NeoSetTextSlot(INT32 nSlot)
243{
244
245}
246
247
248
249
250
251
25271static void MapVectorTable(bool bMapBoardROM)
25372{
25473   /*
25574    if (!bMapBoardROM && Neo68KROMActive) {
256        SekMapMemory(Neo68KFix[nNeoActiveSlot], 0x000000, 0x0003FF, SM_ROM);
75        SekMapMemory(Neo68KFix, 0x000000, 0x0003FF, SM_ROM);
25776    } else {
25877        SekMapMemory(NeoVectorActive, 0x000000, 0x0003FF, SM_ROM);
25978    }
r19245r19246
26584{
26685public:
26786   ng_aes_state(const machine_config &mconfig, device_type type, const char *tag)
268      : neogeo_state(mconfig, type, tag)
87      : neogeo_state(mconfig, type, tag),
88      m_tempcdc(*this,"tempcdc")
26989   {
270      nff0002 = 0;
271      nIRQAcknowledge = ~0;
272      for (int i=0;i<10;i++)
273         NeoCDCommsCommandFIFO[i] = 0;
274      for (int i=0;i<10;i++)
275         NeoCDCommsStatusFIFO[i] = 0;
276      NeoCDCommsWordCount = 0;
277      NeoCDAssyStatus = 0;
278      NeoCDTrack = 0;
279      NeoCDSectorMin = 0;
280      NeoCDSectorSec = 0;
281      NeoCDSectorFrm = 0;
282      NeoCDSectorLBA = 0;
283      for (int i=0;i<2352;i++)
284         NeoCDSectorData[i] = 0;
285      bNeoCDLoadSector = false;
286      NeoCDDMAAddress1 = 0;
287      NeoCDDMAAddress2 = 0;
288      NeoCDDMAValue1   = 0;
289      NeoCDDMAValue2   = 0;
290      NeoCDDMACount    = 0;
291      NeoCDDMAMode = 0;
292      nLC8951Register = 0;
293      nNeoCDIRQVectorAck = 0;
294      nNeoCDIRQVector = 0;
90
29591   }
29692
93   required_device<lc89510_temp_device> m_tempcdc;
94
95
29796   UINT8 *m_memcard_data;
29897   DECLARE_WRITE8_MEMBER(audio_cpu_clear_nmi_w);
29998   DECLARE_WRITE16_MEMBER(io_control_w);
r19245r19246
326125   DECLARE_CUSTOM_INPUT_MEMBER(get_memcard_status);
327126
328127   // neoCD
329   TIMER_DEVICE_CALLBACK_MEMBER( neocd_access_timer_callback );
330   INT32 nIRQAcknowledge;
331   UINT16 nff0002;
332   UINT16 nff0016;
333128
129   UINT16 neogeoReadWordCDROM(UINT32 sekAddress);
130   void neogeoWriteWordCDROM(UINT32 sekAddress, UINT16 wordValue);
131   UINT8 neogeoReadTransfer(UINT32 sekAddress, int is_byte_transfer);
132   void neogeoWriteTransfer(UINT32 sekAddress, UINT8 byteValue, int is_byte_transfer);
334133
335   INT32 nLC8951Register;
336   INT32 LC8951RegistersR[16];
337   INT32 LC8951RegistersW[16];
338
339134   INT32 nActiveTransferArea;
340135   INT32 nSpriteTransferBank;
341136   INT32 nADPCMTransferBank;
342137
343138   UINT8 nTransferWriteEnable;
344139
345   bool NeoCDOBJBankUpdate[4];
346
347   bool bNeoCDCommsClock, bNeoCDCommsSend;
348
349   UINT8 NeoCDCommsCommandFIFO[10];
350   UINT8 NeoCDCommsStatusFIFO[10];
351
352   INT32 NeoCDCommsWordCount;
353
354   INT32 NeoCDAssyStatus;
355
356   INT32 NeoCDTrack;
357
358   INT32 NeoCDSectorMin;
359   INT32 NeoCDSectorSec;
360   INT32 NeoCDSectorFrm;
361   INT32 NeoCDSectorLBA;
362
363   char NeoCDSectorData[2352];
364
365   bool bNeoCDLoadSector;
366
367   INT32 NeoCDDMAAddress1;
368   INT32 NeoCDDMAAddress2;
369   INT32 NeoCDDMAValue1;
370   INT32 NeoCDDMAValue2;
371   INT32 NeoCDDMACount;
372
373   INT32 NeoCDDMAMode;
374
375
376
377   void NeoCDIRQUpdate(UINT8 byteValue);
378   void NeoCDReadSector();
379   void NeoCDCommsControl(UINT8 clock, UINT8 send);
380   void NeoCDProcessCommand();
381   void LC8951UpdateHeader();
382   char* LC8915InitTransfer();
383   void LC8915EndTransfer();
384   void LC8951Reset();
385   void NeoCDLBAToMSF(const INT32 LBA);
386   void NeoCDCommsWrite(UINT8 data);
387   UINT8 NeoCDCommsread();
388   void NeoCDCommsReset();
389   void NeoCDDoDMA();
390   UINT16 neogeoReadWordCDROM(UINT32 sekAddress);
391   void neogeoWriteWordCDROM(UINT32 sekAddress, UINT16 wordValue);
392   UINT8 neogeoReadTransfer(UINT32 sekAddress, int is_byte_transfer);
393   void neogeoWriteTransfer(UINT32 sekAddress, UINT8 byteValue, int is_byte_transfer);
394   void NeoIRQUpdate(UINT16 wordValue);
395   void SekWriteWord(UINT32 a, UINT16 d);
396   void SekWriteByte(UINT32 a, UINT8 d);
397   UINT32 SekReadByte(UINT32 a);
398   UINT32 SekReadWord(UINT32 a);
399140   address_space* curr_space;
400   int nNeoCDIRQVectorAck;
401   int nNeoCDIRQVector;
402141
142
403143};
404144
405void ng_aes_state::SekWriteWord(UINT32 a, UINT16 d)
406{
407//  printf("write word %08x %04x\n", a, d);
408   curr_space->write_word(a,d);
409}
410145
411void ng_aes_state::SekWriteByte(UINT32 a, UINT8 d)
412{
413//  printf("write byte %08x %02x\n", a, d);
414   curr_space->write_byte(a,d);
415}
416
417UINT32 ng_aes_state::SekReadByte(UINT32 a)
418{
419//  printf("read byte %08x\n", a);
420   return curr_space->read_byte(a);
421}
422
423
424UINT32 ng_aes_state::SekReadWord(UINT32 a)
425{
426//  printf("read WORD %08x\n", a);
427   return curr_space->read_word(a);
428}
429
430
431
432146#define LOG_VIDEO_SYSTEM      (0)
433147#define LOG_CPU_COMM         (0)
434148#define LOG_MAIN_CPU_BANKING   (1)
r19245r19246
896610   }
897611}
898612
899/*
900 *  CD-ROM / DMA control
901 *
902 *  DMA
903613
904    FF0061  Write 0x40 means start DMA transfer
905    FF0064  Source address (in copy mode), Target address (in filll mode)
906    FF0068  Target address (in copy mode)
907    FF006C  Fill word
908    FF0070  Words count
909    FF007E  \
910    ......   | DMA programming words?   NeoGeoCD uses Sanyo Puppet LC8359 chip to
911    FF008E  /                           interface with CD, and do DMA transfers
912
913    Memory access control
914
915    FF011C  DIP SWITCH (Region code)
916    FF0105  Area Selector (5 = FIX, 0 = SPR, 4 = Z80, 1 = PCM)
917    FF01A1  Sprite bank selector
918    FF01A3  PCM bank selector
919    FF0120  Prepare sprite area for transfer
920    FF0122  Prepare PCM area for transfer
921    FF0126  Prepare Z80 area for transfer
922    FF0128  Prepare Fix area for transfer
923    FF0140  Terminate work on Spr Area  (Sprites must be decoded here)
924    FF0142  Terminate work on Pcm Area
925    FF0146  Terminate work on Z80 Area  (Z80 needs to be reset)
926    FF0148  Terminate work on Fix Area
927
928    CD-ROM:
929    0xff0102 == 0xF0 start cd transfer
930    int m=bcd(fast_r8(0x10f6c8));
931    int s=bcd(fast_r8(0x10f6c9));
932    int f=bcd(fast_r8(0x10f6ca));
933    int seccount=fast_r16(0x10f688);
934
935    inisec=((m*60)+s)*75+f;
936    inisec-=150;
937    dstaddr=0x111204; // this must come from somewhere
938
939    the value @ 0x10f688 is decremented each time a sector is read until it's 0.
940
941 *
942 */
943
944
945void ng_aes_state::NeoCDReadSector()
946{
947   if ((nff0002 & 0x0500)) {
948      if (NeoCDAssyStatus == 1 && bNeoCDLoadSector) {
949
950//          if (LC8951RegistersW[10] & 0x80) {
951            NeoCDSectorLBA++;
952            NeoCDSectorLBA = CDEmuLoadSector(NeoCDSectorLBA, NeoCDSectorData + 4) -1;
953//          }
954
955         if (LC8951RegistersW[10] & 0x80) {
956            LC8951UpdateHeader();
957
958            LC8951RegistersR[12] = 0x80;                              // STAT0
959            LC8951RegistersR[13] = 0;                                 // STAT1
960            LC8951RegistersR[14] = 0x10;                              // STAT2
961            LC8951RegistersR[15] = 0;                                 // STAT3
962
963//              bprintf(PRINT_IMPORTANT, _T("    Sector %08i (%02i:%02i:%02i) read\n"), NeoCDSectorLBA, NeoCDSectorMin, NeoCDSectorSec, NeoCDSectorFrm);
964
965// CDZ protection hack? (error correction on the CDC should correct this?)
966#if 1
967            if (NeoCDSectorData[4 + 64] == 'g' && !strncmp(NeoCDSectorData + 4, "Copyright by SNK", 16)) {
968//                  printf(PRINT_ERROR, _T("    simulated CDZ protection error\n"));
969//                  bprintf(PRINT_ERROR, _T("    %.70hs\n"), NeoCDSectorData + 4);
970
971               NeoCDSectorData[4 + 64] = 'f';
972
973               // LC8951RegistersR[12] = 0x00;                                 // STAT0
974            }
975#endif
976
977            nIRQAcknowledge &= ~0x20;
978            NeoCDIRQUpdate(0);
979
980            LC8951RegistersR[1] &= ~0x20;
981
982//              bprintf(PRINT_IMPORTANT, _T("    DECI interrupt triggered\n"));
983         }
984      }
985
986      bNeoCDLoadSector = true;
987//      bNeoCDLoadSector = false;
988   }
989}
990
991
992
993614UINT8 ng_aes_state::neogeoReadTransfer(UINT32 sekAddress, int is_byte_transfer)
994615{
995616//  if ((sekAddress & 0x0FFFFF) < 16)
r19245r19246
1002623         return NeoSpriteRAM[nSpriteTransferBank + (sekAddress & 0x0FFFFF)];
1003624         break;
1004625      case 1:                     // ADPCM
1005         return YM2610ADPCMAROM[nNeoActiveSlot][nADPCMTransferBank + ((sekAddress & 0x0FFFFF) >> 1)];
626         return YM2610ADPCMAROM[nADPCMTransferBank + ((sekAddress & 0x0FFFFF) >> 1)];
1006627         break;
1007628      case 4:                     // Z80
1008629         if ((sekAddress & 0xfffff) >= 0x20000) break;
r19245r19246
1043664         //  NeoCDOBJBankUpdate[nSpriteTransferBank >> 20] = true;
1044665         break;
1045666      case 1:                     // ADPCM
1046         YM2610ADPCMAROM[nNeoActiveSlot][nADPCMTransferBank + ((sekAddress & 0x0FFFFF) >> 1)] = byteValue;
667         YM2610ADPCMAROM[nADPCMTransferBank + ((sekAddress & 0x0FFFFF) >> 1)] = byteValue;
1047668         break;
1048669      case 4:                     // Z80
1049670         if ((sekAddress & 0xfffff) >= 0x20000) break;
r19245r19246
1073694   switch (sekAddress & 0xFFFF) {
1074695
1075696      case 0x0016:
1076         return nff0016;
697         return m_tempcdc->nff0016_r();
1077698
1078699      // LC8951 registers
1079700      case 0x0100:
1080//          bprintf(PRINT_NORMAL, _T("  - LC8951 register read (PC: 0x%06X)\n"), SekGetPC(-1));
1081         return nLC8951Register;
1082      case 0x0102: {
1083//          bprintf(PRINT_NORMAL, _T("  - LC8951 register 0x%X read (PC: 0x%06X)\n"), nLC8951Register, SekGetPC(-1));
701         return m_tempcdc->segacd_cdc_mode_address_r(*curr_space, 0, 0xffff);
702      case 0x0102:
703         return m_tempcdc->nLC8951_r();
1084704
1085         INT32 reg = LC8951RegistersR[nLC8951Register];
1086
1087         switch (nLC8951Register) {
1088            case 0x03:                                          // DBCH
1089               LC8951RegistersR[3] &=  0x0F;
1090               LC8951RegistersR[3] |=  (LC8951RegistersR[1] & 0x40) ? 0x00 : 0xF0;
1091               break;
1092            case 0x0D:                                          // STAT3
1093               LC8951RegistersR[1] |= 0x20;                        // reset DECI
1094               // bprintf(PRINT_ERROR, _T("  - DECI (PC: 0x%06X)\n"), SekGetPC(-1));
1095               break;
1096         }
1097
1098         nLC8951Register = (nLC8951Register + 1) & 0x0F;
1099         return reg;
1100      }
1101
1102705      // CD mechanism communication
1103706      case 0x0160:
1104         return NeoCDCommsread();
707         return m_tempcdc->neocd_cdd_rx_r();
1105708
1106709      case 0x011C: // region
1107710         return ~((0x10 | (NeoSystem & 3)) << 8);
r19245r19246
1121724
1122725   switch (sekAddress & 0xFFFE) {
1123726      case 0x0002:
1124//          bprintf(PRINT_IMPORTANT, _T("  - NGCD Interrupt mask -> 0x%04X (PC: 0x%06X)\n"), wordValue, SekGetPC(-1));
1125         nff0002 = wordValue;
1126727
1127// LC8951RegistersR[1] |= 0x20;
728         m_tempcdc->nff0002_set(wordValue);
1128729
1129         //if (nff0002 & 0x0500)
1130         //  nNeoCDCyclesIRQPeriod = (INT32)(12000000.0 * nBurnCPUSpeedAdjust / (256.0 * 75.0));
1131         //else
1132         //  nNeoCDCyclesIRQPeriod = (INT32)(12000000.0 * nBurnCPUSpeedAdjust / (256.0 *  75.0));
1133
1134730         break;
1135731
1136732      case 0x000E:
1137         NeoCDIRQUpdate(wordValue); // irqack
733         m_tempcdc->NeoCDIRQUpdate(wordValue); // irqack
1138734         break;
1139735
1140736      case 0x0016:
1141         nff0016 = byteValue;
737         m_tempcdc->nff0016_set(byteValue);
1142738         break;
1143739
1144740         // DMA controller
1145741      case 0x0060:
1146742         if (byteValue & 0x40) {
1147            NeoCDDoDMA();
743            m_tempcdc->NeoCDDoDMA();
1148744         }
1149745         break;
1150746
1151
1152747      case 0x0064:
1153         NeoCDDMAAddress1 &= 0x0000FFFF;
1154         NeoCDDMAAddress1 |= wordValue << 16;
1155         break;
1156748      case 0x0066:
1157         NeoCDDMAAddress1 &= 0xFFFF0000;
1158         NeoCDDMAAddress1 |= wordValue;
1159         break;
1160749      case 0x0068:
1161         NeoCDDMAAddress2 &= 0x0000FFFF;
1162         NeoCDDMAAddress2 |= wordValue << 16;
1163         break;
1164750      case 0x006A:
1165         NeoCDDMAAddress2 &= 0xFFFF0000;
1166         NeoCDDMAAddress2 |= wordValue;
1167         break;
1168751      case 0x006C:
1169         NeoCDDMAValue1 = wordValue;
1170         break;
1171752      case 0x006E:
1172         NeoCDDMAValue2 = wordValue;
1173         break;
1174753      case 0x0070:
1175         NeoCDDMACount &= 0x0000FFFF;
1176         NeoCDDMACount |= wordValue << 16;
1177         break;
1178754      case 0x0072:
1179         NeoCDDMACount &= 0xFFFF0000;
1180         NeoCDDMACount |= wordValue;
1181         break;
1182
1183755      case 0x007E:
1184         NeoCDDMAMode = wordValue;
1185//          bprintf(PRINT_NORMAL, _T("  - DMA controller 0x%2X -> 0x%04X (PC: 0x%06X)\n"), sekAddress & 0xFF, wordValue, SekGetPC(-1));
756         m_tempcdc->set_DMA_regs(sekAddress & 0xFFFE, wordValue);
1186757         break;
1187758
1188759      // upload DMA controller program
r19245r19246
1200771
1201772      // LC8951 registers
1202773      case 0x0100:
1203         nLC8951Register = byteValue & 0x0F;
1204//          bprintf(PRINT_NORMAL, _T("  - LC8951 register -> 0x%02X (PC: 0x%06X)\n"), nLC8951Register, SekGetPC(-1));
774         m_tempcdc->segacd_cdc_mode_address_w(*curr_space, 0, byteValue, 0xffff);
1205775         break;
1206776      case 0x0102:
1207//          bprintf(PRINT_NORMAL, _T("  - LC8951 register 0x%X -> 0x%02X (PC: 0x%06X)\n"), nLC8951Register, byteValue, SekGetPC(-1));
1208         switch (nLC8951Register) {
1209            case 3:                                             // DBCH
1210               LC8951RegistersW[ 3]  = byteValue & 0x0F;
1211               break;
1212            case 6:                                             // DTTRG
1213               LC8951RegistersW[ 6]  = ~0x00;
1214               LC8951RegistersR[ 1] &= ~0x08;
1215               break;
1216            case 7:                                             // DTACK
1217               LC8951RegistersW[ 7]  = ~0x00;
1218               LC8951RegistersR[ 1] &= ~0x40;
1219               break;
1220//              case 10:
1221//                  LC8951RegistersW[nLC8951Register] = byteValue;
1222//                  bprintf(PRINT_NORMAL, _T("  - CTRL0 -> %02X (PC: 0x%06X)\n"), LC8951RegistersW[nLC8951Register], byteValue, SekGetPC(-1));
1223//                  break;
1224            case 11:
1225               LC8951RegistersW[11]  = byteValue;                     // CTRL1
1226               LC8951UpdateHeader();
1227               break;
1228            case 15:
1229               LC8951Reset();
1230               break;
1231            default:
1232               LC8951RegistersW[nLC8951Register] = byteValue;
1233         }
1234         nLC8951Register = (nLC8951Register + 1) & 0x0F;
777         m_tempcdc->nLC8951_w(byteValue);
1235778         break;
1236779
1237780      case 0x0104:
r19245r19246
1241784
1242785      case 0x0120:
1243786//          bprintf(PRINT_NORMAL, _T("  - NGCD OBJ BUSREQ -> 1 (PC: 0x%06X)\n"), SekGetPC(-1));
1244         NeoSetSpriteSlot(1);
1245         memset(NeoCDOBJBankUpdate, 0, sizeof(NeoCDOBJBankUpdate));
1246787         break;
1247788      case 0x0122:
1248789//          bprintf(PRINT_NORMAL, _T("  - NGCD PCM BUSREQ -> 1 (PC: 0x%06X) %x\n"), SekGetPC(-1), byteValue);
r19245r19246
1255796         break;
1256797      case 0x0128:
1257798//          bprintf(PRINT_NORMAL, _T("  - NGCD FIX BUSREQ -> 1 (PC: 0x%06X)\n"), SekGetPC(-1));
1258         NeoSetTextSlot(1);
1259799         break;
1260800
1261801      case 0x0140:
r19245r19246
1277817
1278818      // CD mechanism communication
1279819      case 0x0162:
1280         NeoCDCommsWrite(byteValue);
820         m_tempcdc->neocd_cdd_tx_w(byteValue);
1281821         break;
1282822      case 0x0164:
1283         NeoCDCommsControl(byteValue & 1, byteValue & 2);
823         m_tempcdc->NeoCDCommsControl(byteValue & 1, byteValue & 2);
1284824         break;
1285825
1286826      case 0x016c:
r19245r19246
1332872}
1333873
1334874
1335void ng_aes_state::NeoCDLBAToMSF(const INT32 LBA)
1336{
1337   NeoCDSectorMin = (LBA + CD_FRAMES_PREGAP)                    / CD_FRAMES_MINUTE;
1338   NeoCDSectorSec = (LBA + CD_FRAMES_PREGAP) % CD_FRAMES_MINUTE / CD_FRAMES_SECOND;
1339   NeoCDSectorFrm = (LBA + CD_FRAMES_PREGAP) % CD_FRAMES_SECOND;
1340}
1341875
1342void ng_aes_state::NeoCDCommsWrite(UINT8 data)
1343{
1344   //printf("NeoCDCommsWrite %d, %02x\n", NeoCDCommsWordCount, data);
1345
1346   if (NeoCDCommsWordCount >= 0 && NeoCDCommsWordCount < 10) {
1347      NeoCDCommsCommandFIFO[NeoCDCommsWordCount] = data & 0x0F;
1348   }
1349}
1350
1351UINT8 ng_aes_state::NeoCDCommsread()
1352{
1353   UINT8 ret = 0;
1354
1355   if (NeoCDCommsWordCount >= 0 && NeoCDCommsWordCount < 10) {
1356      ret = NeoCDCommsStatusFIFO[NeoCDCommsWordCount] & 0x0F;
1357   }
1358
1359   if (bNeoCDCommsClock) {
1360      ret |= 0x10;
1361   }
1362
1363   return ret;
1364}
1365
1366void ng_aes_state::NeoCDCommsReset()
1367{
1368   bNeoCDCommsSend  = false;
1369   bNeoCDCommsClock = true;
1370
1371   memset(NeoCDCommsCommandFIFO, 0, sizeof(NeoCDCommsCommandFIFO));
1372   memset(NeoCDCommsStatusFIFO,  0, sizeof(NeoCDCommsStatusFIFO));
1373
1374   NeoCDCommsWordCount = 0;
1375
1376   NeoCDAssyStatus = 9;
1377
1378   memset(NeoCDSectorData, 0, sizeof(NeoCDSectorData));
1379
1380   bNeoCDLoadSector = false;
1381
1382   nff0016 = 0;
1383}
1384
1385
1386void ng_aes_state::NeoCDDoDMA()
1387{
1388
1389   // The LC8953 chip has a programmable DMA controller, which is not properly emulated.
1390   // Since the software only uses it in a limited way, we can apply a simple heuristic
1391   // to determnine the requested operation.
1392
1393   // Additionally, we don't know how many cycles DMA operations take.
1394   // Here, only bus access is used to get a rough approximation --
1395   // each read/write takes a single cycle, setup and everything else is ignored.
1396
1397//  bprintf(PRINT_IMPORTANT, _T("  - DMA controller transfer started (PC: 0x%06X)\n"), SekGetPC(-1));
1398
1399   switch (NeoCDDMAMode) {
1400
1401      case 0xCFFD: {
1402//          bprintf(PRINT_NORMAL, _T("    adr : 0x%08X - 0x%08X <- address, skip odd bytes\n"), NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 8);
1403
1404         //  - DMA controller 0x7E -> 0xCFFD (PC: 0xC07CE2)
1405         //  - DMA controller program[00] -> 0xFCF5 (PC: 0xC07CE8)
1406         //  - DMA controller program[02] -> 0xE8DA (PC: 0xC07CEE)
1407         //  - DMA controller program[04] -> 0x92DA (PC: 0xC07CF4)
1408         //  - DMA controller program[06] -> 0x92DB (PC: 0xC07CFA)
1409         //  - DMA controller program[08] -> 0x96DB (PC: 0xC07D00)
1410         //  - DMA controller program[10] -> 0x96F6 (PC: 0xC07D06)
1411         //  - DMA controller program[12] -> 0x2E02 (PC: 0xC07D0C)
1412         //  - DMA controller program[14] -> 0xFDFF (PC: 0xC07D12)
1413
1414         SekIdle(NeoCDDMACount * 4);
1415
1416         while (NeoCDDMACount--) {
1417            SekWriteWord(NeoCDDMAAddress1 + 0, NeoCDDMAAddress1 >> 24);
1418            SekWriteWord(NeoCDDMAAddress1 + 2, NeoCDDMAAddress1 >> 16);
1419            SekWriteWord(NeoCDDMAAddress1 + 4, NeoCDDMAAddress1 >>  8);
1420            SekWriteWord(NeoCDDMAAddress1 + 6, NeoCDDMAAddress1 >>  0);
1421            NeoCDDMAAddress1 += 8;
1422         }
1423
1424         break;
1425      }
1426
1427      case 0xE2DD: {
1428//          bprintf(PRINT_NORMAL, _T("    copy: 0x%08X - 0x%08X <- 0x%08X - 0x%08X, skip odd bytes\n"), NeoCDDMAAddress2, NeoCDDMAAddress2 + NeoCDDMACount * 2, NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 4);
1429
1430         //  - DMA controller 0x7E -> 0xE2DD (PC: 0xC0A190)
1431         //  - DMA controller program[00] -> 0xFCF5 (PC: 0xC0A192)
1432         //  - DMA controller program[02] -> 0x82BE (PC: 0xC0A194)
1433         //  - DMA controller program[04] -> 0x93DA (PC: 0xC0A196)
1434         //  - DMA controller program[06] -> 0xBE93 (PC: 0xC0A198)
1435         //  - DMA controller program[08] -> 0xDABE (PC: 0xC0A19A)
1436         //  - DMA controller program[10] -> 0xF62D (PC: 0xC0A19C)
1437         //  - DMA controller program[12] -> 0x02FD (PC: 0xC0A19E)
1438         //  - DMA controller program[14] -> 0xFFFF (PC: 0xC0A1A0)
1439
1440         SekIdle(NeoCDDMACount * 1);
1441
1442         while (NeoCDDMACount--) {
1443            SekWriteWord(NeoCDDMAAddress2 + 0, SekReadByte(NeoCDDMAAddress1 + 0));
1444            SekWriteWord(NeoCDDMAAddress2 + 2, SekReadByte(NeoCDDMAAddress1 + 1));
1445            NeoCDDMAAddress1 += 2;
1446            NeoCDDMAAddress2 += 4;
1447         }
1448
1449         break;
1450      }
1451
1452      case 0xFC2D: {
1453//          bprintf(PRINT_NORMAL, _T("    copy: 0x%08X - 0x%08X <- LC8951 external buffer, skip odd bytes\n"), NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 4);
1454
1455         //  - DMA controller 0x7E -> 0xFC2D (PC: 0xC0A190)
1456         //  - DMA controller program[00] -> 0xFCF5 (PC: 0xC0A192)
1457         //  - DMA controller program[02] -> 0x8492 (PC: 0xC0A194)
1458         //  - DMA controller program[04] -> 0xDA92 (PC: 0xC0A196)
1459         //  - DMA controller program[06] -> 0xDAF6 (PC: 0xC0A198)
1460         //  - DMA controller program[08] -> 0x2A02 (PC: 0xC0A19A)
1461         //  - DMA controller program[10] -> 0xFDFF (PC: 0xC0A19C)
1462         //  - DMA controller program[12] -> 0x48E7 (PC: 0xC0A19E)
1463         //  - DMA controller program[14] -> 0xFFFE (PC: 0xC0A1A0)
1464
1465         char* data = LC8915InitTransfer();
1466         if (data == NULL) {
1467            break;
1468         }
1469
1470         SekIdle(NeoCDDMACount * 4);
1471
1472         while (NeoCDDMACount--) {
1473            SekWriteByte(NeoCDDMAAddress1 + 0, data[0]);
1474            SekWriteByte(NeoCDDMAAddress1 + 2, data[1]);
1475            NeoCDDMAAddress1 += 4;
1476            data += 2;
1477         }
1478
1479         LC8915EndTransfer();
1480
1481         break;
1482      }
1483
1484      case 0xFE3D:
1485
1486         //  - DMA controller 0x7E -> 0xFE3D (PC: 0xC0A190)
1487         //  - DMA controller program[00] -> 0xFCF5 (PC: 0xC0A192)
1488         //  - DMA controller program[02] -> 0x82BF (PC: 0xC0A194)
1489         //  - DMA controller program[04] -> 0x93BF (PC: 0xC0A196)
1490         //  - DMA controller program[06] -> 0xF629 (PC: 0xC0A198)
1491         //  - DMA controller program[08] -> 0x02FD (PC: 0xC0A19A)
1492         //  - DMA controller program[10] -> 0xFFFF (PC: 0xC0A19C)
1493         //  - DMA controller program[12] -> 0xF17D (PC: 0xC0A19E)
1494         //  - DMA controller program[14] -> 0xFCF5 (PC: 0xC0A1A0)
1495
1496      case 0xFE6D: {
1497//          bprintf(PRINT_NORMAL, _T("    copy: 0x%08X - 0x%08X <- 0x%08X - 0x%08X\n"), NeoCDDMAAddress2, NeoCDDMAAddress2 + NeoCDDMACount * 2, NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 2);
1498
1499         //  - DMA controller 0x7E -> 0xFE6D (PC: 0xC0FD7A)
1500         //  - DMA controller program[00] -> 0xFCF5 (PC: 0xC0FD7C)
1501         //  - DMA controller program[02] -> 0x82BF (PC: 0xC0FD7E)
1502         //  - DMA controller program[04] -> 0xF693 (PC: 0xC0FD80)
1503         //  - DMA controller program[06] -> 0xBF29 (PC: 0xC0FD82)
1504         //  - DMA controller program[08] -> 0x02FD (PC: 0xC0FD84)
1505         //  - DMA controller program[10] -> 0xFFFF (PC: 0xC0FD86)
1506         //  - DMA controller program[12] -> 0xC515 (PC: 0xC0FD88)
1507         //  - DMA controller program[14] -> 0xFCF5 (PC: 0xC0FD8A)
1508
1509         SekIdle(NeoCDDMACount * 1);
1510
1511         while (NeoCDDMACount--) {
1512            SekWriteWord(NeoCDDMAAddress2, SekReadWord(NeoCDDMAAddress1));
1513            NeoCDDMAAddress1 += 2;
1514            NeoCDDMAAddress2 += 2;
1515         }
1516
1517if (NeoCDDMAAddress2 == 0x0800)  {
1518// MapVectorTable(false);
1519//  bprintf(PRINT_ERROR, _T("    RAM vectors mapped (PC = 0x%08X\n"), SekGetPC(0));
1520//  extern INT32 bRunPause;
1521//  bRunPause = 1;
1522}
1523         break;
1524      }
1525
1526      case 0xFEF5: {
1527//          bprintf(PRINT_NORMAL, _T("    adr : 0x%08X - 0x%08X <- address\n"), NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 4);
1528
1529         //  - DMA controller 0x7E -> 0xFEF5 (PC: 0xC07CE2)
1530         //  - DMA controller program[00] -> 0xFCF5 (PC: 0xC07CE8)
1531         //  - DMA controller program[02] -> 0x92E8 (PC: 0xC07CEE)
1532         //  - DMA controller program[04] -> 0xBE96 (PC: 0xC07CF4)
1533         //  - DMA controller program[06] -> 0xF629 (PC: 0xC07CFA)
1534         //  - DMA controller program[08] -> 0x02FD (PC: 0xC07D00)
1535         //  - DMA controller program[10] -> 0xFFFF (PC: 0xC07D06)
1536         //  - DMA controller program[12] -> 0xFC3D (PC: 0xC07D0C)
1537         //  - DMA controller program[14] -> 0xFCF5 (PC: 0xC07D12)
1538
1539         SekIdle(NeoCDDMACount * 2);
1540
1541         while (NeoCDDMACount--) {
1542            SekWriteWord(NeoCDDMAAddress1 + 0, NeoCDDMAAddress1 >> 16);
1543            SekWriteWord(NeoCDDMAAddress1 + 2, NeoCDDMAAddress1 >>  0);
1544            NeoCDDMAAddress1 += 4;
1545         }
1546
1547         break;
1548      }
1549
1550      case 0xFFC5: {
1551//          bprintf(PRINT_NORMAL, _T("    copy: 0x%08X - 0x%08X <- LC8951 external buffer\n"), NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 2);
1552
1553         //  - DMA controller 0x7E -> 0xFFC5 (PC: 0xC0A190)
1554         //  - DMA controller program[00] -> 0xFCF5 (PC: 0xC0A192)
1555         //  - DMA controller program[02] -> 0xA6F6 (PC: 0xC0A194)
1556         //  - DMA controller program[04] -> 0x2602 (PC: 0xC0A196)
1557         //  - DMA controller program[06] -> 0xFDFF (PC: 0xC0A198)
1558         //  - DMA controller program[08] -> 0xFC2D (PC: 0xC0A19A)
1559         //  - DMA controller program[10] -> 0xFCF5 (PC: 0xC0A19C)
1560         //  - DMA controller program[12] -> 0x8492 (PC: 0xC0A19E)
1561         //  - DMA controller program[14] -> 0xDA92 (PC: 0xC0A1A0)
1562
1563         char* data = LC8915InitTransfer();
1564         if (data == NULL) {
1565            break;
1566         }
1567
1568         SekIdle(NeoCDDMACount * 4);
1569
1570         while (NeoCDDMACount--) {
1571            SekWriteByte(NeoCDDMAAddress1 + 0, data[0]);
1572            SekWriteByte(NeoCDDMAAddress1 + 1, data[1]);
1573            NeoCDDMAAddress1 += 2;
1574            data += 2;
1575         }
1576
1577         LC8915EndTransfer();
1578
1579         break;
1580      }
1581
1582      case 0xFFCD:
1583
1584         //  - DMA controller 0x7E -> 0xFFCD (PC: 0xC0A190)
1585         //  - DMA controller program[00] -> 0xFCF5 (PC: 0xC0A192)
1586         //  - DMA controller program[02] -> 0x92F6 (PC: 0xC0A194)
1587         //  - DMA controller program[04] -> 0x2602 (PC: 0xC0A196)
1588         //  - DMA controller program[06] -> 0xFDFF (PC: 0xC0A198)
1589         //  - DMA controller program[08] -> 0x7006 (PC: 0xC0A19A)
1590         //  - DMA controller program[10] -> 0x6100 (PC: 0xC0A19C)
1591         //  - DMA controller program[12] -> 0x2412 (PC: 0xC0A19E)
1592         //  - DMA controller program[14] -> 0x13FC (PC: 0xC0A1A0)
1593
1594      case 0xFFDD: {
1595//          bprintf(PRINT_NORMAL, _T("    Fill: 0x%08X - 0x%08X <- 0x%04X\n"), NeoCDDMAAddress1, NeoCDDMAAddress1 + NeoCDDMACount * 2, NeoCDDMAValue1);
1596
1597         //  - DMA controller 0x7E -> 0xFFDD (PC: 0xC07CE2)
1598         //  - DMA controller program[00] -> 0xFCF5 (PC: 0xC07CE8)
1599         //  - DMA controller program[02] -> 0x92F6 (PC: 0xC07CEE)
1600         //  - DMA controller program[04] -> 0x2602 (PC: 0xC07CF4)
1601         //  - DMA controller program[06] -> 0xFDFF (PC: 0xC07CFA)
1602         //  - DMA controller program[08] -> 0xFFFF (PC: 0xC07D00)
1603         //  - DMA controller program[10] -> 0xFCF5 (PC: 0xC07D06)
1604         //  - DMA controller program[12] -> 0x8AF0 (PC: 0xC07D0C)
1605         //  - DMA controller program[14] -> 0x1609 (PC: 0xC07D12)
1606
1607         SekIdle(NeoCDDMACount * 1);
1608
1609         while (NeoCDDMACount--) {
1610            SekWriteWord(NeoCDDMAAddress1, NeoCDDMAValue1);
1611            NeoCDDMAAddress1 += 2;
1612         }
1613
1614         break;
1615      }
1616      default: {
1617         //bprintf(PRINT_ERROR, _T("    Unknown transfer type 0x%04X (PC: 0x%06X)\n"), NeoCDDMAMode, SekGetPC(-1));
1618         //bprintf(PRINT_NORMAL, _T("    ??? : 0x%08X  0x%08X 0x%04X 0x%04X 0x%08X\n"), NeoCDDMAAddress1, NeoCDDMAAddress2, NeoCDDMAValue1, NeoCDDMAValue2, NeoCDDMACount);
1619
1620//extern INT32 bRunPause;
1621//bRunPause = 1;
1622
1623      }
1624   }
1625}
1626
1627
1628void ng_aes_state::NeoCDProcessCommand()
1629{
1630   memset(NeoCDCommsStatusFIFO,  0, sizeof(NeoCDCommsStatusFIFO));
1631
1632   if (NeoCDCommsCommandFIFO[0]) {
1633      NeoCDCommsStatusFIFO[1] = 15;
1634   }
1635
1636   switch (NeoCDCommsCommandFIFO[0]) {
1637      case 0:
1638         break;
1639      case 1:
1640//                              //bprintf(PRINT_ERROR, _T("    CD comms received command %i\n"), NeoCDCommsCommandFIFO[0]);
1641         CDEmuStop();
1642
1643         NeoCDAssyStatus = 0x0E;
1644         bNeoCDLoadSector = false;
1645         break;
1646      case 2:
1647//                              //bprintf(PRINT_ERROR, _T("    CD comms received command %i\n"), NeoCDCommsCommandFIFO[0]);
1648         NeoCDCommsStatusFIFO[1] = NeoCDCommsCommandFIFO[3];
1649          switch (NeoCDCommsCommandFIFO[3]) {
1650
1651            case 0: {
1652               UINT8* ChannelData = CDEmuReadQChannel(NeoCDSectorLBA);
1653
1654               NeoCDCommsStatusFIFO[2] = ChannelData[1] / 10;
1655               NeoCDCommsStatusFIFO[3] = ChannelData[1] % 10;
1656
1657               NeoCDCommsStatusFIFO[4] = ChannelData[2] / 10;
1658               NeoCDCommsStatusFIFO[5] = ChannelData[2] % 10;
1659
1660               NeoCDCommsStatusFIFO[6] = ChannelData[3] / 10;
1661               NeoCDCommsStatusFIFO[7] = ChannelData[3] % 10;
1662
1663               NeoCDCommsStatusFIFO[8] = ChannelData[7];
1664
1665// //bprintf(PRINT_ERROR, _T("    %02i %02i:%02i:%02i %02i:%02i:%02i %02i\n"), ChannelData[0], ChannelData[1], ChannelData[2], ChannelData[3], ChannelData[4], ChannelData[5], ChannelData[6], ChannelData[7]);
1666
1667               break;
1668            }
1669            case 1: {
1670               UINT8* ChannelData = CDEmuReadQChannel(NeoCDSectorLBA);
1671
1672               NeoCDCommsStatusFIFO[2] = ChannelData[4] / 10;
1673               NeoCDCommsStatusFIFO[3] = ChannelData[4] % 10;
1674
1675               NeoCDCommsStatusFIFO[4] = ChannelData[5] / 10;
1676               NeoCDCommsStatusFIFO[5] = ChannelData[5] % 10;
1677
1678               NeoCDCommsStatusFIFO[6] = ChannelData[6] / 10;
1679               NeoCDCommsStatusFIFO[7] = ChannelData[6] % 10;
1680
1681               NeoCDCommsStatusFIFO[8] = ChannelData[7];
1682
1683               break;
1684            }
1685            case 2: {
1686
1687               UINT8* ChannelData = CDEmuReadQChannel(NeoCDSectorLBA);
1688
1689               NeoCDCommsStatusFIFO[2] = ChannelData[0] / 10;
1690               NeoCDCommsStatusFIFO[3] = ChannelData[0] % 10;
1691
1692
1693               NeoCDCommsStatusFIFO[8] = ChannelData[7];
1694
1695               break;
1696            }
1697            case 3: {
1698               UINT8* TOCEntry = CDEmuReadTOC(-2);
1699
1700               NeoCDCommsStatusFIFO[2] = TOCEntry[0] / 10;
1701               NeoCDCommsStatusFIFO[3] = TOCEntry[0] % 10;
1702
1703               NeoCDCommsStatusFIFO[4] = TOCEntry[1] / 10;
1704               NeoCDCommsStatusFIFO[5] = TOCEntry[1] % 10;
1705
1706               NeoCDCommsStatusFIFO[6] = TOCEntry[2] / 10;
1707               NeoCDCommsStatusFIFO[7] = TOCEntry[2] % 10;
1708
1709               break;
1710            }
1711            case 4: {
1712               UINT8* TOCEntry = CDEmuReadTOC(-1);
1713
1714               NeoCDCommsStatusFIFO[2] = TOCEntry[0] / 10;
1715               NeoCDCommsStatusFIFO[3] = TOCEntry[0] % 10;
1716
1717               NeoCDCommsStatusFIFO[4] = TOCEntry[1] / 10;
1718               NeoCDCommsStatusFIFO[5] = TOCEntry[1] % 10;
1719
1720               break;
1721            }
1722            case 5:   {
1723               NeoCDTrack = NeoCDCommsCommandFIFO[4] * 10 + NeoCDCommsCommandFIFO[5];
1724
1725               UINT8* TOCEntry = CDEmuReadTOC(NeoCDTrack);
1726
1727               NeoCDCommsStatusFIFO[2] = TOCEntry[0] / 10;
1728               NeoCDCommsStatusFIFO[3] = TOCEntry[0] % 10;
1729
1730               NeoCDCommsStatusFIFO[4] = TOCEntry[1] / 10;
1731               NeoCDCommsStatusFIFO[5] = TOCEntry[1] % 10;
1732
1733               NeoCDCommsStatusFIFO[6] = TOCEntry[2] / 10;
1734               NeoCDCommsStatusFIFO[7] = TOCEntry[2] % 10;
1735
1736               // bit 3 of the 1st minutes digit indicates a data track
1737               if (TOCEntry[3] & 4) {
1738                  NeoCDCommsStatusFIFO[6] |= 8;
1739               }
1740
1741               NeoCDCommsStatusFIFO[8] = NeoCDTrack % 10;
1742
1743               break;
1744            }
1745
1746            case 6: {
1747
1748               UINT8* ChannelData = CDEmuReadQChannel(NeoCDSectorLBA);
1749
1750               NeoCDCommsStatusFIFO[8] = ChannelData[7];
1751
1752               break;
1753            }
1754
1755            case 7: {
1756
1757               // must be 02, 0E, 0F, or 05
1758               NeoCDCommsStatusFIFO[2] = 0;
1759               NeoCDCommsStatusFIFO[3] = 5;
1760
1761               NeoCDCommsStatusFIFO[4] = 0;
1762               NeoCDCommsStatusFIFO[5] = 0;
1763
1764               NeoCDCommsStatusFIFO[6] = 0;
1765               NeoCDCommsStatusFIFO[7] = 0;
1766               break;
1767            }
1768          }
1769         break;
1770
1771      case 3: {
1772
1773         if (LC8951RegistersW[10] & 4) {
1774
1775            if (CDEmuGetStatus() == playing) {
1776               //bprintf(PRINT_ERROR, _T("*** Switching CD mode to CD-ROM while in audio mode!(PC: 0x%06X)\n"), SekGetPC(-1));
1777            }
1778
1779            NeoCDSectorLBA  = NeoCDCommsCommandFIFO[2] * (10 * CD_FRAMES_MINUTE);
1780            NeoCDSectorLBA += NeoCDCommsCommandFIFO[3] * ( 1 * CD_FRAMES_MINUTE);
1781            NeoCDSectorLBA += NeoCDCommsCommandFIFO[4] * (10 * CD_FRAMES_SECOND);
1782            NeoCDSectorLBA += NeoCDCommsCommandFIFO[5] * ( 1 * CD_FRAMES_SECOND);
1783            NeoCDSectorLBA += NeoCDCommsCommandFIFO[6] * (10                   );
1784            NeoCDSectorLBA += NeoCDCommsCommandFIFO[7] * ( 1                   );
1785
1786            NeoCDSectorLBA -= CD_FRAMES_PREGAP;
1787
1788            CDEmuStartRead();
1789//              LC8951RegistersR[1] |= 0x20;
1790         } else {
1791
1792            if (CDEmuGetStatus() == reading) {
1793               //bprintf(PRINT_ERROR, _T("*** Switching CD mode to audio while in CD-ROM mode!(PC: 0x%06X)\n"), SekGetPC(-1));
1794            }
1795
1796            CDEmuPlay((NeoCDCommsCommandFIFO[2] * 10) + NeoCDCommsCommandFIFO[3], (NeoCDCommsCommandFIFO[4] * 10) + NeoCDCommsCommandFIFO[5], (NeoCDCommsCommandFIFO[6] * 10) + NeoCDCommsCommandFIFO[7]);
1797         }
1798
1799         NeoCDAssyStatus = 1;
1800         bNeoCDLoadSector = true;
1801
1802         break;
1803      }
1804      case 4:
1805//          //bprintf(PRINT_ERROR, _T("    CD comms received command %i\n"), NeoCDCommsCommandFIFO[0]);
1806         CDEmuPause();
1807         break;
1808      case 5:
1809//          //bprintf(PRINT_ERROR, _T("    CD comms received command %i\n"), NeoCDCommsCommandFIFO[0]);
1810//          NeoCDAssyStatus = 9;
1811//          bNeoCDLoadSector = false;
1812         break;
1813
1814      case 6:
1815//          //bprintf(PRINT_ERROR, _T("    CD comms received command %i\n"), NeoCDCommsCommandFIFO[0]);
1816         NeoCDAssyStatus = 4;
1817         bNeoCDLoadSector = false;
1818         break;
1819      case 7:
1820//          //bprintf(PRINT_ERROR, _T("    CD comms received command %i\n"), NeoCDCommsCommandFIFO[0]);
1821         NeoCDAssyStatus = 1;
1822         bNeoCDLoadSector = true;
1823         break;
1824
1825      case 8:
1826      case 9:
1827      case 10:
1828      case 11:
1829      case 12:
1830      case 13:
1831      case 14:
1832      case 15:
1833//          //bprintf(PRINT_ERROR, _T("    CD comms received command %i\n"), NeoCDCommsCommandFIFO[0]);
1834         NeoCDAssyStatus = 9;
1835         bNeoCDLoadSector = false;
1836         break;
1837   }
1838}
1839
1840void ng_aes_state::NeoCDCommsControl(UINT8 clock, UINT8 send)
1841{
1842   if (clock && !bNeoCDCommsClock) {
1843      NeoCDCommsWordCount++;
1844      if (NeoCDCommsWordCount >= 10) {
1845         NeoCDCommsWordCount = 0;
1846
1847         if (send) {
1848
1849            // command receive complete
1850
1851            if (NeoCDCommsCommandFIFO[0]) {
1852               INT32  sum = 0;
1853
1854                  printf("has command %02x\n", NeoCDCommsCommandFIFO[0]);
1855
1856//                  bprintf(PRINT_NORMAL, _T("  - CD mechanism command receive completed : 0x"));
1857               for (INT32 i = 0; i < 9; i++) {
1858//                      bprintf(PRINT_NORMAL, _T("%X"), NeoCDCommsCommandFIFO[i]);
1859                  sum += NeoCDCommsCommandFIFO[i];
1860               }
1861               sum = ~(sum + 5) & 0x0F;
1862//                  bprintf(PRINT_NORMAL, _T(" (CS 0x%X, %s)\n"), NeoCDCommsCommandFIFO[9], (sum == NeoCDCommsCommandFIFO[9]) ? _T("OK") : _T("NG"));
1863               if (sum == NeoCDCommsCommandFIFO[9]) {
1864
1865                  printf("request to process command %02x\n", NeoCDCommsCommandFIFO[0]);
1866
1867                  NeoCDProcessCommand();
1868
1869                  if (NeoCDCommsCommandFIFO[0]) {
1870
1871                     if (NeoCDAssyStatus == 1) {
1872                        if (CDEmuGetStatus() == idle) {
1873                           NeoCDAssyStatus = 0x0E;
1874                           bNeoCDLoadSector = false;
1875                        }
1876                     }
1877
1878                     NeoCDCommsStatusFIFO[0] = NeoCDAssyStatus;
1879
1880                     // compute checksum
1881
1882                     sum = 0;
1883
1884                     for (INT32 i = 0; i < 9; i++) {
1885                        sum += NeoCDCommsStatusFIFO[i];
1886                     }
1887                     NeoCDCommsStatusFIFO[9] = ~(sum + 5) & 0x0F;
1888                  }
1889               }
1890            }
1891         } else {
1892
1893            // status send complete
1894
1895//              if (NeoCDCommsStatusFIFO[0] || NeoCDCommsStatusFIFO[1]) {
1896//                  INT32  sum = 0;
1897//
1898//                  bprintf(PRINT_NORMAL, _T("  - CD mechanism status send completed : 0x"));
1899//                  for (INT32 i = 0; i < 9; i++) {
1900//                      bprintf(PRINT_NORMAL, _T("%X"), NeoCDCommsStatusFIFO[i]);
1901//                      sum += NeoCDCommsStatusFIFO[i];
1902//                  }
1903//                  sum = ~(sum + 5) & 0x0F;
1904//                  bprintf(PRINT_NORMAL, _T(" (CS 0x%X, %s)\n"), NeoCDCommsStatusFIFO[9], (sum == NeoCDCommsStatusFIFO[9]) ? _T("OK") : _T("NG"));
1905//              }
1906
1907//              if (NeoCDAssyStatus == 0xE) {
1908//                  NeoCDAssyStatus = 9;
1909//              }
1910         }
1911
1912      }
1913      bNeoCDCommsSend = send;
1914   }
1915   bNeoCDCommsClock = clock;
1916}
1917
1918
1919void ng_aes_state::LC8951UpdateHeader()
1920{
1921   NeoCDLBAToMSF(NeoCDSectorLBA);
1922
1923   if (LC8951RegistersW[11] & 1) {
1924
1925      // HEAD registers have sub-header
1926
1927      LC8951RegistersR[4] = 0;                                       // HEAD0
1928      LC8951RegistersR[5] = 0;                                       // HEAD1
1929      LC8951RegistersR[6] = 0;                                       // HEAD2
1930      LC8951RegistersR[7] = 0;                                       // HEAD3
1931
1932   } else {
1933
1934      // HEAD registers have header
1935
1936      LC8951RegistersR[4] = ((NeoCDSectorMin / 10) << 4) | (NeoCDSectorMin % 10);   // HEAD0
1937      LC8951RegistersR[5] = ((NeoCDSectorSec / 10) << 4) | (NeoCDSectorSec % 10);   // HEAD1
1938      LC8951RegistersR[6] = ((NeoCDSectorFrm / 10) << 4) | (NeoCDSectorFrm % 10);   // HEAD2
1939      LC8951RegistersR[7] = 1;                                       // HEAD3
1940   }
1941}
1942
1943char* ng_aes_state::LC8915InitTransfer()
1944{
1945   if (!LC8951RegistersW[6]) {
1946      //bprintf(PRINT_ERROR, _T("    LC8951 DTTRG status invalid\n"));
1947      return NULL;
1948   }
1949   if (!(LC8951RegistersW[1] & 0x02)) {
1950      //bprintf(PRINT_ERROR, _T("    LC8951 DOUTEN status invalid\n"));
1951      return NULL;
1952   }
1953   if (((LC8951RegistersW[5] << 8) | LC8951RegistersW[4]) + (NeoCDDMACount << 1) > 2352) {
1954      //bprintf(PRINT_ERROR, _T("    DMA transfer exceeds current sector in LC8951 external buffer\n"));
1955      return NULL;
1956   }
1957
1958   return NeoCDSectorData + ((LC8951RegistersW[5] << 8) | LC8951RegistersW[4]);
1959}
1960
1961void ng_aes_state::LC8915EndTransfer()
1962{
1963   LC8951RegistersW[6]  = 0x00;                                    // reset DTTRG
1964
1965   LC8951RegistersR[1] |= 0x48;                                    //   set DTEI & DTBSY
1966   if (LC8951RegistersW[1] & 0x40) {
1967
1968      // trigger DTE interrupt
1969
1970      // the Neo Geo CD doesn't use the DTE interrupt
1971      // nIRQAcknowledge &= ~0x20;
1972      // NeoCDIRQUpdate(0);
1973
1974   }
1975}
1976
1977void ng_aes_state::LC8951Reset()
1978{
1979   memset(LC8951RegistersR, 0, sizeof(LC8951RegistersR));
1980   memset(LC8951RegistersW, 0, sizeof(LC8951RegistersW));
1981   LC8951RegistersR[0x01] = 0xFF;
1982   LC8951RegistersR[0x0F] = 0x80;
1983
1984   LC8951UpdateHeader();
1985}
1986
1987
1988
1989876READ16_MEMBER(ng_aes_state::neocd_control_r)
1990877{
1991878   return neogeoReadWordCDROM(0xff0000+ (offset*2));
r19245r19246
22091096   UINT8* ROM = machine().root_device().memregion("mainbios")->base();
22101097   UINT8* RAM = machine().root_device().memregion("maincpu")->base();
22111098   UINT8* Z80bios = machine().root_device().memregion("audiobios")->base();
2212   UINT8* FIXbios = memregion("fixedbios")->base();
22131099   int x;
22141100
22151101   common_machine_start(machine());
r19245r19246
22341120      Z80bios[x+1] = ROM[x+0x20000];
22351121   }
22361122
2237   // copy fixed tiles into FIX space (from 0x70000)
2238   memcpy(FIXbios,ROM+0x70000,0x10000);
22391123
22401124   // for custom vectors
22411125   machine().device("maincpu")->execute().set_irq_acknowledge_callback(neocd_int_callback);
22421126
2243   {
2244      cdrom_image_device *cddevice = machine().device<cdrom_image_device>("cdrom");
2245      if ( cddevice )
2246      {
2247         neocd.cd = cddevice->get_cdrom_file();
2248         if ( neocd.cd )
2249         {
2250            printf("found cd\n");
2251            neocd.toc = cdrom_get_toc( neocd.cd );
2252            cdda_set_cdrom( machine().device("cdda"), neocd.cd );
2253            cdda_stop_audio( machine().device( "cdda" ) ); //stop any pending CD-DA
2254         }
2255      }
2256   }
2257
2258
1127   m_tempcdc->reset_NeoCd();
1128   
22591129}
22601130
22611131//static DEVICE_IMAGE_LOAD(aes_cart)
r19245r19246
22961166   neogeo_set_fixed_layer_source(machine(),1);
22971167
22981168   NeoSpriteRAM = memregion("sprites")->base();
2299   YM2610ADPCMAROM[0] = memregion("ymsnd")->base();
1169   YM2610ADPCMAROM = memregion("ymsnd")->base();
23001170   NeoZ80ROMActive = memregion("audiocpu")->base();
23011171   NeoTextRAM = memregion("fixed")->base();
23021172   curr_space = &machine().device("maincpu")->memory().space(AS_PROGRAM);
1173   m_tempcdc->dma_space = curr_space;
23031174
2304   NeoCDCommsReset();
23051175
1176   m_tempcdc->NeoCDCommsReset();
1177
23061178   nTransferWriteEnable = 0;
23071179
23081180}
r19245r19246
27021574   MCFG_MACHINE_START_OVERRIDE(ng_aes_state, neogeo)
27031575   MCFG_MACHINE_RESET_OVERRIDE(ng_aes_state, neogeo)
27041576
1577   // temporary until things are cleaned up
1578   MCFG_DEVICE_ADD("tempcdc", LC89510_TEMP, 0) // cd controller
1579   MCFG_SEGACD_HACK_SET_NEOCD
1580
27051581   /* video hardware */
27061582   MCFG_DEFAULT_LAYOUT(layout_neogeo)
27071583
r19245r19246
27461622
27471623   if (irqline==4)
27481624   {
2749      if (state->nNeoCDIRQVectorAck) {
2750         state->nNeoCDIRQVectorAck = 0;
2751         return state->nNeoCDIRQVector;
1625      if (state->m_tempcdc->get_nNeoCDIRQVectorAck()) {
1626         state->m_tempcdc->set_nNeoCDIRQVectorAck(0);
1627         return state->m_tempcdc->get_nNeoCDIRQVector();
27521628      }
27531629   }
27541630
27551631   return (0x60+irqline*4)/4;
27561632}
27571633
2758void ng_aes_state::NeoCDIRQUpdate(UINT8 byteValue)
2759{
2760   // do we also need to check the regular interrupts like FBA?
27611634
2762   nIRQAcknowledge |= (byteValue & 0x38);
27631635
2764   if ((nIRQAcknowledge & 0x08) == 0) {
2765      nNeoCDIRQVector = 0x17;
2766      nNeoCDIRQVectorAck = 1;
2767      m_maincpu->set_input_line(4, HOLD_LINE);
2768      return;
2769   }
2770   if ((nIRQAcknowledge & 0x10) == 0) {
2771      nNeoCDIRQVector = 0x16;
2772      nNeoCDIRQVectorAck = 1;
2773      m_maincpu->set_input_line(4, HOLD_LINE);
2774      return;
2775   }
2776   if ((nIRQAcknowledge & 0x20) == 0) {
2777      nNeoCDIRQVector = 0x15;
2778      nNeoCDIRQVectorAck = 1;
2779      m_maincpu->set_input_line(4, HOLD_LINE);
2780      return;
2781   }
2782}
2783
2784TIMER_DEVICE_CALLBACK_MEMBER( ng_aes_state::neocd_access_timer_callback )
2785{
2786   //CheckCommand(machine());
2787
2788   if (nff0002 & 0x0050) {
2789      nIRQAcknowledge &= ~0x10;
2790      NeoCDIRQUpdate(0);
2791
2792      if (nff0002 & 0x0500) {
2793         NeoCDReadSector();
2794      }
2795   }
2796}
2797
2798
27991636struct cdrom_interface neocd_cdrom =
28001637{
28011638   "neocd_cdrom",
r19245r19246
28141651
28151652   MCFG_MACHINE_START_OVERRIDE(ng_aes_state,neocd)
28161653
2817   MCFG_TIMER_DRIVER_ADD_PERIODIC("hock_timer", ng_aes_state, neocd_access_timer_callback, attotime::from_hz(75))
28181654   MCFG_CDROM_ADD( "cdrom",neocd_cdrom )
28191655   MCFG_SOFTWARE_LIST_ADD("cd_list","neocd")
2820
2821   MCFG_SOUND_ADD( "cdda", CDDA, 0 )
2822   MCFG_SOUND_ROUTE( 0, "lspeaker", 0.50 )
2823   MCFG_SOUND_ROUTE( 1, "rspeaker", 0.50 )
28241656MACHINE_CONFIG_END
28251657
28261658/*************************************
trunk/src/mess/mess.mak
r19245r19246
448448   $(MAME_MACHINE)/pcshare.o   \
449449   $(MAME_MACHINE)/megadriv.o  \
450450   $(MAME_MACHINE)/megacd.o \
451   $(MAME_MACHINE)/megacdcd.o \
451452   $(MAME_MACHINE)/mega32x.o \
452453   $(MAME_MACHINE)/megasvp.o \
453454   $(MAME_MACHINE)/megavdp.o \

Previous 199869 Revisions Next


© 1997-2024 The MAME Team