mirror of
https://github.com/holub/mame
synced 2025-06-07 13:23:50 +03:00
wpc_95: Make it testable [O. Galibert]
This commit is contained in:
parent
72f44639ef
commit
2f867f94f8
@ -304,24 +304,24 @@ static ADDRESS_MAP_START( dcs_8k_data_map, AS_DATA, 16, dcs_audio_device )
|
|||||||
AM_RANGE(0x0000, 0x07ff) AM_RAM
|
AM_RANGE(0x0000, 0x07ff) AM_RAM
|
||||||
AM_RANGE(0x0800, 0x1fff) AM_READWRITE(dcs_dataram_r, dcs_dataram_w)
|
AM_RANGE(0x0800, 0x1fff) AM_READWRITE(dcs_dataram_r, dcs_dataram_w)
|
||||||
AM_RANGE(0x2000, 0x2fff) AM_ROMBANK("databank")
|
AM_RANGE(0x2000, 0x2fff) AM_ROMBANK("databank")
|
||||||
AM_RANGE(0x3000, 0x33ff) AM_WRITE(dcs_data_bank_select_w)
|
AM_RANGE(0x3000, 0x3000) AM_WRITE(dcs_data_bank_select_w)
|
||||||
AM_RANGE(0x3400, 0x37ff) AM_READWRITE(input_latch_r, output_latch_w)
|
AM_RANGE(0x3400, 0x3403) AM_READWRITE(input_latch_r, output_latch_w)
|
||||||
AM_RANGE(0x3800, 0x39ff) AM_RAM
|
AM_RANGE(0x3800, 0x39ff) AM_RAM
|
||||||
AM_RANGE(0x3fe0, 0x3fff) AM_READWRITE(adsp_control_r, adsp_control_w)
|
AM_RANGE(0x3fe0, 0x3fff) AM_READWRITE(adsp_control_r, adsp_control_w)
|
||||||
ADDRESS_MAP_END
|
ADDRESS_MAP_END
|
||||||
|
|
||||||
|
|
||||||
/* Williams WPC DCS/Security Pinball */
|
/* Williams WPC DCS/Security Pinball */
|
||||||
static ADDRESS_MAP_START( dcs_wpc_program_map, AS_PROGRAM, 32, dcs_audio_device )
|
static ADDRESS_MAP_START( dcs_wpc_program_map, AS_PROGRAM, 32, dcs_audio_device )
|
||||||
AM_RANGE(0x0000, 0x07ff) AM_RAM AM_SHARE("dcsint")
|
AM_RANGE(0x0000, 0x03ff) AM_RAM AM_SHARE("dcsint")
|
||||||
AM_RANGE(0x0800, 0x2fff) AM_RAM AM_SHARE("dcsext")
|
AM_RANGE(0x1000, 0x3fff) AM_RAM AM_SHARE("dcsext")
|
||||||
AM_RANGE(0x3000, 0x3001) AM_READWRITE16(input_latch_r, output_latch_w,0xffff)
|
|
||||||
ADDRESS_MAP_END
|
ADDRESS_MAP_END
|
||||||
|
|
||||||
static ADDRESS_MAP_START( dcs_wpc_data_map, AS_DATA, 16, dcs_audio_device )
|
static ADDRESS_MAP_START( dcs_wpc_data_map, AS_DATA, 16, dcs_audio_wpc_device )
|
||||||
AM_RANGE(0x0000, 0x1fff) AM_READWRITE(dcs_dataram_r, dcs_dataram_w)
|
AM_RANGE(0x0000, 0x07ff) AM_ROMBANK("databank")
|
||||||
AM_RANGE(0x2000, 0x2fff) AM_ROMBANK("databank")
|
AM_RANGE(0x1000, 0x2fff) AM_READWRITE(dcs_dataram_r, dcs_dataram_w)
|
||||||
AM_RANGE(0x3000, 0x33ff) AM_WRITE(dcs_data_bank_select_w)
|
AM_RANGE(0x3000, 0x3000) AM_WRITE(dcs_data_bank_select_w)
|
||||||
|
AM_RANGE(0x3100, 0x3100) AM_WRITE(dcs_data_bank_select2_w)
|
||||||
|
AM_RANGE(0x3300, 0x3303) AM_READWRITE(input_latch_r, output_latch_w)
|
||||||
AM_RANGE(0x3800, 0x39ff) AM_RAM
|
AM_RANGE(0x3800, 0x39ff) AM_RAM
|
||||||
AM_RANGE(0x3fe0, 0x3fff) AM_READWRITE(adsp_control_r, adsp_control_w)
|
AM_RANGE(0x3fe0, 0x3fff) AM_READWRITE(adsp_control_r, adsp_control_w)
|
||||||
ADDRESS_MAP_END
|
ADDRESS_MAP_END
|
||||||
@ -600,8 +600,9 @@ void dcs_audio_device::dcs_boot()
|
|||||||
|
|
||||||
switch (m_rev)
|
switch (m_rev)
|
||||||
{
|
{
|
||||||
/* rev 1: use the last set data bank to boot from */
|
/* rev 1/1.5: use the last set data bank to boot from */
|
||||||
case 1:
|
case 1:
|
||||||
|
case 15:
|
||||||
|
|
||||||
/* determine the base */
|
/* determine the base */
|
||||||
// max_banks = m_bootrom_words / 0x1000;
|
// max_banks = m_bootrom_words / 0x1000;
|
||||||
@ -659,8 +660,9 @@ TIMER_CALLBACK_MEMBER( dcs_audio_device::dcs_reset )
|
|||||||
/* reset the memory banking */
|
/* reset the memory banking */
|
||||||
switch (m_rev)
|
switch (m_rev)
|
||||||
{
|
{
|
||||||
/* rev 1: just reset the bank to 0 */
|
/* rev 1/1.5: just reset the bank to 0 */
|
||||||
case 1:
|
case 1:
|
||||||
|
case 15:
|
||||||
m_sounddata_bank = 0;
|
m_sounddata_bank = 0;
|
||||||
membank("databank")->set_entry(0);
|
membank("databank")->set_entry(0);
|
||||||
break;
|
break;
|
||||||
@ -782,12 +784,12 @@ void dcs_audio_device::dcs_register_state()
|
|||||||
// dcs_audio_device - constructor
|
// dcs_audio_device - constructor
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
dcs_audio_device::dcs_audio_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) :
|
dcs_audio_device::dcs_audio_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source, int rev) :
|
||||||
device_t(mconfig, type, name, tag, owner, clock, shortname, source),
|
device_t(mconfig, type, name, tag, owner, clock, shortname, source),
|
||||||
m_cpu(NULL),
|
m_cpu(NULL),
|
||||||
m_program(NULL),
|
m_program(NULL),
|
||||||
m_data(NULL),
|
m_data(NULL),
|
||||||
m_rev(0),
|
m_rev(rev),
|
||||||
m_polling_offset(0),
|
m_polling_offset(0),
|
||||||
m_polling_count(0),
|
m_polling_count(0),
|
||||||
m_channels(0),
|
m_channels(0),
|
||||||
@ -833,6 +835,10 @@ dcs_audio_device::dcs_audio_device(const machine_config &mconfig, device_type ty
|
|||||||
memset(&m_transfer, 0, sizeof(m_transfer));
|
memset(&m_transfer, 0, sizeof(m_transfer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dcs_audio_device::device_reset()
|
||||||
|
{
|
||||||
|
dcs_reset(NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void dcs_audio_device::device_start()
|
void dcs_audio_device::device_start()
|
||||||
{
|
{
|
||||||
@ -848,7 +854,6 @@ void dcs_audio_device::device_start()
|
|||||||
|
|
||||||
m_program = &m_cpu->space(AS_PROGRAM);
|
m_program = &m_cpu->space(AS_PROGRAM);
|
||||||
m_data = &m_cpu->space(AS_DATA);
|
m_data = &m_cpu->space(AS_DATA);
|
||||||
m_rev = 1;
|
|
||||||
m_channels = 1;
|
m_channels = 1;
|
||||||
m_dmadac[0] = subdevice<dmadac_sound_device>("dac");
|
m_dmadac[0] = subdevice<dmadac_sound_device>("dac");
|
||||||
|
|
||||||
@ -857,8 +862,16 @@ void dcs_audio_device::device_start()
|
|||||||
m_bootrom_words = machine().root_device().memregion("dcs")->bytes() / 2;
|
m_bootrom_words = machine().root_device().memregion("dcs")->bytes() / 2;
|
||||||
m_sounddata = m_bootrom;
|
m_sounddata = m_bootrom;
|
||||||
m_sounddata_words = m_bootrom_words;
|
m_sounddata_words = m_bootrom_words;
|
||||||
|
if (m_rev == 1)
|
||||||
|
{
|
||||||
m_sounddata_banks = m_sounddata_words / 0x1000;
|
m_sounddata_banks = m_sounddata_words / 0x1000;
|
||||||
membank("databank")->configure_entries(0, m_sounddata_banks, m_sounddata, 0x1000*2);
|
membank("databank")->configure_entries(0, m_sounddata_banks, m_sounddata, 0x1000*2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_sounddata_banks = m_sounddata_words / 0x800;
|
||||||
|
membank("databank")->configure_entries(0, m_sounddata_banks, m_sounddata, 0x800*2);
|
||||||
|
}
|
||||||
|
|
||||||
/* create the timers */
|
/* create the timers */
|
||||||
m_internal_timer = subdevice<timer_device>("dcs_int_timer");
|
m_internal_timer = subdevice<timer_device>("dcs_int_timer");
|
||||||
@ -973,24 +986,34 @@ READ16_MEMBER( dcs_audio_device::dcs_dataram_r )
|
|||||||
|
|
||||||
WRITE16_MEMBER( dcs_audio_device::dcs_dataram_w )
|
WRITE16_MEMBER( dcs_audio_device::dcs_dataram_w )
|
||||||
{
|
{
|
||||||
UINT16 newdata = m_external_program_ram[offset] >> 8;
|
UINT16 val = m_external_program_ram[offset] >> 8;
|
||||||
COMBINE_DATA(&newdata);
|
COMBINE_DATA(&val);
|
||||||
m_external_program_ram[offset] = (newdata << 8) | (m_external_program_ram[offset] & 0xff);
|
m_external_program_ram[offset] = (val << 8) | (m_external_program_ram[offset] & 0x0000ff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
WRITE16_MEMBER( dcs_audio_device::dcs_data_bank_select_w )
|
WRITE16_MEMBER( dcs_audio_device::dcs_data_bank_select_w )
|
||||||
{
|
{
|
||||||
|
if (m_rev != 15)
|
||||||
m_sounddata_bank = data & 0x7ff;
|
m_sounddata_bank = data & 0x7ff;
|
||||||
|
else
|
||||||
|
m_sounddata_bank = (m_sounddata_bank & 0xff00) | (data & 0xff);
|
||||||
|
|
||||||
membank("databank")->set_entry(m_sounddata_bank % m_sounddata_banks);
|
membank("databank")->set_entry(m_sounddata_bank % m_sounddata_banks);
|
||||||
|
|
||||||
/* bit 11 = sound board led */
|
/* bit 11 = sound board led */
|
||||||
#if 0
|
#if 0
|
||||||
|
if (m_rev != 15)
|
||||||
set_led_status(machine(), 2, data & 0x800);
|
set_led_status(machine(), 2, data & 0x800);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WRITE16_MEMBER( dcs_audio_device::dcs_data_bank_select2_w )
|
||||||
|
{
|
||||||
|
m_sounddata_bank = (m_sounddata_bank & 0x00ff) | ((data & 0x01) << 8) | ((data & 0xfc) << 7);
|
||||||
|
|
||||||
|
membank("databank")->set_entry(m_sounddata_bank % m_sounddata_banks);
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************
|
/*************************************
|
||||||
*
|
*
|
||||||
@ -1416,6 +1439,8 @@ int dcs_audio_device::control_r()
|
|||||||
/* only boost for DCS2 boards */
|
/* only boost for DCS2 boards */
|
||||||
if (!m_auto_ack && !m_transfer.hle_enabled)
|
if (!m_auto_ack && !m_transfer.hle_enabled)
|
||||||
machine().scheduler().boost_interleave(attotime::from_nsec(500), attotime::from_usec(5));
|
machine().scheduler().boost_interleave(attotime::from_nsec(500), attotime::from_usec(5));
|
||||||
|
if (m_rev == 15)
|
||||||
|
return IS_OUTPUT_FULL() ? 0x80 : 0x00;
|
||||||
return m_latch_control;
|
return m_latch_control;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1467,7 +1492,7 @@ READ16_MEMBER( dcs_audio_device::fifo_input_r )
|
|||||||
INPUT LATCH (data from host to DCS)
|
INPUT LATCH (data from host to DCS)
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void dcs_audio_device::dcs_delayed_data_w(int data)
|
void dcs_audio_device::dcs_delayed_data_w(UINT8 data)
|
||||||
{
|
{
|
||||||
if (LOG_DCS_IO)
|
if (LOG_DCS_IO)
|
||||||
logerror("%s:dcs_data_w(%04X)\n", machine().describe_context(), data);
|
logerror("%s:dcs_data_w(%04X)\n", machine().describe_context(), data);
|
||||||
@ -1494,7 +1519,7 @@ TIMER_CALLBACK_MEMBER( dcs_audio_device::dcs_delayed_data_w_callback )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void dcs_audio_device::data_w(int data)
|
void dcs_audio_device::data_w(UINT8 data)
|
||||||
{
|
{
|
||||||
/* preprocess the write */
|
/* preprocess the write */
|
||||||
if (preprocess_write(data))
|
if (preprocess_write(data))
|
||||||
@ -1526,8 +1551,6 @@ READ16_MEMBER( dcs_audio_device::input_latch_r )
|
|||||||
return m_input_data;
|
return m_input_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
OUTPUT LATCH (data from DCS to host)
|
OUTPUT LATCH (data from DCS to host)
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -1537,15 +1560,16 @@ TIMER_CALLBACK_MEMBER( dcs_audio_device::latch_delayed_w )
|
|||||||
if (!m_last_output_full && !m_output_full_cb.isnull())
|
if (!m_last_output_full && !m_output_full_cb.isnull())
|
||||||
m_output_full_cb(m_last_output_full = 1);
|
m_output_full_cb(m_last_output_full = 1);
|
||||||
SET_OUTPUT_FULL();
|
SET_OUTPUT_FULL();
|
||||||
m_output_data = param;
|
m_output_data = m_pre_output_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
WRITE16_MEMBER( dcs_audio_device::output_latch_w )
|
WRITE16_MEMBER( dcs_audio_device::output_latch_w )
|
||||||
{
|
{
|
||||||
|
m_pre_output_data = data;
|
||||||
if (LOG_DCS_IO)
|
if (LOG_DCS_IO)
|
||||||
logerror("%08X:output_latch_w(%04X) (empty=%d)\n", space.device().safe_pc(), data, IS_OUTPUT_EMPTY());
|
logerror("%08X:output_latch_w(%04X) (empty=%d)\n", space.device().safe_pc(), data, IS_OUTPUT_EMPTY());
|
||||||
machine().scheduler().synchronize(timer_expired_delegate(FUNC(dcs_audio_device::latch_delayed_w),this), data);
|
machine().scheduler().synchronize(timer_expired_delegate(FUNC(dcs_audio_device::latch_delayed_w),this), data>>8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1567,9 +1591,9 @@ void dcs_audio_device::ack_w()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int dcs_audio_device::data_r()
|
UINT8 dcs_audio_device::data_r()
|
||||||
{
|
{
|
||||||
/* data is actually only 8 bit (read from d8-d15) */
|
/* data is actually only 8 bit (read from d8-d15, which is d0-d7 from the data access instructions POV) */
|
||||||
if (m_last_output_full && !m_output_full_cb.isnull())
|
if (m_last_output_full && !m_output_full_cb.isnull())
|
||||||
m_output_full_cb(m_last_output_full = 0);
|
m_output_full_cb(m_last_output_full = 0);
|
||||||
if (m_auto_ack)
|
if (m_auto_ack)
|
||||||
@ -1758,6 +1782,7 @@ READ16_MEMBER( dcs_audio_device::adsp_control_r )
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case IDMA_CONTROL_REG:
|
case IDMA_CONTROL_REG:
|
||||||
|
if (m_rev == 3 || m_rev == 4)
|
||||||
result = downcast<adsp2181_device *>(m_cpu)->idma_addr_r();
|
result = downcast<adsp2181_device *>(m_cpu)->idma_addr_r();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1839,6 +1864,7 @@ WRITE16_MEMBER(dcs_audio_device:: adsp_control_w )
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case IDMA_CONTROL_REG:
|
case IDMA_CONTROL_REG:
|
||||||
|
if (m_rev == 3 || m_rev == 4)
|
||||||
downcast<adsp2181_device *>(m_cpu)->idma_addr_w(data);
|
downcast<adsp2181_device *>(m_cpu)->idma_addr_w(data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1856,7 +1882,7 @@ TIMER_DEVICE_CALLBACK_MEMBER( dcs_audio_device::dcs_irq )
|
|||||||
|
|
||||||
/* copy the current data into the buffer */
|
/* copy the current data into the buffer */
|
||||||
{
|
{
|
||||||
int count = m_size / 2;
|
int count = m_size / (2*(m_incs ? m_incs : 1));
|
||||||
INT16 buffer[0x400];
|
INT16 buffer[0x400];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -1867,7 +1893,7 @@ TIMER_DEVICE_CALLBACK_MEMBER( dcs_audio_device::dcs_irq )
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_channels)
|
if (m_channels)
|
||||||
dmadac_transfer(&m_dmadac[0], m_channels, 1, m_channels, (m_size / 2) / m_channels, buffer);
|
dmadac_transfer(&m_dmadac[0], m_channels, 1, m_channels, count / m_channels, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for wrapping */
|
/* check for wrapping */
|
||||||
@ -1911,7 +1937,7 @@ void dcs_audio_device::recompute_sample_rate()
|
|||||||
dmadac_set_frequency(&m_dmadac[0], m_channels, ATTOSECONDS_TO_HZ(sample_period.attoseconds));
|
dmadac_set_frequency(&m_dmadac[0], m_channels, ATTOSECONDS_TO_HZ(sample_period.attoseconds));
|
||||||
dmadac_enable(&m_dmadac[0], m_channels, 1);
|
dmadac_enable(&m_dmadac[0], m_channels, 1);
|
||||||
|
|
||||||
/* fire off a timer wich will hit every half-buffer */
|
/* fire off a timer which will hit every half-buffer */
|
||||||
if (m_incs)
|
if (m_incs)
|
||||||
{
|
{
|
||||||
attotime period = (sample_period * m_size) / (2 * m_channels * m_incs);
|
attotime period = (sample_period * m_size) / (2 * m_channels * m_incs);
|
||||||
@ -1919,7 +1945,6 @@ void dcs_audio_device::recompute_sample_rate()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
WRITE32_MEMBER(dcs_audio_device::sound_tx_callback)
|
WRITE32_MEMBER(dcs_audio_device::sound_tx_callback)
|
||||||
{
|
{
|
||||||
/* check if it's for SPORT1 */
|
/* check if it's for SPORT1 */
|
||||||
@ -1942,7 +1967,7 @@ WRITE32_MEMBER(dcs_audio_device::sound_tx_callback)
|
|||||||
lreg = m_ireg;
|
lreg = m_ireg;
|
||||||
|
|
||||||
/* now get the register contents in a more legible format */
|
/* now get the register contents in a more legible format */
|
||||||
/* we depend on register indexes to be continuous (wich is the case in our core) */
|
/* we depend on register indexes to be continuous (which is the case in our core) */
|
||||||
source = m_cpu->state_int(ADSP2100_I0 + m_ireg);
|
source = m_cpu->state_int(ADSP2100_I0 + m_ireg);
|
||||||
m_incs = m_cpu->state_int(ADSP2100_M0 + mreg);
|
m_incs = m_cpu->state_int(ADSP2100_M0 + mreg);
|
||||||
m_size = m_cpu->state_int(ADSP2100_L0 + lreg);
|
m_size = m_cpu->state_int(ADSP2100_L0 + lreg);
|
||||||
@ -2381,7 +2406,7 @@ const device_type DCS_AUDIO_WPC = &device_creator<dcs_audio_wpc_device>;
|
|||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
|
|
||||||
dcs_audio_wpc_device::dcs_audio_wpc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
dcs_audio_wpc_device::dcs_audio_wpc_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||||
dcs_audio_device(mconfig, DCS_AUDIO_WPC, "DCS Audio WPC", tag, owner, clock, "dcs_audio_wpc", __FILE__)
|
dcs_audio_device(mconfig, DCS_AUDIO_WPC, "DCS Audio WPC", tag, owner, clock, "dcs_audio_wpc", __FILE__, 15)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ class dcs_audio_device : public device_t
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// construction/destruction
|
// construction/destruction
|
||||||
dcs_audio_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
|
dcs_audio_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source, int rev = 1);
|
||||||
|
|
||||||
// for dcs2 (int dram_in_mb, offs_t polling_offset)
|
// for dcs2 (int dram_in_mb, offs_t polling_offset)
|
||||||
static void static_set_dram_in_mb(device_t &device, int dram_in_mb) { downcast<dcs_audio_device &>(device).m_dram_in_mb = dram_in_mb; }
|
static void static_set_dram_in_mb(device_t &device, int dram_in_mb) { downcast<dcs_audio_device &>(device).m_dram_in_mb = dram_in_mb; }
|
||||||
@ -34,12 +34,12 @@ public:
|
|||||||
void set_fifo_callbacks(read16_delegate fifo_data_r, read16_delegate fifo_status_r, write_line_delegate fifo_reset_w);
|
void set_fifo_callbacks(read16_delegate fifo_data_r, read16_delegate fifo_status_r, write_line_delegate fifo_reset_w);
|
||||||
void set_io_callbacks(write_line_delegate output_full_cb, write_line_delegate input_empty_cb);
|
void set_io_callbacks(write_line_delegate output_full_cb, write_line_delegate input_empty_cb);
|
||||||
|
|
||||||
int data_r();
|
UINT8 data_r();
|
||||||
void ack_w();
|
void ack_w();
|
||||||
int data2_r();
|
int data2_r();
|
||||||
int control_r();
|
int control_r();
|
||||||
|
|
||||||
void data_w(int data);
|
void data_w(UINT8 data);
|
||||||
void reset_w(int state);
|
void reset_w(int state);
|
||||||
|
|
||||||
void fifo_notify(int count, int max);
|
void fifo_notify(int count, int max);
|
||||||
@ -48,6 +48,9 @@ public:
|
|||||||
DECLARE_WRITE32_MEMBER( dsio_idma_data_w );
|
DECLARE_WRITE32_MEMBER( dsio_idma_data_w );
|
||||||
DECLARE_READ32_MEMBER( dsio_idma_data_r );
|
DECLARE_READ32_MEMBER( dsio_idma_data_r );
|
||||||
|
|
||||||
|
DECLARE_READ32_MEMBER(de_r);
|
||||||
|
DECLARE_WRITE32_MEMBER(de_w);
|
||||||
|
|
||||||
// non public
|
// non public
|
||||||
void dcs_boot();
|
void dcs_boot();
|
||||||
TIMER_CALLBACK_MEMBER( dcs_reset );
|
TIMER_CALLBACK_MEMBER( dcs_reset );
|
||||||
@ -55,6 +58,9 @@ public:
|
|||||||
DECLARE_READ16_MEMBER( dcs_dataram_r );
|
DECLARE_READ16_MEMBER( dcs_dataram_r );
|
||||||
DECLARE_WRITE16_MEMBER( dcs_dataram_w );
|
DECLARE_WRITE16_MEMBER( dcs_dataram_w );
|
||||||
DECLARE_WRITE16_MEMBER( dcs_data_bank_select_w );
|
DECLARE_WRITE16_MEMBER( dcs_data_bank_select_w );
|
||||||
|
DECLARE_WRITE16_MEMBER( dcs_data_bank_select2_w );
|
||||||
|
DECLARE_READ16_MEMBER( dcs_dataram_bank_select_r );
|
||||||
|
DECLARE_WRITE16_MEMBER( dcs_dataram_bank_select_w );
|
||||||
inline void sdrc_update_bank_pointers();
|
inline void sdrc_update_bank_pointers();
|
||||||
void sdrc_remap_memory();
|
void sdrc_remap_memory();
|
||||||
void sdrc_reset();
|
void sdrc_reset();
|
||||||
@ -68,7 +74,7 @@ public:
|
|||||||
DECLARE_WRITE16_MEMBER( denver_w );
|
DECLARE_WRITE16_MEMBER( denver_w );
|
||||||
DECLARE_READ16_MEMBER( latch_status_r );
|
DECLARE_READ16_MEMBER( latch_status_r );
|
||||||
DECLARE_READ16_MEMBER( fifo_input_r );
|
DECLARE_READ16_MEMBER( fifo_input_r );
|
||||||
void dcs_delayed_data_w(int data);
|
void dcs_delayed_data_w(UINT8 data);
|
||||||
TIMER_CALLBACK_MEMBER( dcs_delayed_data_w_callback );
|
TIMER_CALLBACK_MEMBER( dcs_delayed_data_w_callback );
|
||||||
DECLARE_WRITE16_MEMBER( input_latch_ack_w );
|
DECLARE_WRITE16_MEMBER( input_latch_ack_w );
|
||||||
DECLARE_READ16_MEMBER( input_latch_r );
|
DECLARE_READ16_MEMBER( input_latch_r );
|
||||||
@ -102,6 +108,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
// device-level overrides
|
// device-level overrides
|
||||||
virtual void device_start();
|
virtual void device_start();
|
||||||
|
virtual void device_reset();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct sdrc_state
|
struct sdrc_state
|
||||||
@ -164,8 +171,9 @@ protected:
|
|||||||
/* I/O with the host */
|
/* I/O with the host */
|
||||||
UINT8 m_auto_ack;
|
UINT8 m_auto_ack;
|
||||||
UINT16 m_latch_control;
|
UINT16 m_latch_control;
|
||||||
UINT16 m_input_data;
|
UINT8 m_input_data;
|
||||||
UINT16 m_output_data;
|
UINT8 m_output_data;
|
||||||
|
UINT8 m_pre_output_data;
|
||||||
UINT16 m_output_control;
|
UINT16 m_output_control;
|
||||||
UINT64 m_output_control_cycles;
|
UINT64 m_output_control_cycles;
|
||||||
UINT8 m_last_output_full;
|
UINT8 m_last_output_full;
|
||||||
@ -259,7 +267,6 @@ public:
|
|||||||
|
|
||||||
// optional information overrides
|
// optional information overrides
|
||||||
virtual machine_config_constructor device_mconfig_additions() const;
|
virtual machine_config_constructor device_mconfig_additions() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// device type definition
|
// device type definition
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,74 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Olivier Galibert
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
#include "wpc_lamp.h"
|
||||||
|
|
||||||
|
const device_type WPC_LAMP = &device_creator<wpc_lamp_device>;
|
||||||
|
|
||||||
|
wpc_lamp_device::wpc_lamp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||||
|
device_t(mconfig, WPC_LAMP, "Williams Pinball Controller lamp control", tag, owner, clock, "wpc_lamp", __FILE__)
|
||||||
|
{
|
||||||
|
names = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpc_lamp_device::~wpc_lamp_device()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_lamp_device::set_names(const char *const *_names)
|
||||||
|
{
|
||||||
|
names = _names;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_lamp_device::update()
|
||||||
|
{
|
||||||
|
for(int i=0; i<8; i++)
|
||||||
|
if(row & (1 << i))
|
||||||
|
for(int j=0; j<8; j++)
|
||||||
|
if(col & (1 << j))
|
||||||
|
state[(j<<3)|i] |= 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER(wpc_lamp_device::row_w)
|
||||||
|
{
|
||||||
|
row = data;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER(wpc_lamp_device::col_w)
|
||||||
|
{
|
||||||
|
col = data;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_lamp_device::device_start()
|
||||||
|
{
|
||||||
|
save_item(NAME(state));
|
||||||
|
save_item(NAME(col));
|
||||||
|
save_item(NAME(row));
|
||||||
|
|
||||||
|
timer = timer_alloc(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_lamp_device::device_reset()
|
||||||
|
{
|
||||||
|
memset(state, 0x00, 64);
|
||||||
|
timer->adjust(attotime::from_hz(60), 0, attotime::from_hz(60));
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_lamp_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||||
|
{
|
||||||
|
for(int i=0; i<64; i++) {
|
||||||
|
UINT8 s = state[i];
|
||||||
|
state[i] = s >> 1;
|
||||||
|
if((s & 0xc0) == 0x40 || (s & 0xc0) == 0x80) {
|
||||||
|
char buffer[256];
|
||||||
|
if(names && names[i])
|
||||||
|
sprintf(buffer, "l:%s", names[i]);
|
||||||
|
else
|
||||||
|
sprintf(buffer, "l:%d%d", 1+(i >> 3), 1 + (i & 7));
|
||||||
|
output_set_value(buffer, (s & 0xc0) == 0x80);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Olivier Galibert
|
||||||
|
|
||||||
|
// Williams Pinball Controller lamp control
|
||||||
|
|
||||||
|
#ifndef WPC_LAMP_H
|
||||||
|
#define WPC_LAMP_H
|
||||||
|
|
||||||
|
#define MCFG_WPC_LAMP_ADD( _tag ) \
|
||||||
|
MCFG_DEVICE_ADD( _tag, WPC_LAMP, 0 )
|
||||||
|
|
||||||
|
class wpc_lamp_device : public device_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wpc_lamp_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
virtual ~wpc_lamp_device();
|
||||||
|
|
||||||
|
DECLARE_WRITE8_MEMBER(row_w);
|
||||||
|
DECLARE_WRITE8_MEMBER(col_w);
|
||||||
|
|
||||||
|
void set_names(const char *const *lamp_names);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
UINT8 state[64];
|
||||||
|
UINT8 col, row;
|
||||||
|
emu_timer *timer;
|
||||||
|
const char *const *names;
|
||||||
|
|
||||||
|
virtual void device_start();
|
||||||
|
virtual void device_reset();
|
||||||
|
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||||
|
|
||||||
|
void update();
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const device_type WPC_LAMP;
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,144 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Olivier Galibert
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
#include "wpc_out.h"
|
||||||
|
|
||||||
|
const device_type WPC_OUT = &device_creator<wpc_out_device>;
|
||||||
|
|
||||||
|
wpc_out_device::wpc_out_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||||
|
device_t(mconfig, WPC_OUT, "Williams Pinball Controller output control", tag, owner, clock, "wpc_out", __FILE__)
|
||||||
|
{
|
||||||
|
names = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpc_out_device::~wpc_out_device()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_out_device::set_names(const char *const *_names)
|
||||||
|
{
|
||||||
|
names = _names;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_out_device::set_handler(handler_t cb)
|
||||||
|
{
|
||||||
|
handler_cb = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_out_device::set_gi_count(int _count)
|
||||||
|
{
|
||||||
|
gi_count = _count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_out_device::gi_update()
|
||||||
|
{
|
||||||
|
attotime now = machine().time();
|
||||||
|
attotime delta = now - previous_gi_update;
|
||||||
|
UINT32 delta_us = delta.as_ticks(1e6);
|
||||||
|
for(int i=0; i<gi_count; i++)
|
||||||
|
if(gi & (1 <<i))
|
||||||
|
gi_time[i] += delta_us;
|
||||||
|
previous_gi_update = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_out_device::send_output(int sid, int state)
|
||||||
|
{
|
||||||
|
if(!handler_cb.isnull() && handler_cb(sid, state))
|
||||||
|
return;
|
||||||
|
|
||||||
|
char buffer[32];
|
||||||
|
const char *name;
|
||||||
|
if(names && names[sid-1])
|
||||||
|
name = names[sid-1];
|
||||||
|
else {
|
||||||
|
sprintf(buffer, "u:output %02d", sid);
|
||||||
|
name = buffer;
|
||||||
|
}
|
||||||
|
output_set_value(name, state);
|
||||||
|
|
||||||
|
if(sid == 41)
|
||||||
|
coin_counter_w(machine(), 0, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER(wpc_out_device::out_w)
|
||||||
|
{
|
||||||
|
logerror("%s: out_w %d, %02x (%04x)\n", tag(), offset, data, space.device().safe_pc());
|
||||||
|
|
||||||
|
first_after_led = false;
|
||||||
|
UINT8 diff = state[offset] ^ data;
|
||||||
|
state[offset] = data;
|
||||||
|
if(diff)
|
||||||
|
for(int i=0; i<8; i++)
|
||||||
|
if(diff & (1 << i)) {
|
||||||
|
int id = (offset << 3) | i;
|
||||||
|
int sid;
|
||||||
|
if(id <= 3)
|
||||||
|
sid = id + 25;
|
||||||
|
else if(id <= 7)
|
||||||
|
sid = id + 33;
|
||||||
|
else if(id <= 15)
|
||||||
|
sid = id-7;
|
||||||
|
else if(id <= 23)
|
||||||
|
sid = id+1;
|
||||||
|
else if(id <= 31)
|
||||||
|
sid = id-15;
|
||||||
|
else if(id <= 39)
|
||||||
|
sid = id-3;
|
||||||
|
else
|
||||||
|
sid = id+2;
|
||||||
|
|
||||||
|
send_output(sid, (data & (1<<i)) != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER(wpc_out_device::out4_w)
|
||||||
|
{
|
||||||
|
// This is gross, probably wrong, but also the best I could find.
|
||||||
|
// Test case is No Good Gofers (ngg_13).
|
||||||
|
out_w(space, first_after_led ? 5 : 4, data, mem_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER(wpc_out_device::gi_w)
|
||||||
|
{
|
||||||
|
gi_update();
|
||||||
|
if((gi^data) & 0x80)
|
||||||
|
send_output(41, data & 0x80 ? 1 : 0);
|
||||||
|
gi = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER(wpc_out_device::led_w)
|
||||||
|
{
|
||||||
|
first_after_led = true;
|
||||||
|
output_set_value("L:cpu led", data & 0x80 ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_out_device::device_start()
|
||||||
|
{
|
||||||
|
save_item(NAME(state));
|
||||||
|
save_item(NAME(gi));
|
||||||
|
save_item(NAME(first_after_led));
|
||||||
|
save_item(NAME(previous_gi_update));
|
||||||
|
save_item(NAME(gi_time));
|
||||||
|
|
||||||
|
timer = timer_alloc(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_out_device::device_reset()
|
||||||
|
{
|
||||||
|
memset(state, 0x00, 6);
|
||||||
|
first_after_led = false;
|
||||||
|
gi = 0x00;
|
||||||
|
previous_gi_update = attotime::zero;
|
||||||
|
memset(gi_time, 0, sizeof(gi_time));
|
||||||
|
timer->adjust(attotime::from_hz(10), 0, attotime::from_hz(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_out_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||||
|
{
|
||||||
|
gi_update();
|
||||||
|
for(int i=0; i<gi_count; i++) {
|
||||||
|
// fprintf(stderr, "gi[%d] = %d\n", i, gi_time[i]);
|
||||||
|
gi_time[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Olivier Galibert
|
||||||
|
|
||||||
|
// Williams Pinball Controller outputs control (solenoids, flashers, generic logic, global illumination, coin counter, cpu led)
|
||||||
|
|
||||||
|
#ifndef WPC_OUT_H
|
||||||
|
#define WPC_OUT_H
|
||||||
|
|
||||||
|
#define MCFG_WPC_OUT_ADD( _tag, _count ) \
|
||||||
|
MCFG_DEVICE_ADD( _tag, WPC_OUT, 0 ) \
|
||||||
|
downcast<wpc_out_device *>(device)->set_gi_count(_count);
|
||||||
|
|
||||||
|
class wpc_out_device : public device_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef delegate<bool (int, bool)> handler_t;
|
||||||
|
|
||||||
|
wpc_out_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
virtual ~wpc_out_device();
|
||||||
|
|
||||||
|
DECLARE_WRITE8_MEMBER(out_w);
|
||||||
|
DECLARE_WRITE8_MEMBER(out4_w); // fixed offset 4
|
||||||
|
DECLARE_WRITE8_MEMBER(gi_w);
|
||||||
|
DECLARE_WRITE8_MEMBER(led_w);
|
||||||
|
|
||||||
|
void set_names(const char *const *names);
|
||||||
|
void set_handler(handler_t cb);
|
||||||
|
void set_gi_count(int _count);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
UINT8 state[6], gi;
|
||||||
|
bool first_after_led;
|
||||||
|
attotime previous_gi_update;
|
||||||
|
int gi_count;
|
||||||
|
UINT32 gi_time[5];
|
||||||
|
emu_timer *timer;
|
||||||
|
const char *const *names;
|
||||||
|
handler_t handler_cb;
|
||||||
|
|
||||||
|
void send_output(int sid, int state);
|
||||||
|
|
||||||
|
virtual void device_start();
|
||||||
|
virtual void device_reset();
|
||||||
|
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||||
|
|
||||||
|
void gi_update();
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const device_type WPC_OUT;
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,141 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Olivier Galibert
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
#include "wpc_pic.h"
|
||||||
|
|
||||||
|
const device_type WPC_PIC = &device_creator<wpc_pic_device>;
|
||||||
|
|
||||||
|
wpc_pic_device::wpc_pic_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||||
|
device_t(mconfig, WPC_PIC, "Williams Pinball Controller pic security", tag, owner, clock, "wpc_pic", __FILE__),
|
||||||
|
swarray(*this, ":SW")
|
||||||
|
{
|
||||||
|
serial = "000 000000 00000 000";
|
||||||
|
}
|
||||||
|
|
||||||
|
wpc_pic_device::~wpc_pic_device()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_pic_device::set_serial(const char *_serial)
|
||||||
|
{
|
||||||
|
serial = _serial;
|
||||||
|
}
|
||||||
|
|
||||||
|
READ8_MEMBER(wpc_pic_device::read)
|
||||||
|
{
|
||||||
|
UINT8 data = 0x00;
|
||||||
|
if(curcmd == 0x0d)
|
||||||
|
data = count;
|
||||||
|
|
||||||
|
else if((curcmd & 0xf0) == 0x70) {
|
||||||
|
data = mem[curcmd & 0xf];
|
||||||
|
scrambler = (scrambler >> 4) | (curcmd << 4);
|
||||||
|
mem[ 5]= (mem[ 5]^scrambler) + mem[13];
|
||||||
|
mem[13]= (mem[13]+scrambler) ^ mem[ 5];
|
||||||
|
|
||||||
|
} else if(curcmd >= 0x16 && curcmd < 0x1e)
|
||||||
|
data = swarray[curcmd - 0x16]->read();
|
||||||
|
|
||||||
|
else
|
||||||
|
logerror("%s: cmd=%02x (%04x)\n", tag(), curcmd, space.device().safe_pc());
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_pic_device::check_game_id()
|
||||||
|
{
|
||||||
|
UINT32 cmp = (cmpchk[0] << 16) | (cmpchk[1] << 8) | cmpchk[2];
|
||||||
|
for(int i=0; i<1000; i++) {
|
||||||
|
UINT32 v = (i >> 8) * 0x3133 + (i & 0xff) * 0x3231;
|
||||||
|
v = v & 0xffffff;
|
||||||
|
if(v == cmp)
|
||||||
|
logerror("%s: Detected game id %03d\n", tag(), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER(wpc_pic_device::write)
|
||||||
|
{
|
||||||
|
if(chk_count) {
|
||||||
|
cmpchk[3-chk_count] = data;
|
||||||
|
|
||||||
|
if(data != cmpchk[3-chk_count]) {
|
||||||
|
logerror("%s: WARNING: validation error, checksum[%d] got %02x, expected %02x\n", tag(), 3-chk_count, data, chk[3-chk_count]);
|
||||||
|
if(chk_count == 1)
|
||||||
|
check_game_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
chk_count--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data == 0x00) {
|
||||||
|
scrambler = 0xa5;
|
||||||
|
count = 0x20;
|
||||||
|
mem[ 5] = mem[0]^mem[15];
|
||||||
|
mem[13] = mem[2]^mem[12];
|
||||||
|
} else if(data == 0x0d)
|
||||||
|
count = (count - 1) & 0x1f;
|
||||||
|
else if(data == 0x20)
|
||||||
|
chk_count = 3;
|
||||||
|
else if((data < 0x16 || data >= 0x1e) && ((data & 0xf0) != 0x70))
|
||||||
|
logerror("%s: write %02x (%04x)\n", tag(), data, space.device().safe_pc());
|
||||||
|
|
||||||
|
curcmd = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_pic_device::serial_to_pic()
|
||||||
|
{
|
||||||
|
UINT32 no[20];
|
||||||
|
for(int i=0; i<20; i++)
|
||||||
|
no[i] = serial[i] - '0';
|
||||||
|
UINT32 v;
|
||||||
|
|
||||||
|
mem[10] = 0x12; // Random?
|
||||||
|
mem[ 2] = 0x34; // Random?
|
||||||
|
|
||||||
|
v = (100*no[1] + 10*no[8] + no[5] + mem[10]*5)*0x1bcd + 0x1f3f0;
|
||||||
|
mem[ 1] = v >> 16;
|
||||||
|
mem[11] = v >> 8;
|
||||||
|
mem[ 9] = v;
|
||||||
|
|
||||||
|
v = (10000*no[2] + 1000*no[18] + 100*no[0] + 10*no[9] + no[7] + mem[10]*2 + mem[2])*0x107f + 0x71e259;
|
||||||
|
mem[ 7] = v >> 24;
|
||||||
|
mem[12] = v >> 16;
|
||||||
|
mem[ 0] = v >> 8;
|
||||||
|
mem[ 8] = v;
|
||||||
|
|
||||||
|
v = (1000*no[19] + 100*no[4] + 10*no[6] + no[17] + mem[2])*0x245 + 0x3d74;
|
||||||
|
mem[ 3] = v >> 16;
|
||||||
|
mem[14] = v >> 8;
|
||||||
|
mem[ 6] = v;
|
||||||
|
|
||||||
|
v = 99999 - 10000*no[15] - 1000*no[14] - 100*no[13] - 10*no[12] - no[11];
|
||||||
|
mem[15] = v >> 8;
|
||||||
|
mem[ 4] = v;
|
||||||
|
|
||||||
|
v = 100*no[0] + 10*no[1] + no[2];
|
||||||
|
v = (v >> 8) * ((serial[17] << 8) | serial[19]) + (v & 0xff) * ((serial[18] << 8) | serial[17]);
|
||||||
|
chk[0] = v >> 16;
|
||||||
|
chk[1] = v >> 8;
|
||||||
|
chk[2] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_pic_device::device_start()
|
||||||
|
{
|
||||||
|
save_item(NAME(mem));
|
||||||
|
save_item(NAME(chk));
|
||||||
|
save_item(NAME(curcmd));
|
||||||
|
save_item(NAME(scrambler));
|
||||||
|
save_item(NAME(count));
|
||||||
|
save_item(NAME(chk_count));
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_pic_device::device_reset()
|
||||||
|
{
|
||||||
|
serial_to_pic();
|
||||||
|
curcmd = 0x00;
|
||||||
|
scrambler = 0x00;
|
||||||
|
count = 0x00;
|
||||||
|
chk_count = 0;
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Olivier Galibert
|
||||||
|
|
||||||
|
// Williams Pinball Controller Pic-based protection simulation
|
||||||
|
|
||||||
|
#ifndef WPC_PIC_H
|
||||||
|
#define WPC_PIC_H
|
||||||
|
|
||||||
|
#define MCFG_WPC_PIC_ADD( _tag ) \
|
||||||
|
MCFG_DEVICE_ADD( _tag, WPC_PIC, 0 )
|
||||||
|
|
||||||
|
class wpc_pic_device : public device_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wpc_pic_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
virtual ~wpc_pic_device();
|
||||||
|
|
||||||
|
DECLARE_READ8_MEMBER(read);
|
||||||
|
DECLARE_WRITE8_MEMBER(write);
|
||||||
|
|
||||||
|
void set_serial(const char *serial);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
required_ioport_array<8> swarray;
|
||||||
|
|
||||||
|
UINT8 mem[16], chk[3], curcmd, scrambler, count, chk_count, cmpchk[3];
|
||||||
|
const char *serial;
|
||||||
|
|
||||||
|
virtual void device_start();
|
||||||
|
virtual void device_reset();
|
||||||
|
|
||||||
|
void serial_to_pic();
|
||||||
|
void check_game_id();
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const device_type WPC_PIC;
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,78 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Olivier Galibert
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
#include "wpc_shift.h"
|
||||||
|
|
||||||
|
const device_type WPC_SHIFT = &device_creator<wpc_shift_device>;
|
||||||
|
|
||||||
|
wpc_shift_device::wpc_shift_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||||
|
device_t(mconfig, WPC_SHIFT, "Williams Pinball Controller shifter", tag, owner, clock, "wpc_shift", __FILE__)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
wpc_shift_device::~wpc_shift_device()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DEVICE_ADDRESS_MAP_START( registers, 8, wpc_shift_device )
|
||||||
|
AM_RANGE(0, 0) AM_READWRITE(adrh_r, adrh_w)
|
||||||
|
AM_RANGE(1, 1) AM_READWRITE(adrl_r, adrl_w)
|
||||||
|
AM_RANGE(2, 2) AM_READWRITE(val1_r, val1_w)
|
||||||
|
AM_RANGE(3, 3) AM_READWRITE(val2_r, val2_w)
|
||||||
|
ADDRESS_MAP_END
|
||||||
|
|
||||||
|
|
||||||
|
READ8_MEMBER(wpc_shift_device::adrh_r)
|
||||||
|
{
|
||||||
|
return (adr + (val1 >> 3)) >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER(wpc_shift_device::adrh_w)
|
||||||
|
{
|
||||||
|
adr = (adr & 0xff) | (data << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
READ8_MEMBER(wpc_shift_device::adrl_r)
|
||||||
|
{
|
||||||
|
return adr + (val1 >> 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER(wpc_shift_device::adrl_w)
|
||||||
|
{
|
||||||
|
adr = (adr & 0xff00) | data;
|
||||||
|
}
|
||||||
|
|
||||||
|
READ8_MEMBER(wpc_shift_device::val1_r)
|
||||||
|
{
|
||||||
|
return 1 << (val1 & 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER(wpc_shift_device::val1_w)
|
||||||
|
{
|
||||||
|
val1 = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
READ8_MEMBER(wpc_shift_device::val2_r)
|
||||||
|
{
|
||||||
|
return 1 << (val2 & 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER(wpc_shift_device::val2_w)
|
||||||
|
{
|
||||||
|
val2 = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_shift_device::device_start()
|
||||||
|
{
|
||||||
|
save_item(NAME(adr));
|
||||||
|
save_item(NAME(val1));
|
||||||
|
save_item(NAME(val2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_shift_device::device_reset()
|
||||||
|
{
|
||||||
|
adr = 0x0000;
|
||||||
|
val1 = 0x00;
|
||||||
|
val2 = 0x00;
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Olivier Galibert
|
||||||
|
|
||||||
|
// Williams Pinball Controller Shift-based protection simulation
|
||||||
|
|
||||||
|
#ifndef WPC_SHIFT_H
|
||||||
|
#define WPC_SHIFT_H
|
||||||
|
|
||||||
|
#define MCFG_WPC_SHIFT_ADD( _tag ) \
|
||||||
|
MCFG_DEVICE_ADD( _tag, WPC_SHIFT, 0 )
|
||||||
|
|
||||||
|
class wpc_shift_device : public device_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wpc_shift_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
virtual ~wpc_shift_device();
|
||||||
|
|
||||||
|
DECLARE_ADDRESS_MAP(registers, 8);
|
||||||
|
|
||||||
|
DECLARE_READ8_MEMBER(adrh_r);
|
||||||
|
DECLARE_WRITE8_MEMBER(adrh_w);
|
||||||
|
DECLARE_READ8_MEMBER(adrl_r);
|
||||||
|
DECLARE_WRITE8_MEMBER(adrl_w);
|
||||||
|
DECLARE_READ8_MEMBER(val1_r);
|
||||||
|
DECLARE_WRITE8_MEMBER(val1_w);
|
||||||
|
DECLARE_READ8_MEMBER(val2_r);
|
||||||
|
DECLARE_WRITE8_MEMBER(val2_w);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
UINT16 adr;
|
||||||
|
UINT8 val1, val2;
|
||||||
|
|
||||||
|
virtual void device_start();
|
||||||
|
virtual void device_reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const device_type WPC_SHIFT;
|
||||||
|
|
||||||
|
#endif
|
@ -2157,6 +2157,11 @@ $(MAMEOBJ)/pinball.a: \
|
|||||||
$(DRIVERS)/wpc_s.o \
|
$(DRIVERS)/wpc_s.o \
|
||||||
$(MACHINE)/wpc.o \
|
$(MACHINE)/wpc.o \
|
||||||
$(AUDIO)/wpcsnd.o \
|
$(AUDIO)/wpcsnd.o \
|
||||||
|
$(VIDEO)/wpc_dmd.o \
|
||||||
|
$(MACHINE)/wpc_pic.o \
|
||||||
|
$(MACHINE)/wpc_lamp.o \
|
||||||
|
$(MACHINE)/wpc_out.o \
|
||||||
|
$(MACHINE)/wpc_shift.o \
|
||||||
$(DRIVERS)/zac_1.o \
|
$(DRIVERS)/zac_1.o \
|
||||||
$(DRIVERS)/zac_2.o \
|
$(DRIVERS)/zac_2.o \
|
||||||
$(DRIVERS)/zac_proto.o \
|
$(DRIVERS)/zac_proto.o \
|
||||||
|
@ -0,0 +1,199 @@
|
|||||||
|
#include "emu.h"
|
||||||
|
#include "wpc_dmd.h"
|
||||||
|
|
||||||
|
const device_type WPC_DMD = &device_creator<wpc_dmd_device>;
|
||||||
|
|
||||||
|
DEVICE_ADDRESS_MAP_START( registers, 8, wpc_dmd_device )
|
||||||
|
AM_RANGE(0, 0) AM_WRITE(bank2_w)
|
||||||
|
AM_RANGE(1, 1) AM_WRITE(bank0_w)
|
||||||
|
AM_RANGE(2, 2) AM_WRITE(bank6_w)
|
||||||
|
AM_RANGE(3, 3) AM_WRITE(bank4_w)
|
||||||
|
AM_RANGE(4, 4) AM_WRITE(banka_w)
|
||||||
|
AM_RANGE(5, 5) AM_WRITE(firq_scanline_w)
|
||||||
|
AM_RANGE(6, 6) AM_WRITE(bank8_w)
|
||||||
|
AM_RANGE(7, 7) AM_WRITE(visible_page_w)
|
||||||
|
ADDRESS_MAP_END
|
||||||
|
|
||||||
|
static MACHINE_CONFIG_FRAGMENT( wpc_dmd )
|
||||||
|
MCFG_SCREEN_ADD("screen", LCD)
|
||||||
|
MCFG_SCREEN_REFRESH_RATE(60)
|
||||||
|
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500))
|
||||||
|
MCFG_SCREEN_UPDATE_DEVICE(DEVICE_SELF, wpc_dmd_device, screen_update)
|
||||||
|
MCFG_SCREEN_SIZE(128*4, 32*4)
|
||||||
|
MCFG_SCREEN_VISIBLE_AREA(0, 128*4-1, 0, 32*4-1)
|
||||||
|
MCFG_DEFAULT_LAYOUT(layout_lcd)
|
||||||
|
|
||||||
|
MCFG_TIMER_DRIVER_ADD_PERIODIC("scanline", wpc_dmd_device, scanline_timer, attotime::from_hz(60*4*32))
|
||||||
|
MACHINE_CONFIG_END
|
||||||
|
|
||||||
|
|
||||||
|
wpc_dmd_device::wpc_dmd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
|
||||||
|
device_t(mconfig, WPC_DMD, "Williams Pinball Controller Dot Matrix Display", tag, owner, clock, "wpc_dmd", __FILE__),
|
||||||
|
scanline_cb(*this),
|
||||||
|
dmd0(*this, ":dmd0"),
|
||||||
|
dmd2(*this, ":dmd2"),
|
||||||
|
dmd4(*this, ":dmd4"),
|
||||||
|
dmd6(*this, ":dmd6"),
|
||||||
|
dmd8(*this, ":dmd8"),
|
||||||
|
dmda(*this, ":dmda")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
wpc_dmd_device::~wpc_dmd_device()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
machine_config_constructor wpc_dmd_device::device_mconfig_additions() const
|
||||||
|
{
|
||||||
|
return MACHINE_CONFIG_NAME( wpc_dmd );
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_dmd_device::device_start()
|
||||||
|
{
|
||||||
|
scanline_cb.resolve_safe();
|
||||||
|
|
||||||
|
ram.resize(0x2000);
|
||||||
|
screen_buffer.resize(128*32);
|
||||||
|
bitcounts.resize(256);
|
||||||
|
|
||||||
|
dmd0->configure_entries(0, 0x10, ram, 0x200);
|
||||||
|
dmd2->configure_entries(0, 0x10, ram, 0x200);
|
||||||
|
dmd4->configure_entries(0, 0x10, ram, 0x200);
|
||||||
|
dmd6->configure_entries(0, 0x10, ram, 0x200);
|
||||||
|
dmd8->configure_entries(0, 0x10, ram, 0x200);
|
||||||
|
dmda->configure_entries(0, 0x10, ram, 0x200);
|
||||||
|
|
||||||
|
memset(ram, 0x00, 0x2000);
|
||||||
|
|
||||||
|
for(int i=0; i<256; i++) {
|
||||||
|
int bc = i;
|
||||||
|
bc = ((bc & 0xaa) >> 1) + (bc & 0x55);
|
||||||
|
bc = ((bc & 0xcc) >> 2) + (bc & 0x33);
|
||||||
|
bc = ((bc & 0xf0) >> 4) + (bc & 0x0f);
|
||||||
|
bitcounts[i] = bc;
|
||||||
|
}
|
||||||
|
|
||||||
|
save_item(NAME(visible_page));
|
||||||
|
save_item(NAME(cur_scanline));
|
||||||
|
save_item(NAME(firq_scanline));
|
||||||
|
save_item(NAME(ram));
|
||||||
|
save_item(NAME(screen_buffer));
|
||||||
|
save_item(NAME(bitcounts));
|
||||||
|
}
|
||||||
|
|
||||||
|
void wpc_dmd_device::device_reset()
|
||||||
|
{
|
||||||
|
dmd0->set_entry(0);
|
||||||
|
dmd2->set_entry(1);
|
||||||
|
dmd4->set_entry(2);
|
||||||
|
dmd6->set_entry(3);
|
||||||
|
dmd8->set_entry(4);
|
||||||
|
dmda->set_entry(5);
|
||||||
|
|
||||||
|
memset(screen_buffer, 0x00, 128*32);
|
||||||
|
visible_page = 0;
|
||||||
|
firq_scanline = 0;
|
||||||
|
cur_scanline = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 wpc_dmd_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||||
|
{
|
||||||
|
const UINT8 *src = screen_buffer;
|
||||||
|
for(int y=0; y<32; y++) {
|
||||||
|
UINT32 *pix0 = reinterpret_cast<UINT32 *>(bitmap.raw_pixptr(y*4));
|
||||||
|
UINT32 *pix1 = reinterpret_cast<UINT32 *>(bitmap.raw_pixptr(y*4+1));
|
||||||
|
UINT32 *pix2 = reinterpret_cast<UINT32 *>(bitmap.raw_pixptr(y*4+2));
|
||||||
|
UINT32 *pix3 = reinterpret_cast<UINT32 *>(bitmap.raw_pixptr(y*4+3));
|
||||||
|
for(int x=0; x<128; x++) {
|
||||||
|
UINT8 v = bitcounts[*src++ & 0x3f];
|
||||||
|
UINT8 v0 = v < 2 ? 0 : v-2;
|
||||||
|
UINT8 v1 = v < 1 ? 0 : v-1;
|
||||||
|
UINT8 v2 = v > 5 ? 5 : v;
|
||||||
|
v0 = 255*v0/5;
|
||||||
|
v1 = 255*v1/5;
|
||||||
|
v2 = 255*v2/5;
|
||||||
|
|
||||||
|
UINT32 xv0 = (v0 << 16) | (v0 << 8);
|
||||||
|
UINT32 xv1 = (v1 << 16) | (v1 << 8);
|
||||||
|
UINT32 xv2 = (v2 << 16) | (v2 << 8);
|
||||||
|
*pix0++ = xv0;
|
||||||
|
*pix0++ = xv1;
|
||||||
|
*pix0++ = xv1;
|
||||||
|
*pix0++ = xv0;
|
||||||
|
|
||||||
|
*pix1++ = xv1;
|
||||||
|
*pix1++ = xv2;
|
||||||
|
*pix1++ = xv2;
|
||||||
|
*pix1++ = xv1;
|
||||||
|
|
||||||
|
*pix2++ = xv1;
|
||||||
|
*pix2++ = xv2;
|
||||||
|
*pix2++ = xv2;
|
||||||
|
*pix2++ = xv1;
|
||||||
|
|
||||||
|
*pix3++ = xv0;
|
||||||
|
*pix3++ = xv1;
|
||||||
|
*pix3++ = xv1;
|
||||||
|
*pix3++ = xv0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TIMER_DEVICE_CALLBACK_MEMBER(wpc_dmd_device::scanline_timer)
|
||||||
|
{
|
||||||
|
const UINT8 *src = ram + 0x200*(visible_page & 0xf) + 16*cur_scanline;
|
||||||
|
UINT8 *base = &screen_buffer[128*cur_scanline];
|
||||||
|
|
||||||
|
for(int x1=0; x1<16; x1++) {
|
||||||
|
UINT8 v = *src++;
|
||||||
|
for(int x2=0; x2<8; x2++) {
|
||||||
|
*base = (*base << 1) | ((v & (0x01 << x2)) ? 1 : 0);
|
||||||
|
base++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_scanline = (cur_scanline+1) & 0x1f;
|
||||||
|
scanline_cb(cur_scanline == (firq_scanline & 0x1f));
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER(wpc_dmd_device::firq_scanline_w)
|
||||||
|
{
|
||||||
|
firq_scanline = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER(wpc_dmd_device::bank0_w)
|
||||||
|
{
|
||||||
|
dmd0->set_entry(data & 0xf);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER(wpc_dmd_device::bank2_w)
|
||||||
|
{
|
||||||
|
dmd2->set_entry(data & 0xf);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER(wpc_dmd_device::bank4_w)
|
||||||
|
{
|
||||||
|
dmd4->set_entry(data & 0xf);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER(wpc_dmd_device::bank6_w)
|
||||||
|
{
|
||||||
|
dmd6->set_entry(data & 0xf);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER(wpc_dmd_device::bank8_w)
|
||||||
|
{
|
||||||
|
dmd8->set_entry(data & 0xf);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER(wpc_dmd_device::banka_w)
|
||||||
|
{
|
||||||
|
dmda->set_entry(data & 0xf);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE8_MEMBER(wpc_dmd_device::visible_page_w)
|
||||||
|
{
|
||||||
|
visible_page = data;
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
// license:BSD-3-Clause
|
||||||
|
// copyright-holders:Olivier Galibert
|
||||||
|
|
||||||
|
// Williams Pinball Controller Dot Matrix Display
|
||||||
|
|
||||||
|
// A 128x32 plasma display with 16 pages and refreshed at 240Hz (for PWM luminosity control)
|
||||||
|
|
||||||
|
#ifndef WPC_DMD_H
|
||||||
|
#define WPC_DMD_H
|
||||||
|
|
||||||
|
#define MCFG_WPC_DMD_ADD( _tag, _scanline_cb ) \
|
||||||
|
MCFG_DEVICE_ADD( _tag, WPC_DMD, 0 ) \
|
||||||
|
devcb = &wpc_dmd_device::set_scanline_cb(*device, DEVCB_##_scanline_cb);
|
||||||
|
|
||||||
|
class wpc_dmd_device : public device_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
wpc_dmd_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
|
virtual ~wpc_dmd_device();
|
||||||
|
|
||||||
|
DECLARE_ADDRESS_MAP(registers, 8);
|
||||||
|
|
||||||
|
DECLARE_WRITE8_MEMBER(bank0_w);
|
||||||
|
DECLARE_WRITE8_MEMBER(bank2_w);
|
||||||
|
DECLARE_WRITE8_MEMBER(bank4_w);
|
||||||
|
DECLARE_WRITE8_MEMBER(bank6_w);
|
||||||
|
DECLARE_WRITE8_MEMBER(bank8_w);
|
||||||
|
DECLARE_WRITE8_MEMBER(banka_w);
|
||||||
|
DECLARE_WRITE8_MEMBER(visible_page_w);
|
||||||
|
DECLARE_WRITE8_MEMBER(firq_scanline_w);
|
||||||
|
|
||||||
|
TIMER_DEVICE_CALLBACK_MEMBER(scanline_timer);
|
||||||
|
UINT32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||||
|
|
||||||
|
template<class _Object> static devcb_base &set_scanline_cb(device_t &device, _Object object) { return downcast<wpc_dmd_device &>(device).scanline_cb.set_callback(object); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
devcb_write_line scanline_cb;
|
||||||
|
required_memory_bank dmd0, dmd2, dmd4, dmd6, dmd8, dmda;
|
||||||
|
|
||||||
|
UINT8 cur_scanline, visible_page, firq_scanline;
|
||||||
|
dynamic_array<UINT8> ram, screen_buffer, bitcounts;
|
||||||
|
|
||||||
|
virtual void device_start();
|
||||||
|
virtual void device_reset();
|
||||||
|
virtual machine_config_constructor device_mconfig_additions() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const device_type WPC_DMD;
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user