summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/sp0256.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound/sp0256.cpp')
-rw-r--r--src/devices/sound/sp0256.cpp126
1 files changed, 59 insertions, 67 deletions
diff --git a/src/devices/sound/sp0256.cpp b/src/devices/sound/sp0256.cpp
index 54c17fcaf21..ba84d002eb5 100644
--- a/src/devices/sound/sp0256.cpp
+++ b/src/devices/sound/sp0256.cpp
@@ -4,7 +4,7 @@
GI SP0256 Narrator Speech Processor
GI SPB640 Speech Buffer
- By Joe Zbiciak. Ported to MESS by tim lindner.
+ By Joe Zbiciak. Ported to MAME by tim lindner.
Unimplemented:
- Microsequencer repeat count of zero
@@ -23,7 +23,6 @@
#include "emu.h"
#include "sp0256.h"
-#define LOG_GENERAL (1U << 0)
#define LOG_FIFO (1U << 1)
//#define VERBOSE (LOG_GENERAL | LOG_FIFO)
@@ -56,10 +55,10 @@ sp0256_device::sp0256_device(const machine_config &mconfig, const char *tag, dev
, device_sound_interface(mconfig, *this)
, m_rom(*this, DEVICE_SELF)
, m_stream(nullptr)
+ , m_stream_timer(nullptr)
, m_drq_cb(*this)
, m_sby_cb(*this)
, m_scratch()
- , m_lrq_timer(nullptr)
{
}
@@ -69,12 +68,19 @@ sp0256_device::sp0256_device(const machine_config &mconfig, const char *tag, dev
void sp0256_device::device_start()
{
- m_drq_cb.resolve_safe();
- m_sby_cb.resolve_safe();
m_drq_cb(1);
m_sby_cb(1);
+ m_sby_line = 1;
- m_stream = machine().sound().stream_alloc(*this, 0, 1, clock() / CLOCK_DIVIDER);
+ int sample_rate = clock() / CLOCK_DIVIDER;
+ m_stream = stream_alloc(0, 1, sample_rate);
+
+ // if callbacks are used, update the stream at sample rate frequency to ensure they get picked up in a timely matter
+ if (!m_drq_cb.isunset() || !m_sby_cb.isunset())
+ {
+ m_stream_timer = timer_alloc(FUNC(sp0256_device::delayed_stream_update), this);
+ m_stream_timer->adjust(attotime::from_hz(sample_rate), 0, attotime::from_hz(sample_rate));
+ }
/* -------------------------------------------------------------------- */
/* Configure our internal variables. */
@@ -82,7 +88,7 @@ void sp0256_device::device_start()
m_filt.rng = 1;
/* -------------------------------------------------------------------- */
- /* Allocate a scratch buffer for generating ~10kHz samples. */
+ /* Allocate a scratch buffer for generating ~10kHz samples. */
/* -------------------------------------------------------------------- */
m_scratch = std::make_unique<int16_t[]>(SCBUF_SIZE);
save_pointer(NAME(m_scratch), SCBUF_SIZE);
@@ -94,7 +100,7 @@ void sp0256_device::device_start()
/* -------------------------------------------------------------------- */
m_halted = 1;
m_filt.rpt = -1;
- m_lrq = 0x8000;
+ m_lrq = 1;
m_page = 0x1000 << 3;
m_silent = 1;
@@ -106,8 +112,6 @@ void sp0256_device::device_start()
// TODO: because of this, check if the bitrev functions are even used anywhere else
// bitrevbuff(m_rom, 0, 0xffff);
- m_lrq_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sp0256_device::set_lrq_timer_proc),this));
-
// save device variables
save_item(NAME(m_sby_line));
save_item(NAME(m_cur_len));
@@ -126,6 +130,7 @@ void sp0256_device::device_start()
save_item(NAME(m_fifo_tail));
save_item(NAME(m_fifo_bitp));
save_item(NAME(m_fifo));
+
// save filter variables
save_item(NAME(m_filt.rpt));
save_item(NAME(m_filt.cnt));
@@ -146,6 +151,9 @@ void sp0256_device::device_start()
void sp0256_device::device_reset()
{
+ if (machine().time() > attotime::zero)
+ m_stream->update();
+
// reset FIFO and SP0256
m_fifo_head = m_fifo_tail = m_fifo_bitp = 0;
@@ -153,10 +161,10 @@ void sp0256_device::device_reset()
m_halted = 1;
m_filt.rpt = -1;
m_filt.rng = 1;
- m_lrq = 0x8000;
- m_ald = 0x0000;
- m_pc = 0x0000;
- m_stack = 0x0000;
+ m_lrq = 1;
+ m_ald = 0;
+ m_pc = 0;
+ m_stack = 0;
m_fifo_sel = 0;
m_mode = 0;
m_page = 0x1000 << 3;
@@ -164,9 +172,6 @@ void sp0256_device::device_reset()
m_sby_line = 0;
m_drq_cb(1);
SET_SBY(1);
-
- m_lrq = 0;
- m_lrq_timer->adjust(attotime::from_ticks(50, m_clock));
}
@@ -730,7 +735,7 @@ void sp0256_device::bitrevbuff(uint8_t *buffer, unsigned int start, unsigned int
/* ======================================================================== */
/* SP0256_GETB -- Get up to 8 bits at the current PC. */
/* ======================================================================== */
-uint32_t sp0256_device::getb( int len )
+uint32_t sp0256_device::getb(int len)
{
uint32_t data;
uint32_t d0, d1;
@@ -759,7 +764,8 @@ uint32_t sp0256_device::getb( int len )
m_fifo_tail++;
m_fifo_bitp -= 10;
}
- } else
+ }
+ else
{
/* ---------------------------------------------------------------- */
/* Figure out which ROMs are being fetched into, and grab two */
@@ -792,8 +798,8 @@ uint32_t sp0256_device::getb( int len )
/* ======================================================================== */
void sp0256_device::micro()
{
- uint8_t immed4;
- uint8_t opcode;
+ uint8_t immed4;
+ uint8_t opcode;
uint16_t cr;
int ctrl_xfer;
int repeat;
@@ -813,7 +819,7 @@ void sp0256_device::micro()
m_pc = m_ald | (0x1000 << 3);
m_fifo_sel = 0;
m_halted = 0;
- m_lrq = 0x8000;
+ m_lrq = 1;
m_ald = 0;
for (i = 0; i < 16; i++)
m_filt.r[i] = 0;
@@ -826,7 +832,7 @@ void sp0256_device::micro()
if (m_halted)
{
m_filt.rpt = 1;
- m_lrq = 0x8000;
+ m_lrq = 1;
m_ald = 0;
for (i = 0; i < 16; i++)
m_filt.r[i] = 0;
@@ -867,10 +873,12 @@ void sp0256_device::micro()
if (immed4) /* SETPAGE */
{
m_page = bitrev32(immed4) >> 13;
- } else
+ }
+
/* -------------------------------------------------------- */
/* Otherwise, this is an RTS / HLT. */
/* -------------------------------------------------------- */
+ else
{
uint32_t btrg;
@@ -890,7 +898,8 @@ void sp0256_device::micro()
m_halted = 1;
m_pc = 0;
ctrl_xfer = 1;
- } else
+ }
+ else
{
m_pc = btrg;
ctrl_xfer = 1;
@@ -907,7 +916,7 @@ void sp0256_device::micro()
case 0xE:
case 0xD:
{
- int btrg;
+ uint32_t btrg;
/* -------------------------------------------------------- */
/* Figure out our branch target. */
@@ -1143,6 +1152,8 @@ void sp0256_device::micro()
void sp0256_device::ald_w(uint8_t data)
{
+ m_stream->update();
+
/* ---------------------------------------------------------------- */
/* Drop writes to the ALD register if we're busy. */
/* ---------------------------------------------------------------- */
@@ -1158,66 +1169,59 @@ void sp0256_device::ald_w(uint8_t data)
/* get the new PC address. */
/* ---------------------------------------------------------------- */
m_lrq = 0;
- m_ald = (0xff & data) << 4;
+ m_ald = data << 4;
m_drq_cb(0);
SET_SBY(0);
-
- return;
}
-READ_LINE_MEMBER( sp0256_device::lrq_r )
+int sp0256_device::lrq_r()
{
- // force stream update
m_stream->update();
-
- return m_lrq == 0x8000;
+ return m_lrq;
}
-READ_LINE_MEMBER( sp0256_device::sby_r )
+int sp0256_device::sby_r()
{
- // TODO: force stream update??
-
+ m_stream->update();
return m_sby_line;
}
uint16_t sp0256_device::spb640_r(offs_t offset)
{
+ m_stream->update();
+ offset &= 1;
+
/* -------------------------------------------------------------------- */
/* Offset 0 returns the SP0256 LRQ status on bit 15. */
/* -------------------------------------------------------------------- */
if (offset == 0)
{
- return m_lrq;
+ return m_lrq << 15;
}
/* -------------------------------------------------------------------- */
/* Offset 1 returns the SPB640 FIFO full status on bit 15. */
/* -------------------------------------------------------------------- */
- if (offset == 1)
+ else
{
return (m_fifo_head - m_fifo_tail) >= 64 ? 0x8000 : 0;
}
-
- /* -------------------------------------------------------------------- */
- /* Just return 255 for all other addresses in our range. */
- /* -------------------------------------------------------------------- */
- return 0x00ff;
}
void sp0256_device::spb640_w(offs_t offset, uint16_t data)
{
+ m_stream->update();
+ offset &= 1;
+
if (offset == 0)
{
ald_w(data & 0xff);
- return;
}
-
- if (offset == 1)
+ else
{
/* ---------------------------------------------------------------- */
/* If Bit 10 is set, reset the FIFO, and SP0256. */
/* ---------------------------------------------------------------- */
-
if (data & 0x400)
{
m_fifo_head = m_fifo_tail = m_fifo_bitp = 0;
@@ -1237,13 +1241,10 @@ void sp0256_device::spb640_w(offs_t offset, uint16_t data)
/* ---------------------------------------------------------------- */
/* FIFO up the lower 10 bits of the data. */
/* ---------------------------------------------------------------- */
-
LOG("spb640: WR_FIFO %.3X %d.%d %d\n", data & 0x3ff,
m_fifo_tail, m_fifo_bitp, m_fifo_head);
m_fifo[m_fifo_head++ & 63] = data & 0x3ff;
-
- return;
}
}
@@ -1254,51 +1255,42 @@ void sp0256_device::set_clock(int clock)
}
-TIMER_CALLBACK_MEMBER(sp0256_device::set_lrq_timer_proc)
-{
- m_lrq = 0x8000;
-}
-
//-------------------------------------------------
// sound_stream_update - handle a stream update
//-------------------------------------------------
-void sp0256_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+void sp0256_device::sound_stream_update(sound_stream &stream)
{
- stream_sample_t *output = outputs[0];
int output_index = 0;
- int length, did_samp/*, old_idx*/;
- while (output_index < samples)
+ while (output_index < stream.samples())
{
/* ---------------------------------------------------------------- */
/* First, drain as much of our scratch buffer as we can into the */
/* sound buffer. */
/* ---------------------------------------------------------------- */
-
while (m_sc_tail != m_sc_head)
{
- output[output_index++] = m_scratch[m_sc_tail++ & SCBUF_MASK];
+ stream.put_int(0, output_index++, m_scratch[m_sc_tail++ & SCBUF_MASK], 32768);
m_sc_tail &= SCBUF_MASK;
- if (output_index > samples)
+ if (output_index >= stream.samples())
break;
}
/* ---------------------------------------------------------------- */
/* If output outputs is full, then we're done. */
/* ---------------------------------------------------------------- */
- if (output_index > samples)
+ if (output_index > stream.samples())
break;
- length = samples - output_index;
+ int length = stream.samples() - output_index;
/* ---------------------------------------------------------------- */
/* Process the current set of filter coefficients as long as the */
/* repeat count holds up and we have room in our scratch buffer. */
/* ---------------------------------------------------------------- */
- did_samp = 0;
- //old_idx = m_sc_head;
+ int did_samp = 0;
if (length > 0) do
{
int do_samp;
@@ -1325,7 +1317,7 @@ void sp0256_device::sound_stream_update(sound_stream &stream, stream_sample_t **
for (int x = 0; x < do_samp; x++)
m_scratch[y++ & SCBUF_MASK] = 0;
m_sc_head += do_samp;
- did_samp += do_samp;
+ did_samp += do_samp;
}
else
{