mirror of
https://github.com/holub/mame
synced 2025-07-01 00:09:18 +03:00
preliminary Toshiba TC8830F emulation [hap]
This commit is contained in:
parent
fb3e6359e8
commit
1e79fda5b2
@ -1,13 +1,15 @@
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
|
|
||||||
tc8830f.c - Toshiba TC8830F, CMOS voice recording/reproducing LSI
|
tc8830f.c - Toshiba TC8830F, CMOS voice recording/reproducing LSI
|
||||||
|
1-bit ADM (Adaptive Delta Modulation), similar to TC8801 and T6668.
|
||||||
|
|
||||||
Very preliminary...
|
Very preliminary...
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
|
- ADM decoder
|
||||||
- remaining commands
|
- remaining commands
|
||||||
- cpu manual mode
|
- manual control
|
||||||
- status read
|
- chip read
|
||||||
- RAM
|
- RAM
|
||||||
- recording
|
- recording
|
||||||
|
|
||||||
@ -35,26 +37,173 @@ void tc8830f_device::device_start()
|
|||||||
m_mem_base = (UINT8 *)device().machine().root_device().memregion(":tc8830f")->base();
|
m_mem_base = (UINT8 *)device().machine().root_device().memregion(":tc8830f")->base();
|
||||||
m_mem_mask = device().machine().root_device().memregion(":tc8830f")->bytes() - 1;
|
m_mem_mask = device().machine().root_device().memregion(":tc8830f")->bytes() - 1;
|
||||||
|
|
||||||
|
// register for savestates
|
||||||
|
save_item(NAME(m_playing));
|
||||||
|
save_item(NAME(m_address));
|
||||||
|
save_item(NAME(m_stop_address));
|
||||||
|
save_item(NAME(m_bitcount));
|
||||||
|
save_item(NAME(m_bitrate));
|
||||||
|
save_item(NAME(m_command));
|
||||||
|
save_item(NAME(m_cmd_rw));
|
||||||
|
save_item(NAME(m_phrase));
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void tc8830f_device::device_post_load()
|
||||||
|
{
|
||||||
|
device_clock_changed();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void tc8830f_device::device_clock_changed()
|
||||||
|
{
|
||||||
|
int divisor = 0x10 * (4 - (m_bitrate & 3));
|
||||||
|
m_stream->set_sample_rate(clock() / divisor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void tc8830f_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
void tc8830f_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < samples; i++)
|
for (int i = 0; i < samples; i++)
|
||||||
{
|
{
|
||||||
outputs[0][i] = 0;
|
int mix = 0;
|
||||||
|
if (m_playing)
|
||||||
|
{
|
||||||
|
// get bit
|
||||||
|
int bit = m_mem_base[m_address] >> m_bitcount & 1;
|
||||||
|
m_bitcount = (m_bitcount + 1) & 7;
|
||||||
|
if (m_bitcount == 0)
|
||||||
|
{
|
||||||
|
m_address = (m_address + 1) & m_mem_mask;
|
||||||
|
if (m_address == m_stop_address)
|
||||||
|
m_playing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute sample
|
||||||
|
// this is a placeholder until ADM is implemented
|
||||||
|
mix = bit * 0x7fff;
|
||||||
|
}
|
||||||
|
outputs[0][i] = mix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void tc8830f_device::reset()
|
void tc8830f_device::reset()
|
||||||
{
|
{
|
||||||
;
|
m_stream->update();
|
||||||
|
|
||||||
|
m_playing = false;
|
||||||
|
m_address = 0x100;
|
||||||
|
m_bitcount = 0;
|
||||||
|
m_cmd_rw = 0;
|
||||||
|
|
||||||
|
// in cpu control, enter play mode and reset bitrate
|
||||||
|
write_p(1);
|
||||||
|
write_p(6);
|
||||||
|
write_p(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void tc8830f_device::write_p(UINT8 data)
|
void tc8830f_device::write_p(UINT8 data)
|
||||||
{
|
{
|
||||||
m_stream->update();
|
m_stream->update();
|
||||||
|
data &= 0xf;
|
||||||
|
|
||||||
|
if (m_cmd_rw == 0)
|
||||||
|
{
|
||||||
|
// select command
|
||||||
|
m_command = data;
|
||||||
|
switch (m_command)
|
||||||
|
{
|
||||||
|
// immediate commands
|
||||||
|
case 0x1:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x2:
|
||||||
|
m_playing = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x3:
|
||||||
|
m_playing = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// multi-nibble commands
|
||||||
|
case 0x4: case 0x5: case 0x6: case 0x7:
|
||||||
|
m_cmd_rw = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x8: case 0x9: case 0xa: case 0xb:
|
||||||
|
logerror("tc8830f: Unemulated command %X\n", m_command);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
logerror("tc8830f: Invalid command %X\n", m_command);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// write command
|
||||||
|
switch (m_command)
|
||||||
|
{
|
||||||
|
case 0x4:
|
||||||
|
// ADLD1: set address counter
|
||||||
|
m_address = (m_address & ~(0xf << (m_cmd_rw*4))) | (data << (m_cmd_rw*4));
|
||||||
|
if (m_cmd_rw == 5)
|
||||||
|
{
|
||||||
|
m_address &= m_mem_mask;
|
||||||
|
m_bitcount = 0;
|
||||||
|
m_cmd_rw = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x5:
|
||||||
|
// ADLD2: set address stop
|
||||||
|
m_stop_address = (m_stop_address & ~(0xf << (m_cmd_rw*4))) | (data << (m_cmd_rw*4));
|
||||||
|
if (m_cmd_rw == 5)
|
||||||
|
{
|
||||||
|
m_stop_address &= m_mem_mask;
|
||||||
|
m_cmd_rw = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x6:
|
||||||
|
// CNDT: d0-d1: bitrate, d2: enable overflow
|
||||||
|
m_bitrate = data & 3;
|
||||||
|
device_clock_changed();
|
||||||
|
m_cmd_rw = -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x7:
|
||||||
|
// LABEL: set phrase
|
||||||
|
if (m_cmd_rw == 1)
|
||||||
|
{
|
||||||
|
m_phrase = (m_phrase & 0x30) | data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_phrase = (m_phrase & 0x0f) | (data << 4 & 0x30);
|
||||||
|
|
||||||
|
// update addresses and start
|
||||||
|
UINT8 offs = m_phrase * 4;
|
||||||
|
m_address = (m_mem_base[offs] | m_mem_base[offs|1]<<8 | m_mem_base[offs|2]<<16) & m_mem_mask;
|
||||||
|
offs += 4;
|
||||||
|
m_stop_address = (m_mem_base[offs] | m_mem_base[offs|1]<<8 | m_mem_base[offs|2]<<16) & m_mem_mask;
|
||||||
|
|
||||||
|
m_bitcount = 0;
|
||||||
|
m_playing = true;
|
||||||
|
m_cmd_rw = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
m_cmd_rw = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_cmd_rw++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,10 @@
|
|||||||
// INTERFACE CONFIGURATION MACROS
|
// INTERFACE CONFIGURATION MACROS
|
||||||
//**************************************************************************
|
//**************************************************************************
|
||||||
|
|
||||||
#define MCFG_TC8830F_SND_ADD(_tag, _clock) \
|
#define MCFG_TC8830F_ADD(_tag, _clock) \
|
||||||
MCFG_DEVICE_ADD(_tag, TC8830F, _clock)
|
MCFG_DEVICE_ADD(_tag, TC8830F, _clock)
|
||||||
|
|
||||||
#define MCFG_TC8830F_SND_REPLACE(_tag, _clock) \
|
#define MCFG_TC8830F_REPLACE(_tag, _clock) \
|
||||||
MCFG_DEVICE_REPLACE(_tag, TC8830F, _clock)
|
MCFG_DEVICE_REPLACE(_tag, TC8830F, _clock)
|
||||||
|
|
||||||
|
|
||||||
@ -40,10 +40,21 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
// device-level overrides
|
// device-level overrides
|
||||||
virtual void device_start();
|
virtual void device_start();
|
||||||
|
virtual void device_post_load();
|
||||||
|
virtual void device_clock_changed();
|
||||||
|
|
||||||
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
|
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool m_playing;
|
||||||
|
UINT32 m_address;
|
||||||
|
UINT32 m_stop_address;
|
||||||
|
UINT8 m_bitcount;
|
||||||
|
UINT8 m_bitrate;
|
||||||
|
UINT8 m_command;
|
||||||
|
int m_cmd_rw;
|
||||||
|
UINT8 m_phrase;
|
||||||
|
|
||||||
UINT8 *m_mem_base;
|
UINT8 *m_mem_base;
|
||||||
UINT32 m_mem_mask;
|
UINT32 m_mem_mask;
|
||||||
};
|
};
|
||||||
|
@ -101,7 +101,7 @@ static WRITE8_DEVICE_HANDLER(chkun_sound_w)
|
|||||||
// d0-d3: P0-P3
|
// d0-d3: P0-P3
|
||||||
// d5: /R (unused?)
|
// d5: /R (unused?)
|
||||||
// d6: /W
|
// d6: /W
|
||||||
if (data & 0x40)
|
if (~data & 0x40)
|
||||||
state->m_tc8830f->write_p(data);
|
state->m_tc8830f->write_p(data);
|
||||||
|
|
||||||
// d4 (or d7?): /ACL
|
// d4 (or d7?): /ACL
|
||||||
@ -515,8 +515,8 @@ static MACHINE_CONFIG_DERIVED( chkun, bikkuric )
|
|||||||
MCFG_SOUND_MODIFY("ay2")
|
MCFG_SOUND_MODIFY("ay2")
|
||||||
MCFG_SOUND_CONFIG(chkun_ay2_interface)
|
MCFG_SOUND_CONFIG(chkun_ay2_interface)
|
||||||
|
|
||||||
MCFG_TC8830F_SND_ADD("tc8830f", 500000)
|
MCFG_TC8830F_ADD("tc8830f", XTAL_18_432MHz/3/12)
|
||||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
|
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.10)
|
||||||
MACHINE_CONFIG_END
|
MACHINE_CONFIG_END
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user