#ifndef _included_psxcdrom_
#define _included_psxcdrom_
#include "imagedev/chd_cd.h"
#include "sound/spu.h"
#define MAX_PSXCD_TIMERS (4)
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_PSXCD_ADD(_tag, _devname) \
MCFG_DEVICE_ADD(_tag, PSXCD, 0)
#define MCFG_PSXCD_IRQ_HANDLER(_devcb) \
devcb = &psxcd_device::set_irq_handler(*device, DEVCB2_##_devcb);
class psxcd_device : public cdrom_image_device
{
public:
psxcd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// static configuration helpers
template<class _Object> static devcb2_base &set_irq_handler(device_t &device, _Object object) { return downcast<psxcd_device &>(device).m_irq_handler.set_callback(object); }
static void static_set_devname(device_t &device, const char *devname);
virtual bool call_load();
virtual void call_unload();
DECLARE_WRITE8_MEMBER( write );
DECLARE_READ8_MEMBER( read );
void start_dma(UINT8 *mainram, UINT32 size);
protected:
virtual void device_start();
virtual void device_stop();
virtual void device_reset();
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
private:
void write_command(UINT8 byte);
typedef void (psxcd_device::*cdcmd)();
struct command_result
{
UINT8 data[32], sz, res;
command_result *next;
};
union CDPOS {
UINT8 b[4];
UINT32 w;
};
void cdcmd_sync();
void cdcmd_nop();
void cdcmd_setloc();
void cdcmd_play();
void cdcmd_forward();
void cdcmd_backward();
void cdcmd_readn();
void cdcmd_standby();
void cdcmd_stop();
void cdcmd_pause();
void cdcmd_init();
void cdcmd_mute();
void cdcmd_demute();
void cdcmd_setfilter();
void cdcmd_setmode();
void cdcmd_getparam();
void cdcmd_getlocl();
void cdcmd_getlocp();
void cdcmd_gettn();
void cdcmd_gettd();
void cdcmd_seekl();
void cdcmd_seekp();
void cdcmd_test();
void cdcmd_id();
void cdcmd_reads();
void cdcmd_reset();
void cdcmd_readtoc();
void cdcmd_unknown12();
void cdcmd_illegal17();
void cdcmd_illegal18();
void cdcmd_illegal1d();
static const cdcmd cmd_table[31];
void illegalcmd(UINT8 cmd);
void cmd_complete(command_result *res);
void send_result(UINT8 res, UINT8 *data=NULL, int sz=0, int delay=default_irq_delay, UINT8 errcode = 0);
command_result *prepare_result(UINT8 res, UINT8 *data=NULL, int sz=0, UINT8 errcode = 0);
void start_read();
void start_play();
void stop_read();
void read_sector();
void play_sector();
UINT32 sub_loc(CDPOS src1, CDPOS src2);
int add_system_event(int type, UINT64 t, command_result *ptr);
UINT8 bcd_to_decimal(const UINT8 bcd) { return ((bcd>>4)*10)+(bcd&0xf); }
UINT8 decimal_to_bcd(const UINT8 dec) { return ((dec/10)<<4)|(dec%10); }
UINT32 msf_to_lba_ps(UINT32 msf) { msf = msf_to_lba(msf); return (msf>150)?(msf-150):msf; }
UINT32 lba_to_msf_ps(UINT32 lba) { return lba_to_msf_alt(lba+150); }
static const unsigned int sector_buffer_size=16, default_irq_delay=16000; //480; //8000; //2000<<2;
static const unsigned int raw_sector_size=2352;
UINT8 cmdbuf[64], mode, secbuf[sector_buffer_size][raw_sector_size];
UINT8 filter_file, filter_channel, lastsechdr[8], status;
int rdp;
UINT8 m_cursec, sectail;
UINT16 m_transcurr;
UINT8 m_transbuf[raw_sector_size];
command_result *res_queue, *m_int1;
struct {
UINT8 sr, ir, imr;
struct {
UINT8 ll, lr, rl, rr;
} vol;
} m_regs;
CDPOS loc, curpos;
#ifdef LSB_FIRST
enum {
M = 2,
S = 1,
F = 0
};
#else
enum {
M = 1,
S = 2,
F = 3
};
#endif
bool open, m_mute, m_dmaload;
device_timer_id next_read_event;
INT64 next_sector_t;
unsigned int autopause_sector, start_read_delay, read_sector_cycles, preread_delay;
UINT32 m_param_count;
UINT32 m_sysclock;
emu_timer *m_timers[MAX_PSXCD_TIMERS];
bool m_timerinuse[MAX_PSXCD_TIMERS];
devcb2_write_line m_irq_handler;
cpu_device *m_maincpu;
spu_device *m_spu;
};
// device type definition
extern const device_type PSXCD;
#endif