// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/******************************************************************************
CD-i Mono-I CDIC MCU simulation
-------------------
written by Ryan Holtz
*******************************************************************************
STATUS:
- Just enough for the Mono-I CD-i board to work somewhat properly.
TODO:
- Decapping and proper emulation.
*******************************************************************************/
#ifndef MAME_MACHINE_CDICDIC_H
#define MAME_MACHINE_CDICDIC_H
#pragma once
#include "imagedev/chd_cd.h"
#include "machine/scc68070.h"
#include "sound/cdda.h"
#include "sound/dmadac.h"
#include "cdrom.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> cdicdic_device
class cdicdic_device : public device_t
{
public:
// construction/destruction
cdicdic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
void set_clock2(uint32_t clock) { m_clock2 = clock; }
void set_clock2(const XTAL &xtal) { set_clock2(xtal.value()); }
uint32_t clock2() const { return m_clock2; }
auto intreq_callback() { return m_intreq_callback.bind(); }
// non-static internal members
void sample_trigger();
void process_delayed_command();
uint16_t regs_r(offs_t offset, uint16_t mem_mask = ~0);
void regs_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint16_t ram_r(offs_t offset, uint16_t mem_mask = ~0);
void ram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
uint8_t intack_r();
protected:
// device-level overrides
virtual void device_resolve_objects() override;
virtual void device_start() override;
virtual void device_reset() override;
// internal callbacks
TIMER_CALLBACK_MEMBER( periodic_sample_trigger );
TIMER_CALLBACK_MEMBER( audio_sample_trigger );
TIMER_CALLBACK_MEMBER( initial_sample_trigger );
TIMER_CALLBACK_MEMBER( trigger_readback_int );
private:
enum
{
CDIC_SECTOR_SYNC = 0,
CDIC_SECTOR_HEADER = 12,
CDIC_SECTOR_MODE = 15,
CDIC_SECTOR_FILE1 = 16,
CDIC_SECTOR_CHAN1 = 17,
CDIC_SECTOR_SUBMODE1 = 18,
CDIC_SECTOR_CODING1 = 19,
CDIC_SECTOR_FILE2 = 20,
CDIC_SECTOR_CHAN2 = 21,
CDIC_SECTOR_SUBMODE2 = 22,
CDIC_SECTOR_CODING2 = 23,
CDIC_SECTOR_DATA = 24,
CDIC_SECTOR_SIZE = 2352,
CDIC_SECTOR_DATASIZE = 2048,
CDIC_SECTOR_AUDIOSIZE = 2304,
CDIC_SECTOR_VIDEOSIZE = 2324,
CDIC_SUBMODE_EOF = 0x80,
CDIC_SUBMODE_RT = 0x40,
CDIC_SUBMODE_FORM = 0x20,
CDIC_SUBMODE_TRIG = 0x10,
CDIC_SUBMODE_DATA = 0x08,
CDIC_SUBMODE_AUDIO = 0x04,
CDIC_SUBMODE_VIDEO = 0x02,
CDIC_SUBMODE_EOR = 0x01
};
int is_valid_sample_buf(uint16_t addr) const;
double sample_buf_freq(uint16_t addr) const;
int sample_buf_size(uint16_t addr) const;
devcb_write_line m_intreq_callback;
required_address_space m_memory_space;
required_device_array<dmadac_sound_device, 2> m_dmadac;
required_device<scc68070_device> m_scc;
required_device<cdda_device> m_cdda;
optional_device<cdrom_image_device> m_cdrom_dev;
uint32_t m_clock2;
// internal state
uint16_t m_command; // CDIC Command Register (0x303c00)
uint32_t m_time; // CDIC Time Register (0x303c02)
uint16_t m_file; // CDIC File Register (0x303c06)
uint32_t m_channel; // CDIC Channel Register (0x303c08)
uint16_t m_audio_channel; // CDIC Audio Channel Register (0x303c0c)
uint16_t m_audio_buffer; // CDIC Audio Buffer Register (0x303ff4)
uint16_t m_x_buffer; // CDIC X-Buffer Register (0x303ff6)
uint16_t m_dma_control; // CDIC DMA Control Register (0x303ff8)
uint16_t m_z_buffer; // CDIC Z-Buffer Register (0x303ffa)
uint16_t m_interrupt_vector; // CDIC Interrupt Vector Register (0x303ffc)
uint16_t m_data_buffer; // CDIC Data Buffer Register (0x303ffe)
emu_timer *m_interrupt_timer;
cdrom_file *m_cd;
emu_timer *m_audio_sample_timer;
emu_timer *m_audio_playback_timer;
emu_timer *m_periodic_sample_timer[2];
int32_t m_audio_sample_freq;
int32_t m_audio_sample_size;
uint16_t m_decode_addr;
uint8_t m_decode_delay;
attotime m_decode_period;
bool m_break_on_achan;
bool m_valid_audio_sample;
int m_xa_last[4];
std::unique_ptr<uint16_t[]> m_ram;
std::unique_ptr<int16_t[]> m_samples[2];
static void decode_xa_mono(int32_t *cdic_xa_last, const uint8_t *xa, int16_t *dp);
static void decode_xa_mono8(int32_t *cdic_xa_last, const uint8_t *xa, int16_t *dp);
static void decode_xa_stereo(int32_t *cdic_xa_last, const uint8_t *xa, int16_t *dp);
static void decode_xa_stereo8(int32_t *cdic_xa_last, const uint8_t *xa, int16_t *dp);
static const int32_t s_cdic_adpcm_filter_coef[5][2];
uint32_t increment_cdda_frame_bcd(uint32_t bcd);
uint32_t increment_cdda_sector_bcd(uint32_t bcd);
void decode_audio_sector(const uint8_t *xa, int32_t triggered);
void play_audio_sector();
};
// device type definition
DECLARE_DEVICE_TYPE(CDI_CDIC, cdicdic_device)
#endif // MAME_MACHINE_CDICDIC_H