From 14efb71aa4e00561f45efec43965852daa48aee4 Mon Sep 17 00:00:00 2001 From: hap Date: Thu, 17 Oct 2024 14:12:33 +0200 Subject: source org: move dedicated dave soundchip to enterprise folder --- scripts/src/sound.lua | 12 - src/devices/sound/dave.cpp | 620 ------------------------------------------- src/devices/sound/dave.h | 119 --------- src/mame/enterprise/dave.cpp | 619 ++++++++++++++++++++++++++++++++++++++++++ src/mame/enterprise/dave.h | 117 ++++++++ src/mame/enterprise/ep64.cpp | 4 +- src/mame/enterprise/nick.cpp | 36 ++- src/mame/enterprise/nick.h | 1 + 8 files changed, 755 insertions(+), 773 deletions(-) delete mode 100644 src/devices/sound/dave.cpp delete mode 100644 src/devices/sound/dave.h create mode 100644 src/mame/enterprise/dave.cpp create mode 100644 src/mame/enterprise/dave.h diff --git a/scripts/src/sound.lua b/scripts/src/sound.lua index 054d87a266f..06589a4fad9 100644 --- a/scripts/src/sound.lua +++ b/scripts/src/sound.lua @@ -1466,18 +1466,6 @@ if (SOUNDS["MM5837"]~=null) then } end ---------------------------------------------------- --- Intelligent Designs DAVE ---@src/devices/sound/dave.h,SOUNDS["DAVE"] = true ---------------------------------------------------- - -if (SOUNDS["DAVE"]~=null) then - files { - MAME_DIR .. "src/devices/sound/dave.cpp", - MAME_DIR .. "src/devices/sound/dave.h", - } -end - --------------------------------------------------- -- Toshiba TA7630 --@src/devices/sound/ta7630.h,SOUNDS["TA7630"] = true diff --git a/src/devices/sound/dave.cpp b/src/devices/sound/dave.cpp deleted file mode 100644 index e56fa34bd64..00000000000 --- a/src/devices/sound/dave.cpp +++ /dev/null @@ -1,620 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Curt Coder -/********************************************************************** - - Intelligent Designs DAVE emulation - -**********************************************************************/ - -#include "emu.h" -#include "dave.h" - -//#define VERBOSE 1 -#include "logmacro.h" - - -//************************************************************************** -// MACROS / CONSTANTS -//************************************************************************** - -#define STEP 0x08000 - - - -//************************************************************************** -// DEVICE DEFINITIONS -//************************************************************************** - -DEFINE_DEVICE_TYPE(DAVE, dave_device, "dave", "Intelligent Designs DAVE") - - -void dave_device::z80_program_map(address_map &map) -{ - map(0x0000, 0xffff).rw(FUNC(dave_device::program_r), FUNC(dave_device::program_w)); -} - -void dave_device::z80_io_map(address_map &map) -{ - map(0x0000, 0xffff).rw(FUNC(dave_device::io_r), FUNC(dave_device::io_w)); -} - - -void dave_device::program_map(address_map &map) -{ -} - -void dave_device::io_map(address_map &map) -{ -} - - - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - -//------------------------------------------------- -// dave_device - constructor -//------------------------------------------------- - -dave_device::dave_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, DAVE, tag, owner, clock), - device_memory_interface(mconfig, *this), - device_sound_interface(mconfig, *this), - m_program_space_config("program", ENDIANNESS_LITTLE, 8, 22, 0, address_map_constructor(FUNC(dave_device::program_map), this)), - m_io_space_config("io", ENDIANNESS_LITTLE, 8, 16, 0, address_map_constructor(FUNC(dave_device::io_map), this)), - m_write_irq(*this), - m_write_lh(*this), - m_write_rh(*this), - m_irq_status(0) -{ -} - - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void dave_device::device_start() -{ - // allocate timers - m_timer_1hz = timer_alloc(FUNC(dave_device::update_1hz_timer), this); - m_timer_1hz->adjust(attotime::from_hz(2), 0, attotime::from_hz(2)); - - m_timer_50hz = timer_alloc(FUNC(dave_device::update_50hz_timer), this); - m_timer_50hz->adjust(attotime::from_hz(2000), 0, attotime::from_hz(2000)); - - // state saving - save_item(NAME(m_segment)); - save_item(NAME(m_irq_status)); - save_item(NAME(m_irq_enable)); - 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)); - - for (auto & elem : m_period) - elem = (STEP * machine().sample_rate()) / 125000; - - for (auto & elem : m_count) - elem = (STEP * machine().sample_rate()) / 125000; - - for (auto & elem : m_level) - elem = 0; - - for (auto & elem : m_level_or) - elem = 0; - - for (auto & elem : m_level_and) - elem = 0; - - for (auto & elem : m_mame_volumes) - elem = 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 = stream_alloc(0, 2, machine().sample_rate()); -} - - -//------------------------------------------------- -// device_reset - device-specific reset -//------------------------------------------------- - -void dave_device::device_reset() -{ - m_write_irq(CLEAR_LINE); - - for (auto & elem : m_segment) - elem = 0; - - m_irq_status = 0; - m_irq_enable = 0; - - for (auto & elem : m_regs) - elem = 0; -} - - -//------------------------------------------------- -// update_1hz_timer - -//------------------------------------------------- - -TIMER_CALLBACK_MEMBER(dave_device::update_1hz_timer) -{ - m_irq_status ^= IRQ_1HZ_DIVIDER; - - if (m_irq_status & IRQ_1HZ_DIVIDER) - m_irq_status |= IRQ_1HZ_LATCH; - - update_interrupt(); -} - - -//------------------------------------------------- -// update_50hz_timer - -//------------------------------------------------- - -TIMER_CALLBACK_MEMBER(dave_device::update_50hz_timer) -{ - m_irq_status ^= IRQ_50HZ_DIVIDER; - - if (m_irq_status & IRQ_50HZ_DIVIDER) - m_irq_status |= IRQ_50HZ_LATCH; - - update_interrupt(); -} - - -//------------------------------------------------- -// memory_space_config - return a description of -// any address spaces owned by this device -//------------------------------------------------- - -device_memory_interface::space_config_vector dave_device::memory_space_config() const -{ - return space_config_vector { - std::make_pair(AS_PROGRAM, &m_program_space_config), - std::make_pair(AS_IO, &m_io_space_config) - }; -} - - -//------------------------------------------------- -// sound_stream_update - handle a stream update -//------------------------------------------------- - -void dave_device::sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) -{ - /* 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"); - - auto &buffer1 = outputs[0]; - auto &buffer2 = outputs[1]; - - for (int sampindex = 0; sampindex < buffer1.samples(); sampindex++) - { - 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]; - right_volume = output_volumes[1] + output_volumes[3] + output_volumes[5] + output_volumes[7]; - - buffer1.put_int(sampindex, left_volume, 32768 * 4); - buffer2.put_int(sampindex, right_volume, 32768 * 4); - } -} - - -//------------------------------------------------- -// int1_w - interrupt 1 write -//------------------------------------------------- - -void dave_device::int1_w(int state) -{ - if (!(m_irq_status & IRQ_INT1) && state) - m_irq_status |= IRQ_INT1_LATCH; - - if (state) - m_irq_status |= IRQ_INT1; - else - m_irq_status &= ~IRQ_INT1; - - update_interrupt(); -} - - -//------------------------------------------------- -// int2_w - interrupt 2 write -//------------------------------------------------- - -void dave_device::int2_w(int state) -{ - if (!(m_irq_status & IRQ_INT2) && state) - m_irq_status |= IRQ_INT2_LATCH; - - if (state) - m_irq_status |= IRQ_INT2; - else - m_irq_status &= ~IRQ_INT2; - - update_interrupt(); -} - - -//------------------------------------------------- -// program_r - program space read -//------------------------------------------------- - -uint8_t dave_device::program_r(offs_t offset) -{ - uint8_t segment = m_segment[offset >> 14]; - offset = (segment << 14) | (offset & 0x3fff); - - return this->space(AS_PROGRAM).read_byte(offset); -} - - -//------------------------------------------------- -// program_w - program space write -//------------------------------------------------- - -void dave_device::program_w(offs_t offset, uint8_t data) -{ - uint8_t segment = m_segment[offset >> 14]; - offset = (segment << 14) | (offset & 0x3fff); - - this->space(AS_PROGRAM).write_byte(offset, data); -} - - -//------------------------------------------------- -// io_r - I/O space read -//------------------------------------------------- - -uint8_t dave_device::io_r(offs_t offset) -{ - uint8_t data = 0; - - switch (offset & 0xff) - { - case 0xa0: - case 0xa1: - case 0xa2: - case 0xa3: - case 0xa4: - case 0xa5: - case 0xa6: - case 0xa7: - case 0xa8: - case 0xa9: - case 0xaa: - case 0xab: - case 0xac: - case 0xad: - case 0xae: - case 0xaf: - case 0xb8: - case 0xb9: - case 0xba: - case 0xbb: - case 0xbc: - case 0xbd: - case 0xbe: - case 0xbf: - data = 0xff; - break; - - case 0xb0: case 0xb1: case 0xb2: case 0xb3: - data = m_segment[offset & 0x03]; - break; - - case 0xb4: - data = m_irq_status; - break; - - default: - data = this->space(AS_IO).read_byte(offset); - } - - return data; -} - - -//------------------------------------------------- -// io_w - I/O space write -//------------------------------------------------- - -void dave_device::io_w(offs_t offset, uint8_t data) -{ - switch (offset & 0xff) - { - /* channel 0 down-counter */ - case 0xa0: - case 0xa1: - /* channel 1 down-counter */ - case 0xa2: - case 0xa3: - /* channel 2 down-counter */ - case 0xa4: - case 0xa5: - { - int count = 0; - int channel_index = (offset>>1)&3; - - /* Fout = 125,000 / (n+1) Hz */ - - /* sample rate/clock */ - - - /* get down-count */ - switch (offset & 0x01) - { - case 0: - { - count = (data & 0x0ff) | ((m_regs[(offset & 0x1f) + 1] & 0x0f)<<8); - } - break; - - case 1: - { - count = (m_regs[(offset & 0x1f) - 1] & 0x0ff) | ((data & 0x0f)<<8); - - } - break; - } - - count++; - - - m_period[channel_index] = ((STEP * machine().sample_rate())/125000) * count; - - m_regs[offset & 0x1f] = data; - } - break; - - /* channel 0 left volume */ - case 0xa8: - /* channel 1 left volume */ - case 0xa9: - /* channel 2 left volume */ - case 0xaa: - /* noise channel left volume */ - case 0xab: - /* channel 0 right volume */ - case 0xac: - /* channel 1 right volume */ - case 0xad: - /* channel 2 right volume */ - case 0xae: - /* noise channel right volume */ - case 0xaf: - { - /* update mame version of volume from data written */ - /* 0x03f->0x07e00. Max is 0x07fff */ - /* I believe the volume is linear - to be checked! */ - m_mame_volumes[(offset & 0x1f) - 8] = (data & 0x03f) << 9; - - m_regs[offset & 0x1f] = data; - } - break; - - case 0xa6: - break; - - case 0xa7: - { - /* force => the value of this register is forced regardless of the wave - state, - remove => this value is force to zero so that it has no influence over - the final volume calculation, regardless of wave state - use => the volume value is dependant on the wave state and is included - in the final volume calculation */ - - //logerror("selectable int "); - switch ((data>>5) & 0x03) - { - case 0: - { - //logerror("1kHz\n"); - m_timer_50hz->adjust(attotime::from_hz(2000), 0, attotime::from_hz(2000)); - } - break; - - case 1: - { - //logerror("50Hz\n"); - m_timer_50hz->adjust(attotime::from_hz(100), 0, attotime::from_hz(100)); - } - break; - - case 2: - { - //logerror("tone channel 0\n"); - } - break; - - case 3: - { - //logerror("tone channel 1\n"); - } - break; - } - - - - /* turn L.H audio output into D/A, outputting value in R8 */ - if (data & (1<<3)) - { - /* force r8 value */ - m_level_or[0] = 0x0ffff; - m_level_and[0] = 0x00; - - /* remove r9 value */ - m_level_or[2] = 0x000; - m_level_and[2] = 0x00; - - /* remove r10 value */ - m_level_or[4] = 0x000; - m_level_and[4] = 0x00; - - /* remove r11 value */ - m_level_or[6] = 0x000; - m_level_and[6] = 0x00; - } - else - { - /* use r8 value */ - m_level_or[0] = 0x000; - m_level_and[0] = 0xffff; - - /* use r9 value */ - m_level_or[2] = 0x000; - m_level_and[2] = 0xffff; - - /* use r10 value */ - m_level_or[4] = 0x000; - m_level_and[4] = 0xffff; - - /* use r11 value */ - 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 */ - m_level_or[1] = 0x0ffff; - m_level_and[1] = 0x00; - - /* remove r13 value */ - m_level_or[3] = 0x000; - m_level_and[3] = 0x00; - - /* remove r14 value */ - m_level_or[5] = 0x000; - m_level_and[5] = 0x00; - - /* remove r15 value */ - m_level_or[7] = 0x000; - m_level_and[7] = 0x00; - } - else - { - /* use r12 value */ - m_level_or[1] = 0x000; - m_level_and[1] = 0xffff; - - /* use r13 value */ - m_level_or[3] = 0x000; - m_level_and[3] = 0xffff; - - /* use r14 value */ - m_level_or[5] = 0x000; - m_level_and[5] = 0xffff; - - /* use r15 value */ - m_level_or[7] = 0x000; - m_level_and[7] = 0xffff; - } - - m_regs[offset & 0x1f] = data; - } - break; - - case 0xb0: case 0xb1: case 0xb2: case 0xb3: - m_segment[offset & 0x03] = data; - - m_regs[offset & 0x1f] = data; - break; - - case 0xb4: - m_irq_enable = data; - m_irq_status &= ~(m_irq_enable & IRQ_LATCH); - update_interrupt(); - - m_regs[offset & 0x1f] = data; - break; - - case 0xbf: - m_regs[offset & 0x1f] = data; - break; - - default: - this->space(AS_IO).write_byte(offset, data); - } -} - - -//------------------------------------------------- -// update_interrupt - -//------------------------------------------------- - -void dave_device::update_interrupt() -{ - int state = ((m_irq_status & (m_irq_enable << 1)) & IRQ_LATCH) ? ASSERT_LINE : CLEAR_LINE; - - m_write_irq(state); -} diff --git a/src/devices/sound/dave.h b/src/devices/sound/dave.h deleted file mode 100644 index cb3a6cc4b64..00000000000 --- a/src/devices/sound/dave.h +++ /dev/null @@ -1,119 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Curt Coder -/********************************************************************** - - Intelligent Designs DAVE emulation - -**********************************************************************/ - -#ifndef MAME_SOUND_DAVE_H -#define MAME_SOUND_DAVE_H - -#pragma once - - -///************************************************************************* -// TYPE DEFINITIONS -///************************************************************************* - -// ======================> dave_device - -class dave_device : public device_t, - public device_memory_interface, - public device_sound_interface -{ -public: - dave_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - auto irq_wr() { return m_write_irq.bind(); } - auto lh_wr() { return m_write_lh.bind(); } - auto rh_wr() { return m_write_rh.bind(); } - - virtual void z80_program_map(address_map &map) ATTR_COLD; - virtual void z80_io_map(address_map &map) ATTR_COLD; - - void int1_w(int state); - void int2_w(int state); - - void io_map(address_map &map) ATTR_COLD; - void program_map(address_map &map) ATTR_COLD; -protected: - // device-level overrides - virtual void device_start() override ATTR_COLD; - virtual void device_reset() override ATTR_COLD; - - // device_memory_interface overrides - virtual space_config_vector memory_space_config() const override; - - // sound stream update overrides - virtual void sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) override; - - TIMER_CALLBACK_MEMBER(update_1hz_timer); - TIMER_CALLBACK_MEMBER(update_50hz_timer); - - uint8_t program_r(offs_t offset); - void program_w(offs_t offset, uint8_t data); - - uint8_t io_r(offs_t offset); - void io_w(offs_t offset, uint8_t data); - -private: - enum - { - IRQ_50HZ_DIVIDER = 0x01, - IRQ_50HZ_LATCH = 0x02, - IRQ_1HZ_DIVIDER = 0x04, - IRQ_1HZ_LATCH = 0x08, - IRQ_INT1 = 0x10, - IRQ_INT1_LATCH = 0x20, - IRQ_INT2 = 0x40, - IRQ_INT2_LATCH = 0x80, - IRQ_LATCH = IRQ_INT2_LATCH | IRQ_INT1_LATCH | IRQ_1HZ_LATCH | IRQ_50HZ_LATCH - }; - - void update_interrupt(); - - const address_space_config m_program_space_config; - const address_space_config m_io_space_config; - - devcb_write_line m_write_irq; - devcb_write8 m_write_lh; - devcb_write8 m_write_rh; - - uint8_t m_segment[4]; - - uint8_t m_irq_status; - uint8_t m_irq_enable; - - emu_timer *m_timer_1hz; - emu_timer *m_timer_50hz; - - /* SOUND SYNTHESIS */ - uint8_t m_regs[32]; - 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; -}; - - -// device type definition -DECLARE_DEVICE_TYPE(DAVE, dave_device) - -#endif // MAME_SOUND_DAVE_H diff --git a/src/mame/enterprise/dave.cpp b/src/mame/enterprise/dave.cpp new file mode 100644 index 00000000000..67d5142806a --- /dev/null +++ b/src/mame/enterprise/dave.cpp @@ -0,0 +1,619 @@ +// license:BSD-3-Clause +// copyright-holders:Curt Coder +/********************************************************************** + + Intelligent Designs DAVE emulation + +**********************************************************************/ + +#include "emu.h" +#include "dave.h" + +//#define VERBOSE 1 +#include "logmacro.h" + + +//************************************************************************** +// MACROS / CONSTANTS +//************************************************************************** + +#define STEP 0x08000 + + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(DAVE, dave_device, "dave", "Intelligent Designs DAVE") + + +void dave_device::z80_program_map(address_map &map) +{ + map(0x0000, 0xffff).rw(FUNC(dave_device::program_r), FUNC(dave_device::program_w)); +} + +void dave_device::z80_io_map(address_map &map) +{ + map(0x0000, 0xffff).rw(FUNC(dave_device::io_r), FUNC(dave_device::io_w)); +} + + +void dave_device::program_map(address_map &map) +{ +} + +void dave_device::io_map(address_map &map) +{ +} + + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// dave_device - constructor +//------------------------------------------------- + +dave_device::dave_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, DAVE, tag, owner, clock), + device_memory_interface(mconfig, *this), + device_sound_interface(mconfig, *this), + m_program_space_config("program", ENDIANNESS_LITTLE, 8, 22, 0, address_map_constructor(FUNC(dave_device::program_map), this)), + m_io_space_config("io", ENDIANNESS_LITTLE, 8, 16, 0, address_map_constructor(FUNC(dave_device::io_map), this)), + m_write_irq(*this), + m_write_lh(*this), + m_write_rh(*this), + m_irq_status(0) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void dave_device::device_start() +{ + // allocate timers + m_timer_1hz = timer_alloc(FUNC(dave_device::update_1hz_timer), this); + m_timer_1hz->adjust(attotime::from_hz(2), 0, attotime::from_hz(2)); + + m_timer_50hz = timer_alloc(FUNC(dave_device::update_50hz_timer), this); + m_timer_50hz->adjust(attotime::from_hz(2000), 0, attotime::from_hz(2000)); + + // state saving + save_item(NAME(m_segment)); + save_item(NAME(m_irq_status)); + save_item(NAME(m_irq_enable)); + 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)); + + for (auto & elem : m_period) + elem = (STEP * machine().sample_rate()) / 125000; + + for (auto & elem : m_count) + elem = (STEP * machine().sample_rate()) / 125000; + + for (auto & elem : m_level) + elem = 0; + + for (auto & elem : m_level_or) + elem = 0; + + for (auto & elem : m_level_and) + elem = 0; + + for (auto & elem : m_mame_volumes) + elem = 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 = stream_alloc(0, 2, machine().sample_rate()); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void dave_device::device_reset() +{ + m_write_irq(CLEAR_LINE); + + for (auto & elem : m_segment) + elem = 0; + + m_irq_status = 0; + m_irq_enable = 0; + + for (auto & elem : m_regs) + elem = 0; +} + + +//------------------------------------------------- +// update_1hz_timer - +//------------------------------------------------- + +TIMER_CALLBACK_MEMBER(dave_device::update_1hz_timer) +{ + m_irq_status ^= IRQ_1HZ_DIVIDER; + + if (m_irq_status & IRQ_1HZ_DIVIDER) + m_irq_status |= IRQ_1HZ_LATCH; + + update_interrupt(); +} + + +//------------------------------------------------- +// update_50hz_timer - +//------------------------------------------------- + +TIMER_CALLBACK_MEMBER(dave_device::update_50hz_timer) +{ + m_irq_status ^= IRQ_50HZ_DIVIDER; + + if (m_irq_status & IRQ_50HZ_DIVIDER) + m_irq_status |= IRQ_50HZ_LATCH; + + update_interrupt(); +} + + +//------------------------------------------------- +// memory_space_config - return a description of +// any address spaces owned by this device +//------------------------------------------------- + +device_memory_interface::space_config_vector dave_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(AS_PROGRAM, &m_program_space_config), + std::make_pair(AS_IO, &m_io_space_config) + }; +} + + +//------------------------------------------------- +// sound_stream_update - handle a stream update +//------------------------------------------------- + +void dave_device::sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) +{ + /* 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"); + + auto &buffer1 = outputs[0]; + auto &buffer2 = outputs[1]; + + for (int sampindex = 0; sampindex < buffer1.samples(); sampindex++) + { + 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]; + right_volume = output_volumes[1] + output_volumes[3] + output_volumes[5] + output_volumes[7]; + + buffer1.put_int(sampindex, left_volume, 32768 * 4); + buffer2.put_int(sampindex, right_volume, 32768 * 4); + } +} + + +//------------------------------------------------- +// int1_w - interrupt 1 write +//------------------------------------------------- + +void dave_device::int1_w(int state) +{ + if (!(m_irq_status & IRQ_INT1) && state) + m_irq_status |= IRQ_INT1_LATCH; + + if (state) + m_irq_status |= IRQ_INT1; + else + m_irq_status &= ~IRQ_INT1; + + update_interrupt(); +} + + +//------------------------------------------------- +// int2_w - interrupt 2 write +//------------------------------------------------- + +void dave_device::int2_w(int state) +{ + if (!(m_irq_status & IRQ_INT2) && state) + m_irq_status |= IRQ_INT2_LATCH; + + if (state) + m_irq_status |= IRQ_INT2; + else + m_irq_status &= ~IRQ_INT2; + + update_interrupt(); +} + + +//------------------------------------------------- +// program_r - program space read +//------------------------------------------------- + +uint8_t dave_device::program_r(offs_t offset) +{ + uint8_t segment = m_segment[offset >> 14]; + offset = (segment << 14) | (offset & 0x3fff); + + return this->space(AS_PROGRAM).read_byte(offset); +} + + +//------------------------------------------------- +// program_w - program space write +//------------------------------------------------- + +void dave_device::program_w(offs_t offset, uint8_t data) +{ + uint8_t segment = m_segment[offset >> 14]; + offset = (segment << 14) | (offset & 0x3fff); + + this->space(AS_PROGRAM).write_byte(offset, data); +} + + +//------------------------------------------------- +// io_r - I/O space read +//------------------------------------------------- + +uint8_t dave_device::io_r(offs_t offset) +{ + uint8_t data = 0; + + switch (offset & 0xff) + { + case 0xa0: + case 0xa1: + case 0xa2: + case 0xa3: + case 0xa4: + case 0xa5: + case 0xa6: + case 0xa7: + case 0xa8: + case 0xa9: + case 0xaa: + case 0xab: + case 0xac: + case 0xad: + case 0xae: + case 0xaf: + case 0xb8: + case 0xb9: + case 0xba: + case 0xbb: + case 0xbc: + case 0xbd: + case 0xbe: + case 0xbf: + data = 0xff; + break; + + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + data = m_segment[offset & 0x03]; + break; + + case 0xb4: + data = m_irq_status; + break; + + default: + data = this->space(AS_IO).read_byte(offset); + } + + return data; +} + + +//------------------------------------------------- +// io_w - I/O space write +//------------------------------------------------- + +void dave_device::io_w(offs_t offset, uint8_t data) +{ + switch (offset & 0xff) + { + /* channel 0 down-counter */ + case 0xa0: + case 0xa1: + /* channel 1 down-counter */ + case 0xa2: + case 0xa3: + /* channel 2 down-counter */ + case 0xa4: + case 0xa5: + { + int count = 0; + int channel_index = (offset>>1)&3; + + /* Fout = 125,000 / (n+1) Hz */ + + /* sample rate/clock */ + + + /* get down-count */ + switch (offset & 0x01) + { + case 0: + { + count = (data & 0x0ff) | ((m_regs[(offset & 0x1f) + 1] & 0x0f)<<8); + } + break; + + case 1: + { + count = (m_regs[(offset & 0x1f) - 1] & 0x0ff) | ((data & 0x0f)<<8); + + } + break; + } + + count++; + + + m_period[channel_index] = ((STEP * machine().sample_rate())/125000) * count; + + m_regs[offset & 0x1f] = data; + } + break; + + /* channel 0 left volume */ + case 0xa8: + /* channel 1 left volume */ + case 0xa9: + /* channel 2 left volume */ + case 0xaa: + /* noise channel left volume */ + case 0xab: + /* channel 0 right volume */ + case 0xac: + /* channel 1 right volume */ + case 0xad: + /* channel 2 right volume */ + case 0xae: + /* noise channel right volume */ + case 0xaf: + { + /* update mame version of volume from data written */ + /* 0x03f->0x07e00. Max is 0x07fff */ + /* I believe the volume is linear - to be checked! */ + m_mame_volumes[(offset & 0x1f) - 8] = (data & 0x03f) << 9; + + m_regs[offset & 0x1f] = data; + } + break; + + case 0xa6: + break; + + case 0xa7: + { + /* force => the value of this register is forced regardless of the wave + state, + remove => this value is force to zero so that it has no influence over + the final volume calculation, regardless of wave state + use => the volume value is dependant on the wave state and is included + in the final volume calculation */ + + //logerror("selectable int "); + switch ((data>>5) & 0x03) + { + case 0: + { + //logerror("1kHz\n"); + m_timer_50hz->adjust(attotime::from_hz(2000), 0, attotime::from_hz(2000)); + } + break; + + case 1: + { + //logerror("50Hz\n"); + m_timer_50hz->adjust(attotime::from_hz(100), 0, attotime::from_hz(100)); + } + break; + + case 2: + { + //logerror("tone channel 0\n"); + } + break; + + case 3: + { + //logerror("tone channel 1\n"); + } + break; + } + + + /* turn L.H audio output into D/A, outputting value in R8 */ + if (data & (1<<3)) + { + /* force r8 value */ + m_level_or[0] = 0x0ffff; + m_level_and[0] = 0x00; + + /* remove r9 value */ + m_level_or[2] = 0x000; + m_level_and[2] = 0x00; + + /* remove r10 value */ + m_level_or[4] = 0x000; + m_level_and[4] = 0x00; + + /* remove r11 value */ + m_level_or[6] = 0x000; + m_level_and[6] = 0x00; + } + else + { + /* use r8 value */ + m_level_or[0] = 0x000; + m_level_and[0] = 0xffff; + + /* use r9 value */ + m_level_or[2] = 0x000; + m_level_and[2] = 0xffff; + + /* use r10 value */ + m_level_or[4] = 0x000; + m_level_and[4] = 0xffff; + + /* use r11 value */ + 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 */ + m_level_or[1] = 0x0ffff; + m_level_and[1] = 0x00; + + /* remove r13 value */ + m_level_or[3] = 0x000; + m_level_and[3] = 0x00; + + /* remove r14 value */ + m_level_or[5] = 0x000; + m_level_and[5] = 0x00; + + /* remove r15 value */ + m_level_or[7] = 0x000; + m_level_and[7] = 0x00; + } + else + { + /* use r12 value */ + m_level_or[1] = 0x000; + m_level_and[1] = 0xffff; + + /* use r13 value */ + m_level_or[3] = 0x000; + m_level_and[3] = 0xffff; + + /* use r14 value */ + m_level_or[5] = 0x000; + m_level_and[5] = 0xffff; + + /* use r15 value */ + m_level_or[7] = 0x000; + m_level_and[7] = 0xffff; + } + + m_regs[offset & 0x1f] = data; + } + break; + + case 0xb0: case 0xb1: case 0xb2: case 0xb3: + m_segment[offset & 0x03] = data; + + m_regs[offset & 0x1f] = data; + break; + + case 0xb4: + m_irq_enable = data; + m_irq_status &= ~(m_irq_enable & IRQ_LATCH); + update_interrupt(); + + m_regs[offset & 0x1f] = data; + break; + + case 0xbf: + m_regs[offset & 0x1f] = data; + break; + + default: + this->space(AS_IO).write_byte(offset, data); + } +} + + +//------------------------------------------------- +// update_interrupt - +//------------------------------------------------- + +void dave_device::update_interrupt() +{ + int state = ((m_irq_status & (m_irq_enable << 1)) & IRQ_LATCH) ? ASSERT_LINE : CLEAR_LINE; + + m_write_irq(state); +} diff --git a/src/mame/enterprise/dave.h b/src/mame/enterprise/dave.h new file mode 100644 index 00000000000..3287c909e1f --- /dev/null +++ b/src/mame/enterprise/dave.h @@ -0,0 +1,117 @@ +// license:BSD-3-Clause +// copyright-holders:Curt Coder +/********************************************************************** + + Intelligent Designs DAVE emulation + +**********************************************************************/ + +#ifndef MAME_SOUND_DAVE_H +#define MAME_SOUND_DAVE_H + +#pragma once + + +///************************************************************************* +// TYPE DEFINITIONS +///************************************************************************* + +// ======================> dave_device + +class dave_device : public device_t, + public device_memory_interface, + public device_sound_interface +{ +public: + dave_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + auto irq_wr() { return m_write_irq.bind(); } + auto lh_wr() { return m_write_lh.bind(); } + auto rh_wr() { return m_write_rh.bind(); } + + virtual void z80_program_map(address_map &map) ATTR_COLD; + virtual void z80_io_map(address_map &map) ATTR_COLD; + + void int1_w(int state); + void int2_w(int state); + + void io_map(address_map &map) ATTR_COLD; + void program_map(address_map &map) ATTR_COLD; + +protected: + // device-level overrides + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + + // device_memory_interface overrides + virtual space_config_vector memory_space_config() const override; + + // sound stream update overrides + virtual void sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) override; + + TIMER_CALLBACK_MEMBER(update_1hz_timer); + TIMER_CALLBACK_MEMBER(update_50hz_timer); + + uint8_t program_r(offs_t offset); + void program_w(offs_t offset, uint8_t data); + + uint8_t io_r(offs_t offset); + void io_w(offs_t offset, uint8_t data); + +private: + enum + { + IRQ_50HZ_DIVIDER = 0x01, + IRQ_50HZ_LATCH = 0x02, + IRQ_1HZ_DIVIDER = 0x04, + IRQ_1HZ_LATCH = 0x08, + IRQ_INT1 = 0x10, + IRQ_INT1_LATCH = 0x20, + IRQ_INT2 = 0x40, + IRQ_INT2_LATCH = 0x80, + IRQ_LATCH = IRQ_INT2_LATCH | IRQ_INT1_LATCH | IRQ_1HZ_LATCH | IRQ_50HZ_LATCH + }; + + void update_interrupt(); + + const address_space_config m_program_space_config; + const address_space_config m_io_space_config; + + devcb_write_line m_write_irq; + devcb_write8 m_write_lh; + devcb_write8 m_write_rh; + + uint8_t m_segment[4]; + + uint8_t m_irq_status; + uint8_t m_irq_enable; + + emu_timer *m_timer_1hz; + emu_timer *m_timer_50hz; + + /* SOUND SYNTHESIS */ + uint8_t m_regs[32]; + 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]; + + sound_stream *m_sound_stream_var; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(DAVE, dave_device) + +#endif // MAME_SOUND_DAVE_H diff --git a/src/mame/enterprise/ep64.cpp b/src/mame/enterprise/ep64.cpp index 8d8f893d9c5..e06a3dfff9e 100644 --- a/src/mame/enterprise/ep64.cpp +++ b/src/mame/enterprise/ep64.cpp @@ -159,7 +159,8 @@ Notes: (All IC's shown) #include "cpu/z80/z80.h" #include "imagedev/cassette.h" #include "machine/ram.h" -#include "sound/dave.h" + +#include "dave.h" #include "nick.h" #include "softlist_dev.h" @@ -595,6 +596,7 @@ void ep64_state::ep64(machine_config &config) // sound hardware SPEAKER(config, "lspeaker").front_left(); SPEAKER(config, "rspeaker").front_right(); + DAVE(config, m_dave, XTAL(8'000'000)); m_dave->set_addrmap(AS_PROGRAM, &ep64_state::dave_64k_mem); m_dave->set_addrmap(AS_IO, &ep64_state::dave_io); diff --git a/src/mame/enterprise/nick.cpp b/src/mame/enterprise/nick.cpp index fa17197b853..734a90136f4 100644 --- a/src/mame/enterprise/nick.cpp +++ b/src/mame/enterprise/nick.cpp @@ -73,7 +73,7 @@ // DEVICE DEFINITIONS //************************************************************************** -DEFINE_DEVICE_TYPE(NICK, nick_device, "nick", "NICK") +DEFINE_DEVICE_TYPE(NICK, nick_device, "nick", "Intelligent Designs NICK") void nick_device::vram_map(address_map &map) @@ -105,20 +105,20 @@ void nick_device::nick_map(address_map &map) // nick_device - constructor //------------------------------------------------- -nick_device::nick_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, NICK, tag, owner, clock), - device_memory_interface(mconfig, *this), - device_video_interface(mconfig, *this), - m_space_config("vram", ENDIANNESS_LITTLE, 8, 16, 0, address_map_constructor(FUNC(nick_device::nick_map), this)), - m_write_virq(*this), - m_scanline_count(0), - m_FIXBIAS(0), - m_BORDER(0), - m_LPL(0), - m_LPH(0), - m_LD1(0), - m_LD2(0), - m_virq(CLEAR_LINE) +nick_device::nick_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, NICK, tag, owner, clock), + device_memory_interface(mconfig, *this), + device_video_interface(mconfig, *this), + m_space_config("vram", ENDIANNESS_LITTLE, 8, 16, 0, address_map_constructor(FUNC(nick_device::nick_map), this)), + m_write_virq(*this), + m_scanline_count(0), + m_FIXBIAS(0), + m_BORDER(0), + m_LPL(0), + m_LPH(0), + m_LD1(0), + m_LD2(0), + m_virq(CLEAR_LINE) { memset(&m_LPT, 0x00, sizeof(m_LPT)); } @@ -508,7 +508,6 @@ void nick_device::write_pixels(uint8_t data_byte, uint8_t char_idx) } #endif - write_pixels2color(pen_offs, (pen_offs | 0x01), data); } break; @@ -598,8 +597,6 @@ void nick_device::write_pixels(uint8_t data_byte, uint8_t char_idx) write_pixel(pal_idx); write_pixel(pal_idx); write_pixel(pal_idx); - - } break; } @@ -661,7 +658,6 @@ void nick_device::write_pixels_lpixel(uint8_t data_byte, uint8_t char_idx) } #endif - write_pixels2color_lpixel(pen_offs, (pen_offs | 0x01), data); } break; @@ -765,8 +761,6 @@ void nick_device::write_pixels_lpixel(uint8_t data_byte, uint8_t char_idx) write_pixel(pal_idx); write_pixel(pal_idx); write_pixel(pal_idx); - - } break; } diff --git a/src/mame/enterprise/nick.h b/src/mame/enterprise/nick.h index dd520c94772..a0c67de3532 100644 --- a/src/mame/enterprise/nick.h +++ b/src/mame/enterprise/nick.h @@ -75,6 +75,7 @@ public: uint32_t screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); void nick_map(address_map &map) ATTR_COLD; + protected: // device-level overrides virtual void device_start() override ATTR_COLD; -- cgit v1.2.3