mirror of
https://github.com/holub/mame
synced 2025-04-19 15:11:37 +03:00
spg2xx: Increased SPU channel count from 6 to 16. Greatly improves audio in most cases. [Ryan Holtz]
This commit is contained in:
parent
a8fc81d360
commit
efb15dc59e
@ -18,7 +18,7 @@ DEFINE_DEVICE_TYPE(SPG28X, spg28x_device, "spg28x", "SPG280-series System-on-a-C
|
||||
|
||||
#define VERBOSE_LEVEL (4)
|
||||
|
||||
#define ENABLE_VERBOSE_LOG (1)
|
||||
#define ENABLE_VERBOSE_LOG (0)
|
||||
|
||||
#if SPG2XX_VISUAL_AUDIO_DEBUG
|
||||
static const uint32_t s_visual_debug_palette[8] = {
|
||||
@ -55,7 +55,7 @@ inline void spg2xx_device::verboselog(int n_level, const char *s_fmt, ...)
|
||||
#define SPG_DEBUG_VIDEO (0)
|
||||
#define SPG_DEBUG_AUDIO (0)
|
||||
#define SPG_DEBUG_ENVELOPES (0)
|
||||
#define SPG_DEBUG_SAMPLES (1)
|
||||
#define SPG_DEBUG_SAMPLES (0)
|
||||
|
||||
#define IO_IRQ_ENABLE m_io_regs[0x21]
|
||||
#define IO_IRQ_STATUS m_io_regs[0x22]
|
||||
@ -110,7 +110,7 @@ void spg2xx_device::map(address_map &map)
|
||||
void spg2xx_device::device_start()
|
||||
{
|
||||
#if SPG2XX_VISUAL_AUDIO_DEBUG
|
||||
m_audio_debug_buffer = std::make_unique<uint8_t[]>(640*480);
|
||||
m_audio_debug_buffer = std::make_unique<uint8_t[]>(1024*768);
|
||||
#endif
|
||||
m_porta_out.resolve_safe();
|
||||
m_portb_out.resolve_safe();
|
||||
@ -135,19 +135,21 @@ void spg2xx_device::device_start()
|
||||
m_audio_beat->adjust(attotime::never);
|
||||
|
||||
m_stream = stream_alloc(0, 2, 44100);
|
||||
|
||||
m_channel_debug = -1;
|
||||
}
|
||||
|
||||
void spg2xx_device::device_reset()
|
||||
{
|
||||
memset(m_audio_regs, 0, 0x800 * sizeof(uint16_t));
|
||||
memset(m_sample_shift, 0, 6);
|
||||
memset(m_sample_count, 0, sizeof(uint32_t) * 6);
|
||||
memset(m_sample_addr, 0, sizeof(uint32_t) * 6);
|
||||
memset(m_channel_rate, 0, sizeof(double) * 6);
|
||||
memset(m_channel_rate_accum, 0, sizeof(double) * 6);
|
||||
memset(m_rampdown_frame, 0, sizeof(uint32_t) * 6);
|
||||
memset(m_envclk_frame, 4, sizeof(uint32_t) * 6);
|
||||
memset(m_envelope_addr, 0, sizeof(uint32_t) * 6);
|
||||
memset(m_sample_shift, 0, 16);
|
||||
memset(m_sample_count, 0, sizeof(uint32_t) * 16);
|
||||
memset(m_sample_addr, 0, sizeof(uint32_t) * 16);
|
||||
memset(m_channel_rate, 0, sizeof(double) * 16);
|
||||
memset(m_channel_rate_accum, 0, sizeof(double) * 16);
|
||||
memset(m_rampdown_frame, 0, sizeof(uint32_t) * 16);
|
||||
memset(m_envclk_frame, 4, sizeof(uint32_t) * 16);
|
||||
memset(m_envelope_addr, 0, sizeof(uint32_t) * 16);
|
||||
|
||||
memset(m_video_regs, 0, 0x100 * sizeof(uint16_t));
|
||||
memset(m_io_regs, 0, 0x200 * sizeof(uint16_t));
|
||||
@ -441,11 +443,11 @@ void spg2xx_device::blit_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect
|
||||
uint32_t spg2xx_device::debug_screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
bitmap.fill(0, cliprect);
|
||||
for (int y = 0; y < 480; y++)
|
||||
for (int y = 0; y < 768; y++)
|
||||
{
|
||||
for (int x = 0; x < 640; x++)
|
||||
for (int x = 0; x < 1024; x++)
|
||||
{
|
||||
bitmap.pix32(y, x) = s_visual_debug_palette[m_audio_debug_buffer[y*640+x]];
|
||||
bitmap.pix32(y, x) = s_visual_debug_palette[m_audio_debug_buffer[y*1024+x]];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -454,7 +456,7 @@ uint32_t spg2xx_device::debug_screen_update(screen_device &screen, bitmap_rgb32
|
||||
void spg2xx_device::advance_debug_pos()
|
||||
{
|
||||
m_audio_debug_x++;
|
||||
if (m_audio_debug_x == 640)
|
||||
if (m_audio_debug_x == 1024)
|
||||
{
|
||||
m_audio_debug_x = 0;
|
||||
}
|
||||
@ -630,6 +632,18 @@ WRITE_LINE_MEMBER(spg2xx_device::vblank)
|
||||
m_debug_samples = !m_debug_samples;
|
||||
if (machine().input().code_pressed_once(KEYCODE_4))
|
||||
m_debug_rates = !m_debug_rates;
|
||||
if (machine().input().code_pressed_once(KEYCODE_1))
|
||||
{
|
||||
m_channel_debug--;
|
||||
if (m_channel_debug < -1)
|
||||
m_channel_debug = 15;
|
||||
}
|
||||
if (machine().input().code_pressed_once(KEYCODE_2))
|
||||
{
|
||||
m_channel_debug++;
|
||||
if (m_channel_debug == 16)
|
||||
m_channel_debug = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
const uint16_t old = VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS;
|
||||
@ -706,7 +720,7 @@ READ16_MEMBER(spg2xx_device::io_r)
|
||||
|
||||
case 0x31: // UART Status
|
||||
verboselog(5, "io_r: UART Status = %04x (%04x)\n", 3, mem_mask);
|
||||
val = 3; // HACK
|
||||
val = 0; // HACK
|
||||
break;
|
||||
|
||||
case 0x36: // UART RX Data
|
||||
@ -774,7 +788,7 @@ WRITE16_MEMBER(spg2xx_device::io_w)
|
||||
|
||||
case 0x21: // IRQ Enable
|
||||
{
|
||||
verboselog(5, "io_w: IRQ Control = %04x (%04x)\n", data, mem_mask);
|
||||
verboselog(4, "io_w: IRQ Enable = %04x (%04x)\n", data, mem_mask);
|
||||
const uint16_t old = IO_IRQ_ENABLE & IO_IRQ_STATUS;
|
||||
COMBINE_DATA(&IO_IRQ_ENABLE);
|
||||
const uint16_t changed = old ^ (IO_IRQ_ENABLE & IO_IRQ_STATUS);
|
||||
@ -938,6 +952,7 @@ void spg2xx_device::check_irqs(const uint16_t changed)
|
||||
// verboselog(0, "audio 1 IRQ\n");
|
||||
// m_cpu->set_input_line(UNSP_IRQ1_LINE, ASSERT_LINE);
|
||||
// }
|
||||
|
||||
if (changed & 0x0c00) // Timer A, Timer B IRQ
|
||||
m_cpu->set_input_line(UNSP_IRQ2_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0c00) ? ASSERT_LINE : CLEAR_LINE);
|
||||
|
||||
@ -1031,7 +1046,7 @@ READ16_MEMBER(spg2xx_device::audio_r)
|
||||
switch (offset)
|
||||
{
|
||||
case AUDIO_CHANNEL_ENABLE:
|
||||
verboselog(0, "audio_r: Channel Enable: %04x\n", data);
|
||||
verboselog(5, "audio_r: Channel Enable: %04x\n", data);
|
||||
break;
|
||||
|
||||
case AUDIO_MAIN_VOLUME:
|
||||
@ -1054,12 +1069,14 @@ READ16_MEMBER(spg2xx_device::audio_r)
|
||||
verboselog(0, "audio_r: Beat Count: %04x\n", data);
|
||||
break;
|
||||
|
||||
case AUDIO_ENVCLK:
|
||||
verboselog(0, "audio_r: Envelope Interval (lo): %04x\n", data);
|
||||
case AUDIO_ENVCLK0:
|
||||
case AUDIO_ENVCLK1:
|
||||
verboselog(0, "audio_r: Envelope Interval %d (lo): %04x\n", offset == AUDIO_ENVCLK0 ? 0 : 1, data);
|
||||
break;
|
||||
|
||||
case AUDIO_ENVCLK_HIGH:
|
||||
verboselog(0, "audio_r: Envelope Interval (hi): %04x\n", data);
|
||||
case AUDIO_ENVCLK0_HIGH:
|
||||
case AUDIO_ENVCLK1_HIGH:
|
||||
verboselog(0, "audio_r: Envelope Interval %d (hi): %04x\n", offset == AUDIO_ENVCLK0_HIGH ? 0 : 1, data);
|
||||
break;
|
||||
|
||||
case AUDIO_ENV_RAMP_DOWN:
|
||||
@ -1067,7 +1084,7 @@ READ16_MEMBER(spg2xx_device::audio_r)
|
||||
break;
|
||||
|
||||
case AUDIO_CHANNEL_STOP:
|
||||
verboselog(0, "audio_r: Channel Stop Status: %04x\n", data);
|
||||
verboselog(5, "audio_r: Channel Stop Status: %04x\n", data);
|
||||
break;
|
||||
|
||||
case AUDIO_CHANNEL_ZERO_CROSS:
|
||||
@ -1151,7 +1168,7 @@ READ16_MEMBER(spg2xx_device::audio_r)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (channel < 6)
|
||||
else if (channel < 16)
|
||||
{
|
||||
switch (offset & AUDIO_CHAN_OFFSET_MASK)
|
||||
{
|
||||
@ -1253,6 +1270,10 @@ READ16_MEMBER(spg2xx_device::audio_r)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (channel >= 16)
|
||||
{
|
||||
logerror("audio_r: Trying to read from channel %d\n", channel);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -1268,19 +1289,21 @@ WRITE16_MEMBER(spg2xx_device::audio_w)
|
||||
{
|
||||
verboselog(0, "audio_w: Channel Enable: %04x\n", data);
|
||||
const uint16_t changed = m_audio_regs[AUDIO_CHANNEL_STATUS] ^ data;
|
||||
for (uint32_t channel_bit = 0; channel_bit < 6; channel_bit++)
|
||||
for (uint32_t channel_bit = 0; channel_bit < 16; channel_bit++)
|
||||
{
|
||||
const uint16_t mask = 1 << channel_bit;
|
||||
if (!(changed & mask))
|
||||
continue;
|
||||
|
||||
//if (channel_bit == 10)
|
||||
//continue;
|
||||
if (data & mask)
|
||||
{
|
||||
//printf("Enabling channel %d\n", channel_bit);
|
||||
verboselog(0, "Enabling channel %d\n", channel_bit);
|
||||
m_audio_regs[offset] |= mask;
|
||||
if (!(m_audio_regs[AUDIO_CHANNEL_STOP] & mask))
|
||||
{
|
||||
//printf("Stop not set, starting playback on channel %d, mask %04x\n", channel_bit, mask);
|
||||
verboselog(0, "Stop not set, starting playback on channel %d, mask %04x\n", channel_bit, mask);
|
||||
m_audio_regs[AUDIO_CHANNEL_STATUS] |= mask;
|
||||
m_sample_addr[channel_bit] = get_wave_addr(channel_bit);
|
||||
m_envelope_addr[channel_bit] = get_envelope_addr(channel_bit);
|
||||
@ -1338,52 +1361,48 @@ WRITE16_MEMBER(spg2xx_device::audio_w)
|
||||
break;
|
||||
}
|
||||
|
||||
case AUDIO_ENVCLK:
|
||||
case AUDIO_ENVCLK0:
|
||||
case AUDIO_ENVCLK1:
|
||||
{
|
||||
verboselog(0, "audio_w: Envelope Interval (lo): %04x\n", data);
|
||||
verboselog(0, "audio_w: Envelope Interval %d (lo): %04x\n", offset == AUDIO_ENVCLK0 ? 0 : 1, data);
|
||||
const uint16_t old = m_audio_regs[offset];
|
||||
m_audio_regs[offset] = data;
|
||||
const uint16_t changed = old ^ m_audio_regs[offset];
|
||||
|
||||
if (!changed)
|
||||
{
|
||||
if (SPG_DEBUG_ENVELOPES) logerror("No change, %04x %04x %04x\n", old, data, m_audio_regs[offset]);
|
||||
break;
|
||||
}
|
||||
|
||||
const uint8_t channel_offset = offset == AUDIO_ENVCLK0 ? 0 : 8;
|
||||
for (uint8_t channel_bit = 0; channel_bit < 4; channel_bit++)
|
||||
{
|
||||
const uint8_t shift = channel_bit << 2;
|
||||
const uint16_t mask = 0x0f << shift;
|
||||
if (changed & mask)
|
||||
{
|
||||
m_envclk_frame[channel_bit] = get_envclk_frame_count(channel_bit);
|
||||
if (SPG_DEBUG_ENVELOPES) logerror("envclk_frame %d: %08x\n", channel_bit, m_envclk_frame[channel_bit]);
|
||||
m_envclk_frame[channel_bit + channel_offset] = get_envclk_frame_count(channel_bit + channel_offset);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case AUDIO_ENVCLK_HIGH:
|
||||
case AUDIO_ENVCLK0_HIGH:
|
||||
case AUDIO_ENVCLK1_HIGH:
|
||||
{
|
||||
verboselog(0, "audio_w: Envelope Interval (hi): %04x\n", data);
|
||||
verboselog(0, "audio_w: Envelope Interval %d (hi): %04x\n", offset == AUDIO_ENVCLK0_HIGH ? 0 : 1, data);
|
||||
const uint16_t old = m_audio_regs[offset];
|
||||
m_audio_regs[offset] = data & AUDIO_ENVCLK_HIGH_MASK;
|
||||
m_audio_regs[offset] = data;
|
||||
const uint16_t changed = old ^ m_audio_regs[offset];
|
||||
if (!changed)
|
||||
{
|
||||
if (SPG_DEBUG_ENVELOPES) logerror("No change, %04x %04x %04x\n", old, data, m_audio_regs[offset]);
|
||||
break;
|
||||
}
|
||||
|
||||
for (uint8_t channel_bit = 0; channel_bit < 2; channel_bit++)
|
||||
const uint8_t channel_offset = offset == AUDIO_ENVCLK0_HIGH ? 0 : 8;
|
||||
for (uint8_t channel_bit = 0; channel_bit < 4; channel_bit++)
|
||||
{
|
||||
const uint8_t shift = channel_bit << 2;
|
||||
const uint16_t mask = 0x0f << shift;
|
||||
if (changed & mask)
|
||||
{
|
||||
m_envclk_frame[channel_bit + 4] = get_envclk_frame_count(channel_bit);
|
||||
if (SPG_DEBUG_ENVELOPES) logerror("envclk_frame %d: %08x\n", channel_bit + 4, m_envclk_frame[channel_bit + 4]);
|
||||
m_envclk_frame[channel_bit + channel_offset + 4] = get_envclk_frame_count(channel_bit + channel_offset);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1402,7 +1421,7 @@ WRITE16_MEMBER(spg2xx_device::audio_w)
|
||||
break;
|
||||
}
|
||||
|
||||
for (uint32_t channel_bit = 0; channel_bit < 6; channel_bit++)
|
||||
for (uint32_t channel_bit = 0; channel_bit < 16; channel_bit++)
|
||||
{
|
||||
const uint16_t mask = 1 << channel_bit;
|
||||
if ((changed & mask) && (data & mask))
|
||||
@ -1524,7 +1543,7 @@ WRITE16_MEMBER(spg2xx_device::audio_w)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (channel < 6)
|
||||
else if (channel < 16)
|
||||
{
|
||||
switch (offset & AUDIO_CHAN_OFFSET_MASK)
|
||||
{
|
||||
@ -1558,7 +1577,7 @@ WRITE16_MEMBER(spg2xx_device::audio_w)
|
||||
|
||||
case AUDIO_ENVELOPE_DATA:
|
||||
m_audio_regs[offset] = data & AUDIO_ENVELOPE_DATA_MASK;
|
||||
verboselog(0, "audio_w: Channel %d: Envelope Data: %04x (CNT:%d, EDD:%02x)\n", channel, data,
|
||||
verboselog(5, "audio_w: Channel %d: Envelope Data: %04x (CNT:%d, EDD:%02x)\n", channel, data,
|
||||
get_envelope_count(channel), get_edd(channel));
|
||||
break;
|
||||
|
||||
@ -1605,7 +1624,7 @@ WRITE16_MEMBER(spg2xx_device::audio_w)
|
||||
m_audio_regs[offset] = data & AUDIO_PHASE_HIGH_MASK;
|
||||
m_channel_rate[channel] = ((double)get_phase(channel) * 140625.0 * 2.0) / (double)(1 << 19);
|
||||
m_channel_rate_accum[channel] = 0.0;
|
||||
verboselog(0, "audio_w: Channel %d: Phase High: %04x (rate: %f)\n", channel, data, m_channel_rate[channel]);
|
||||
verboselog(5, "audio_w: Channel %d: Phase High: %04x (rate: %f)\n", channel, data, m_channel_rate[channel]);
|
||||
break;
|
||||
|
||||
case AUDIO_PHASE_ACCUM_HIGH:
|
||||
@ -1627,7 +1646,7 @@ WRITE16_MEMBER(spg2xx_device::audio_w)
|
||||
m_audio_regs[offset] = data;
|
||||
m_channel_rate[channel] = ((double)get_phase(channel) * 140625.0 * 2.0) / (double)(1 << 19);
|
||||
m_channel_rate_accum[channel] = 0.0;
|
||||
verboselog(0, "audio_w: Channel %d: Phase: %04x (rate: %f)\n", channel, data, m_channel_rate[channel]);
|
||||
verboselog(5, "audio_w: Channel %d: Phase: %04x (rate: %f)\n", channel, data, m_channel_rate[channel]);
|
||||
break;
|
||||
|
||||
case AUDIO_PHASE_ACCUM:
|
||||
@ -1652,6 +1671,10 @@ WRITE16_MEMBER(spg2xx_device::audio_w)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (channel >= 16)
|
||||
{
|
||||
logerror("audio_r: Trying to write from channel %d: %04x = %04x & %04x\n", channel, 0x3000 + offset, data, mem_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_audio_regs[offset] = data;
|
||||
@ -1671,24 +1694,37 @@ void spg2xx_device::sound_stream_update(sound_stream &stream, stream_sample_t **
|
||||
int32_t active_count = 0;
|
||||
|
||||
#if SPG2XX_VISUAL_AUDIO_DEBUG
|
||||
for (int y = 0; y < 480; y++)
|
||||
for (int y = 0; y < 768; y++)
|
||||
{
|
||||
m_audio_debug_buffer[y*640 + m_audio_debug_x] = 0;
|
||||
m_audio_debug_buffer[y*1024 + m_audio_debug_x] = 0;
|
||||
}
|
||||
#endif
|
||||
for (uint32_t ch_index = 0; ch_index < 6; ch_index++)
|
||||
for (uint32_t ch_index = 0; ch_index < 16; ch_index++)
|
||||
{
|
||||
#if SPG2XX_VISUAL_AUDIO_DEBUG
|
||||
const uint32_t debug_y = ch_index * 80;
|
||||
uint32_t debug_y = 0;
|
||||
if (m_channel_debug < 0)
|
||||
debug_y = ch_index * 48;
|
||||
#endif
|
||||
if (!get_channel_status(ch_index))
|
||||
{
|
||||
#if SPG2XX_VISUAL_AUDIO_DEBUG
|
||||
m_audio_debug_buffer[(debug_y + 79)*640 + m_audio_debug_x] |= SPG_VDB_WAVE;
|
||||
int edd_y = (int)((float)get_edd(ch_index) * 0.625f);
|
||||
m_audio_debug_buffer[(debug_y + edd_y)*640 + m_audio_debug_x] |= SPG_VDB_EDD;
|
||||
int vol_y = (int)((float)get_volume(ch_index) * 0.625f);
|
||||
m_audio_debug_buffer[(debug_y + vol_y)*640 + m_audio_debug_x] |= SPG_VDB_VOL;
|
||||
if (m_channel_debug == -1)
|
||||
{
|
||||
m_audio_debug_buffer[(debug_y + 47)*1024 + m_audio_debug_x] |= SPG_VDB_WAVE;
|
||||
int edd_y = (int)((float)get_edd(ch_index) * 0.375f);
|
||||
m_audio_debug_buffer[(debug_y + (47 - edd_y))*1024 + m_audio_debug_x] |= SPG_VDB_EDD;
|
||||
int vol_y = (int)((float)get_volume(ch_index) * 0.375f);
|
||||
m_audio_debug_buffer[(debug_y + (47 - vol_y))*1024 + m_audio_debug_x] |= SPG_VDB_VOL;
|
||||
}
|
||||
else if (ch_index == m_channel_debug)
|
||||
{
|
||||
m_audio_debug_buffer[(debug_y + 767)*1024 + m_audio_debug_x] |= SPG_VDB_WAVE;
|
||||
int edd_y = (int)((float)get_edd(ch_index) * 3.74f);
|
||||
m_audio_debug_buffer[(debug_y + (767 - edd_y))*1024 + m_audio_debug_x] |= SPG_VDB_EDD;
|
||||
int vol_y = (int)((float)get_volume(ch_index) * 3.74f);
|
||||
m_audio_debug_buffer[(debug_y + (767 - vol_y))*1024 + m_audio_debug_x] |= SPG_VDB_VOL;
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
@ -1700,12 +1736,24 @@ void spg2xx_device::sound_stream_update(sound_stream &stream, stream_sample_t **
|
||||
{
|
||||
int32_t sample = (int16_t)(m_audio_regs[(ch_index << 4) | AUDIO_WAVE_DATA] ^ 0x8000);
|
||||
#if SPG2XX_VISUAL_AUDIO_DEBUG
|
||||
int sample_y = (int)((float)m_audio_regs[(ch_index << 4) | AUDIO_WAVE_DATA] / 819.0f);
|
||||
m_audio_debug_buffer[(debug_y + sample_y)*640 + m_audio_debug_x] |= SPG_VDB_WAVE;
|
||||
int edd_y = (int)((float)get_edd(ch_index) * 0.625f);
|
||||
m_audio_debug_buffer[(debug_y + edd_y)*640 + m_audio_debug_x] |= SPG_VDB_EDD;
|
||||
int vol_y = (int)((float)get_volume(ch_index) * 0.625f);
|
||||
m_audio_debug_buffer[(debug_y + vol_y)*640 + m_audio_debug_x] |= SPG_VDB_VOL;
|
||||
if (m_channel_debug == -1)
|
||||
{
|
||||
int sample_y = (int)((float)m_audio_regs[(ch_index << 4) | AUDIO_WAVE_DATA] / 1365.0f);
|
||||
m_audio_debug_buffer[(debug_y + (47 - sample_y))*1024 + m_audio_debug_x] |= SPG_VDB_WAVE;
|
||||
int edd_y = (int)((float)get_edd(ch_index) * 0.375f);
|
||||
m_audio_debug_buffer[(debug_y + (47 - edd_y))*1024 + m_audio_debug_x] |= SPG_VDB_EDD;
|
||||
int vol_y = (int)((float)get_volume(ch_index) * 0.375f);
|
||||
m_audio_debug_buffer[(debug_y + (47 - vol_y))*1024 + m_audio_debug_x] |= SPG_VDB_VOL;
|
||||
}
|
||||
else if (ch_index == m_channel_debug)
|
||||
{
|
||||
int sample_y = (int)((float)m_audio_regs[(ch_index << 4) | AUDIO_WAVE_DATA] / 136.0f);
|
||||
m_audio_debug_buffer[(debug_y + (767 - sample_y))*1024 + m_audio_debug_x] |= SPG_VDB_WAVE;
|
||||
int edd_y = (int)((float)get_edd(ch_index) * 0.375f);
|
||||
m_audio_debug_buffer[(debug_y + (767 - edd_y))*1024 + m_audio_debug_x] |= SPG_VDB_EDD;
|
||||
int vol_y = (int)((float)get_volume(ch_index) * 0.375f);
|
||||
m_audio_debug_buffer[(debug_y + (767 - vol_y))*1024 + m_audio_debug_x] |= SPG_VDB_VOL;
|
||||
}
|
||||
#endif
|
||||
if (!(m_audio_regs[AUDIO_CONTROL] & AUDIO_CONTROL_NOINT_MASK))
|
||||
{
|
||||
@ -1756,12 +1804,13 @@ void spg2xx_device::sound_stream_update(sound_stream &stream, stream_sample_t **
|
||||
}
|
||||
|
||||
#if SPG2XX_VISUAL_AUDIO_DEBUG
|
||||
for (int y = 0; y < 480; y++)
|
||||
for (int y = 0; y < 768; y++)
|
||||
{
|
||||
m_audio_debug_buffer[y*640 + m_audio_debug_x] = 7;
|
||||
m_audio_debug_buffer[y*1024 + m_audio_debug_x] = 7;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
//printf("\n");
|
||||
}
|
||||
|
||||
inline void spg2xx_device::stop_channel(const uint32_t channel)
|
||||
@ -1769,7 +1818,7 @@ inline void spg2xx_device::stop_channel(const uint32_t channel)
|
||||
// TODO: IRQs
|
||||
m_audio_regs[AUDIO_CHANNEL_STATUS] &= ~(1 << channel);
|
||||
m_audio_regs[AUDIO_CHANNEL_STOP] |= (1 << channel);
|
||||
m_audio_regs[(channel << 4) | AUDIO_MODE] &= ~AUDIO_ADPCM_MASK;
|
||||
//m_audio_regs[(channel << 4) | AUDIO_MODE] &= ~AUDIO_ADPCM_MASK;
|
||||
m_audio_regs[AUDIO_CHANNEL_TONE_RELEASE] &= ~(1 << channel);
|
||||
}
|
||||
|
||||
@ -1851,7 +1900,7 @@ bool spg2xx_device::fetch_sample(address_space &space, const uint32_t channel)
|
||||
{
|
||||
// ADPCM mode
|
||||
m_audio_regs[wave_data_reg] >>= m_sample_shift[channel];
|
||||
m_audio_regs[wave_data_reg] = (uint16_t)(m_adpcm[channel].clock((uint8_t)(m_audio_regs[wave_data_reg] & 0x000f)) * 8) ^ 0x8000;
|
||||
m_audio_regs[wave_data_reg] = (uint16_t)(m_adpcm[channel].clock((uint8_t)(m_audio_regs[wave_data_reg] & 0x000f)) * 7) ^ 0x8000;
|
||||
if (tone_mode != 0 && raw_sample == 0xffff)
|
||||
{
|
||||
if (tone_mode == AUDIO_TONE_MODE_HW_ONESHOT)
|
||||
@ -1936,12 +1985,12 @@ void spg2xx_device::audio_frame_tick()
|
||||
audio_beat_tick();
|
||||
|
||||
address_space &space = m_cpu->space(AS_PROGRAM);
|
||||
for (uint32_t channel = 0; channel < 6; channel++)
|
||||
bool any_changed = false;
|
||||
for (uint32_t channel = 0; channel < 16; channel++)
|
||||
{
|
||||
const uint16_t mask = (1 << channel);
|
||||
if (!(m_audio_regs[AUDIO_CHANNEL_STATUS] & mask))
|
||||
{
|
||||
//if (SPG_DEBUG_ENVELOPES) printf("Skipping channel due to status\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1950,10 +1999,11 @@ void spg2xx_device::audio_frame_tick()
|
||||
m_rampdown_frame[channel]--;
|
||||
if (m_rampdown_frame[channel] == 0)
|
||||
{
|
||||
logerror("Ticking rampdown for channel %d\n", channel);
|
||||
if (SPG_DEBUG_ENVELOPES) logerror("Ticking rampdown for channel %d\n", channel);
|
||||
audio_rampdown_tick(channel);
|
||||
continue;
|
||||
any_changed = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(m_audio_regs[AUDIO_CHANNEL_ENV_MODE] & mask))
|
||||
@ -1962,14 +2012,15 @@ void spg2xx_device::audio_frame_tick()
|
||||
if (m_envclk_frame[channel] == 0)
|
||||
{
|
||||
if (SPG_DEBUG_ENVELOPES) logerror("Ticking envelope for channel %d\n", channel);
|
||||
audio_envelope_tick(space, channel);
|
||||
any_changed = audio_envelope_tick(space, channel) || any_changed;
|
||||
m_envclk_frame[channel] = get_envclk_frame_count(channel);
|
||||
}
|
||||
}
|
||||
else if (SPG_DEBUG_ENVELOPES)
|
||||
{
|
||||
//logerror("Not ticking envelope for channel %d\n", channel);
|
||||
}
|
||||
}
|
||||
|
||||
if (any_changed)
|
||||
{
|
||||
m_stream->update();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1982,7 +2033,7 @@ void spg2xx_device::audio_beat_tick()
|
||||
m_audio_curr_beat_base_count--;
|
||||
if (m_audio_curr_beat_base_count == 0)
|
||||
{
|
||||
//printf("Beat base count elapsed, reloading with %d\n", m_audio_regs[AUDIO_BEAT_BASE_COUNT]);
|
||||
logerror("Beat base count elapsed, reloading with %d\n", m_audio_regs[AUDIO_BEAT_BASE_COUNT]);
|
||||
m_audio_curr_beat_base_count = m_audio_regs[AUDIO_BEAT_BASE_COUNT];
|
||||
|
||||
beat_count--;
|
||||
@ -1992,13 +2043,13 @@ void spg2xx_device::audio_beat_tick()
|
||||
{
|
||||
if (m_audio_regs[AUDIO_BEAT_COUNT] & AUDIO_BIE_MASK)
|
||||
{
|
||||
//printf("Beat count elapsed, triggering IRQ\n");
|
||||
logerror("Beat count elapsed, setting Status bit and checking IRQs\n");
|
||||
m_audio_regs[AUDIO_BEAT_COUNT] |= AUDIO_BIS_MASK;
|
||||
check_irqs(AUDIO_BIS_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("Beat count elapsed but IRQ not enabled\n");
|
||||
logerror("Beat count elapsed but IRQ not enabled\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2054,17 +2105,22 @@ uint32_t spg2xx_device::get_envclk_frame_count(const uint32_t channel)
|
||||
uint32_t spg2xx_device::get_envelope_clock(const offs_t channel) const
|
||||
{
|
||||
if (channel < 4)
|
||||
return (m_audio_regs[AUDIO_ENVCLK] >> (channel << 2)) & 0x000f;
|
||||
return (m_audio_regs[AUDIO_ENVCLK0] >> (channel << 2)) & 0x000f;
|
||||
else if (channel < 8)
|
||||
return (m_audio_regs[AUDIO_ENVCLK0_HIGH] >> ((channel - 4) << 2)) & 0x000f;
|
||||
else if (channel < 12)
|
||||
return (m_audio_regs[AUDIO_ENVCLK1] >> ((channel - 8) << 2)) & 0x000f;
|
||||
else
|
||||
return (m_audio_regs[AUDIO_ENVCLK_HIGH] >> ((channel - 4) << 2)) & 0x000f;
|
||||
return (m_audio_regs[AUDIO_ENVCLK1_HIGH] >> ((channel - 12) << 2)) & 0x000f;
|
||||
}
|
||||
|
||||
void spg2xx_device::audio_envelope_tick(address_space &space, const uint32_t channel)
|
||||
bool spg2xx_device::audio_envelope_tick(address_space &space, const uint32_t channel)
|
||||
{
|
||||
const uint16_t channel_mask = channel << 4;
|
||||
uint16_t new_count = get_envelope_count(channel);
|
||||
const uint16_t curr_edd = get_edd(channel);
|
||||
if (SPG_DEBUG_ENVELOPES) logerror("envelope %d tick, count is %04x, curr edd is %04x\n", channel, new_count, curr_edd);
|
||||
bool edd_changed = false;
|
||||
if (new_count == 0)
|
||||
{
|
||||
const uint16_t target = get_envelope_target(channel);
|
||||
@ -2086,7 +2142,7 @@ void spg2xx_device::audio_envelope_tick(address_space &space, const uint32_t cha
|
||||
{
|
||||
if (SPG_DEBUG_ENVELOPES) logerror("Envelope %d at 0, stopping channel\n", channel);
|
||||
stop_channel(channel);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -2128,22 +2184,19 @@ void spg2xx_device::audio_envelope_tick(address_space &space, const uint32_t cha
|
||||
if (SPG_DEBUG_ENVELOPES) logerror("Fetched envelopes %04x %04x\n", m_audio_regs[channel_mask | AUDIO_ENVELOPE0], m_audio_regs[channel_mask | AUDIO_ENVELOPE1]);
|
||||
m_envelope_addr[channel] += 2;
|
||||
}
|
||||
// FIXME: This makes things sound markedly worse even though the docs indicate
|
||||
// the envelope count should be reloaded by the envelope load register! Why?
|
||||
set_envelope_count(channel, get_envelope_load(channel));
|
||||
new_count = get_envelope_load(channel);
|
||||
set_envelope_count(channel, new_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SPG_DEBUG_ENVELOPES) logerror("Envelope %d not yet at target %04x (%04x)\n", channel, target, new_edd);
|
||||
// FIXME: This makes things sound markedly worse even though the docs indicate
|
||||
// the envelope count should be reloaded by the envelope load register! So instead,
|
||||
// we just reload with zero, which at least keeps the channels going. Why?
|
||||
new_count = get_envelope_load(channel);
|
||||
set_envelope_count(channel, new_count);
|
||||
}
|
||||
if (SPG_DEBUG_ENVELOPES) logerror("Envelope %d new count %04x\n", channel, new_count);
|
||||
|
||||
set_edd(channel, new_edd);
|
||||
edd_changed = true;
|
||||
if (SPG_DEBUG_ENVELOPES) logerror("Setting channel %d edd to %04x, register is %04x\n", channel, new_edd, m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_DATA]);
|
||||
}
|
||||
else
|
||||
@ -2152,4 +2205,5 @@ void spg2xx_device::audio_envelope_tick(address_space &space, const uint32_t cha
|
||||
set_envelope_count(channel, new_count);
|
||||
}
|
||||
if (SPG_DEBUG_ENVELOPES) logerror("envelope %d post-tick, count is now %04x, register is %04x\n", channel, new_count, m_audio_regs[(channel << 4) | AUDIO_ENVELOPE_DATA]);
|
||||
return edd_changed;
|
||||
}
|
@ -81,7 +81,7 @@ protected:
|
||||
void audio_frame_tick();
|
||||
void audio_beat_tick();
|
||||
void audio_rampdown_tick(const uint32_t channel);
|
||||
void audio_envelope_tick(address_space &space, const uint32_t channel);
|
||||
bool audio_envelope_tick(address_space &space, const uint32_t channel);
|
||||
inline uint32_t get_rampdown_frame_count(const uint32_t channel);
|
||||
inline uint32_t get_envclk_frame_count(const uint32_t channel);
|
||||
|
||||
@ -245,16 +245,16 @@ protected:
|
||||
AUDIO_CHAN_OFFSET_MASK = 0xf0f,
|
||||
|
||||
AUDIO_CHANNEL_ENABLE = 0x400,
|
||||
AUDIO_CHANNEL_ENABLE_MASK = 0x003f,
|
||||
AUDIO_CHANNEL_ENABLE_MASK = 0xffff,
|
||||
|
||||
AUDIO_MAIN_VOLUME = 0x401,
|
||||
AUDIO_MAIN_VOLUME_MASK = 0x007f,
|
||||
|
||||
AUDIO_CHANNEL_FIQ_ENABLE = 0x402,
|
||||
AUDIO_CHANNEL_FIQ_ENABLE_MASK = 0x003f,
|
||||
AUDIO_CHANNEL_FIQ_ENABLE_MASK = 0xffff,
|
||||
|
||||
AUDIO_CHANNEL_FIQ_STATUS = 0x403,
|
||||
AUDIO_CHANNEL_FIQ_STATUS_MASK = 0x003f,
|
||||
AUDIO_CHANNEL_FIQ_STATUS_MASK = 0xffff,
|
||||
|
||||
AUDIO_BEAT_BASE_COUNT = 0x404,
|
||||
AUDIO_BEAT_BASE_COUNT_MASK = 0x07ff,
|
||||
@ -264,19 +264,24 @@ protected:
|
||||
AUDIO_BIS_MASK = 0x4000,
|
||||
AUDIO_BIE_MASK = 0x8000,
|
||||
|
||||
AUDIO_ENVCLK = 0x406,
|
||||
AUDIO_ENVCLK0 = 0x406,
|
||||
|
||||
AUDIO_ENVCLK_HIGH = 0x407,
|
||||
AUDIO_ENVCLK_HIGH_MASK = 0x00ff,
|
||||
AUDIO_ENVCLK0_HIGH = 0x407,
|
||||
AUDIO_ENVCLK0_HIGH_MASK = 0xffff,
|
||||
|
||||
AUDIO_ENVCLK1 = 0x408,
|
||||
|
||||
AUDIO_ENVCLK1_HIGH = 0x409,
|
||||
AUDIO_ENVCLK1_HIGH_MASK = 0xffff,
|
||||
|
||||
AUDIO_ENV_RAMP_DOWN = 0x40a,
|
||||
AUDIO_ENV_RAMP_DOWN_MASK = 0x003f,
|
||||
AUDIO_ENV_RAMP_DOWN_MASK = 0xffff,
|
||||
|
||||
AUDIO_CHANNEL_STOP = 0x40b,
|
||||
AUDIO_CHANNEL_STOP_MASK = 0x003f,
|
||||
AUDIO_CHANNEL_STOP_MASK = 0xffff,
|
||||
|
||||
AUDIO_CHANNEL_ZERO_CROSS = 0x40c,
|
||||
AUDIO_CHANNEL_ZERO_CROSS_MASK = 0x003f,
|
||||
AUDIO_CHANNEL_ZERO_CROSS_MASK = 0xffff,
|
||||
|
||||
AUDIO_CONTROL = 0x40d,
|
||||
AUDIO_CONTROL_MASK = 0x9fe8,
|
||||
@ -303,7 +308,7 @@ protected:
|
||||
AUDIO_COMPRESS_CTRL_RATIO_MASK = 0x0007,
|
||||
|
||||
AUDIO_CHANNEL_STATUS = 0x40f,
|
||||
AUDIO_CHANNEL_STATUS_MASK = 0x003f,
|
||||
AUDIO_CHANNEL_STATUS_MASK = 0xffff,
|
||||
|
||||
AUDIO_WAVE_IN_L = 0x410,
|
||||
|
||||
@ -318,19 +323,19 @@ protected:
|
||||
AUDIO_WAVE_OUT_R = 0x413,
|
||||
|
||||
AUDIO_CHANNEL_REPEAT = 0x414,
|
||||
AUDIO_CHANNEL_REPEAT_MASK = 0x003f,
|
||||
AUDIO_CHANNEL_REPEAT_MASK = 0xffff,
|
||||
|
||||
AUDIO_CHANNEL_ENV_MODE = 0x415,
|
||||
AUDIO_CHANNEL_ENV_MODE_MASK = 0x003f,
|
||||
AUDIO_CHANNEL_ENV_MODE_MASK = 0xffff,
|
||||
|
||||
AUDIO_CHANNEL_TONE_RELEASE = 0x416,
|
||||
AUDIO_CHANNEL_TONE_RELEASE_MASK = 0x003f,
|
||||
AUDIO_CHANNEL_TONE_RELEASE_MASK = 0xffff,
|
||||
|
||||
AUDIO_CHANNEL_ENV_IRQ = 0x417,
|
||||
AUDIO_CHANNEL_ENV_IRQ_MASK = 0x003f,
|
||||
AUDIO_CHANNEL_ENV_IRQ_MASK = 0xffff,
|
||||
|
||||
AUDIO_CHANNEL_PITCH_BEND = 0x418,
|
||||
AUDIO_CHANNEL_PITCH_BEND_MASK = 0x003f,
|
||||
AUDIO_CHANNEL_PITCH_BEND_MASK = 0xffff,
|
||||
|
||||
AUDIO_SOFT_PHASE = 0x419,
|
||||
|
||||
@ -411,14 +416,15 @@ protected:
|
||||
bool m_debug_rates;
|
||||
|
||||
uint16_t m_audio_regs[0x800];
|
||||
uint8_t m_sample_shift[6];
|
||||
uint32_t m_sample_count[6];
|
||||
uint32_t m_sample_addr[6];
|
||||
double m_channel_rate[6];
|
||||
double m_channel_rate_accum[6];
|
||||
uint32_t m_rampdown_frame[6];
|
||||
uint32_t m_envclk_frame[6];
|
||||
uint32_t m_envelope_addr[6];
|
||||
uint8_t m_sample_shift[16];
|
||||
uint32_t m_sample_count[16];
|
||||
uint32_t m_sample_addr[16];
|
||||
double m_channel_rate[16];
|
||||
double m_channel_rate_accum[16];
|
||||
uint32_t m_rampdown_frame[16];
|
||||
uint32_t m_envclk_frame[16];
|
||||
uint32_t m_envelope_addr[16];
|
||||
int m_channel_debug;
|
||||
uint16_t m_audio_curr_beat_base_count;
|
||||
|
||||
uint16_t m_video_regs[0x100];
|
||||
@ -444,7 +450,7 @@ protected:
|
||||
emu_timer *m_audio_beat;
|
||||
|
||||
sound_stream *m_stream;
|
||||
oki_adpcm_state m_adpcm[6];
|
||||
oki_adpcm_state m_adpcm[16];
|
||||
|
||||
required_device<cpu_device> m_cpu;
|
||||
required_device<screen_device> m_screen;
|
||||
|
@ -50,12 +50,26 @@ also on this hardware
|
||||
Dream Life ? x16 48 not dumped no Sunplus
|
||||
|
||||
Detailed list of bugs:
|
||||
- When loading a cart from file manager, sometimes it will crash
|
||||
- On 'vii_vc1' & 'vii_vc2' cart, the left-right keys are transposed with the up-down keys
|
||||
- In the default bios (no cart loaded):
|
||||
-- The "MOTOR" option in the diagnostic menu does nothing when selected
|
||||
- Zone 60 / Wireless 60:
|
||||
-- Basketball: emulator crashes when starting the game due to jumping to invalid code.
|
||||
|
||||
- all systems:
|
||||
Various inaccuracies in samples/envelopes.
|
||||
- vsmile:
|
||||
Games loop the first legal screen rather than continuing.
|
||||
- walle:
|
||||
Voice sample on the title screen is continually retriggered by the game code.
|
||||
Title screen lacks New Game / Continue Game menu options.
|
||||
- rad_skat:
|
||||
Palette issues on the High Score screen.
|
||||
- vii:
|
||||
Music does not loop.
|
||||
When loading a cart from file manager, sometimes MAME will crash.
|
||||
The "MOTOR" option in the diagnostic menu does nothing when selected.
|
||||
The "SPEECH IC" option in the diagnostic menu does nothing when selected.
|
||||
On 'vii_vc1' & 'vii_vc2' cart, the left-right keys are transposed with the up-down keys.
|
||||
This is not a bug per se, as the games are played with the controller physically rotated 90 degrees.
|
||||
- zone60/wirels60:
|
||||
All Games: Music does not loop.
|
||||
Basketball: MAME fatalerrors when starting the game due to jumping to invalid code.
|
||||
|
||||
|
||||
*******************************************************************************/
|
||||
@ -638,8 +652,8 @@ void spg2xx_game_state::spg2xx_base(machine_config &config)
|
||||
#if SPG2XX_VISUAL_AUDIO_DEBUG
|
||||
SCREEN(config, m_debug_screen, SCREEN_TYPE_RASTER);
|
||||
m_debug_screen->set_refresh_hz(60);
|
||||
m_debug_screen->set_size(640, 480);
|
||||
m_debug_screen->set_visarea(0, 640-1, 0, 480-1);
|
||||
m_debug_screen->set_size(1024, 768);
|
||||
m_debug_screen->set_visarea(0, 1024-1, 0, 768-1);
|
||||
m_debug_screen->set_screen_update("spg", FUNC(spg2xx_device::debug_screen_update));
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user