uPD934G: Preliminary emulation

This commit is contained in:
Dirk Best 2018-03-17 09:08:28 +01:00
parent 61f1bf7477
commit 3ffd6b839f
5 changed files with 245 additions and 0 deletions

View File

@ -1459,3 +1459,15 @@ if (SOUNDS["LC7535"]~=null) then
MAME_DIR .. "src/devices/sound/lc7535.h",
}
end
---------------------------------------------------
-- NEC uPD934G
--@src/devices/sound/upd934g.h,SOUNDS["UPD934G"] = true
---------------------------------------------------
if (SOUNDS["UPD934G"]~=null) then
files {
MAME_DIR .. "src/devices/sound/upd934g.cpp",
MAME_DIR .. "src/devices/sound/upd934g.h",
}
end

View File

@ -268,6 +268,7 @@ SOUNDS["TA7630"] = true
SOUNDS["MM5837"] = true
--SOUNDS["DAVE"] = true
SOUNDS["LC7535"] = true
--SOUNDS["UPD934G"] = true
--------------------------------------------------
-- specify available video cores

View File

@ -270,6 +270,7 @@ SOUNDS["MEA8000"] = true
--SOUNDS["MM5837"] = true
SOUNDS["DAVE"] = true
--SOUNDS["LC7535"] = true
SOUNDS["UPD934G"] = true
--------------------------------------------------
-- specify available video cores

View File

@ -0,0 +1,161 @@
// license: BSD-3-Clause
// copyright-holders: Dirk Best
/***************************************************************************
NEC μPD934G
Percussion Generator
TODO:
- Play MUTED and ACCENTED
- T1 input
- 8 channels?
***************************************************************************/
#include "emu.h"
#include "upd934g.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(UPD934G, upd934g_device, "upd934g", "NEC uPD934G")
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// upd934g_device - constructor
//-------------------------------------------------
upd934g_device::upd934g_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, UPD934G, tag, owner, clock),
device_sound_interface(mconfig, *this),
m_data_cb(*this),
m_stream(nullptr),
m_sample(0),
m_ready(false)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void upd934g_device::device_start()
{
// create sound stream
m_stream = machine().sound().stream_alloc(*this, 0, 4, 20000);
// resolve callbacks
m_data_cb.resolve_safe(0);
// register for save states
save_pointer(NAME(m_addr), 16);
for (unsigned i = 0; i < 4; i++)
{
save_item(NAME(m_channel[i].pos), i);
save_item(NAME(m_channel[i].playing), i);
save_item(NAME(m_channel[i].volume), i);
}
save_item(NAME(m_sample));
save_item(NAME(m_ready));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void upd934g_device::device_reset()
{
m_ready = false;
for (unsigned i = 0; i < 4; i++)
m_channel[i].playing = -1;
}
//-------------------------------------------------
// sound_stream_update - handle update requests for
// our sound stream
//-------------------------------------------------
void upd934g_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{
for (unsigned ch = 0; ch < 4; ch++)
{
std::fill(&outputs[ch][0], &outputs[ch][samples], 0);
if (m_ready && m_channel[ch].playing != -1)
{
uint16_t end = m_addr[m_channel[ch].playing + 1] - 1;
for (unsigned i = 0; i < samples; i++)
{
int8_t raw = static_cast<int8_t>(m_data_cb(m_channel[ch].pos));
outputs[ch][i] = raw * (m_channel[ch].volume + 1) * 64;
if (++m_channel[ch].pos >= end)
{
m_channel[ch].playing = -1;
break;
}
}
}
}
}
//**************************************************************************
// INTERFACE
//**************************************************************************
WRITE8_MEMBER( upd934g_device::write )
{
switch (offset)
{
case 0:
// format of data written here is:
// 76------ command
// --5432-- sample number
// ------10 volume?
m_sample = (data >> 2) & 0x0f;
switch (data >> 6)
{
case 0:
logerror("CMD STORE ADDRESS sample %x\n", m_sample);
break;
case 1:
logerror("CMD PLAY sample %x (channel %d)\n", m_sample, m_sample >> 1);
if (m_sample < 8)
{
m_channel[m_sample >> 1].pos = m_addr[m_sample];
m_channel[m_sample >> 1].playing = m_sample;
m_channel[m_sample >> 1].volume = data & 0x03;
}
break;
case 2:
logerror("CMD PLAY MUTED sample %x (channel %d)\n", m_sample, m_sample >> 1);
break;
case 3:
logerror("CMD PLAY ACCENTED sample %x (channel %d)\n", m_sample, m_sample >> 1);
break;
}
break;
case 1:
m_addr[m_sample] = (m_addr[m_sample] & 0xff00) | (data << 0);
break;
case 2:
m_addr[m_sample] = (m_addr[m_sample] & 0x00ff) | (data << 8);
logerror(" sample %x address = %04x\n", m_sample, m_addr[m_sample]);
break;
case 3:
m_ready = true;
break;
}
}

View File

@ -0,0 +1,70 @@
// license: BSD-3-Clause
// copyright-holders: Dirk Best
/***************************************************************************
NEC μPD934G
Percussion Generator
***************************************************************************/
#ifndef MAME_SOUND_UPD934G_H
#define MAME_SOUND_UPD934G_H
#pragma once
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define MCFG_UPD934G_DATA_CB(_devcb) \
devcb = &downcast<upd934g_device &>(*device).set_data_callback(DEVCB_##_devcb);
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class upd934g_device : public device_t, public device_sound_interface
{
public:
static constexpr feature_type imperfect_features() { return feature::SOUND; }
// construction/destruction
upd934g_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// configuration
template <class Object> devcb_base &set_data_callback(Object &&cb) { return m_data_cb.set_callback(std::forward<Object>(cb)); }
DECLARE_WRITE8_MEMBER(write);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
private:
devcb_read8 m_data_cb;
sound_stream *m_stream;
uint16_t m_addr[16];
struct
{
uint16_t pos;
int playing;
int volume;
}
m_channel[4];
int m_sample;
bool m_ready;
};
// device type definition
DECLARE_DEVICE_TYPE(UPD934G, upd934g_device)
#endif // MAME_SOUND_UPD934G_H