(MESS) enterp: modernized the Dave sound chip. [Fabio Priuli]

This commit is contained in:
Fabio Priuli 2013-05-29 16:02:15 +00:00
parent 4b43e63aec
commit ee4c06f902
4 changed files with 404 additions and 466 deletions

View File

@ -24,171 +24,110 @@
#define STEP 0x08000
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
struct dave_t
{
devcb_resolved_read8 reg_r;
devcb_resolved_write8 reg_w;
devcb_resolved_write_line int_callback;
unsigned char Regs[32];
/* int latches (used by 1Hz, int1 and int2) */
unsigned long int_latch;
/* int enables */
unsigned long int_enable;
/* int inputs */
unsigned long int_input;
unsigned long int_irq;
/* INTERRUPTS */
/* internal timer */
/* bit 2: 1kHz timer irq */
/* bit 1: 50kHz timer irq */
int timer_irq;
/* 1khz timer - divided into 1kHz, 50Hz and 1Hz timer */
emu_timer *int_timer;
/* state of 1kHz timer */
unsigned long one_khz_state;
/* state of 50Hz timer */
unsigned long fifty_hz_state;
/* counter used to trigger 50Hz from 1kHz timer */
unsigned long fifty_hz_count;
/* counter used to trigger 1Hz from 1kHz timer */
unsigned long one_hz_count;
/* SOUND SYNTHESIS */
int Period[4];
int Count[4];
int level[4];
/* these are used to force channels on/off */
/* if one of the or values is 0x0ff, this means
the volume will be forced on,else it is dependant on
the state of the wave */
int level_or[8];
/* if one of the values is 0x00, this means the
volume is forced off, else it is dependant on the wave */
int level_and[8];
/* these are the current channel volumes in MAME form */
int mame_volumes[8];
/* update step */
int UpdateStep;
sound_stream *sound_stream_var;
/* temp here */
int nick_virq;
};
/***************************************************************************
INLINE FUNCTIONS
***************************************************************************/
INLINE dave_t *get_token(device_t *device)
{
assert(device != NULL);
assert(device->type() == DAVE);
return (dave_t *) downcast<dave_sound_device *>(device)->token();
}
INLINE const dave_interface *get_interface(device_t *device)
{
assert(device != NULL);
assert(device->type() == DAVE);
return (const dave_interface *) device->static_config();
}
/***************************************************************************
PROTOTYPES
***************************************************************************/
static void dave_set_external_int_state(device_t *device, int IntID, int State);
static TIMER_CALLBACK(dave_1khz_callback);
static STREAM_UPDATE(dave_update_sound);
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
/*-------------------------------------------------
DEVICE_START( dave_sound )
-------------------------------------------------*/
const device_type DAVE = &device_creator<dave_sound_device>;
static DEVICE_START( dave_sound )
dave_sound_device::dave_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, DAVE, "Dave", tag, owner, clock),
device_sound_interface(mconfig, *this)
{
int i;
dave_t *dave = get_token(device);
const dave_interface *intf = get_interface(device);
memset(dave, 0, sizeof(*dave));
/* resolve callbacks */
dave->reg_r.resolve(intf->reg_r, *device);
dave->reg_w.resolve(intf->reg_w, *device);
dave->int_callback.resolve(intf->int_callback, *device);
/* temp! */
dave->nick_virq = 0;
/* initialise 1kHz timer */
dave->int_latch = 0;
dave->int_input = 0;
dave->int_enable = 0;
dave->timer_irq = 0;
dave->fifty_hz_state = 0;
dave->one_khz_state = 0;
dave->fifty_hz_count = DAVE_FIFTY_HZ_COUNTER_RELOAD;
dave->one_hz_count = DAVE_ONE_HZ_COUNTER_RELOAD;
device->machine().scheduler().timer_pulse(attotime::from_hz(1000), FUNC(dave_1khz_callback), 0, (void *) device);
for (i=0; i<3; i++)
{
dave->Period[i] = (STEP * device->machine().sample_rate()) / 125000;
dave->Count[i] = (STEP * device->machine().sample_rate()) / 125000;
dave->level[i] = 0;
}
/* dave has 3 tone channels and 1 noise channel.
the volumes are mixed internally and output as left and right volume */
/* 3 tone channels + 1 noise channel */
dave->sound_stream_var = device->machine().sound().stream_alloc(*device, 0, 2, device->machine().sample_rate(), NULL, dave_update_sound);
}
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
//-------------------------------------------------
/*-------------------------------------------------
DEVICE_RESET( dave_sound )
-------------------------------------------------*/
static DEVICE_RESET( dave_sound )
void dave_sound_device::device_config_complete()
{
dave_t *dave = get_token(device);
int i;
// inherit a copy of the static data
const dave_interface *intf = reinterpret_cast<const dave_interface *>(static_config());
if (intf != NULL)
*static_cast<dave_interface *>(this) = *intf;
// or initialize to defaults if none provided
else
{
memset(&m_reg_r_cb, 0, sizeof(m_reg_r_cb));
memset(&m_reg_w_cb, 0, sizeof(m_reg_w_cb));
memset(&m_int_cb, 0, sizeof(m_int_cb));
}
}
for (i = 0; i < 32; i++)
dave->Regs[i] = 0;
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
address_space &space = device->machine().driver_data()->generic_space();
dave_reg_w(device, space, 0x10, 0);
dave_reg_w(device, space, 0x11, 0);
dave_reg_w(device, space, 0x12, 0);
dave_reg_w(device, space, 0x13, 0);
void dave_sound_device::device_start()
{
m_reg_r.resolve(m_reg_r_cb, *this);
m_reg_w.resolve(m_reg_w_cb, *this);
m_int_callback.resolve(m_int_cb, *this);
/* temp! */
m_nick_virq = 0;
/* initialise 1kHz timer */
m_int_latch = 0;
m_int_input = 0;
m_int_enable = 0;
m_timer_irq = 0;
m_fifty_hz_state = 0;
m_one_khz_state = 0;
m_fifty_hz_count = DAVE_FIFTY_HZ_COUNTER_RELOAD;
m_one_hz_count = DAVE_ONE_HZ_COUNTER_RELOAD;
machine().scheduler().timer_pulse(attotime::from_hz(1000), timer_expired_delegate(FUNC(dave_sound_device::dave_1khz_callback),this));
for (int i = 0; i < 3; i++)
{
m_period[i] = (STEP * machine().sample_rate()) / 125000;
m_count[i] = (STEP * machine().sample_rate()) / 125000;
m_level[i] = 0;
}
/* dave has 3 tone channels and 1 noise channel.
the volumes are mixed internally and output as left and right volume */
/* 3 tone channels + 1 noise channel */
m_sound_stream_var = machine().sound().stream_alloc(*this, 0, 2, machine().sample_rate(), this);
save_item(NAME(m_regs));
save_item(NAME(m_int_latch));
save_item(NAME(m_int_enable));
save_item(NAME(m_int_input));
save_item(NAME(m_int_irq));
save_item(NAME(m_timer_irq));
save_item(NAME(m_one_khz_state));
save_item(NAME(m_one_hz_count));
save_item(NAME(m_fifty_hz_state));
save_item(NAME(m_fifty_hz_count));
save_item(NAME(m_period));
save_item(NAME(m_count));
save_item(NAME(m_level));
save_item(NAME(m_level_or));
save_item(NAME(m_level_and));
save_item(NAME(m_mame_volumes));
save_item(NAME(m_nick_virq));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void dave_sound_device::device_reset()
{
for (int i = 0; i < 32; i++)
m_regs[i] = 0;
address_space &space = machine().driver_data()->generic_space();
reg_w(space, 0x10, 0);
reg_w(space, 0x11, 0);
reg_w(space, 0x12, 0);
reg_w(space, 0x13, 0);
}
@ -196,15 +135,14 @@ static DEVICE_RESET( dave_sound )
dave_refresh_ints
-------------------------------------------------*/
static void dave_refresh_ints(device_t *device)
void dave_sound_device::refresh_ints()
{
dave_t *dave = get_token(device);
int int_wanted;
logerror("int latch: %02x enable: %02x input: %02x\n", (int) dave->int_latch, (int) dave->int_enable, (int) dave->int_input);
logerror("int latch: %02x enable: %02x input: %02x\n", (int) m_int_latch, (int) m_int_enable, (int) m_int_input);
int_wanted = ((dave->int_enable<<1) & dave->int_latch) != 0;
dave->int_callback(int_wanted);
int_wanted = ((m_int_enable << 1) & m_int_latch) != 0;
m_int_callback(int_wanted);
}
@ -212,43 +150,37 @@ static void dave_refresh_ints(device_t *device)
dave_refresh_selectable_int
-------------------------------------------------*/
static void dave_refresh_selectable_int(device_t *device)
void dave_sound_device::refresh_selectable_int()
{
dave_t *dave = get_token(device);
/* update 1kHz/50Hz/tg latch and int input */
switch ((dave->Regs[7]>>5) & 0x03)
switch ((m_regs[7]>>5) & 0x03)
{
/* 1kHz */
case 0:
{
dave->int_latch &=~(1<<1);
dave->int_latch |= (dave->int_irq>>1) & 0x02;
m_int_latch &= ~(1<<1);
m_int_latch |= (m_int_irq >> 1) & 0x02;
/* set int input state */
dave->int_input &= ~(1<<0);
dave->int_input |= (dave->one_khz_state & 0x01)<<0;
}
break;
m_int_input &= ~(1<<0);
m_int_input |= (m_one_khz_state & 0x01) << 0;
break;
/* 50Hz */
case 1:
{
dave->int_latch &=~(1<<1);
dave->int_latch |= dave->int_irq & 0x02;
m_int_latch &= ~(1<<1);
m_int_latch |= m_int_irq & 0x02;
/* set int input state */
dave->int_input &= ~(1<<0);
dave->int_input |= (dave->fifty_hz_state & 0x01)<<0;
}
break;
m_int_input &= ~(1<<0);
m_int_input |= (m_fifty_hz_state & 0x01) << 0;
break;
default:
break;
}
dave_refresh_ints(device);
refresh_ints();
}
@ -256,147 +188,56 @@ static void dave_refresh_selectable_int(device_t *device)
dave_1khz_callback
-------------------------------------------------*/
static TIMER_CALLBACK(dave_1khz_callback)
TIMER_CALLBACK_MEMBER(dave_sound_device::dave_1khz_callback)
{
device_t *device = (device_t *)ptr;
dave_t *dave = get_token(device);
/* time over - want int */
dave->one_khz_state ^= 0x0ffffffff;
m_one_khz_state ^= 0x0ffffffff;
/* lo-high transition causes int */
if (dave->one_khz_state!=0)
if (m_one_khz_state != 0)
{
dave->int_irq |=(1<<2);
m_int_irq |= (1<<2);
}
/* update fifty Hz counter */
dave->fifty_hz_count--;
m_fifty_hz_count--;
if (dave->fifty_hz_count==0)
if (m_fifty_hz_count == 0)
{
/* these two lines are temp here */
dave->nick_virq ^= 0x0ffffffff;
dave_set_external_int_state(device, DAVE_INT1_ID, dave->nick_virq);
m_nick_virq ^= 0x0ffffffff;
set_external_int_state(DAVE_INT1_ID, m_nick_virq);
dave->fifty_hz_count = DAVE_FIFTY_HZ_COUNTER_RELOAD;
dave->fifty_hz_state^=0x0ffffffff;
m_fifty_hz_count = DAVE_FIFTY_HZ_COUNTER_RELOAD;
m_fifty_hz_state ^= 0x0ffffffff;
if (dave->fifty_hz_state!=0)
if (m_fifty_hz_state != 0)
{
dave->int_irq |= (1<<1);
m_int_irq |= (1<<1);
}
}
dave->one_hz_count--;
m_one_hz_count--;
if (dave->one_hz_count==0)
if (m_one_hz_count == 0)
{
/* reload counter */
dave->one_hz_count = DAVE_ONE_HZ_COUNTER_RELOAD;
m_one_hz_count = DAVE_ONE_HZ_COUNTER_RELOAD;
/* change state */
dave->int_input ^= (1<<2);
m_int_input ^= (1<<2);
if (dave->int_input & (1<<2))
if (m_int_input & (1<<2))
{
/* transition from 0->1 */
/* int requested */
dave->int_latch |=(1<<3);
m_int_latch |=(1<<3);
}
}
dave_refresh_selectable_int(device);
}
/*-------------------------------------------------
dave_update_sound
-------------------------------------------------*/
static STREAM_UPDATE( dave_update_sound )
{
dave_t *dave = get_token(device);
stream_sample_t *buffer1, *buffer2;
/* 0 = channel 0 left volume, 1 = channel 0 right volume,
2 = channel 1 left volume, 3 = channel 1 right volume,
4 = channel 2 left volume, 5 = channel 2 right volume
6 = noise channel left volume, 7 = noise channel right volume */
int output_volumes[8];
int left_volume;
int right_volume;
//logerror("sound update!\n");
buffer1 = outputs[0];
buffer2 = outputs[1];
while (samples)
{
int vol[4];
int i;
/* vol[] keeps track of how long each square wave stays */
/* in the 1 position during the sample period. */
vol[0] = vol[1] = vol[2] = vol[3] = 0;
for (i = 0;i < 3;i++)
{
if ((dave->Regs[7] & (1<<i))==0)
{
if (dave->level[i]) vol[i] += dave->Count[i];
dave->Count[i] -= STEP;
/* Period[i] is the half period of the square wave. Here, in each */
/* loop I add Period[i] twice, so that at the end of the loop the */
/* square wave is in the same status (0 or 1) it was at the start. */
/* vol[i] is also incremented by Period[i], since the wave has been 1 */
/* exactly half of the time, regardless of the initial position. */
/* If we exit the loop in the middle, Output[i] has to be inverted */
/* and vol[i] incremented only if the exit status of the square */
/* wave is 1. */
while (dave->Count[i] <= 0)
{
dave->Count[i] += dave->Period[i];
if (dave->Count[i] > 0)
{
dave->level[i] ^= 0x0ffffffff;
if (dave->level[i]) vol[i] += dave->Period[i];
break;
}
dave->Count[i] += dave->Period[i];
vol[i] += dave->Period[i];
}
if (dave->level[i])
vol[i] -= dave->Count[i];
}
}
/* update volume outputs */
/* setup output volumes for each channel */
/* channel 0 */
output_volumes[0] = ((dave->level[0] & dave->level_and[0]) | dave->level_or[0]) & dave->mame_volumes[0];
output_volumes[1] = ((dave->level[0] & dave->level_and[1]) | dave->level_or[1]) & dave->mame_volumes[4];
/* channel 1 */
output_volumes[2] = ((dave->level[1] & dave->level_and[2]) | dave->level_or[2]) & dave->mame_volumes[1];
output_volumes[3] = ((dave->level[1] & dave->level_and[3]) | dave->level_or[3]) & dave->mame_volumes[5];
/* channel 2 */
output_volumes[4] = ((dave->level[2] & dave->level_and[4]) | dave->level_or[4]) & dave->mame_volumes[2];
output_volumes[5] = ((dave->level[2] & dave->level_and[5]) | dave->level_or[5]) & dave->mame_volumes[6];
/* channel 3 */
output_volumes[6] = ((dave->level[3] & dave->level_and[6]) | dave->level_or[6]) & dave->mame_volumes[3];
output_volumes[7] = ((dave->level[3] & dave->level_and[7]) | dave->level_or[7]) & dave->mame_volumes[7];
left_volume = (output_volumes[0] + output_volumes[2] + output_volumes[4] + output_volumes[6])>>2;
right_volume = (output_volumes[1] + output_volumes[3] + output_volumes[5] + output_volumes[7])>>2;
*(buffer1++) = left_volume;
*(buffer2++) = right_volume;
samples--;
}
refresh_selectable_int();
}
@ -405,12 +246,10 @@ static STREAM_UPDATE( dave_update_sound )
based on data writes
-------------------------------------------------*/
static WRITE8_DEVICE_HANDLER(dave_sound_w)
WRITE8_MEMBER(dave_sound_device::sound_w)
{
dave_t *dave = get_token(device);
/* update stream */
dave->sound_stream_var->update();
m_sound_stream_var->update();
/* new write */
switch (offset)
@ -438,13 +277,13 @@ static WRITE8_DEVICE_HANDLER(dave_sound_w)
{
case 0:
{
count = (data & 0x0ff) | ((dave->Regs[offset+1] & 0x0f)<<8);
count = (data & 0x0ff) | ((m_regs[offset + 1] & 0x0f)<<8);
}
break;
case 1:
{
count = (dave->Regs[offset-1] & 0x0ff) | ((data & 0x0f)<<8);
count = (m_regs[offset - 1] & 0x0ff) | ((data & 0x0f)<<8);
}
break;
@ -453,7 +292,7 @@ static WRITE8_DEVICE_HANDLER(dave_sound_w)
count++;
dave->Period[channel_index] = ((STEP * space.machine().sample_rate())/125000) * count;
m_period[channel_index] = ((STEP * machine().sample_rate())/125000) * count;
}
break;
@ -478,7 +317,7 @@ static WRITE8_DEVICE_HANDLER(dave_sound_w)
/* update mame version of volume from data written */
/* 0x03f->0x07e00. Max is 0x07fff */
/* I believe the volume is linear - to be checked! */
dave->mame_volumes[offset-8] = (data & 0x03f)<<9;
m_mame_volumes[offset - 8] = (data & 0x03f) << 9;
}
break;
@ -525,76 +364,76 @@ static WRITE8_DEVICE_HANDLER(dave_sound_w)
if (data & (1<<3))
{
/* force r8 value */
dave->level_or[0] = 0x0ffff;
dave->level_and[0] = 0x00;
m_level_or[0] = 0x0ffff;
m_level_and[0] = 0x00;
/* remove r9 value */
dave->level_or[2] = 0x000;
dave->level_and[2] = 0x00;
m_level_or[2] = 0x000;
m_level_and[2] = 0x00;
/* remove r10 value */
dave->level_or[4] = 0x000;
dave->level_and[4] = 0x00;
m_level_or[4] = 0x000;
m_level_and[4] = 0x00;
/* remove r11 value */
dave->level_or[6] = 0x000;
dave->level_and[6] = 0x00;
m_level_or[6] = 0x000;
m_level_and[6] = 0x00;
}
else
{
/* use r8 value */
dave->level_or[0] = 0x000;
dave->level_and[0] = 0xffff;
m_level_or[0] = 0x000;
m_level_and[0] = 0xffff;
/* use r9 value */
dave->level_or[2] = 0x000;
dave->level_and[2] = 0xffff;
m_level_or[2] = 0x000;
m_level_and[2] = 0xffff;
/* use r10 value */
dave->level_or[4] = 0x000;
dave->level_and[4] = 0xffff;
m_level_or[4] = 0x000;
m_level_and[4] = 0xffff;
/* use r11 value */
dave->level_or[6] = 0x000;
dave->level_and[6] = 0xffff;
m_level_or[6] = 0x000;
m_level_and[6] = 0xffff;
}
/* turn L.H audio output into D/A, outputting value in R12 */
if (data & (1<<4))
{
/* force r12 value */
dave->level_or[1] = 0x0ffff;
dave->level_and[1] = 0x00;
m_level_or[1] = 0x0ffff;
m_level_and[1] = 0x00;
/* remove r13 value */
dave->level_or[3] = 0x000;
dave->level_and[3] = 0x00;
m_level_or[3] = 0x000;
m_level_and[3] = 0x00;
/* remove r14 value */
dave->level_or[5] = 0x000;
dave->level_and[5] = 0x00;
m_level_or[5] = 0x000;
m_level_and[5] = 0x00;
/* remove r15 value */
dave->level_or[7] = 0x000;
dave->level_and[7] = 0x00;
m_level_or[7] = 0x000;
m_level_and[7] = 0x00;
}
else
{
/* use r12 value */
dave->level_or[1] = 0x000;
dave->level_and[1] = 0xffff;
m_level_or[1] = 0x000;
m_level_and[1] = 0xffff;
/* use r13 value */
dave->level_or[3] = 0x000;
dave->level_and[3] = 0xffff;
m_level_or[3] = 0x000;
m_level_and[3] = 0xffff;
/* use r14 value */
dave->level_or[5] = 0x000;
dave->level_and[5] = 0xffff;
m_level_or[5] = 0x000;
m_level_and[5] = 0xffff;
/* use r15 value */
dave->level_or[7] = 0x000;
dave->level_and[7] = 0xffff;
m_level_or[7] = 0x000;
m_level_and[7] = 0xffff;
}
}
break;
@ -609,47 +448,41 @@ static WRITE8_DEVICE_HANDLER(dave_sound_w)
dave_reg_w
-------------------------------------------------*/
WRITE8_DEVICE_HANDLER ( dave_reg_w )
WRITE8_MEMBER( dave_sound_device::reg_w )
{
dave_t *dave = get_token(device);
logerror("dave w: %04x %02x\n",offset,data);
dave_sound_w(device, space, offset, data, mem_mask);
sound_w(space, offset, data, mem_mask);
dave->Regs[offset & 0x01f] = data;
m_regs[offset & 0x01f] = data;
switch (offset)
{
case 0x07:
{
dave_refresh_selectable_int(device);
}
break;
refresh_selectable_int();
break;
case 0x014:
{
/* enabled ints */
dave->int_enable = data & 0x055;
m_int_enable = data & 0x055;
/* clear latches */
dave->int_latch &=~(data & 0x0aa);
m_int_latch &=~(data & 0x0aa);
/* reset 1kHz, 50Hz latch */
if (data & (1<<1))
{
dave->int_irq = 0;
m_int_irq = 0;
}
/* refresh ints */
dave_refresh_ints(device);
}
break;
refresh_ints();
break;
default:
break;
}
dave->reg_w(offset, data);
m_reg_w(offset, data);
}
@ -657,10 +490,9 @@ WRITE8_DEVICE_HANDLER ( dave_reg_w )
dave_set_reg
-------------------------------------------------*/
void dave_set_reg(device_t *device, offs_t offset, UINT8 data)
void dave_sound_device::set_reg(offs_t offset, UINT8 data)
{
dave_t *dave = get_token(device);
dave->Regs[offset & 0x01f] = data;
m_regs[offset & 0x01f] = data;
}
@ -668,13 +500,11 @@ void dave_set_reg(device_t *device, offs_t offset, UINT8 data)
dave_reg_r
-------------------------------------------------*/
READ8_DEVICE_HANDLER( dave_reg_r )
READ8_MEMBER( dave_sound_device::reg_r )
{
dave_t *dave = get_token(device);
logerror("dave r: %04x\n",offset);
dave->reg_r(offset);
m_reg_r(offset);
switch (offset)
{
@ -705,14 +535,14 @@ READ8_DEVICE_HANDLER( dave_reg_r )
return 0x0ff;
case 0x014:
return (dave->int_latch & 0x0aa) | (dave->int_input & 0x055);
return (m_int_latch & 0x0aa) | (m_int_input & 0x055);
default:
break;
}
return dave->Regs[offset & 0x01f];
return m_regs[offset & 0x01f];
}
@ -721,36 +551,34 @@ READ8_DEVICE_HANDLER( dave_reg_r )
triggered
-------------------------------------------------*/
static void dave_set_external_int_state(device_t *device, int IntID, int State)
void dave_sound_device::set_external_int_state(int int_id, int state)
{
dave_t *dave = get_token(device);
switch (IntID)
switch (int_id)
{
/* connected to Nick virq */
case DAVE_INT1_ID:
{
int previous_state;
previous_state = dave->int_input;
previous_state = m_int_input;
dave->int_input &=~(1<<4);
m_int_input &= ~(1<<4);
if (State)
if (state)
{
dave->int_input |=(1<<4);
m_int_input |= (1<<4);
}
if ((previous_state ^ dave->int_input) & (1<<4))
if ((previous_state ^ m_int_input) & (1<<4))
{
/* changed state */
if (dave->int_input & (1<<4))
if (m_int_input & (1<<4))
{
/* int request */
dave->int_latch |= (1<<5);
m_int_latch |= (1<<5);
dave_refresh_ints(device);
refresh_ints();
}
}
@ -761,25 +589,25 @@ static void dave_set_external_int_state(device_t *device, int IntID, int State)
{
int previous_state;
previous_state = dave->int_input;
previous_state = m_int_input;
dave->int_input &= ~(1<<6);
m_int_input &= ~(1<<6);
if (State)
if (state)
{
dave->int_input |=(1<<6);
m_int_input |= (1<<6);
}
if ((previous_state ^ dave->int_input) & (1<<6))
if ((previous_state ^ m_int_input) & (1<<6))
{
/* changed state */
if (dave->int_input & (1<<6))
if (m_int_input & (1<<6))
{
/* int request */
dave->int_latch|=(1<<7);
m_int_latch |= (1<<7);
dave_refresh_ints(device);
refresh_ints();
}
}
}
@ -816,49 +644,87 @@ b0 = 1: Enable 1kHz/50Hz/TG latch
const device_type DAVE = &device_creator<dave_sound_device>;
dave_sound_device::dave_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, DAVE, "Dave", tag, owner, clock),
device_sound_interface(mconfig, *this)
{
m_token = global_alloc_clear(dave_t);
}
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
//-------------------------------------------------
void dave_sound_device::device_config_complete()
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void dave_sound_device::device_start()
{
DEVICE_START_NAME( dave_sound )(this);
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void dave_sound_device::device_reset()
{
DEVICE_RESET_NAME( dave_sound )(this);
}
//-------------------------------------------------
// sound_stream_update - handle a stream update
//-------------------------------------------------
void dave_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{
// should never get here
fatalerror("sound_stream_update called; not applicable to legacy sound devices\n");
stream_sample_t *buffer1, *buffer2;
/* 0 = channel 0 left volume, 1 = channel 0 right volume,
2 = channel 1 left volume, 3 = channel 1 right volume,
4 = channel 2 left volume, 5 = channel 2 right volume
6 = noise channel left volume, 7 = noise channel right volume */
int output_volumes[8];
int left_volume;
int right_volume;
//logerror("sound update!\n");
buffer1 = outputs[0];
buffer2 = outputs[1];
while (samples)
{
int vol[4];
/* vol[] keeps track of how long each square wave stays */
/* in the 1 position during the sample period. */
vol[0] = vol[1] = vol[2] = vol[3] = 0;
for (int i = 0; i < 3; i++)
{
if ((m_regs[7] & (1 << i))==0)
{
if (m_level[i]) vol[i] += m_count[i];
m_count[i] -= STEP;
/* Period[i] is the half period of the square wave. Here, in each */
/* loop I add Period[i] twice, so that at the end of the loop the */
/* square wave is in the same status (0 or 1) it was at the start. */
/* vol[i] is also incremented by Period[i], since the wave has been 1 */
/* exactly half of the time, regardless of the initial position. */
/* If we exit the loop in the middle, Output[i] has to be inverted */
/* and vol[i] incremented only if the exit status of the square */
/* wave is 1. */
while (m_count[i] <= 0)
{
m_count[i] += m_period[i];
if (m_count[i] > 0)
{
m_level[i] ^= 0x0ffffffff;
if (m_level[i]) vol[i] += m_period[i];
break;
}
m_count[i] += m_period[i];
vol[i] += m_period[i];
}
if (m_level[i])
vol[i] -= m_count[i];
}
}
/* update volume outputs */
/* setup output volumes for each channel */
/* channel 0 */
output_volumes[0] = ((m_level[0] & m_level_and[0]) | m_level_or[0]) & m_mame_volumes[0];
output_volumes[1] = ((m_level[0] & m_level_and[1]) | m_level_or[1]) & m_mame_volumes[4];
/* channel 1 */
output_volumes[2] = ((m_level[1] & m_level_and[2]) | m_level_or[2]) & m_mame_volumes[1];
output_volumes[3] = ((m_level[1] & m_level_and[3]) | m_level_or[3]) & m_mame_volumes[5];
/* channel 2 */
output_volumes[4] = ((m_level[2] & m_level_and[4]) | m_level_or[4]) & m_mame_volumes[2];
output_volumes[5] = ((m_level[2] & m_level_and[5]) | m_level_or[5]) & m_mame_volumes[6];
/* channel 3 */
output_volumes[6] = ((m_level[3] & m_level_and[6]) | m_level_or[6]) & m_mame_volumes[3];
output_volumes[7] = ((m_level[3] & m_level_and[7]) | m_level_or[7]) & m_mame_volumes[7];
left_volume = (output_volumes[0] + output_volumes[2] + output_volumes[4] + output_volumes[6])>>2;
right_volume = (output_volumes[1] + output_volumes[3] + output_volumes[5] + output_volumes[7])>>2;
*(buffer1++) = left_volume;
*(buffer2++) = right_volume;
samples--;
}
}

View File

@ -10,35 +10,6 @@
#include "devcb.h"
/***************************************************************************
MACROS / CONSTANTS
***************************************************************************/
class dave_sound_device : public device_t,
public device_sound_interface
{
public:
dave_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~dave_sound_device() { global_free(m_token); }
// access to legacy token
void *token() const { assert(m_token != NULL); return m_token; }
protected:
// device-level overrides
virtual void device_config_complete();
virtual void device_start();
virtual void device_reset();
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
private:
// internal state
void *m_token;
};
extern const device_type DAVE;
#define DAVE_INT_SELECTABLE 0
#define DAVE_INT_1KHZ_50HZ_TG 1
#define DAVE_INT_1HZ 2
@ -57,23 +28,110 @@ enum
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
TYPE DEFINITIONS
***************************************************************************/
struct dave_interface
{
devcb_read8 reg_r;
devcb_write8 reg_w;
devcb_write_line int_callback;
devcb_read8 m_reg_r_cb;
devcb_write8 m_reg_w_cb;
devcb_write_line m_int_cb;
};
/***************************************************************************
PROTOTYPES
MACROS / CONSTANTS
***************************************************************************/
void dave_set_reg(device_t *device, offs_t offset, UINT8 data);
DECLARE_READ8_DEVICE_HANDLER ( dave_reg_r );
DECLARE_WRITE8_DEVICE_HANDLER ( dave_reg_w );
class dave_sound_device : public device_t,
public device_sound_interface,
public dave_interface
{
public:
dave_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
~dave_sound_device() {}
DECLARE_WRITE8_MEMBER(reg_w);
DECLARE_READ8_MEMBER(reg_r);
void set_reg(offs_t offset, UINT8 data);
protected:
// device-level overrides
virtual void device_config_complete();
virtual void device_start();
virtual void device_reset();
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
private:
// internal state
devcb_resolved_read8 m_reg_r;
devcb_resolved_write8 m_reg_w;
devcb_resolved_write_line m_int_callback;
TIMER_CALLBACK_MEMBER(dave_1khz_callback);
DECLARE_WRITE8_MEMBER(sound_w);
void refresh_ints();
void refresh_selectable_int();
void set_external_int_state(int int_id, int state);
UINT8 m_regs[32];
/* int latches (used by 1Hz, int1 and int2) */
UINT32 m_int_latch;
/* int enables */
UINT32 m_int_enable;
/* int inputs */
UINT32 m_int_input;
UINT32 m_int_irq;
/* INTERRUPTS */
/* internal timer */
/* bit 2: 1kHz timer irq */
/* bit 1: 50kHz timer irq */
int m_timer_irq;
/* 1khz timer - divided into 1kHz, 50Hz and 1Hz timer */
emu_timer *m_int_timer;
/* state of 1kHz timer */
UINT32 m_one_khz_state;
/* state of 50Hz timer */
UINT32 m_fifty_hz_state;
/* counter used to trigger 50Hz from 1kHz timer */
UINT32 m_fifty_hz_count;
/* counter used to trigger 1Hz from 1kHz timer */
UINT32 m_one_hz_count;
/* SOUND SYNTHESIS */
int m_period[4];
int m_count[4];
int m_level[4];
/* these are used to force channels on/off */
/* if one of the or values is 0x0ff, this means
the volume will be forced on,else it is dependant on
the state of the wave */
int m_level_or[8];
/* if one of the values is 0x00, this means the
volume is forced off, else it is dependant on the wave */
int m_level_and[8];
/* these are the current channel volumes in MAME form */
int m_mame_volumes[8];
/* update step */
int m_update_step;
sound_stream *m_sound_stream_var;
/* temp here */
int m_nick_virq;
};
extern const device_type DAVE;
#endif /* __DAVE_H__ */

View File

@ -17,11 +17,9 @@
#include "emu.h"
#include "cpu/z80/z80.h"
#include "audio/dave.h"
#include "machine/wd17xx.h"
#include "imagedev/flopdrv.h"
#include "formats/basicdsk.h"
#include "machine/ram.h"
#include "includes/enterp.h"
#define ENTERPRISE_XTAL_X1 XTAL_8MHz
@ -117,23 +115,17 @@ WRITE8_MEMBER(ep_state::enterprise_dave_reg_write)
READ8_MEMBER(ep_state::enterprise_dave_reg_read)
{
static const char *const keynames[] =
{
"LINE0", "LINE1", "LINE2", "LINE3", "LINE4",
"LINE5", "LINE6", "LINE7", "LINE8", "LINE9"
};
switch (offset)
{
case 0x015:
/* read keyboard line */
dave_set_reg(machine().device("custom"), 0x015, ioport(keynames[keyboard_line])->read());
m_dave->set_reg(0x015, m_key[keyboard_line]->read());
break;
case 0x016:
{
int ExternalJoystickInputs;
int ExternalJoystickPortInput = ioport("JOY1")->read();
int ExternalJoystickPortInput = m_joy->read();
if (keyboard_line <= 4)
{
@ -144,7 +136,7 @@ READ8_MEMBER(ep_state::enterprise_dave_reg_read)
ExternalJoystickInputs = 1;
}
dave_set_reg(machine().device("custom"), 0x016, (0x0fe | (ExternalJoystickInputs & 0x01)));
m_dave->set_reg(0x016, (0x0fe | (ExternalJoystickInputs & 0x01)));
}
break;
@ -165,6 +157,19 @@ static const dave_interface enterprise_dave_interface =
};
void ep_state::machine_start()
{
m_maincpu->set_input_line_vector(0, 0xff);
for (int i = 0; i < 10; i++)
{
char str[5];
sprintf(str, "LINE%i", i);
m_key[i] = ioport(str);
}
}
void ep_state::machine_reset()
{
m_maincpu->set_input_line_vector(0, 0xff);
@ -247,7 +252,7 @@ static ADDRESS_MAP_START( enterprise_io, AS_IO, 8, ep_state )
AM_RANGE(0x10, 0x13) AM_MIRROR(0x04) AM_DEVREADWRITE_LEGACY("wd1770", wd17xx_r, wd17xx_w)
AM_RANGE(0x18, 0x18) AM_MIRROR(0x04) AM_READWRITE(exdos_card_r, exdos_card_w)
AM_RANGE(0x80, 0x8f) AM_WRITE(epnick_reg_w)
AM_RANGE(0xa0, 0xbf) AM_DEVREADWRITE_LEGACY("custom", dave_reg_r, dave_reg_w)
AM_RANGE(0xa0, 0xbf) AM_DEVREADWRITE("custom", dave_sound_device, reg_r, reg_w)
ADDRESS_MAP_END
@ -441,7 +446,6 @@ static MACHINE_CONFIG_START( ep64, ep_state )
MCFG_CPU_PROGRAM_MAP(enterprise_mem)
MCFG_CPU_IO_MAP(enterprise_io)
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_REFRESH_RATE(50)
@ -452,7 +456,6 @@ static MACHINE_CONFIG_START( ep64, ep_state )
MCFG_PALETTE_LENGTH(NICK_PALETTE_SIZE)
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("custom", DAVE, 0)

View File

@ -14,6 +14,8 @@
#define NICK_PALETTE_SIZE 256
#include "machine/ram.h"
#include "audio/dave.h"
struct NICK_STATE;
class ep_state : public driver_device
@ -22,15 +24,26 @@ public:
ep_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_ram(*this, RAM_TAG) { }
m_dave(*this, "custom"),
m_ram(*this, RAM_TAG),
m_joy(*this, "JOY1") { }
required_device<cpu_device> m_maincpu;
required_device<dave_sound_device> m_dave;
required_device<ram_device> m_ram;
required_ioport m_joy;
UINT8 exdos_card_value; /* state of the wd1770 irq/drq lines */
UINT8 keyboard_line; /* index of keyboard line to read */
bitmap_ind16 m_bitmap;
NICK_STATE *nick;
ioport_port *m_key[10];
DECLARE_READ8_MEMBER(exdos_card_r);
DECLARE_WRITE8_MEMBER(exdos_card_w);
DECLARE_WRITE8_MEMBER(epnick_reg_w);
virtual void machine_start();
virtual void machine_reset();
virtual void video_start();
virtual void palette_init();
@ -39,8 +52,6 @@ public:
DECLARE_READ8_MEMBER(enterprise_dave_reg_read);
DECLARE_WRITE_LINE_MEMBER(enterp_wd1770_intrq_w);
DECLARE_WRITE_LINE_MEMBER(enterp_wd1770_drq_w);
required_device<cpu_device> m_maincpu;
required_device<ram_device> m_ram;
void enterprise_update_memory_page(address_space &space, offs_t page, int index);
char Nick_FetchByte(unsigned long Addr);
void nick_write_pixel(int ci);