summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices')
-rw-r--r--src/devices/sound/okim6376.cpp86
-rw-r--r--src/devices/sound/okim6376.h28
2 files changed, 89 insertions, 25 deletions
diff --git a/src/devices/sound/okim6376.cpp b/src/devices/sound/okim6376.cpp
index e04f051b0f5..2170bd5e898 100644
--- a/src/devices/sound/okim6376.cpp
+++ b/src/devices/sound/okim6376.cpp
@@ -19,8 +19,8 @@
#define MAX_SAMPLE_CHUNK 10000
//#define MAX_WORDS 111
-#define OKIVERBOSE 0
-#define MSM6376LOG(...) do { if (OKIVERBOSE) logerror(__VA_ARGS__); } while (0)
+//#define VERBOSE 1
+#include "logmacro.h"
/* step size index shift table */
static const int index_shift[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
@@ -111,11 +111,12 @@ void okim6376_device::ADPCMVoice::reset()
DEFINE_DEVICE_TYPE(OKIM6376, okim6376_device, "okim6376", "OKI MSM6376 ADPCM")
+DEFINE_DEVICE_TYPE(OKIM6650, okim6650_device, "okim6650", "OKI MSM6650 ADPCM")
-okim6376_device::okim6376_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, OKIM6376, tag, owner, clock),
+okim6376_device::okim6376_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int addrbits)
+ : device_t(mconfig, type, tag, owner, clock),
device_sound_interface(mconfig, *this),
- m_region_base(*this, DEVICE_SELF),
+ device_rom_interface(mconfig, *this, addrbits, ENDIANNESS_BIG, 8),
//m_command[OKIM6376_VOICES],
m_latch(0),
//m_stage[OKIM6376_VOICES],
@@ -133,6 +134,16 @@ okim6376_device::okim6376_device(const machine_config &mconfig, const char *tag,
{
}
+okim6376_device::okim6376_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : okim6376_device(mconfig, OKIM6376, tag, owner, clock, 21)
+{
+}
+
+okim6650_device::okim6650_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : okim6376_device(mconfig, OKIM6650, tag, owner, clock, 23)
+{
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -184,6 +195,11 @@ void okim6376_device::device_reset()
}
+void okim6376_device::rom_bank_updated()
+{
+}
+
+
/**********************************************************************************************
clock_adpcm -- clock the next ADPCM byte
@@ -212,13 +228,34 @@ int16_t okim6376_device::ADPCMVoice::clock(uint8_t nibble)
}
+offs_t okim6376_device::get_start_position(int channel)
+{
+ offs_t base = m_command[channel] * 4;
+
+ // max address space is 16Mbit
+ return (read_byte(base+0) << 16 | read_byte(base+1) << 8 | read_byte(base+2)) & 0x1fffff;
+}
+
+
+offs_t okim6650_device::get_start_position(int channel)
+{
+ offs_t base = 0x000800 + m_command[channel] * 4;
+
+ // determine sampling frequency for phrase
+ uint8_t data = read_byte(base);
+ m_divisor = ((data & 3) == 2 ? 5 : 8 - (data & 3) * 2) * (BIT(data, 2) ? 2 : 1);
+ notify_clock_changed();
+
+ // max address space is 64Mbit
+ return (read_byte(base+1) << 16 | read_byte(base+2) << 8 | read_byte(base+3)) & 0x7fffff;
+}
+
+
void okim6376_device::oki_process(int channel, int command)
{
/* if a command is pending, process the second half */
if ((command != -1) && (command != 0)) //process silence separately
{
- int start;
- unsigned char *base/*, *base_end*/;
/* update the stream */
m_stream->update();
@@ -226,10 +263,8 @@ void okim6376_device::oki_process(int channel, int command)
{
struct ADPCMVoice *voice = &m_voice[channel];
- /* determine the start position, max address space is 16Mbit */
- base = &m_region_base[m_command[channel] * 4];
- //base_end = &m_region_base[(MAX_WORDS+1) * 4];
- start = ((base[0] << 16) + (base[1] << 8) + base[2]) & 0x1fffff;
+ // determine the start position
+ offs_t start = get_start_position(channel);
if (start == 0)
{
@@ -293,7 +328,7 @@ void okim6376_device::generate_adpcm(struct ADPCMVoice *voice, int16_t *buffer,
/* if this voice is active */
if (voice->playing)
{
- uint8_t *base = m_region_base + voice->base_offset;
+ offs_t base = voice->base_offset;
int sample = voice->sample;
int count = voice->count;
@@ -305,7 +340,7 @@ void okim6376_device::generate_adpcm(struct ADPCMVoice *voice, int16_t *buffer,
if (count == 0)
{
/* get the number of samples to play */
- count = (base[sample / 2] & 0x7f) << 1;
+ count = (read_byte(base + sample / 2) & 0x7f) << 1;
/* end of voice marker */
if (count == 0)
@@ -321,7 +356,7 @@ void okim6376_device::generate_adpcm(struct ADPCMVoice *voice, int16_t *buffer,
}
/* compute the new amplitude and update the current step */
- nibble = base[sample / 2] >> (((sample & 1) << 2) ^ 4);
+ nibble = read_byte(base + sample / 2) >> (((sample & 1) << 2) ^ 4);
/* output to the buffer, scaling by the volume */
/* signal in range -4096..4095, volume in range 2..16 => signal * volume / 2 in range -32768..32767 */
@@ -400,6 +435,11 @@ void okim6376_device::device_clock_changed()
m_stream->set_sample_rate(clock() / m_divisor);
}
+void okim6650_device::device_clock_changed()
+{
+ m_stream->set_sample_rate(clock() / 64 / m_divisor);
+}
+
/**********************************************************************************************
@@ -425,14 +465,14 @@ READ_LINE_MEMBER( okim6376_device::busy_r )
READ_LINE_MEMBER( okim6376_device::nar_r )
{
- MSM6376LOG("OKIM6376: NAR %x\n",m_nar);
+ LOG("OKIM6376: NAR %x\n",m_nar);
return m_nar;
}
WRITE_LINE_MEMBER( okim6376_device::ch2_w )
{
m_ch2_update = 0;//Clear flag
- MSM6376LOG("OKIM6376: CH2 %x\n",state);
+ LOG("OKIM6376: CH2 %x\n",state);
if (m_ch2 != state)
{
@@ -445,7 +485,7 @@ WRITE_LINE_MEMBER( okim6376_device::ch2_w )
struct ADPCMVoice *voice0 = &m_voice[0];
struct ADPCMVoice *voice1 = &m_voice[1];
// We set to channel 2
- MSM6376LOG("OKIM6376: Channel 1\n");
+ LOG("OKIM6376: Channel 1\n");
m_channel = 1;
if ((voice0->playing)&&(m_st))
@@ -460,7 +500,7 @@ WRITE_LINE_MEMBER( okim6376_device::ch2_w )
{
m_stage[1]=0;
oki_process(1, m_command[1]);
- MSM6376LOG("OKIM6376: Channel 0\n");
+ LOG("OKIM6376: Channel 0\n");
m_channel = 0;
}
}
@@ -471,7 +511,7 @@ WRITE_LINE_MEMBER( okim6376_device::st_w )
//As in STart, presumably, this triggers everything
m_st_update = 0;//Clear flag
- MSM6376LOG("OKIM6376: ST %x\n",state);
+ LOG("OKIM6376: ST %x\n",state);
if (m_st != state)
{
@@ -483,7 +523,7 @@ WRITE_LINE_MEMBER( okim6376_device::st_w )
struct ADPCMVoice *voice = &m_voice[m_channel];
{
m_st_pulses ++;
- MSM6376LOG("OKIM6376: ST pulses %x\n",m_st_pulses);
+ LOG("OKIM6376: ST pulses %x\n",m_st_pulses);
if (m_st_pulses > 3)
{
m_st_pulses = 3; //undocumented behaviour beyond 3 pulses
@@ -507,6 +547,12 @@ WRITE_LINE_MEMBER( okim6376_device::st_w )
}
}
+
+WRITE_LINE_MEMBER( okim6650_device::cmd_w )
+{
+ // TODO
+}
+
/**********************************************************************************************
okim6376_data_w -- write to the data port of an OKIM6376-compatible chip
diff --git a/src/devices/sound/okim6376.h b/src/devices/sound/okim6376.h
index 91cb3acf7e6..361a9d2ccb0 100644
--- a/src/devices/sound/okim6376.h
+++ b/src/devices/sound/okim6376.h
@@ -7,8 +7,7 @@
/* an interface for the OKIM6376 and similar chips (CPU interface only) */
-class okim6376_device : public device_t,
- public device_sound_interface
+class okim6376_device : public device_t, public device_sound_interface, public device_rom_interface
{
public:
okim6376_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@@ -22,6 +21,8 @@ public:
DECLARE_READ_LINE_MEMBER( nar_r );
protected:
+ okim6376_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int addrbits);
+
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
@@ -31,7 +32,11 @@ protected:
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
-private:
+ // device_rom_interface overrides
+ virtual void rom_bank_updated() override;
+
+ virtual offs_t get_start_position(int channel);
+
/* struct describing a single playing ADPCM voice */
struct ADPCMVoice
{
@@ -50,8 +55,6 @@ private:
};
// internal state
- required_region_ptr<uint8_t> m_region_base; /* pointer to the base of the region */
-
static constexpr unsigned OKIM6376_VOICES = 2;
struct ADPCMVoice m_voice[OKIM6376_VOICES];
int32_t m_command[OKIM6376_VOICES];
@@ -75,6 +78,21 @@ private:
void adpcm_state_save_register(struct ADPCMVoice *voice, int index);
};
+class okim6650_device : public okim6376_device
+{
+public:
+ okim6650_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ DECLARE_WRITE_LINE_MEMBER( cmd_w );
+
+protected:
+ // device-level overrides
+ virtual void device_clock_changed() override;
+
+ virtual offs_t get_start_position(int channel) override;
+};
+
DECLARE_DEVICE_TYPE(OKIM6376, okim6376_device)
+DECLARE_DEVICE_TYPE(OKIM6650, okim6650_device)
#endif // MAME_SOUND_OKIM6376_H