spg2xx: Increased SPU channel count from 6 to 16. Greatly improves audio in most cases. [Ryan Holtz]

This commit is contained in:
mooglyguy 2018-10-13 18:33:17 +02:00
parent a8fc81d360
commit efb15dc59e
3 changed files with 196 additions and 122 deletions

View File

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

View File

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

View File

@ -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