mirror of
https://github.com/holub/mame
synced 2025-07-03 00:56:03 +03:00
(MESS) Modernized uPD1771c sound device. [Fabio Priuli]
src/mess/audio/ is now legacy free, if I'm not making mistakes...
This commit is contained in:
parent
cb34ca297b
commit
cecb42fcb1
@ -162,13 +162,11 @@
|
|||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "upd1771.h"
|
#include "audio/upd1771.h"
|
||||||
|
|
||||||
|
|
||||||
#define LOG 0
|
#define LOG 0
|
||||||
|
|
||||||
#define MAX_PACKET_SIZE 0x8000
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Each of the 8 waveforms have been sampled at 192kHz using period 0xFF,
|
Each of the 8 waveforms have been sampled at 192kHz using period 0xFF,
|
||||||
filtered, and each of the 32 levels have been calculated with averages on around 10 samples
|
filtered, and each of the 32 levels have been calculated with averages on around 10 samples
|
||||||
@ -189,7 +187,6 @@ const char WAVEFORMS[8][32]={
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define NOISE_SIZE 255
|
#define NOISE_SIZE 255
|
||||||
|
|
||||||
|
|
||||||
@ -220,51 +217,86 @@ const char WAVEFORMS[8][32]={
|
|||||||
#define STATE_TONE 2
|
#define STATE_TONE 2
|
||||||
#define STATE_ADPCM 3
|
#define STATE_ADPCM 3
|
||||||
|
|
||||||
struct upd1771_state
|
|
||||||
|
const device_type UPD1771C = &device_creator<upd1771c_device>;
|
||||||
|
|
||||||
|
|
||||||
|
upd1771c_device::upd1771c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||||
|
: device_t(mconfig, UPD1771C, "NEC uPD1771C 017", tag, owner, clock),
|
||||||
|
device_sound_interface(mconfig, *this)
|
||||||
{
|
{
|
||||||
sound_stream *channel;
|
|
||||||
devcb_resolved_write_line ack_out_func;
|
|
||||||
emu_timer *timer;
|
|
||||||
|
|
||||||
UINT8 packet[MAX_PACKET_SIZE];
|
|
||||||
UINT32 index;
|
|
||||||
UINT8 expected_bytes;
|
|
||||||
|
|
||||||
UINT8 state;//0:silence, 1 noise, 2 tone
|
|
||||||
UINT8 pc3;
|
|
||||||
|
|
||||||
//tone
|
|
||||||
UINT8 t_timbre; //[0; 7]
|
|
||||||
UINT8 t_offset; //[0; 32]
|
|
||||||
UINT16 t_period; //[0;255]
|
|
||||||
UINT8 t_volume; //[0; 31]
|
|
||||||
UINT8 t_tpos;//timbre pos
|
|
||||||
UINT16 t_ppos;//period pos
|
|
||||||
|
|
||||||
//noise wavetable LFSR
|
|
||||||
UINT8 nw_timbre; //[0; 7]
|
|
||||||
UINT8 nw_volume; //[0; 31]
|
|
||||||
UINT32 nw_period;
|
|
||||||
UINT32 nw_tpos; //timbre pos
|
|
||||||
UINT32 nw_ppos; //period pos
|
|
||||||
|
|
||||||
//noise pulse components
|
|
||||||
UINT8 n_value[3]; //[0;1]
|
|
||||||
UINT16 n_volume[3]; //[0; 31]
|
|
||||||
UINT32 n_period[3];
|
|
||||||
UINT32 n_ppos[3]; //period pos
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
INLINE upd1771_state *get_safe_token(device_t *device)
|
|
||||||
{
|
|
||||||
assert(device != NULL);
|
|
||||||
assert(device->type() == UPD1771C);
|
|
||||||
return (upd1771_state *)downcast<upd1771c_device *>(device)->token();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
READ8_DEVICE_HANDLER( upd1771_r )
|
//-------------------------------------------------
|
||||||
|
// device_config_complete - perform any
|
||||||
|
// operations now that the configuration is
|
||||||
|
// complete
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void upd1771c_device::device_config_complete()
|
||||||
|
{
|
||||||
|
// inherit a copy of the static data
|
||||||
|
const upd1771_interface *intf = reinterpret_cast<const upd1771_interface *>(static_config());
|
||||||
|
if (intf != NULL)
|
||||||
|
*static_cast<upd1771_interface *>(this) = *intf;
|
||||||
|
|
||||||
|
// or initialize to defaults if none provided
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(&m_ack_callback, 0, sizeof(m_ack_callback));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// device_start - device-specific startup
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void upd1771c_device::device_start()
|
||||||
|
{
|
||||||
|
/* resolve callbacks */
|
||||||
|
m_ack_out_func.resolve(m_ack_callback, *this);
|
||||||
|
|
||||||
|
m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(upd1771c_device::ack_callback),this));
|
||||||
|
|
||||||
|
m_channel = machine().sound().stream_alloc(*this, 0, 1, clock() / 4, this);
|
||||||
|
|
||||||
|
save_item(NAME(m_packet));
|
||||||
|
save_item(NAME(m_index));
|
||||||
|
save_item(NAME(m_expected_bytes));
|
||||||
|
save_item(NAME(m_state));
|
||||||
|
save_item(NAME(m_pc3));
|
||||||
|
save_item(NAME(m_t_timbre));
|
||||||
|
save_item(NAME(m_t_offset));
|
||||||
|
save_item(NAME(m_t_period));
|
||||||
|
save_item(NAME(m_t_volume));
|
||||||
|
save_item(NAME(m_t_tpos));
|
||||||
|
save_item(NAME(m_t_ppos));
|
||||||
|
save_item(NAME(m_nw_timbre));
|
||||||
|
save_item(NAME(m_nw_volume));
|
||||||
|
save_item(NAME(m_nw_period));
|
||||||
|
save_item(NAME(m_nw_tpos));
|
||||||
|
save_item(NAME(m_nw_ppos));
|
||||||
|
save_item(NAME(m_n_value));
|
||||||
|
save_item(NAME(m_n_volume));
|
||||||
|
save_item(NAME(m_n_period));
|
||||||
|
save_item(NAME(m_n_ppos));
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------
|
||||||
|
// device_reset - device-specific reset
|
||||||
|
//-------------------------------------------------
|
||||||
|
|
||||||
|
void upd1771c_device::device_reset()
|
||||||
|
{
|
||||||
|
m_index = 0;
|
||||||
|
m_expected_bytes = 0;
|
||||||
|
m_pc3 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
READ8_MEMBER( upd1771c_device::read )
|
||||||
{
|
{
|
||||||
return 0x80; // TODO
|
return 0x80; // TODO
|
||||||
}
|
}
|
||||||
@ -331,281 +363,116 @@ Byte8: 0b???VVVVV Low Freq1 volume
|
|||||||
Byte9: 0b???VVVVV Low Freq2 volume
|
Byte9: 0b???VVVVV Low Freq2 volume
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WRITE8_DEVICE_HANDLER( upd1771_w )
|
WRITE8_MEMBER( upd1771c_device::write )
|
||||||
{
|
{
|
||||||
upd1771_state *state = get_safe_token( device );
|
|
||||||
|
|
||||||
//if (LOG)
|
//if (LOG)
|
||||||
// logerror( "upd1771_w: received byte 0x%02x\n", data );
|
// logerror( "upd1771_w: received byte 0x%02x\n", data );
|
||||||
|
|
||||||
state->ack_out_func(0);
|
m_ack_out_func(0);
|
||||||
|
|
||||||
if (state->index < MAX_PACKET_SIZE)
|
if (m_index < MAX_PACKET_SIZE)
|
||||||
state->packet[state->index++]=data;
|
m_packet[m_index++] = data;
|
||||||
else{
|
else
|
||||||
|
{
|
||||||
logerror("upd1771_w: received byte 0x%02x overload!\n", data);
|
logerror("upd1771_w: received byte 0x%02x overload!\n", data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(state->packet[0]){
|
switch (m_packet[0])
|
||||||
case 0:
|
|
||||||
{
|
{
|
||||||
state->state = STATE_SILENCE;
|
case 0:
|
||||||
state->index = 0;
|
m_state = STATE_SILENCE;
|
||||||
|
m_index = 0;
|
||||||
//logerror( "upd1771_w: ----------------silence state reset\n");
|
//logerror( "upd1771_w: ----------------silence state reset\n");
|
||||||
}break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
|
if (m_index == 10)
|
||||||
{
|
{
|
||||||
if (state->index == 10){
|
m_state = STATE_NOISE;
|
||||||
state->state = STATE_NOISE;
|
m_index = 0;
|
||||||
state->index = 0;
|
|
||||||
|
|
||||||
state->nw_timbre = (state->packet[1] & 0xE0) >> 5;
|
m_nw_timbre = (m_packet[1] & 0xe0) >> 5;
|
||||||
state->nw_period = ((UINT32)state->packet[2]+1)<<7;
|
m_nw_period = ((UINT32)m_packet[2] + 1) << 7;
|
||||||
state->nw_volume = state->packet[3] & 0x1f;
|
m_nw_volume = m_packet[3] & 0x1f;
|
||||||
|
|
||||||
//very long clocked periods.. used for engine drones
|
//very long clocked periods.. used for engine drones
|
||||||
state->n_period[0] = (((UINT32)state->packet[4])+1)<<7;
|
m_n_period[0] = (((UINT32)m_packet[4]) + 1) << 7;
|
||||||
state->n_period[1] = (((UINT32)state->packet[5])+1)<<7;
|
m_n_period[1] = (((UINT32)m_packet[5]) + 1) << 7;
|
||||||
state->n_period[2] = (((UINT32)state->packet[6])+1)<<7;
|
m_n_period[2] = (((UINT32)m_packet[6]) + 1) << 7;
|
||||||
|
|
||||||
state->n_volume[0] = state->packet[7]& 0x1f;
|
m_n_volume[0] = m_packet[7] & 0x1f;
|
||||||
state->n_volume[1] = state->packet[8]& 0x1f;
|
m_n_volume[1] = m_packet[8] & 0x1f;
|
||||||
state->n_volume[2] = state->packet[9]& 0x1f;
|
m_n_volume[2] = m_packet[9] & 0x1f;
|
||||||
|
|
||||||
//logerror( "upd1771_w: ----------------noise state reset\n");
|
//logerror( "upd1771_w: ----------------noise state reset\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
state->timer->adjust( attotime::from_ticks( 512, device->clock() ) );
|
m_timer->adjust(attotime::from_ticks(512, clock()));
|
||||||
}break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
|
if (m_index == 4)
|
||||||
{
|
{
|
||||||
if (state->index == 4){
|
|
||||||
//logerror( "upd1771_w: ----------------tone state reset\n");
|
//logerror( "upd1771_w: ----------------tone state reset\n");
|
||||||
state->t_timbre = (state->packet[1] & 0xE0) >> 5;
|
m_t_timbre = (m_packet[1] & 0xe0) >> 5;
|
||||||
state->t_offset = (state->packet[1] & 0x1F);
|
m_t_offset = (m_packet[1] & 0x1f);
|
||||||
state->t_period = state->packet[2];
|
m_t_period = m_packet[2];
|
||||||
//smaller periods dont all equal to 0x20
|
//smaller periods dont all equal to 0x20
|
||||||
if (state->t_period < 0x20)
|
if (m_t_period < 0x20)
|
||||||
state->t_period = 0x20;
|
m_t_period = 0x20;
|
||||||
|
|
||||||
state->t_volume = state->packet[3] & 0x1f;
|
m_t_volume = m_packet[3] & 0x1f;
|
||||||
state->state = STATE_TONE;
|
m_state = STATE_TONE;
|
||||||
state->index = 0;
|
m_index = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
state->timer->adjust( attotime::from_ticks( 512, device->clock() ) );
|
m_timer->adjust(attotime::from_ticks(512, clock()));
|
||||||
|
break;
|
||||||
|
|
||||||
}break;
|
case 0x1f:
|
||||||
|
|
||||||
case 0x1F:
|
|
||||||
{
|
|
||||||
//6Khz(ish) DIGI playback
|
//6Khz(ish) DIGI playback
|
||||||
|
|
||||||
//end capture
|
//end capture
|
||||||
if (state->index >= 2 && state->packet[state->index-2] == 0xFE &&
|
if (m_index >= 2 && m_packet[m_index - 2] == 0xfe && m_packet[m_index - 1] == 0x00)
|
||||||
state->packet[state->index-1] == 0x00){
|
{
|
||||||
//TODO play capture!
|
//TODO play capture!
|
||||||
state->index = 0;
|
m_index = 0;
|
||||||
state->packet[0]=0;
|
m_packet[0] = 0;
|
||||||
state->state = STATE_ADPCM;
|
m_state = STATE_ADPCM;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
state->timer->adjust( attotime::from_ticks( 512, device->clock() ) );
|
m_timer->adjust(attotime::from_ticks(512, clock()));
|
||||||
|
break;
|
||||||
}break;
|
|
||||||
|
|
||||||
//garbage: wipe stack
|
//garbage: wipe stack
|
||||||
default:
|
default:
|
||||||
state->state = STATE_SILENCE;
|
m_state = STATE_SILENCE;
|
||||||
state->index = 0;
|
m_index = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
WRITE_LINE_DEVICE_HANDLER( upd1771_pcm_w )
|
WRITE_LINE_MEMBER( upd1771c_device::pcm_write )
|
||||||
{
|
{
|
||||||
upd1771_state *upd1771 = get_safe_token( device );
|
|
||||||
|
|
||||||
//RESET upon HIGH
|
//RESET upon HIGH
|
||||||
if (state != upd1771->pc3){
|
if (state != m_pc3)
|
||||||
|
{
|
||||||
logerror("upd1771_pc3 change!: state = %d\n", state);
|
logerror("upd1771_pc3 change!: state = %d\n", state);
|
||||||
upd1771->index = 0;
|
m_index = 0;
|
||||||
upd1771->packet[0]=0;
|
m_packet[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
upd1771->pc3 = state;
|
m_pc3 = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static STREAM_UPDATE( upd1771c_update )
|
TIMER_CALLBACK_MEMBER( upd1771c_device::ack_callback )
|
||||||
{
|
{
|
||||||
upd1771_state *state = get_safe_token( device );
|
m_ack_out_func(1);
|
||||||
stream_sample_t *buffer = outputs[0];
|
|
||||||
|
|
||||||
switch(state->state){
|
|
||||||
case STATE_TONE:
|
|
||||||
{
|
|
||||||
//logerror( "upd1771_STATE_TONE samps:%d %d %d %d %d %d\n",(int)samples,
|
|
||||||
// (int)state->t_timbre,(int)state->t_offset,(int)state->t_volume,(int)state->t_period,(int)state->t_tpos);
|
|
||||||
|
|
||||||
while ( --samples >= 0 ){
|
|
||||||
*buffer++ = (WAVEFORMS[state->t_timbre][state->t_tpos])*state->t_volume * 2;
|
|
||||||
|
|
||||||
state->t_ppos++;
|
|
||||||
if (state->t_ppos >= state->t_period){
|
|
||||||
state->t_tpos++;
|
|
||||||
if (state->t_tpos == 32)
|
|
||||||
state->t_tpos = state->t_offset;
|
|
||||||
|
|
||||||
state->t_ppos = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}break;
|
|
||||||
|
|
||||||
case STATE_NOISE:
|
|
||||||
{
|
|
||||||
while (--samples >= 0 ){
|
|
||||||
*buffer = 0;
|
|
||||||
|
|
||||||
//"wavetable-LFSR" component
|
|
||||||
int wlfsr_val = ((int)noise_tbl[state->nw_tpos])-127;//data too wide
|
|
||||||
|
|
||||||
state->nw_ppos++;
|
|
||||||
if (state->nw_ppos >= state->nw_period){
|
|
||||||
state->nw_tpos++;
|
|
||||||
if (state->nw_tpos == NOISE_SIZE)
|
|
||||||
state->nw_tpos = 0;
|
|
||||||
state->nw_ppos = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//mix in each of the noise's 3 pulse components
|
|
||||||
char res[3];
|
|
||||||
for (size_t i=0;i<3;++i){
|
|
||||||
res[i] = state->n_value[i]* 127;
|
|
||||||
state->n_ppos[i]++;
|
|
||||||
if (state->n_ppos[i] >= state->n_period[i]){
|
|
||||||
state->n_ppos[i] = 0;
|
|
||||||
state->n_value[i] = !state->n_value[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//not quite, but close.
|
|
||||||
*buffer+= (
|
|
||||||
(wlfsr_val*state->nw_volume) |
|
|
||||||
(res[0]*state->n_volume[0]) |
|
|
||||||
(res[1]*state->n_volume[1]) |
|
|
||||||
(res[2]*state->n_volume[2])
|
|
||||||
) ;
|
|
||||||
|
|
||||||
buffer++;
|
|
||||||
}
|
|
||||||
}break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
//fill buffer with silence
|
|
||||||
while (--samples >= 0 ){
|
|
||||||
*buffer++ = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static TIMER_CALLBACK( upd1771c_callback )
|
|
||||||
{
|
|
||||||
device_t *device = (device_t *)ptr;
|
|
||||||
upd1771_state *state = get_safe_token( device );
|
|
||||||
|
|
||||||
state->ack_out_func(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static DEVICE_START( upd1771c )
|
|
||||||
{
|
|
||||||
const upd1771_interface *intf = (const upd1771_interface *)device->static_config();
|
|
||||||
upd1771_state *state = get_safe_token( device );
|
|
||||||
int sample_rate = device->clock() / 4;
|
|
||||||
|
|
||||||
/* resolve callbacks */
|
|
||||||
state->ack_out_func.resolve(intf->ack_callback, *device);
|
|
||||||
|
|
||||||
state->timer = device->machine().scheduler().timer_alloc(FUNC(upd1771c_callback), (void *)device );
|
|
||||||
|
|
||||||
state->channel = device->machine().sound().stream_alloc( *device, 0, 1, sample_rate, state, upd1771c_update );
|
|
||||||
|
|
||||||
device->save_item( NAME(state->packet) );
|
|
||||||
device->save_item(NAME(state->index) );
|
|
||||||
device->save_item(NAME(state->expected_bytes) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static DEVICE_RESET( upd1771c )
|
|
||||||
{
|
|
||||||
upd1771_state *state = get_safe_token( device );
|
|
||||||
|
|
||||||
state->index = 0;
|
|
||||||
state->expected_bytes = 0;
|
|
||||||
state->pc3 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static DEVICE_STOP( upd1771c )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const device_type UPD1771C = &device_creator<upd1771c_device>;
|
|
||||||
|
|
||||||
upd1771c_device::upd1771c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
|
||||||
: device_t(mconfig, UPD1771C, "NEC uPD1771C 017", tag, owner, clock),
|
|
||||||
device_sound_interface(mconfig, *this)
|
|
||||||
{
|
|
||||||
m_token = global_alloc_clear(upd1771_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
|
||||||
// device_config_complete - perform any
|
|
||||||
// operations now that the configuration is
|
|
||||||
// complete
|
|
||||||
//-------------------------------------------------
|
|
||||||
|
|
||||||
void upd1771c_device::device_config_complete()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
|
||||||
// device_start - device-specific startup
|
|
||||||
//-------------------------------------------------
|
|
||||||
|
|
||||||
void upd1771c_device::device_start()
|
|
||||||
{
|
|
||||||
DEVICE_START_NAME( upd1771c )(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
|
||||||
// device_reset - device-specific reset
|
|
||||||
//-------------------------------------------------
|
|
||||||
|
|
||||||
void upd1771c_device::device_reset()
|
|
||||||
{
|
|
||||||
DEVICE_RESET_NAME( upd1771c )(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
|
||||||
// device_stop - device-specific stop
|
|
||||||
//-------------------------------------------------
|
|
||||||
|
|
||||||
void upd1771c_device::device_stop()
|
|
||||||
{
|
|
||||||
DEVICE_STOP_NAME( upd1771c )(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------
|
//-------------------------------------------------
|
||||||
// sound_stream_update - handle a stream update
|
// sound_stream_update - handle a stream update
|
||||||
@ -613,6 +480,77 @@ void upd1771c_device::device_stop()
|
|||||||
|
|
||||||
void upd1771c_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
void upd1771c_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
|
||||||
{
|
{
|
||||||
// should never get here
|
stream_sample_t *buffer = outputs[0];
|
||||||
fatalerror("sound_stream_update called; not applicable to legacy sound devices\n");
|
|
||||||
|
switch (m_state)
|
||||||
|
{
|
||||||
|
case STATE_TONE:
|
||||||
|
//logerror( "upd1771_STATE_TONE samps:%d %d %d %d %d %d\n",(int)samples,
|
||||||
|
// (int)m_t_timbre,(int)m_t_offset,(int)m_t_volume,(int)m_t_period,(int)m_t_tpos);
|
||||||
|
|
||||||
|
while (--samples >= 0)
|
||||||
|
{
|
||||||
|
*buffer++ = (WAVEFORMS[m_t_timbre][m_t_tpos]) * m_t_volume * 2;
|
||||||
|
|
||||||
|
m_t_ppos++;
|
||||||
|
if (m_t_ppos >= m_t_period)
|
||||||
|
{
|
||||||
|
m_t_tpos++;
|
||||||
|
if (m_t_tpos == 32)
|
||||||
|
m_t_tpos = m_t_offset;
|
||||||
|
|
||||||
|
m_t_ppos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_NOISE:
|
||||||
|
while (--samples >= 0)
|
||||||
|
{
|
||||||
|
*buffer = 0;
|
||||||
|
|
||||||
|
//"wavetable-LFSR" component
|
||||||
|
int wlfsr_val = ((int)noise_tbl[m_nw_tpos]) - 127;//data too wide
|
||||||
|
|
||||||
|
m_nw_ppos++;
|
||||||
|
if (m_nw_ppos >= m_nw_period)
|
||||||
|
{
|
||||||
|
m_nw_tpos++;
|
||||||
|
if (m_nw_tpos == NOISE_SIZE)
|
||||||
|
m_nw_tpos = 0;
|
||||||
|
m_nw_ppos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//mix in each of the noise's 3 pulse components
|
||||||
|
char res[3];
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
res[i] = m_n_value[i] * 127;
|
||||||
|
m_n_ppos[i]++;
|
||||||
|
if (m_n_ppos[i] >= m_n_period[i])
|
||||||
|
{
|
||||||
|
m_n_ppos[i] = 0;
|
||||||
|
m_n_value[i] = !m_n_value[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//not quite, but close.
|
||||||
|
*buffer+= (
|
||||||
|
(wlfsr_val * m_nw_volume) |
|
||||||
|
(res[0] * m_n_volume[0]) |
|
||||||
|
(res[1] * m_n_volume[1]) |
|
||||||
|
(res[2] * m_n_volume[2])
|
||||||
|
) ;
|
||||||
|
|
||||||
|
buffer++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
//fill buffer with silence
|
||||||
|
while (--samples >= 0)
|
||||||
|
{
|
||||||
|
*buffer++ = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,13 +9,15 @@
|
|||||||
|
|
||||||
#include "devcb.h"
|
#include "devcb.h"
|
||||||
|
|
||||||
|
#define MAX_PACKET_SIZE 0x8000
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
TYPE DEFINITIONS
|
TYPE DEFINITIONS
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
struct upd1771_interface
|
struct upd1771_interface
|
||||||
{
|
{
|
||||||
devcb_write_line ack_callback;
|
devcb_write_line m_ack_callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -24,38 +26,64 @@ struct upd1771_interface
|
|||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
class upd1771c_device : public device_t,
|
class upd1771c_device : public device_t,
|
||||||
public device_sound_interface
|
public device_sound_interface,
|
||||||
|
public upd1771_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
upd1771c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
upd1771c_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||||
~upd1771c_device() { global_free(m_token); }
|
~upd1771c_device() {}
|
||||||
|
|
||||||
|
DECLARE_READ8_MEMBER( read );
|
||||||
|
DECLARE_WRITE8_MEMBER( write );
|
||||||
|
WRITE_LINE_MEMBER( pcm_write );
|
||||||
|
|
||||||
// access to legacy token
|
|
||||||
void *token() const { assert(m_token != NULL); return m_token; }
|
|
||||||
protected:
|
protected:
|
||||||
// device-level overrides
|
// device-level overrides
|
||||||
virtual void device_config_complete();
|
virtual void device_config_complete();
|
||||||
virtual void device_start();
|
virtual void device_start();
|
||||||
virtual void device_stop();
|
|
||||||
virtual void device_reset();
|
virtual void device_reset();
|
||||||
|
|
||||||
// sound stream update overrides
|
// sound stream update overrides
|
||||||
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:
|
||||||
// internal state
|
// internal state
|
||||||
void *m_token;
|
sound_stream *m_channel;
|
||||||
|
devcb_resolved_write_line m_ack_out_func;
|
||||||
|
emu_timer *m_timer;
|
||||||
|
|
||||||
|
TIMER_CALLBACK_MEMBER(ack_callback);
|
||||||
|
|
||||||
|
UINT8 m_packet[MAX_PACKET_SIZE];
|
||||||
|
UINT32 m_index;
|
||||||
|
UINT8 m_expected_bytes;
|
||||||
|
|
||||||
|
UINT8 m_state;//0:silence, 1 noise, 2 tone
|
||||||
|
UINT8 m_pc3;
|
||||||
|
|
||||||
|
//tone
|
||||||
|
UINT8 m_t_timbre; //[0; 7]
|
||||||
|
UINT8 m_t_offset; //[0; 32]
|
||||||
|
UINT16 m_t_period; //[0;255]
|
||||||
|
UINT8 m_t_volume; //[0; 31]
|
||||||
|
UINT8 m_t_tpos;//timbre pos
|
||||||
|
UINT16 m_t_ppos;//period pos
|
||||||
|
|
||||||
|
//noise wavetable LFSR
|
||||||
|
UINT8 m_nw_timbre; //[0; 7]
|
||||||
|
UINT8 m_nw_volume; //[0; 31]
|
||||||
|
UINT32 m_nw_period;
|
||||||
|
UINT32 m_nw_tpos; //timbre pos
|
||||||
|
UINT32 m_nw_ppos; //period pos
|
||||||
|
|
||||||
|
//noise pulse components
|
||||||
|
UINT8 m_n_value[3]; //[0;1]
|
||||||
|
UINT16 m_n_volume[3]; //[0; 31]
|
||||||
|
UINT32 m_n_period[3];
|
||||||
|
UINT32 m_n_ppos[3]; //period pos
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const device_type UPD1771C;
|
extern const device_type UPD1771C;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
|
||||||
PROTOTYPES
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
DECLARE_READ8_DEVICE_HANDLER( upd1771_r );
|
|
||||||
DECLARE_WRITE8_DEVICE_HANDLER( upd1771_w );
|
|
||||||
WRITE_LINE_DEVICE_HANDLER( upd1771_pcm_w );
|
|
||||||
|
|
||||||
#endif /* __UPD1771_H__ */
|
#endif /* __UPD1771_H__ */
|
||||||
|
@ -488,7 +488,7 @@ static ADDRESS_MAP_START( apc_io, AS_IO, 16, apc_state )
|
|||||||
// 0x5a APU data (Arithmetic Processing Unit!)
|
// 0x5a APU data (Arithmetic Processing Unit!)
|
||||||
// 0x5b, Power Off
|
// 0x5b, Power Off
|
||||||
// 0x5e APU status/command
|
// 0x5e APU status/command
|
||||||
AM_RANGE(0x60, 0x61) AM_DEVREADWRITE8_LEGACY("upd1771c", upd1771_r, upd1771_w, 0x00ff )
|
AM_RANGE(0x60, 0x61) AM_DEVREADWRITE8("upd1771c", upd1771c_device, read, write, 0x00ff)
|
||||||
// AM_RANGE(0x68, 0x6f) i8255 , ODA printer port (A: status (R) B: data (W) C: command (W))
|
// AM_RANGE(0x68, 0x6f) i8255 , ODA printer port (A: status (R) B: data (W) C: command (W))
|
||||||
// 0x70, 0x76 AM_DEVREADWRITE8("upd7220_btm", upd7220_device, read, write, 0x00ff)
|
// 0x70, 0x76 AM_DEVREADWRITE8("upd7220_btm", upd7220_device, read, write, 0x00ff)
|
||||||
// 0x71, 0x77 IDA Controller
|
// 0x71, 0x77 IDA Controller
|
||||||
|
@ -86,7 +86,7 @@ static ADDRESS_MAP_START( scv_mem, AS_PROGRAM, 8, scv_state )
|
|||||||
|
|
||||||
AM_RANGE( 0x2000, 0x3403 ) AM_RAM AM_SHARE("videoram") /* VRAM + 4 registers */
|
AM_RANGE( 0x2000, 0x3403 ) AM_RAM AM_SHARE("videoram") /* VRAM + 4 registers */
|
||||||
|
|
||||||
AM_RANGE( 0x3600, 0x3600 ) AM_DEVWRITE_LEGACY("upd1771c", upd1771_w )
|
AM_RANGE( 0x3600, 0x3600 ) AM_DEVWRITE("upd1771c", upd1771c_device, write)
|
||||||
|
|
||||||
AM_RANGE( 0x8000, 0x9fff ) AM_ROMBANK("bank0")
|
AM_RANGE( 0x8000, 0x9fff ) AM_ROMBANK("bank0")
|
||||||
AM_RANGE( 0xa000, 0xbfff ) AM_ROMBANK("bank1")
|
AM_RANGE( 0xa000, 0xbfff ) AM_ROMBANK("bank1")
|
||||||
@ -320,7 +320,7 @@ WRITE8_MEMBER( scv_state::scv_portc_w )
|
|||||||
m_portc = data;
|
m_portc = data;
|
||||||
|
|
||||||
scv_set_banks();
|
scv_set_banks();
|
||||||
upd1771_pcm_w( m_upd1771c, m_portc & 0x08 );
|
m_upd1771c->pcm_write(m_portc & 0x08);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user