diff --git a/src/mess/audio/dave.c b/src/mess/audio/dave.c index 65220cc6109..d3d29e24f7e 100644 --- a/src/mess/audio/dave.c +++ b/src/mess/audio/dave.c @@ -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(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; -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(static_config()); + if (intf != NULL) + *static_cast(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<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(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--; + } } diff --git a/src/mess/audio/dave.h b/src/mess/audio/dave.h index 9890c98a6a8..0a2a5a1877a 100644 --- a/src/mess/audio/dave.h +++ b/src/mess/audio/dave.h @@ -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__ */ diff --git a/src/mess/drivers/enterp.c b/src/mess/drivers/enterp.c index 8020ce5d124..a7c0f19aaf1 100644 --- a/src/mess/drivers/enterp.c +++ b/src/mess/drivers/enterp.c @@ -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) diff --git a/src/mess/includes/enterp.h b/src/mess/includes/enterp.h index 7d88614233c..8d1197835d9 100644 --- a/src/mess/includes/enterp.h +++ b/src/mess/includes/enterp.h @@ -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 m_maincpu; + required_device m_dave; + required_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 m_maincpu; - required_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);