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
This commit is contained in:
cam900 2019-03-30 06:57:27 +09:00 committed by R. Belmont
parent 6dbd636a80
commit 80a48d5229
7 changed files with 254 additions and 12 deletions

View File

@ -590,6 +590,7 @@ end
---------------------------------------------------
-- Namco custom sound chips
--@src/devices/sound/namco.h,SOUNDS["NAMCO"] = true
--@src/devices/sound/namco_163.h,SOUNDS["NAMCO_163"] = true
--@src/devices/sound/n63701x.h,SOUNDS["NAMCO_63701X"] = true
--@src/devices/sound/c140.h,SOUNDS["C140"] = true
--@src/devices/sound/c352.h,SOUNDS["C352"] = true
@ -602,6 +603,13 @@ if (SOUNDS["NAMCO"]~=null or SOUNDS["NAMCO_15XX"]~=null or SOUNDS["NAMCO_CUS30"]
}
end
if (SOUNDS["NAMCO_163"]~=null) then
files {
MAME_DIR .. "src/devices/sound/namco_163.cpp",
MAME_DIR .. "src/devices/sound/namco_163.h",
}
end
if (SOUNDS["NAMCO_63701X"]~=null) then
files {
MAME_DIR .. "src/devices/sound/n63701x.cpp",

View File

@ -173,6 +173,7 @@ SOUNDS["NAMCO_15XX"] = true
SOUNDS["NAMCO_CUS30"] = true
SOUNDS["NAMCO_52XX"] = true
SOUNDS["NAMCO_63701X"] = true
--SOUNDS["NAMCO_163"] = true
SOUNDS["T6W28"] = true
SOUNDS["SNKWAVE"] = true
SOUNDS["C140"] = true

View File

@ -181,6 +181,7 @@ SOUNDS["ASTROCADE"] = true
--SOUNDS["NAMCO_CUS30"] = true
--SOUNDS["NAMCO_52XX"] = true
--SOUNDS["NAMCO_63701X"] = true
SOUNDS["NAMCO_163"] = true
SOUNDS["T6W28"] = true
--SOUNDS["SNKWAVE"] = true
--SOUNDS["C140"] = true

View File

@ -16,7 +16,6 @@
* Namcot 340 [mapper 210]
TODO:
- add sound feature of Namcot-163
- Quinty is not working (same issue of Mendel Palace on TxROM boards, of course)
***********************************************************************************************************/
@ -26,6 +25,8 @@
#include "namcot.h"
#include "ui/uimain.h"
#include "speaker.h"
#ifdef NES_PCB_DEBUG
#define VERBOSE 1
#else
@ -83,7 +84,7 @@ nes_namcot175_device::nes_namcot175_device(const machine_config &mconfig, const
}
nes_namcot163_device::nes_namcot163_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: nes_namcot340_device(mconfig, NES_NAMCOT163, tag, owner, clock), m_wram_protect(0), m_latch(0), m_chr_bank(0)
: nes_namcot340_device(mconfig, NES_NAMCOT163, tag, owner, clock), m_wram_protect(0), m_latch(0), m_chr_bank(0), m_namco163snd(*this, "n163")
{
}
@ -550,13 +551,11 @@ void nes_namcot175_device::write_h(offs_t offset, uint8_t data)
Compared to Namcot-175 here we have mapper controlled
mirroring, NTRAM mapping to VRAM and additional
sound hw inside the chip (currently unemulated) and
some internal RAM.
sound hw inside the chip and some internal RAM.
iNES: mapper 19
In MESS: Supported (with no emulation of the
sound component)
In MESS: Supported
-------------------------------------------------*/
@ -614,7 +613,7 @@ void nes_namcot163_device::write_l(offs_t offset, uint8_t data)
switch (offset & 0x1800)
{
case 0x0800:
LOG_MMC(("Namcot-163 sound reg write, data: %02x\n", data));
m_namco163snd->data_w(data);
break;
default:
n340_lowrite(offset, data);
@ -630,8 +629,7 @@ uint8_t nes_namcot163_device::read_l(offs_t offset)
switch (offset & 0x1800)
{
case 0x0800:
LOG_MMC(("Namcot-163 sound reg read\n"));
return 0;
return m_namco163snd->data_r();
default:
return n340_loread(offset);
}
@ -667,7 +665,7 @@ void nes_namcot163_device::write_h(offs_t offset, uint8_t data)
set_mirror(page, data);
break;
case 0x6000:
// TODO: data & 40 (or data & c0) disable sound if set
m_namco163snd->disable_w((data & 0x40) ? ASSERT_LINE : CLEAR_LINE);
prg8_89(data & 0x3f);
break;
case 0x6800:
@ -677,10 +675,23 @@ void nes_namcot163_device::write_h(offs_t offset, uint8_t data)
case 0x7800:
// the lower 4 bits work *BOTH* as WRAM write protect *AND* as sound address!
m_wram_protect = data & 0x0f;
LOG_MMC(("Namcot-163 sound address write, data: %02x\n", data));
m_namco163snd->addr_w(data);
break;
default:
n340_hiwrite(offset, data);
break;
}
}
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void nes_namcot163_device::device_add_mconfig(machine_config &config)
{
// additional sound hardware
SPEAKER(config, "addon").front_center();
// TODO: Correct clock input / divider?
NAMCO_163(config, m_namco163snd, XTAL(21'477'272)/12).add_route(ALL_OUTPUTS, "addon", 0.5);
}

View File

@ -6,6 +6,7 @@
#pragma once
#include "nxrom.h"
#include "sound/namco_163.h"
// ======================> nes_namcot3433_device
@ -157,11 +158,13 @@ protected:
// device-level overrides
virtual void device_start() override;
virtual void device_add_mconfig(machine_config &config) override;
private:
void set_mirror(uint8_t page, uint8_t data);
uint8_t m_wram_protect, m_latch, m_chr_bank;
// TODO: add emulation of the sound part of the chip
required_device<namco_163_sound_device> m_namco163snd;
};

View File

@ -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);
}
}

View File

@ -0,0 +1,42 @@
// license:BSD-3-Clause
// copyright-holders:cam900
#ifndef MAME_SOUND_NAMCO_163_H
#define MAME_SOUND_NAMCO_163_H
#pragma once
class namco_163_sound_device : public device_t,
public device_sound_interface
{
public:
namco_163_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
DECLARE_WRITE_LINE_MEMBER(disable_w);
void addr_w(u8 data);
void data_w(u8 data);
u8 data_r();
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_clock_changed() override;
// global sound parameters
std::unique_ptr<u8[]> m_ram;
u8 m_reg_addr;
u8 m_addr;
bool m_inc;
bool m_disable;
sound_stream *m_stream;
// internals
inline s8 get_sample(u16 addr);
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
};
DECLARE_DEVICE_TYPE(NAMCO_163, namco_163_sound_device)
#endif // MAME_SOUND_NAMCO_163_H