#include "sound/cdda.h" #include "imagedev/chd_cd.h" typedef device_delegate segacd_dma_delegate; typedef device_delegate interrupt_delegate; #define READ_MAIN (0x0200) #define READ_SUB (0x0300) #define REG_W_SBOUT (0x0) #define REG_W_IFCTRL (0x1) #define REG_W_DBCL (0x2) #define REG_W_DBCH (0x3) #define REG_W_DACL (0x4) #define REG_W_DACH (0x5) #define REG_W_DTTRG (0x6) #define REG_W_DTACK (0x7) #define REG_W_WAL (0x8) #define REG_W_WAH (0x9) #define REG_W_CTRL0 (0xA) #define REG_W_CTRL1 (0xB) #define REG_W_PTL (0xC) #define REG_W_PTH (0xD) #define REG_W_CTRL2 (0xE) #define REG_W_RESET (0xF) #define REG_R_COMIN (0x0) #define REG_R_IFSTAT (0x1) #define REG_R_DBCL (0x2) #define REG_R_DBCH (0x3) #define REG_R_HEAD0 (0x4) #define REG_R_HEAD1 (0x5) #define REG_R_HEAD2 (0x6) #define REG_R_HEAD3 (0x7) #define REG_R_PTL (0x8) #define REG_R_PTH (0x9) #define REG_R_WAL (0xa) #define REG_R_WAH (0xb) #define REG_R_STAT0 (0xc) #define REG_R_STAT1 (0xd) #define REG_R_STAT2 (0xe) #define REG_R_STAT3 (0xf) #define CMD_STATUS (0x0) #define CMD_STOPALL (0x1) #define CMD_GETTOC (0x2) #define CMD_READ (0x3) #define CMD_SEEK (0x4) // (0x5) #define CMD_STOP (0x6) #define CMD_RESUME (0x7) #define CMD_FF (0x8) #define CMD_RW (0x9) #define CMD_INIT (0xa) // (0xb) #define CMD_CLOSE (0xc) #define CMD_OPEN (0xd) // (0xe) // (0xf) #define TOCCMD_CURPOS (0x0) #define TOCCMD_TRKPOS (0x1) #define TOCCMD_CURTRK (0x2) #define TOCCMD_LENGTH (0x3) #define TOCCMD_FIRSTLAST (0x4) #define TOCCMD_TRACKADDR (0x5) #define SECTOR_SIZE (2352) #define SET_CDD_DATA_MODE \ CDD_CONTROL |= 0x0100; #define SET_CDD_AUDIO_MODE \ CDD_CONTROL &= ~0x0100; #define STOP_CDC_READ \ SCD_STATUS_CDC &= ~0x01; #define SET_CDC_READ \ SCD_STATUS_CDC |= 0x01; #define SET_CDC_DMA \ SCD_STATUS_CDC |= 0x08; #define STOP_CDC_DMA \ SCD_STATUS_CDC &= ~0x08; #define SCD_READ_ENABLED \ (SCD_STATUS_CDC & 1) #define SCD_DMA_ENABLED \ (SCD_STATUS_CDC & 0x08) #define CLEAR_CDD_RESULT \ CDD_MIN = CDD_SEC = CDD_FRAME = CDD_EXT = 0; #define CHECK_SCD_LV5_INTERRUPT \ if (segacd_irq_mask & 0x20) \ { \ machine.device(":segacd:segacd_68k")->execute().set_input_line(5, HOLD_LINE); \ } #define CHECK_SCD_LV4_INTERRUPT \ if (segacd_irq_mask & 0x10) \ { \ machine.device(":segacd:segacd_68k")->execute().set_input_line(4, HOLD_LINE); \ } #define CHECK_SCD_LV4_INTERRUPT_A \ if (segacd_irq_mask & 0x10) \ { \ machine().device(":segacd:segacd_68k")->execute().set_input_line(4, HOLD_LINE); \ } #define CURRENT_TRACK_IS_DATA \ (segacd.toc->tracks[SCD_CURTRK - 1].trktype != CD_TRACK_AUDIO) #define CDD_PLAYINGCDDA 0x0100 #define CDD_READY 0x0400 #define CDD_STOPPED 0x0900 #define MCFG_SEGACD_HACK_SET_CDC_DO_DMA( _class, _method) \ lc89510_temp_device::set_CDC_Do_DMA(*device, segacd_dma_delegate(&_class::_method, #_class "::" #_method, NULL, (_class *)0)); #define MCFG_SEGACD_HACK_SET_NEOCD \ lc89510_temp_device::set_is_neoCD(*device, true); #define MCFG_SET_TYPE1_INTERRUPT_CALLBACK( _class, _method) \ lc89510_temp_device::set_type1_interrupt_callback(*device, interrupt_delegate(&_class::_method, #_class "::" #_method, NULL, (_class *)0)); #define MCFG_SET_TYPE2_INTERRUPT_CALLBACK( _class, _method) \ lc89510_temp_device::set_type2_interrupt_callback(*device, interrupt_delegate(&_class::_method, #_class "::" #_method, NULL, (_class *)0)); #define MCFG_SET_TYPE3_INTERRUPT_CALLBACK( _class, _method) \ lc89510_temp_device::set_type3_interrupt_callback(*device, interrupt_delegate(&_class::_method, #_class "::" #_method, NULL, (_class *)0)); /* neocd */ #define CD_FRAMES_MINUTE (60 * 75) #define CD_FRAMES_SECOND ( 75) #define CD_FRAMES_PREGAP ( 2 * 75) #define SEK_IRQSTATUS_NONE (0x0000) #define SEK_IRQSTATUS_AUTO (0x2000) #define SEK_IRQSTATUS_ACK (0x1000) #define LC89510_EXTERNAL_BUFFER_SIZE ((32 * 1024 * 2) + SECTOR_SIZE) class lc89510_temp_device : public device_t { public: lc89510_temp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); // HACK for DMA handling segacd_dma_delegate segacd_dma_callback; interrupt_delegate type1_interrupt_callback; interrupt_delegate type2_interrupt_callback; interrupt_delegate type3_interrupt_callback; void Fake_CDC_Do_DMA(int &dmacount, UINT8 *CDC_BUFFER, UINT16 &dma_addrc, UINT16 &destination ); static void set_CDC_Do_DMA(device_t &device,segacd_dma_delegate new_segacd_dma_callback); void dummy_interrupt_callback(void); static void set_type1_interrupt_callback(device_t &device,interrupt_delegate interrupt_callback); static void set_type2_interrupt_callback(device_t &device,interrupt_delegate interrupt_callback); static void set_type3_interrupt_callback(device_t &device,interrupt_delegate interrupt_callback); static void set_is_neoCD(device_t &device, bool is_neoCD); // HACK for neoCD handling bool is_neoCD; struct segacd_t { cdrom_file *cd; const cdrom_toc *toc; UINT32 current_frame; }; segacd_t segacd; UINT8 SCD_BUFFER[2560]; UINT32 SCD_STATUS; UINT32 SCD_STATUS_CDC; INT32 SCD_CURLBA; UINT8 SCD_CURTRK; UINT16 CDC_DECODE; UINT16 CDC_REG0; UINT16 CDC_REG1; UINT8 CDC_BUFFER[LC89510_EXTERNAL_BUFFER_SIZE]; UINT8 CDD_RX[10]; UINT8 CDD_TX[10]; UINT32 CDD_STATUS; UINT32 CDD_MIN; UINT32 CDD_SEC; UINT32 CDD_FRAME; UINT32 CDD_EXT; UINT16 CDD_CONTROL; INT16 CDD_DONE; inline int to_bcd(int val, bool byte); void set_data_audio_mode(void); void CDD_DoChecksum(void); bool CDD_Check_TX_Checksum(void); void CDD_Export(bool neocd_hack = false); void scd_ctrl_checks(running_machine& machine); void scd_advance_current_readpos(void); int Read_LBA_To_Buffer(running_machine& machine); void CDD_GetStatus(void); void CDD_Stop(running_machine &machine); void CDD_GetPos(void); void CDD_GetTrackPos(void); void CDD_GetTrack(void); void CDD_Length(void); void CDD_FirstLast(void); void CDD_GetTrackAdr(void); void CDD_GetTrackType(void); UINT32 getmsf_from_regs(void); void CDD_Play(running_machine &machine); void CDD_Seek(void); void CDD_Pause(running_machine &machine); void CDD_Resume(running_machine &machine); void CDD_FF(running_machine &machine); void CDD_RW(running_machine &machine); void CDD_Open(void); void CDD_Close(void); void CDD_Init(void); void CDD_Default(void); void CDD_Reset(void); void CDC_Reset(void); void lc89510_Reset(void); void CDC_End_Transfer(running_machine& machine); void CDC_Do_DMA(running_machine& machine, int rate); UINT16 CDC_Host_r(running_machine& machine, UINT16 type); UINT8 CDC_Reg_r(void); void CDC_Reg_w(UINT8 data); void CDD_Process(running_machine& machine, int reason); void CDD_Handle_TOC_Commands(void); bool CDD_Import(running_machine& machine); READ16_MEMBER( segacd_irq_mask_r ); WRITE16_MEMBER( segacd_irq_mask_w ); READ16_MEMBER( segacd_cdd_ctrl_r ); WRITE16_MEMBER( segacd_cdd_ctrl_w ); READ8_MEMBER( segacd_cdd_rx_r ); WRITE8_MEMBER( segacd_cdd_tx_w ); READ16_MEMBER( segacd_cdfader_r ); WRITE16_MEMBER( segacd_cdfader_w ); void reset_cd(void); WRITE16_MEMBER( segacd_cdc_mode_address_w ); READ16_MEMBER( segacd_cdc_mode_address_r ); WRITE16_MEMBER( segacd_cdc_data_w ); READ16_MEMBER( segacd_cdc_data_r ); READ16_MEMBER( cdc_data_sub_r ); READ16_MEMBER( cdc_data_main_r ); TIMER_DEVICE_CALLBACK_MEMBER( segacd_access_timer_callback ); UINT16 get_segacd_irq_mask(void) { return segacd_irq_mask; } UINT16 segacd_irq_mask; cdda_device* m_cdda; /* NeoCD */ UINT16 nff0002; UINT16 nff0016; INT32 LC8951RegistersR[16]; INT32 LC8951RegistersW[16]; bool bNeoCDCommsClock; INT32 NeoCDCommsWordCount; INT32 NeoCD_StatusHack; void NeoCDCommsControl(UINT8 clock, UINT8 send); void LC8951UpdateHeader(); char* LC8915InitTransfer(int NeoCDDMACount); void LC8915EndTransfer(); void neocd_cdd_tx_w(UINT8 data); UINT8 neocd_cdd_rx_r(); void NeoCDCommsReset(); UINT16 nff0016_r(void); void nff0016_set(UINT16 wordValue); void nff0002_set(UINT16 wordValue); protected: virtual void device_start(); virtual void device_reset(); virtual machine_config_constructor device_mconfig_additions() const; private: }; extern const device_type LC89510_TEMP;