summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/namco_163.cpp
diff options
context:
space:
mode:
author cam900 <dbtlrchl@naver.com>2019-03-30 06:57:27 +0900
committer R. Belmont <rb6502@users.noreply.github.com>2019-03-29 17:57:27 -0400
commit80a48d5229eb5ff62b4f27ec6351226b672c0030 (patch)
tree4122cd513df488d8b5a68b304abbff7b82f20b8a /src/devices/sound/namco_163.cpp
parent6dbd636a809ce7bda3ec476239f7b32a2d1de537 (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.cpp176
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);
+ }
+}