XaviX - add rate control to sound (#4290)

* XaviX - add rate control to sound

* make sound stereo (nw)

* (nw)

* improved logging of sound (nw)

* (nw)

* maybe, allows monster truck race start sample to complete, but then other sounds go missing (nw)

* new e-kara Software List entries [Team Europe + contributors]
e-kara UK / Europe Volume 2 (UK-E002)
e-kara UK / Europe Volume 3 (UK-E003)
e-kara UK / Europe Volume 6 (UK-E006)

also verified UK vols 1 + 7 on second cartridges, and documented what UK volumes 4+5 are (the collection that was picked up came with a sale sheet advertising them all, complete with track listings)

* note

* same note here (nw)

* typo (nw)

* minor changes (nw)
This commit is contained in:
David Haywood 2018-11-13 22:57:58 +00:00 committed by R. Belmont
parent bd74ecf05c
commit f521d742ba
5 changed files with 348 additions and 109 deletions

View File

@ -212,7 +212,7 @@
<!-- UK / Europe cartridges - these have 'UK' part codes, but multiple languages on the case suggesting they were used for the whole of Europe -->
<!--
<!-- e-kara UK / Europe Volume 1 (UK-E001)
1. "Oops!...I Did It Again" Britney Spears
2. "Thank You" Dido
3. "Bootylicious" Destiny's Child
@ -224,7 +224,6 @@
9. "Nobody Wants to be Lonely" Ricky Martin & Christina Aguilera
10. "I Want It That Way" Backstreet Boys
-->
<software name="uk_vol1">
<description>e-kara UK / Europe Volume 1 (UK-E001)</description>
<year>2002</year>
@ -236,6 +235,101 @@
</part>
</software>
<!-- e-kara UK / Europe Volume 2 (UK-E002)
1. "Independent Woman Part 1" Destiny's Child
2. "Lucky" Britney Spears
3. "Back and Forth" Aaliyah
4. "Thank You" Dido
5. "Crush" Jennifer Paige
6. "Stomp" Steps
7. "All For You" Janet Jackson
8. "Saving All My Love For You" Whitney Houston
9. "Take On Me" a1
10. "Show Me The Meaning of Being Lonely" Backstreet Boys
-->
<software name="uk_vol2">
<description>e-kara UK / Europe Volume 2 (UK-E002)</description>
<year>2002</year>
<publisher>Takara</publisher>
<part name="cart" interface="ekara_cart">
<dataarea name="rom" size="0x100000">
<rom name="uk-e002.u1" size="0x100000" crc="ab011ea3" sha1="dd5c9cc330956861b0d172c5a07a72eb315009a2" offset="0" />
</dataarea>
</part>
</software>
<!-- e-kara UK / Europe Volume 3 (UK-E003)
1. "Stronger" Britney Spears
2. "I Turn To You" Christina Aguilera
3. "Survivor (Album Version)" Destiny's Child
4. "He Loves U Not" Dream
5. "5,6,7,8" Steps
6. "Can't Fight The Moonlight" LeAnn Rimes
7. "Body II Body" Samantha Mumba
8. "Believe" Cher
9. "Larger Than Life" Backstreet Boys
10. "Bye Bye Bye" *N Sync
-->
<software name="uk_vol3">
<description>e-kara UK / Europe Volume 3 (UK-E003)</description>
<year>2002</year>
<publisher>Takara</publisher>
<part name="cart" interface="ekara_cart">
<dataarea name="rom" size="0x100000">
<rom name="uk-e003.u1" size="0x100000" crc="ee16321c" sha1="cc6d22e164164dc678c75a65e13397fb29024b14" offset="0" />
</dataarea>
</part>
</software>
<!-- e-kara UK / Europe Volume 4 (UK-E004) (not dumped) (this is the same tracklist as US-E004, but the code on the UK/EU one would be different as they use a different timing method)
1. "Can't Buy Me Love" The Beatles
2. "A Hard Day's Night" The Beatles
3. "Ticket To Ride" The Beatles
4. "Yesterday" The Beatles
5. "Help" The Beatles
6. "Michelle" The Beatles
7. "Yellow Submarine" The Beatles
8. "All My Loving" The Beatles
9. "Drive My Car" The Beatles
10. "We Can Work It Out" The Beatles
-->
<!-- e-kara UK / Europe Volume 5 (UK-E005) (not dumped) (this is the same tracklist as US-E005, but the code on the UK/EU one would be different as they use a different timing method)
1. "Lucy In the Sky With Diamonds" The Beatles
2. "All You Need Is Love" The Beatles
3. "Hello Goodbye" The Beatles
4. "Hey Jude" The Beatles
5. "Ob-La-Di, Ob-La-Da" The Beatles
6. "Get Back" The Beatles
7. "Come Together" The Beatles
8. "Oh! Darling" The Beatles
9. "Let It Be" The Beatles
10. "The Long And Winding Road" The Beatles
-->
<!-- e-kara UK / Europe Volume 6 (UK-E006)
1. "Genie In A Bottle" Christina Aguilera
2. "Oops!... I Did it Again" Britney Spears
3. "Jumpin', Jumpin'" Destiny's Child
4. "Case Of The Ex" Mya
5. "The First Night" Monica
6. "Someone To Call My Lover" Janet Jackson
7. "American Pie (Album Version)" Madonna
8. "Lovin' You" Minnie Riperton
9. "Let Me Let Go" Faith Hill
10. "Back To Your Heart" Backstreet Boys
-->
<software name="uk_vol6">
<description>e-kara UK / Europe Volume 6 (UK-E006)</description>
<year>2002</year>
<publisher>Takara</publisher>
<part name="cart" interface="ekara_cart">
<dataarea name="rom" size="0x100000">
<rom name="uk-e006.u1" size="0x100000" crc="fad51dc4" sha1="522adfab98c2634bfaa9a01e3b7aebba2f867c1f" offset="0" />
</dataarea>
</part>
</software>
<!--
1. "I'm A Slave 4 U" Britney Spears
2. "It's Gonna Be Me" *N Sync
@ -259,8 +353,8 @@
</part>
</software>
<!-- Note, same lineup as US Starter, but with 2002 copyright, different background picture on 'Stronger'
this has a 'GER' code, which suggests there might be ones for other regions where the ROM will need checking
1. "Stronger" Britney Spears
2. "Bye Bye Bye" *N Sync
3. "Independent Woman Part 1" Destiny's Child
@ -491,7 +585,7 @@
<!-- Japanese e-kara cartridges GC series -->
<software name="gc0002bht">
<software name="gc0002">
<description>BHT Volume 1 (Japan) (GC0002-BHT)</description>
<year>2000</year>
<publisher>Takara</publisher>

View File

@ -27,15 +27,17 @@ void xavix_sound_device::device_start()
m_readregs_cb.resolve_safe(0xff);
m_readsamples_cb.resolve_safe(0x80);
m_stream = stream_alloc(0, 1, 8000);
m_stream = stream_alloc(0, 2, 163840);
}
void xavix_sound_device::device_reset()
{
for (int v = 0; v < 16; v++)
{
m_voice[v].enabled = false;
m_voice[v].position = 0x00;
m_voice[v].enabled[0] = false;
m_voice[v].enabled[1] = false;
m_voice[v].position[0] = 0x00;
m_voice[v].position[1] = 0x00;
m_voice[v].bank = 0x00;
}
}
@ -45,27 +47,50 @@ void xavix_sound_device::sound_stream_update(sound_stream &stream, stream_sample
{
// reset the output stream
memset(outputs[0], 0, samples * sizeof(*outputs[0]));
memset(outputs[1], 0, samples * sizeof(*outputs[1]));
int outpos = 0;
// loop while we still have samples to generate
while (samples-- != 0)
{
for (int v = 0; v < 16; v++)
for (int channel = 0; channel < 2; channel++)
{
if (m_voice[v].enabled == true)
for (int v = 0; v < 16; v++)
{
if (m_voice[v].type == 2 || m_voice[v].type == 3)
if (m_voice[v].enabled[channel] == true)
{
int8_t sample = m_readsamples_cb((m_voice[v].bank << 16) | m_voice[v].position);
if ((uint8_t)sample == 0x80)
// 2 is looping? 3 is single shot? 0/1 are something else?
if (m_voice[v].type == 2 || m_voice[v].type == 3)
{
m_voice[v].enabled = false;
break;
}
uint32_t pos = (m_voice[v].bank << 16) | (m_voice[v].position[channel] >> 14);
int8_t sample = m_readsamples_cb(pos);
outputs[0][outpos] += sample * 0x10;
m_voice[v].position++;
if ((uint8_t)sample == 0x80) // would both channels stop / loop or just one?, Yellow submarine indicates just one, but might be running in some interleaved mode?
{
//if (m_voice[v].type == 3)
{
m_voice[v].enabled[channel] = false;
break;
}
/* need envelopes or some of these loop forever!
else if (m_voice[v].type == 2)
{
m_voice[v].position[channel] = m_voice[v].startposition[channel];
// presumably don't want to play 0x80 byte, so read in a new one
pos = (m_voice[v].bank << 16) | (m_voice[v].position[channel] >> 14);
sample = m_readsamples_cb(pos);
}
*/
}
outputs[channel][outpos] += sample * (m_voice[v].vol + 1);
m_voice[v].position[channel] += m_voice[v].rate;
}
else
{
popmessage("unsupported voice type %01x", m_voice[v].type);
m_voice[v].enabled[channel] = false;
}
}
}
}
@ -73,46 +98,121 @@ void xavix_sound_device::sound_stream_update(sound_stream &stream, stream_sample
}
}
void xavix_sound_device::enable_voice(int voice)
bool xavix_sound_device::is_voice_enabled(int voice)
{
LOG("voice %d 0->1 ", voice);
int voicemembase = voice * 0x10;
m_stream->update();
uint16_t param1 = (m_readregs_cb(voicemembase + 0x1) << 8) | (m_readregs_cb(voicemembase + 0x0)); // sample rate maybe?
uint16_t param2 = (m_readregs_cb(voicemembase + 0x3) << 8) | (m_readregs_cb(voicemembase + 0x2)); // seems to be a start position
uint16_t param3 = (m_readregs_cb(voicemembase + 0x5) << 8) | (m_readregs_cb(voicemembase + 0x4)); // another start position? sometimes same as param6
uint8_t param4a = (m_readregs_cb(voicemembase + 0x7));
uint8_t param4b = (m_readregs_cb(voicemembase + 0x6)); // upper 8 bits of memory address? 8 bits unused?
// these don't seem to be populated as often, maybe some kind of effect / envelope filter?
uint8_t param5a = (m_readregs_cb(voicemembase + 0x9));
uint8_t param5b = (m_readregs_cb(voicemembase + 0x8));
uint16_t param6 = (m_readregs_cb(voicemembase + 0xb) << 8) | (m_readregs_cb(voicemembase + 0xa)); // seems to be a start position
uint16_t param7 = (m_readregs_cb(voicemembase + 0xd) << 8) | (m_readregs_cb(voicemembase + 0xc)); // another start position? sometimes same as param6
uint8_t param8a = (m_readregs_cb(voicemembase + 0xf));
uint8_t param8b = (m_readregs_cb(voicemembase + 0xe)); // upper 8 bits of memory address? 8 bits unused (or not unused?, get populated with increasing values sometimes?)
LOG(" (params %04x %04x %04x %02x %02x %02x %02x %04x %04x %02x %02x)\n", param1, param2, param3, param4a, param4b, param5a, param5b, param6, param7, param8a, param8b);
uint32_t address1 = (param2 | param4b << 16) & 0x00ffffff; // definitely addresses based on rad_snow
uint32_t address2 = (param3 | param4b << 16) & 0x00ffffff;
uint32_t address3 = (param6 | param8b << 16) & 0x00ffffff; // still looks like addresses, sometimes pointing at RAM
uint32_t address4 = (param7 | param8b << 16) & 0x00ffffff;
LOG(" (possible meanings mode %01x rate %04x address1 %08x address2 %08x address3 %08x address4 %08x)\n", param1 & 0x3, param1 >> 2, address1, address2, address3, address4);
m_voice[voice].enabled = true;
m_voice[voice].bank = param4b;
m_voice[voice].position = param2; // param3
m_voice[voice].type = param1 & 0x3;
// samples appear to be PCM, 0x80 terminated
/*
if ((m_voice[voice].enabled[0] == true) || (m_voice[voice].enabled[1] == true))
return true;
else
return false;
*/
if ((m_voice[voice].enabled[0] == true) && (m_voice[voice].enabled[1] == true))
return true;
else
return false;
}
void xavix_sound_device::enable_voice(int voice, bool update_only)
{
m_stream->update();
int voicemembase = voice * 0x10;
uint16_t freq_mode = (m_readregs_cb(voicemembase + 0x1) << 8) | (m_readregs_cb(voicemembase + 0x0)); // sample rate maybe?
uint16_t sampleaddrleft = (m_readregs_cb(voicemembase + 0x3) << 8) | (m_readregs_cb(voicemembase + 0x2)); // seems to be a start position
uint16_t sampleaddrright = (m_readregs_cb(voicemembase + 0x5) << 8) | (m_readregs_cb(voicemembase + 0x4)); // another start position? sometimes same as envaddrleft
uint8_t unused1 = (m_readregs_cb(voicemembase + 0x7)); // data gets written but doesn't look like it's used by the chip?
uint8_t sampleaddrbank = (m_readregs_cb(voicemembase + 0x6)); // upper 8 bits of memory address? 8 bits unused?
// these don't seem to be populated as often, maybe some kind of effect / envelope filter?
uint8_t envfreq = (m_readregs_cb(voicemembase + 0x9));
uint8_t envmode_unk = (m_readregs_cb(voicemembase + 0x8));
uint16_t envaddrleft = (m_readregs_cb(voicemembase + 0xb) << 8) | (m_readregs_cb(voicemembase + 0xa)); // seems to be a start position, lower byte is direct value, not address in some modes??
uint16_t envaddrright = (m_readregs_cb(voicemembase + 0xd) << 8) | (m_readregs_cb(voicemembase + 0xc)); // another start position? sometimes same as envaddrleft
uint8_t unused2 = (m_readregs_cb(voicemembase + 0xf)); // data gets written but doesn't look like it's used by the chip?
uint8_t envaddrbank = (m_readregs_cb(voicemembase + 0xe)); // upper 8 bits of memory address? 8 bits unused (or not unused?, get populated with increasing values sometimes?)
uint32_t sampleaddrleft_full = (sampleaddrleft | sampleaddrbank << 16) & 0x00ffffff; // definitely addresses based on rad_snow
uint32_t sampleaddrright_full = (sampleaddrright | sampleaddrbank << 16) & 0x00ffffff;
uint32_t envaddrleft_full = (envaddrleft | envaddrbank << 16) & 0x00ffffff; // still looks like addresses, sometimes pointing at RAM
uint32_t envaddrright_full = (envaddrright | envaddrbank << 16) & 0x00ffffff;
uint8_t envmode = (envmode_unk >> 4)&3; // upper bits not used?
uint8_t envunk = envmode_unk & 0x0f;
if (update_only) LOG("(UPDATE ONLY) ");
LOG("voice %01x (params %04x %04x %04x %02x %02x %02x %02x %04x %04x %02x %02x)\n", voice, freq_mode, sampleaddrleft, sampleaddrright, unused1, sampleaddrbank, envfreq, envmode_unk, envaddrleft, envaddrright, unused2, envaddrbank);
if (envmode == 0)
{
// mode 0 doesn't seem to use a second pair of addresses for the envelope but instead a fixed value in the lower part of the address registers?, usually used with non-looping samples too? upper bytes of address end up being leftovers from previous sounds
LOG("voice %01x (possible meanings mode %01x rate %04x sampleaddrleft_full %08x sampleaddrright_full %08x envvalue_left %02x envvalue_right %02x envfreq %02x envmode_unk [%01x, %01x])\n", voice, freq_mode & 0x3, freq_mode >> 2, sampleaddrleft_full, sampleaddrright_full, envaddrleft_full & 0xff, envaddrright_full & 0xff, envfreq, envmode, envunk);
}
else
{
// envelopes usually point to 8-byte sequences of values?
// when written from sound_updateenv_w (update only) then mode is usually 0x3 (key off?)
// mode 1 is used for most samples (key on?)
// mode 2 is used on monster truck
LOG("voice %01x (possible meanings mode %01x rate %04x sampleaddrleft_full %08x sampleaddrright_full %08x envaddrleft_full %08x envaddrright_full %08x envfreq %02x envmode_unk [%01x, %01x])\n", voice, freq_mode & 0x3, freq_mode >> 2, sampleaddrleft_full, sampleaddrright_full, envaddrleft_full, envaddrright_full, envfreq, envmode, envunk);
LOG(" (ENV1 ");
for (int i = 0; i < 8; i++)
{
uint8_t env = m_readsamples_cb(envaddrleft_full+i);
LOG("%02x ", env);
}
LOG(") ");
LOG(" (ENV2 ");
for (int i = 0; i < 8; i++)
{
uint8_t env = m_readsamples_cb(envaddrright_full+i);
LOG("%02x ", env);
}
LOG(") \n");
}
if (envmode_unk & 0xc0)
{
LOG(" (unexpected bits set in envmode_unk %02x)\n", envmode_unk & 0xc0);
}
if (!update_only)
{
m_voice[voice].enabled[0] = true;
m_voice[voice].enabled[1] = true;
m_voice[voice].bank = sampleaddrbank;
m_voice[voice].position[0] = sampleaddrleft << 14;
m_voice[voice].position[1] = sampleaddrright << 14;
m_voice[voice].type = freq_mode & 0x3;
m_voice[voice].rate = freq_mode >> 2;
m_voice[voice].vol = envunk;
m_voice[voice].startposition[0] = m_voice[voice].position[0]; // for looping
m_voice[voice].startposition[1] = m_voice[voice].position[1];
}
// 0320 (800) == 8000hz
// 4000 (16384) == 163840hz ? = 163.840kHz
// samples appear to be PCM, 0x80 terminated, looks like there's a way of specifying mono (interleave channels?) or stereo, maybe in master regs?
}
void xavix_sound_device::disable_voice(int voice)
{
m_voice[voice].enabled[0] = false;
m_voice[voice].enabled[1] = false;
}
// xavix_state support
@ -131,13 +231,13 @@ READ8_MEMBER(xavix_state::sound_regram_read_cb)
/* 75f0, 75f1 - 2x8 bits (16 voices?) */
READ8_MEMBER(xavix_state::sound_reg16_0_r)
READ8_MEMBER(xavix_state::sound_startstop_r)
{
LOG("%s: sound_reg16_0_r %02x\n", machine().describe_context(), offset);
LOG("%s: sound_startstop_r %02x\n", machine().describe_context(), offset);
return m_soundreg16_0[offset];
}
WRITE8_MEMBER(xavix_state::sound_reg16_0_w)
WRITE8_MEMBER(xavix_state::sound_startstop_w)
{
/* looks like the sound triggers
@ -162,65 +262,96 @@ WRITE8_MEMBER(xavix_state::sound_reg16_0_w)
data & 0x80 - voice 15 (registers at regbase + 0xf0) eg 0x3bf0 - 0x3bff in monster truck
*/
if (offset == 0)
LOG("%s: sound_reg16_0_w %02x, %02x (%d %d %d %d %d %d %d %d - - - - - - - -)\n", machine().describe_context(), offset, data, (data & 0x01) ? 1 : 0, (data & 0x02) ? 1 : 0, (data & 0x04) ? 1 : 0, (data & 0x08) ? 1 : 0, (data & 0x10) ? 1 : 0, (data & 0x20) ? 1 : 0, (data & 0x40) ? 1 : 0, (data & 0x80) ? 1 : 0);
LOG("%s: sound_startstop_w %02x, %02x (%d %d %d %d %d %d %d %d - - - - - - - -)\n", machine().describe_context(), offset, data, (data & 0x01) ? 1 : 0, (data & 0x02) ? 1 : 0, (data & 0x04) ? 1 : 0, (data & 0x08) ? 1 : 0, (data & 0x10) ? 1 : 0, (data & 0x20) ? 1 : 0, (data & 0x40) ? 1 : 0, (data & 0x80) ? 1 : 0);
else
LOG("%s: sound_reg16_0_w %02x, %02x (- - - - - - - - %d %d %d %d %d %d %d %d)\n", machine().describe_context(), offset, data, (data & 0x01) ? 1 : 0, (data & 0x02) ? 1 : 0, (data & 0x04) ? 1 : 0, (data & 0x08) ? 1 : 0, (data & 0x10) ? 1 : 0, (data & 0x20) ? 1 : 0, (data & 0x40) ? 1 : 0, (data & 0x80) ? 1 : 0);
LOG("%s: sound_startstop_w %02x, %02x (- - - - - - - - %d %d %d %d %d %d %d %d)\n", machine().describe_context(), offset, data, (data & 0x01) ? 1 : 0, (data & 0x02) ? 1 : 0, (data & 0x04) ? 1 : 0, (data & 0x08) ? 1 : 0, (data & 0x10) ? 1 : 0, (data & 0x20) ? 1 : 0, (data & 0x40) ? 1 : 0, (data & 0x80) ? 1 : 0);
for (int i = 0; i < 8; i++)
{
int voice_state = (data & (1 << i));
int old_voice_state = (m_soundreg16_0[offset] & (1 << i));
const int voice_state = (data & (1 << i));
const int old_voice_state = (m_soundreg16_0[offset] & (1 << i));
if (voice_state != old_voice_state)
{
const int voice = (offset * 8 + i);
if (voice_state)
{
int voice = (offset * 8 + i);
m_sound->enable_voice(voice);
m_sound->enable_voice(voice, false);
}
else
{
m_sound->disable_voice(voice);
}
}
}
m_soundreg16_0[offset] = data;
}
/* 75f0, 75f1 - 2x8 bits (16 voices?) */
READ8_MEMBER(xavix_state::sound_reg16_1_r)
READ8_MEMBER(xavix_state::sound_updateenv_r)
{
LOG("%s: sound_reg16_1_r %02x\n", machine().describe_context(), offset);
LOG("%s: sound_updateenv_r %02x\n", machine().describe_context(), offset);
return m_soundreg16_1[offset];
}
WRITE8_MEMBER(xavix_state::sound_reg16_1_w)
WRITE8_MEMBER(xavix_state::sound_updateenv_w)
{
m_soundreg16_1[offset] = data;
if (offset == 0)
LOG("%s: sound_reg16_1_w %02x, %02x (%d %d %d %d %d %d %d %d - - - - - - - -)\n", machine().describe_context(), offset, data, (data & 0x01) ? 1 : 0, (data & 0x02) ? 1 : 0, (data & 0x04) ? 1 : 0, (data & 0x08) ? 1 : 0, (data & 0x10) ? 1 : 0, (data & 0x20) ? 1 : 0, (data & 0x40) ? 1 : 0, (data & 0x80) ? 1 : 0);
LOG("%s: sound_updateenv_w %02x, %02x (%d %d %d %d %d %d %d %d - - - - - - - -)\n", machine().describe_context(), offset, data, (data & 0x01) ? 1 : 0, (data & 0x02) ? 1 : 0, (data & 0x04) ? 1 : 0, (data & 0x08) ? 1 : 0, (data & 0x10) ? 1 : 0, (data & 0x20) ? 1 : 0, (data & 0x40) ? 1 : 0, (data & 0x80) ? 1 : 0);
else
LOG("%s: sound_reg16_1_w %02x, %02x (- - - - - - - - %d %d %d %d %d %d %d %d)\n", machine().describe_context(), offset, data, (data & 0x01) ? 1 : 0, (data & 0x02) ? 1 : 0, (data & 0x04) ? 1 : 0, (data & 0x08) ? 1 : 0, (data & 0x10) ? 1 : 0, (data & 0x20) ? 1 : 0, (data & 0x40) ? 1 : 0, (data & 0x80) ? 1 : 0);
LOG("%s: sound_updateenv_w %02x, %02x (- - - - - - - - %d %d %d %d %d %d %d %d)\n", machine().describe_context(), offset, data, (data & 0x01) ? 1 : 0, (data & 0x02) ? 1 : 0, (data & 0x04) ? 1 : 0, (data & 0x08) ? 1 : 0, (data & 0x10) ? 1 : 0, (data & 0x20) ? 1 : 0, (data & 0x40) ? 1 : 0, (data & 0x80) ? 1 : 0);
// used to update envelopes without restarting sound? for key-off events?
for (int i = 0; i < 8; i++)
{
const int voice_state = (data & (1 << i));
const int old_voice_state = (m_soundreg16_1[offset] & (1 << i));
if (voice_state != old_voice_state)
{
const int voice = (offset * 8 + i);
if (voice_state)
{
m_sound->enable_voice(voice, true);
}
else
{
m_sound->disable_voice(voice);
}
}
}
m_soundreg16_1[offset] = data;
}
/* 75f4, 75f5 - 2x8 bits (16 voices?) status? */
READ8_MEMBER(xavix_state::sound_sta16_r)
{
// used with 75f0/75f1
return machine().rand();
uint8_t ret = 0x00;
for (int i = 0; i < 8; i++)
{
const int voice = (offset * 8 + i);
const bool enabled = m_sound->is_voice_enabled(voice);
ret |= enabled ? 1 << i : 0;
}
return ret;
}
/* 75f6 - master volume control? */
READ8_MEMBER(xavix_state::sound_volume_r)
{
LOG("%s: sound_volume_r\n", machine().describe_context());
return m_soundregs[6];
return m_mastervol;
}
WRITE8_MEMBER(xavix_state::sound_volume_w)
{
m_soundregs[6] = data;
m_mastervol = data;
LOG("%s: sound_volume_w %02x\n", machine().describe_context(), data);
}
@ -239,25 +370,25 @@ WRITE8_MEMBER(xavix_state::sound_regbase_w)
READ8_MEMBER(xavix_state::sound_75f8_r)
{
LOG("%s: sound_75f8_r\n", machine().describe_context());
return m_soundregs[8];
return m_unk_snd75f8;
}
WRITE8_MEMBER(xavix_state::sound_75f8_w)
{
m_soundregs[8] = data;
m_unk_snd75f8 = data;
LOG("%s: sound_75f8_w %02x\n", machine().describe_context(), data);
}
READ8_MEMBER(xavix_state::sound_75f9_r)
{
LOG("%s: sound_75f9_r\n", machine().describe_context());
return 0x00;
return m_unksnd75f9;
}
WRITE8_MEMBER(xavix_state::sound_75f9_w)
{
m_soundregs[9] = data;
LOG("%s: sound_75f9_w %02x\n", machine().describe_context(), data);
m_unksnd75f9 = data;
LOG("%s: sound_75f9_w %02x\n", machine().describe_context().c_str(), data);
}
/* 75fa, 75fb, 75fc, 75fd - timers?? generate interrupts?? */
@ -265,48 +396,48 @@ WRITE8_MEMBER(xavix_state::sound_75f9_w)
READ8_MEMBER(xavix_state::sound_timer0_r)
{
LOG("%s: sound_timer0_r\n", machine().describe_context());
return m_soundregs[10];
return m_sndtimer[0];
}
WRITE8_MEMBER(xavix_state::sound_timer0_w)
{
m_soundregs[10] = data;
m_sndtimer[0] = data;
LOG("%s: sound_timer0_w %02x\n", machine().describe_context(), data);
}
READ8_MEMBER(xavix_state::sound_timer1_r)
{
LOG("%s: sound_timer1_r\n", machine().describe_context());
return m_soundregs[11];
return m_sndtimer[1];
}
WRITE8_MEMBER(xavix_state::sound_timer1_w)
{
m_soundregs[11] = data;
m_sndtimer[1] = data;
LOG("%s: sound_timer1_w %02x\n", machine().describe_context(), data);
}
READ8_MEMBER(xavix_state::sound_timer2_r)
{
LOG("%s: sound_timer2_r\n", machine().describe_context());
return m_soundregs[12];
return m_sndtimer[2];
}
WRITE8_MEMBER(xavix_state::sound_timer2_w)
{
m_soundregs[12] = data;
m_sndtimer[2] = data;
LOG("%s: sound_timer2_w %02x\n", machine().describe_context(), data);
}
READ8_MEMBER(xavix_state::sound_timer3_r)
{
LOG("%s: sound_timer3_r\n", machine().describe_context());
return m_soundregs[13];
return m_sndtimer[3];
}
WRITE8_MEMBER(xavix_state::sound_timer3_w)
{
m_soundregs[13] = data;
m_sndtimer[3] = data;
LOG("%s: sound_timer3_w %02x\n", machine().describe_context(), data);
}
@ -340,7 +471,7 @@ WRITE8_MEMBER(xavix_state::sound_irqstatus_w)
WRITE8_MEMBER(xavix_state::sound_75ff_w)
{
m_soundregs[15] = data;
m_unksnd75ff = data;
LOG("%s: sound_75ff_w %02x\n", machine().describe_context(), data);
}

View File

@ -321,8 +321,8 @@ void xavix_state::xavix_lowbus_map(address_map &map)
// map(0x7400, 0x757f)
// Sound Control
map(0x75f0, 0x75f1).rw(FUNC(xavix_state::sound_reg16_0_r), FUNC(xavix_state::sound_reg16_0_w)); // r/w tested read/written 8 times in a row
map(0x75f2, 0x75f3).rw(FUNC(xavix_state::sound_reg16_1_r), FUNC(xavix_state::sound_reg16_1_w));
map(0x75f0, 0x75f1).rw(FUNC(xavix_state::sound_startstop_r), FUNC(xavix_state::sound_startstop_w)); // r/w tested read/written 8 times in a row
map(0x75f2, 0x75f3).rw(FUNC(xavix_state::sound_updateenv_r), FUNC(xavix_state::sound_updateenv_w));
map(0x75f4, 0x75f5).r(FUNC(xavix_state::sound_sta16_r)); // related to 75f0 / 75f1 (read after writing there - rad_mtrk)
// taitons1 after 75f7/75f8
map(0x75f6, 0x75f6).rw(FUNC(xavix_state::sound_volume_r), FUNC(xavix_state::sound_volume_w)); // r/w tested
@ -818,12 +818,17 @@ MACHINE_CONFIG_START(xavix_state::xavix)
/* sound hardware */
SPEAKER(config, "mono").front_center();
//SPEAKER(config, "mono").front_center();
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
XAVIX_SOUND(config, m_sound, MAIN_CLOCK);
m_sound->read_regs_callback().set(FUNC(xavix_state::sound_regram_read_cb));
m_sound->read_samples_callback().set(FUNC(xavix_state::sample_read));
m_sound->add_route(ALL_OUTPUTS, "mono", 1.0);
//m_sound->add_route(ALL_OUTPUTS, "mono", 1.0);
m_sound->add_route(0, "lspeaker", 1.0);
m_sound->add_route(1, "rspeaker", 1.0);
MACHINE_CONFIG_END
MACHINE_CONFIG_START(xavix_i2c_state::xavix_i2c_24lc04)

View File

@ -26,7 +26,9 @@ public:
auto read_regs_callback() { return m_readregs_cb.bind(); }
auto read_samples_callback() { return m_readsamples_cb.bind(); }
void enable_voice(int voice);
void enable_voice(int voice, bool update_only);
void disable_voice(int voice);
bool is_voice_enabled(int voice);
protected:
// device-level overrides
@ -40,10 +42,13 @@ private:
sound_stream *m_stream;
struct xavix_voice {
bool enabled;
uint16_t position;
bool enabled[2];
uint32_t position[2];
uint32_t startposition[2];
uint8_t bank; // no samples appear to cross a bank boundary, so likely wraps
int type;
int rate;
int vol;
};
devcb_read8 m_readregs_cb;
@ -285,10 +290,10 @@ private:
DECLARE_READ8_MEMBER(dispctrl_6ff8_r);
DECLARE_WRITE8_MEMBER(dispctrl_6ff8_w);
DECLARE_READ8_MEMBER(sound_reg16_0_r);
DECLARE_WRITE8_MEMBER(sound_reg16_0_w);
DECLARE_READ8_MEMBER(sound_reg16_1_r);
DECLARE_WRITE8_MEMBER(sound_reg16_1_w);
DECLARE_READ8_MEMBER(sound_startstop_r);
DECLARE_WRITE8_MEMBER(sound_startstop_w);
DECLARE_READ8_MEMBER(sound_updateenv_r);
DECLARE_WRITE8_MEMBER(sound_updateenv_w);
DECLARE_READ8_MEMBER(sound_sta16_r);
DECLARE_READ8_MEMBER(sound_75f5_r);
@ -424,7 +429,11 @@ private:
uint8_t m_6ff0;
uint8_t m_video_ctrl;
uint8_t m_soundregs[0x10];
uint8_t m_mastervol;
uint8_t m_unk_snd75f8;
uint8_t m_unksnd75f9;
uint8_t m_unksnd75ff;
uint8_t m_sndtimer[4];
uint8_t m_timer_baseval;

View File

@ -850,15 +850,15 @@ void xavix_state::machine_reset()
m_spritereg = 0;
m_soundregs[0] = 0;
m_soundregs[1] = 0;
m_mastervol = 0x00;
m_unk_snd75f8 = 0x00;
m_unksnd75f9 = 0x00;
m_unksnd75ff = 0x00;
m_soundregs[6] = 0;
m_soundregs[8] = 0;
m_soundregs[10] = 0;
m_soundregs[11] = 0;
m_soundregs[12] = 0;
m_soundregs[13] = 0;
for (int i = 0; i < 4; i++)
{
m_sndtimer[i] = 0x00;
}
std::fill(std::begin(m_multparams), std::end(m_multparams), 0x00);
std::fill(std::begin(m_multresults), std::end(m_multresults), 0x00);