mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
XaviX - very preliminary sound (#4275)
* terminology change (nw) * prepare (nw) * move some bits (nw) * prepare (nw) * make some noises (nw) * less loud (nw) * new e-kara Software List entry e-kara UK / Europe Volume 1 (UK-E001) [Team Europe]
This commit is contained in:
parent
a2af88a451
commit
338f278f4d
@ -4,7 +4,13 @@
|
||||
<!-- cartridges contain the ROM only, the XaviX CPU and BIOS are in the base unit -->
|
||||
|
||||
<!-- Each region has it's own set of cartridges (at least US, UK/EU and Japan)
|
||||
The Japanese ones appear to have a number of different genres each with their own numbering -->
|
||||
The Japanese ones appear to have a number of different genres each with their own numbering
|
||||
|
||||
There are some carts which are meant to be compatible with both Japanese e-Kara units and
|
||||
several other systems.
|
||||
-->
|
||||
|
||||
<!-- US cartridges -->
|
||||
|
||||
<!--
|
||||
1. "Stronger" Britney Spears
|
||||
@ -19,7 +25,7 @@
|
||||
<publisher>Takara</publisher>
|
||||
<part name="cart" interface="ekara_cart">
|
||||
<dataarea name="rom" size="0x080000">
|
||||
<rom name="ekara_starter.bin" size="0x080000" crc="8c12c0c2" sha1="8cc1b098894af25a4bfccada884125b66f5fe8b2" offset="0" />
|
||||
<rom name="us-m001.bin" size="0x080000" crc="8c12c0c2" sha1="8cc1b098894af25a4bfccada884125b66f5fe8b2" offset="0" />
|
||||
</dataarea>
|
||||
</part>
|
||||
</software>
|
||||
@ -42,7 +48,7 @@
|
||||
<publisher>Takara</publisher>
|
||||
<part name="cart" interface="ekara_cart">
|
||||
<dataarea name="rom" size="0x100000">
|
||||
<rom name="ekaravol1.bin" size="0x100000" crc="29df4aea" sha1="b95835aaf8630b61b47e5da0968cd4a1dd3bc517" offset="0" />
|
||||
<rom name="us-e001.bin" size="0x100000" crc="29df4aea" sha1="b95835aaf8630b61b47e5da0968cd4a1dd3bc517" offset="0" />
|
||||
</dataarea>
|
||||
</part>
|
||||
</software>
|
||||
@ -65,7 +71,33 @@
|
||||
<publisher>Takara</publisher>
|
||||
<part name="cart" interface="ekara_cart">
|
||||
<dataarea name="rom" size="0x100000">
|
||||
<rom name="ekaravol2.bin" size="0x100000" crc="6c66772e" sha1="e1e719df1e51caaafd9b3af187059334f7abbba3" offset="0" />
|
||||
<rom name="us-e002.bin" size="0x100000" crc="6c66772e" sha1="e1e719df1e51caaafd9b3af187059334f7abbba3" offset="0" />
|
||||
</dataarea>
|
||||
</part>
|
||||
</software>
|
||||
|
||||
<!-- UK / Europe cartridges - these have 'UK' part codes, but multiple languages on the case suggesting they were used for the whole of Europe -->
|
||||
|
||||
<!--
|
||||
1. "Oops!...I Did It Again" Britney Spears
|
||||
2. "Thank You" Dido
|
||||
3. "Bootylicious" Destiny's Child
|
||||
4. "I Need You" LeAnn Rimes
|
||||
5. "Love Don't Cost a Thing" Jennifer Lopez
|
||||
6. "Don't Think I'm Not" Kandi
|
||||
7. "Again" Janet Jackson
|
||||
8. "Hot Stuff" Donna Summer
|
||||
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>2000</year>
|
||||
<publisher>Takara</publisher>
|
||||
<part name="cart" interface="ekara_cart">
|
||||
<dataarea name="rom" size="0x100000">
|
||||
<rom name="uk-e001.bin" size="0x100000" crc="fc0ea770" sha1="47e2ef544cbb35431dd138b74d1f9b7290eba02d" offset="0" />
|
||||
</dataarea>
|
||||
</part>
|
||||
</software>
|
||||
|
@ -7,7 +7,7 @@
|
||||
#define VERBOSE 1
|
||||
#include "logmacro.h"
|
||||
|
||||
// 16 stereo channels?
|
||||
// 16 stereo voices?
|
||||
|
||||
// xavix_sound_device
|
||||
|
||||
@ -17,33 +17,120 @@ xavix_sound_device::xavix_sound_device(const machine_config &mconfig, const char
|
||||
: device_t(mconfig, XAVIX_SOUND, tag, owner, clock)
|
||||
, device_sound_interface(mconfig, *this)
|
||||
, m_stream(nullptr)
|
||||
, m_readregs_cb(*this)
|
||||
, m_readsamples_cb(*this)
|
||||
{
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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].bank = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void xavix_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
||||
{
|
||||
// reset the output stream
|
||||
memset(outputs[0], 0, samples * sizeof(*outputs[0]));
|
||||
|
||||
int outpos = 0;
|
||||
// loop while we still have samples to generate
|
||||
while (samples-- != 0)
|
||||
{
|
||||
//
|
||||
for (int v = 0; v < 16; v++)
|
||||
{
|
||||
if (m_voice[v].enabled == true)
|
||||
{
|
||||
if (m_voice[v].type == 2 || m_voice[v].type == 3)
|
||||
{
|
||||
int8_t sample = m_readsamples_cb((m_voice[v].bank << 16) | m_voice[v].position);
|
||||
|
||||
if ((uint8_t)sample == 0x80)
|
||||
{
|
||||
m_voice[v].enabled = false;
|
||||
break;
|
||||
}
|
||||
|
||||
outputs[0][outpos] += sample * 0x10;
|
||||
m_voice[v].position++;
|
||||
}
|
||||
}
|
||||
}
|
||||
outpos++;
|
||||
}
|
||||
}
|
||||
|
||||
void xavix_sound_device::enable_voice(int voice)
|
||||
{
|
||||
LOG("voice %d 0->1 ", voice);
|
||||
int voicemembase = voice * 0x10;
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
|
||||
// xavix_state support
|
||||
|
||||
/* 75f0, 75f1 - 2x8 bits (16 channels?) */
|
||||
READ8_MEMBER(xavix_state::sound_regram_read_cb)
|
||||
{
|
||||
// 0x00 would be zero page memory, and problematic for many reasons, assume it just doesn't work like that
|
||||
if ((m_sound_regbase & 0x3f) != 0x00)
|
||||
{
|
||||
uint16_t memorybase = (m_sound_regbase & 0x3f) << 8;
|
||||
|
||||
return m_mainram[memorybase + offset];
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
|
||||
/* 75f0, 75f1 - 2x8 bits (16 voices?) */
|
||||
READ8_MEMBER(xavix_state::sound_reg16_0_r)
|
||||
{
|
||||
LOG("%s: sound_reg16_0_r %02x\n", machine().describe_context(), offset);
|
||||
@ -55,24 +142,24 @@ WRITE8_MEMBER(xavix_state::sound_reg16_0_w)
|
||||
/* looks like the sound triggers
|
||||
|
||||
offset 0
|
||||
data & 0x01 - channel 0 (registers at regbase + 0x00) eg 0x3b00 - 0x3b0f in monster truck
|
||||
data & 0x02 - channel 1 (registers at regbase + 0x10) eg 0x3b10 - 0x3b1f in monster truck
|
||||
data & 0x04 - channel 2
|
||||
data & 0x08 - channel 3
|
||||
data & 0x10 - channel 4
|
||||
data & 0x20 - channel 5
|
||||
data & 0x40 - channel 6
|
||||
data & 0x80 - channel 7
|
||||
data & 0x01 - voice 0 (registers at regbase + 0x00) eg 0x3b00 - 0x3b0f in monster truck
|
||||
data & 0x02 - voice 1 (registers at regbase + 0x10) eg 0x3b10 - 0x3b1f in monster truck
|
||||
data & 0x04 - voice 2
|
||||
data & 0x08 - voice 3
|
||||
data & 0x10 - voice 4
|
||||
data & 0x20 - voice 5
|
||||
data & 0x40 - voice 6
|
||||
data & 0x80 - voice 7
|
||||
|
||||
offset 1
|
||||
data & 0x01 - channel 8
|
||||
data & 0x02 - channel 9
|
||||
data & 0x04 - channel 10
|
||||
data & 0x08 - channel 11
|
||||
data & 0x10 - channel 12
|
||||
data & 0x20 - channel 13
|
||||
data & 0x40 - channel 14 (registers at regbase + 0xf0) eg 0x3be0 - 0x3bef in monster truck
|
||||
data & 0x80 - channel 15 (registers at regbase + 0xf0) eg 0x3bf0 - 0x3bff in monster truck
|
||||
data & 0x01 - voice 8
|
||||
data & 0x02 - voice 9
|
||||
data & 0x04 - voice 10
|
||||
data & 0x08 - voice 11
|
||||
data & 0x10 - voice 12
|
||||
data & 0x20 - voice 13
|
||||
data & 0x40 - voice 14 (registers at regbase + 0xf0) eg 0x3be0 - 0x3bef in monster truck
|
||||
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);
|
||||
@ -82,43 +169,15 @@ WRITE8_MEMBER(xavix_state::sound_reg16_0_w)
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
int channel_state = (data & (1 << i));
|
||||
int old_channel_state = (m_soundreg16_0[offset] & (1 << i));
|
||||
if (channel_state != old_channel_state)
|
||||
int voice_state = (data & (1 << i));
|
||||
int old_voice_state = (m_soundreg16_0[offset] & (1 << i));
|
||||
if (voice_state != old_voice_state)
|
||||
{
|
||||
if (channel_state)
|
||||
if (voice_state)
|
||||
{
|
||||
int channel = (offset * 8 + i);
|
||||
int voice = (offset * 8 + i);
|
||||
|
||||
LOG("channel %d 0->1 ", channel);
|
||||
|
||||
uint16_t memorybase = ((m_sound_regbase & 0x3f) << 8) | (channel * 0x10);
|
||||
|
||||
uint16_t param1 = (m_mainram[memorybase + 0x1] << 8) | (m_mainram[memorybase + 0x0]); // sample rate maybe?
|
||||
uint16_t param2 = (m_mainram[memorybase + 0x3] << 8) | (m_mainram[memorybase + 0x2]); // seems to be a start position
|
||||
uint16_t param3 = (m_mainram[memorybase + 0x5] << 8) | (m_mainram[memorybase + 0x4]); // another start position? sometimes same as param6
|
||||
uint8_t param4a = (m_mainram[memorybase + 0x7]);
|
||||
uint8_t param4b = (m_mainram[memorybase + 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_mainram[memorybase + 0x9]);
|
||||
uint8_t param5b = (m_mainram[memorybase + 0x8]);
|
||||
uint16_t param6 = (m_mainram[memorybase + 0xb] << 8) | (m_mainram[memorybase + 0xa]); // seems to be a start position
|
||||
uint16_t param7 = (m_mainram[memorybase + 0xd] << 8) | (m_mainram[memorybase + 0xc]); // another start position? sometimes same as param6
|
||||
uint8_t param8a = (m_mainram[memorybase + 0xf]);
|
||||
uint8_t param8b = (m_mainram[memorybase + 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);
|
||||
|
||||
// samples appear to be PCM, 0x80 terminated
|
||||
m_sound->enable_voice(voice);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -127,7 +186,7 @@ WRITE8_MEMBER(xavix_state::sound_reg16_0_w)
|
||||
|
||||
}
|
||||
|
||||
/* 75f0, 75f1 - 2x8 bits (16 channels?) */
|
||||
/* 75f0, 75f1 - 2x8 bits (16 voices?) */
|
||||
READ8_MEMBER(xavix_state::sound_reg16_1_r)
|
||||
{
|
||||
LOG("%s: sound_reg16_1_r %02x\n", machine().describe_context(), offset);
|
||||
@ -145,7 +204,7 @@ WRITE8_MEMBER(xavix_state::sound_reg16_1_w)
|
||||
}
|
||||
|
||||
|
||||
/* 75f4, 75f5 - 2x8 bits (16 channels?) status? */
|
||||
/* 75f4, 75f5 - 2x8 bits (16 voices?) status? */
|
||||
READ8_MEMBER(xavix_state::sound_sta16_r)
|
||||
{
|
||||
// used with 75f0/75f1
|
||||
@ -170,7 +229,7 @@ WRITE8_MEMBER(xavix_state::sound_volume_w)
|
||||
WRITE8_MEMBER(xavix_state::sound_regbase_w)
|
||||
{
|
||||
// this is the upper 6 bits of the RAM address where the actual sound register sets are
|
||||
// (16x16 regs, so complete 0x100 bytes of RAM eg 0x3b means the complete 0x3b00 - 0x3bff range with 0x3b00 - 0x3b0f being channel 1 etc)
|
||||
// (16x16 regs, so complete 0x100 bytes of RAM eg 0x3b means the complete 0x3b00 - 0x3bff range with 0x3b00 - 0x3b0f being voice 1 etc)
|
||||
m_sound_regbase = data;
|
||||
LOG("%s: sound_regbase_w %02x (sound regs are at 0x%02x00 to 0x%02xff)\n", machine().describe_context(), data, m_sound_regbase & 0x3f, m_sound_regbase & 0x3f);
|
||||
}
|
||||
@ -272,7 +331,7 @@ WRITE8_MEMBER(xavix_state::sound_irqstatus_w)
|
||||
m_sound_irqstatus &= ~data & 0xf0;
|
||||
}
|
||||
|
||||
m_sound_irqstatus = data & 0x0f; // look like IRQ enable flags - 4 sources? channels? timers?
|
||||
m_sound_irqstatus = data & 0x0f; // look like IRQ enable flags - 4 sources? voices? timers?
|
||||
|
||||
LOG("%s: sound_irqstatus_w %02x\n", machine().describe_context(), data);
|
||||
}
|
||||
|
@ -817,10 +817,13 @@ MACHINE_CONFIG_START(xavix_state::xavix)
|
||||
MCFG_PALETTE_ADD("palette", 256)
|
||||
|
||||
/* sound hardware */
|
||||
XAVIX_SOUND(config, "xavix_sound", MAIN_CLOCK);
|
||||
|
||||
SPEAKER(config, "mono").front_center();
|
||||
// sound is PCM
|
||||
|
||||
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);
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
MACHINE_CONFIG_START(xavix_i2c_state::xavix_i2c_24lc04)
|
||||
|
@ -23,6 +23,11 @@ class xavix_sound_device : public device_t, public device_sound_interface
|
||||
public:
|
||||
xavix_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
auto read_regs_callback() { return m_readregs_cb.bind(); }
|
||||
auto read_samples_callback() { return m_readsamples_cb.bind(); }
|
||||
|
||||
void enable_voice(int voice);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
@ -33,6 +38,19 @@ protected:
|
||||
|
||||
private:
|
||||
sound_stream *m_stream;
|
||||
|
||||
struct xavix_voice {
|
||||
bool enabled;
|
||||
uint16_t position;
|
||||
uint8_t bank; // no samples appear to cross a bank boundary, so likely wraps
|
||||
int type;
|
||||
};
|
||||
|
||||
devcb_read8 m_readregs_cb;
|
||||
|
||||
devcb_read8 m_readsamples_cb;
|
||||
|
||||
xavix_voice m_voice[16];
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(XAVIX_SOUND, xavix_sound_device)
|
||||
@ -45,7 +63,6 @@ public:
|
||||
: driver_device(mconfig, type, tag),
|
||||
m_in0(*this, "IN0"),
|
||||
m_in1(*this, "IN1"),
|
||||
m_sound(*this, "xavix_sound"),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_screen(*this, "screen"),
|
||||
m_mainram(*this, "mainram"),
|
||||
@ -68,7 +85,8 @@ public:
|
||||
m_region(*this, "REGION"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_lowbus(*this, "lowbus"),
|
||||
m_hack_timer_disable(false)
|
||||
m_hack_timer_disable(false),
|
||||
m_sound(*this, "xavix_sound")
|
||||
{ }
|
||||
|
||||
void xavix(machine_config &config);
|
||||
@ -93,7 +111,6 @@ protected:
|
||||
required_ioport m_in1;
|
||||
|
||||
private:
|
||||
required_device<xavix_sound_device> m_sound;
|
||||
|
||||
// screen updates
|
||||
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
@ -166,6 +183,11 @@ private:
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
DECLARE_READ8_MEMBER(sample_read)
|
||||
{
|
||||
return read_full_data_sp_bypass(offset);
|
||||
};
|
||||
|
||||
inline uint8_t read_full_data_sp_bypass(uint32_t adr)
|
||||
{
|
||||
uint8_t databank = adr >> 16;
|
||||
@ -467,6 +489,9 @@ private:
|
||||
required_device<address_map_bank_device> m_lowbus;
|
||||
|
||||
bool m_hack_timer_disable;
|
||||
|
||||
required_device<xavix_sound_device> m_sound;
|
||||
DECLARE_READ8_MEMBER(sound_regram_read_cb);
|
||||
};
|
||||
|
||||
class xavix_i2c_state : public xavix_state
|
||||
|
@ -865,6 +865,8 @@ void xavix_state::machine_reset()
|
||||
m_ioevent_active = 0x00;
|
||||
|
||||
m_sound_irqstatus = 0x00;
|
||||
|
||||
m_sound_regbase = 0x00;
|
||||
}
|
||||
|
||||
typedef device_delegate<uint8_t(int which, int half)> xavix_interrupt_vector_delegate;
|
||||
|
Loading…
Reference in New Issue
Block a user