diff options
author | 2019-03-30 06:57:27 +0900 | |
---|---|---|
committer | 2019-03-29 17:57:27 -0400 | |
commit | 80a48d5229eb5ff62b4f27ec6351226b672c0030 (patch) | |
tree | 4122cd513df488d8b5a68b304abbff7b82f20b8a /src/devices/sound/namco_163.cpp | |
parent | 6dbd636a809ce7bda3ec476239f7b32a2d1de537 (diff) |
Add Namco 163 sound emulation (#4814)
* Add Namco 163 sound emulation
* namco_163.cpp : Typo
* namco_163.cpp : Fix spacing
* namco_163.h : Fix comment (nw)
* namco_163.cpp : Correct update behavior
device/bus/nes/namcot.* : Remove / Fix outdated comments
* namco_163.cpp : Remove unnecessary value (nw)
* namco_163.cpp : Add notes (nw)
* namco_163.cpp : inline'd sample function, Minor fix
* namco_163.cpp : Fix notes
Diffstat (limited to 'src/devices/sound/namco_163.cpp')
-rw-r--r-- | src/devices/sound/namco_163.cpp | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/src/devices/sound/namco_163.cpp b/src/devices/sound/namco_163.cpp new file mode 100644 index 00000000000..6fdde572537 --- /dev/null +++ b/src/devices/sound/namco_163.cpp @@ -0,0 +1,176 @@ +// license:BSD-3-Clause +// copyright-holders:cam900 +/*************************************************************************** + + Namco 163 internal sound emulation by cam900 + 4 bit wavetable (variable length), 1 ~ 8 channel + Reference : https://wiki.nesdev.com/w/index.php/Namco_163_audio + +***************************************************************************/ + +#include "emu.h" +#include "namco_163.h" + + +DEFINE_DEVICE_TYPE(NAMCO_163, namco_163_sound_device, "namco_163_sound", "Namco 163 (Sound)") + +namco_163_sound_device::namco_163_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, NAMCO_163, tag, owner, clock) + , device_sound_interface(mconfig, *this) + , m_ram(nullptr) + , m_reg_addr(0x78) + , m_addr(0) + , m_inc(false) + , m_disable(false) + , m_stream(nullptr) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void namco_163_sound_device::device_start() +{ + m_ram = make_unique_clear<u8[]>(0x80); + m_stream = machine().sound().stream_alloc(*this, 0, 1, clock() / 15); + + save_pointer(NAME(m_ram), 0x80); + save_item(NAME(m_reg_addr)); + save_item(NAME(m_addr)); + save_item(NAME(m_inc)); + save_item(NAME(m_disable)); +} + + +//------------------------------------------------- +// device_clock_changed - called if the clock +// changes +//------------------------------------------------- + +void namco_163_sound_device::device_clock_changed() +{ + m_stream->set_sample_rate(clock() / 15); +} + + +inline s8 namco_163_sound_device::get_sample(u16 addr) +{ + return ((m_ram[(addr >> 1) & 0x7f] >> ((addr & 1) << 2)) & 0xf) - 8; +} + + +WRITE_LINE_MEMBER(namco_163_sound_device::disable_w) +{ + m_disable = state; +} + + +/********************************************************************************/ + +/* + Register Map (in RAM) + + 40 ffff ffff Channel 0 Frequency bits 0 - 7 + 41 pppp pppp Channel 0 Phase bits 0 - 7 + 42 ffff ffff Channel 0 Frequency bits 8 - 15 + 43 pppp pppp Channel 0 Phase bits 8 - 15 + 44 ---- --ff Channel 0 Frequency bits 16 - 17 + llll ll-- Channel 0 Waveform Length (256 - (l * 4)) 4 bit samples + 45 pppp pppp Channel 0 Phase bits 16 - 23 + 46 oooo oooo Channel 0 Waveform Offset at 4 bit samples + 47 ---- cccc Channel 0 Volume + + 48 ffff ffff Channel 1 Frequency bits 0 - 7 + 49 pppp pppp Channel 1 Phase bits 0 - 7 + 4a ffff ffff Channel 1 Frequency bits 8 - 15 + 4b pppp pppp Channel 1 Phase bits 8 - 15 + 4c ---- --ff Channel 1 Frequency bits 16 - 17 + llll ll-- Channel 1 Waveform Length (256 - (l * 4)) 4 bit samples + 4d pppp pppp Channel 1 Phase bits 16 - 23 + 4e oooo oooo Channel 1 Waveform Offset at 4 bit samples + 4f ---- cccc Channel 1 Volume + + . + . + . + + 78 ffff ffff Channel 7 Frequency bits 0 - 7 + 79 pppp pppp Channel 7 Phase bits 0 - 7 + 7a ffff ffff Channel 7 Frequency bits 8 - 15 + 7b pppp pppp Channel 7 Phase bits 8 - 15 + 7c ---- --ff Channel 7 Frequency bits 16 - 17 + llll ll-- Channel 7 Waveform Length (256 - (l * 4)) 4 bit samples + 7d pppp pppp Channel 7 Phase bits 16 - 23 + 7e oooo oooo Channel 7 Waveform Offset at 4 bit samples + 7f ---- cccc Channel 7 Volume + -ccc ---- Enable channels + -000 ---- Enable channel 7 only + -001 ---- Enable channel 7, 6 + -010 ---- Enable channel 7, 6, 5 + + . + . + . + + -111 ---- Enable all channels +*/ + +void namco_163_sound_device::addr_w(u8 data) +{ + m_inc = data & 0x80; + m_addr = data & 0x7f; +} + + +void namco_163_sound_device::data_w(u8 data) +{ + m_stream->update(); + m_ram[m_addr] = data; + if (m_inc) + m_addr = (m_addr + 1) & 0x7f; +} + + +u8 namco_163_sound_device::data_r() +{ + u8 val = m_ram[m_addr]; + if (m_inc) + m_addr = (m_addr + 1) & 0x7f; + + return val; +} + + +void namco_163_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) +{ + std::fill_n(&outputs[0][0], samples, 0); + + if (m_disable) + return; + + // Slightly noisy but closer to real hardware behavior + for (int s = 0; s < samples; s++) + { + u32 phase = (m_ram[m_reg_addr + 5] << 16) | (m_ram[m_reg_addr + 3] << 8) | m_ram[m_reg_addr + 1]; + const u32 freq = ((m_ram[m_reg_addr + 4] & 0x3) << 16) | (m_ram[m_reg_addr + 2] << 8) | m_ram[m_reg_addr + 0]; + const u16 length = 256 - (m_ram[m_reg_addr + 4] & 0xfc); + const u16 offset = m_ram[m_reg_addr + 6]; + const u8 vol = m_ram[m_reg_addr + 7] & 0xf; + + phase = (phase + freq) % (length << 16); + s32 output = get_sample((phase >> 16) + offset) * vol; + + m_ram[m_reg_addr + 1] = phase & 0xff; + m_ram[m_reg_addr + 3] = phase >> 8; + m_ram[m_reg_addr + 5] = phase >> 16; + + m_reg_addr += 8; + if (m_reg_addr >= 0x80) + { + m_reg_addr = 0x78 - ((m_ram[0x7f] & 0x70) >> 1); + } + outputs[0][s] = (output << 8); + } +} |