diff options
Diffstat (limited to 'trunk/src/emu/sound/vlm5030.c')
-rw-r--r-- | trunk/src/emu/sound/vlm5030.c | 718 |
1 files changed, 718 insertions, 0 deletions
diff --git a/trunk/src/emu/sound/vlm5030.c b/trunk/src/emu/sound/vlm5030.c new file mode 100644 index 00000000000..05d69fc22b9 --- /dev/null +++ b/trunk/src/emu/sound/vlm5030.c @@ -0,0 +1,718 @@ +/* + vlm5030.c + + Sanyo VLM5030 emulator + + Written by Tatsuyuki Satoh + Based on TMS5220 simulator (tms5220.c) + + +-------,_,-------+ + GND -- | 1 40 | <- RST + (gnd) TST1 -> | 2 39 | ?? TST4 + OSC2 ck | 3 _ 38 | ?? TST3 + OSC1 ck | 4 (_) 37 | ?? TST2 + D0 -> | 5 36 | -> DAO + D1 -> | 6 35 | -- VREF (+5v through 5.6k resistor) + D2 -> | 7 34 | -> MTE + D3 -> | 8 V 33 | -> /ME + D4 -> | 9 L 32 | <- VCU + D5 -> | 10 M 31 | <- START + D6 -> | 11 5 30 | -> BSY + D7 -> | 12 0 29 | -- Vdd (+5v) + A0 <- | 13 3 28 | -> A15 + A1 <- | 14 0 27 | -> A14 + A2 <- | 15 26 | -> A13 + A3 <- | 16 _ 25 | -> A12 + A4 <- | 17 (_) 24 | -> A11 + A5 <- | 18 23 | -> A10 + A6 <- | 19 22 | -> A9 + A7 <- | 20 21 | -> A8 + +-----------------+ + +TST1 is probably a test mode enable pin, must be grounded for normal operation. +TST2-4 are some sort of test pins but can be left floating? +VREF is probably the 0v ref for the output dac +DAO is the output dac +/ME is connected to the voice data rom /OE enable +START strobes in a byte of data over the data bus from host cpu +OSC1/2 are to both ends of a 3.579545MHz xtal with a 100pf cap from each end to gnd +VCU makes the data bus select the upper 8 bits of the word register internally instead of the lower 8 bits. it is only useful if you need more than 256 phrases in rom? (recheck this) +MTE is an output for roms which need to be clocked to latch address before use, or for a latch sitting in front of the voice rom address lines? (recheck this) +RST not only resets the chip on its rising edge but grabs a byte of mode state data from the data bus on its falling edge? (recheck this) + + note: + memory read cycle(==sampling rate) = 122.9u(440clock) + interpolator (LC8109 = 2.5ms) = 20 * samples(125us) + frame time (20ms) = 4 * interpolator + 9bit DAC is composed of 5bit Physical and 3bitPWM. + + todo: + Noise Generator circuit without 'machine.rand()' function. + +----------- command format (Analytical result) ---------- + +1)end of speech (8bit) +:00000011: + +2)silent some frame (8bit) +:????SS01: + +SS : number of silent frames + 00 = 2 frame + 01 = 4 frame + 10 = 6 frame + 11 = 8 frame + +3)-speech frame (48bit) +function: 6th : 5th : 4th : 3rd : 2nd : 1st : +end : --- : --- : --- : --- : --- :00000011: +silent : --- : --- : --- : --- : --- :0000SS01: +speech :11111122:22233334:44455566:67778889:99AAAEEE:EEPPPPP0: + +EEEEE : energy : volume 0=off,0x1f=max +PPPPP : pitch : 0=noize , 1=fast,0x1f=slow +111111 : K1 : 48=off +22222 : K2 : 0=off,1=+min,0x0f=+max,0x10=off,0x11=+max,0x1f=-min + : 16 == special function?? +3333 : K3 : 0=off,1=+min,0x07=+max,0x08=-max,0x0f=-min +4444 : K4 : +555 : K5 : 0=off,1=+min,0x03=+max,0x04=-max,0x07=-min +666 : K6 : +777 : K7 : +888 : K8 : +999 : K9 : +AAA : K10 : + + ---------- chirp table information ---------- + +DAC PWM cycle == 88system clock , (11clock x 8 pattern) = 40.6KHz +one chirp == 5 x PWM cycle == 440systemclock(8,136Hz) + +chirp 0 : volume 10- 8 : with filter +chirp 1 : volume 8- 6 : with filter +chirp 2 : volume 6- 4 : with filter +chirp 3 : volume 4 : no filter ?? +chirp 4- 5: volume 4- 2 : with filter +chirp 6-11: volume 2- 0 : with filter +chirp 12-..: vokume 0 : silent + + ---------- digial output information ---------- + when ME pin = high , some status output to A0..15 pins + + A0..8 : DAC output value (abs) + A9 : DAC sign flag , L=minus,H=Plus + A10 : energy reload flag (pitch pulse) + A11..15 : unknown + + [DAC output value(signed 6bit)] = A9 ? A0..8 : -(A0..8) + +*/ +#include "emu.h" +#include "vlm5030.h" + +/* interpolator per frame */ +#define FR_SIZE 4 +/* samples per interpolator */ +#define IP_SIZE_SLOWER (240/FR_SIZE) +#define IP_SIZE_SLOW (200/FR_SIZE) +#define IP_SIZE_NORMAL (160/FR_SIZE) +#define IP_SIZE_FAST (120/FR_SIZE) +#define IP_SIZE_FASTER ( 80/FR_SIZE) + +typedef struct _vlm5030_state vlm5030_state; +struct _vlm5030_state +{ + device_t *device; + const vlm5030_interface *intf; + + sound_stream * channel; + + /* coefficient tables */ + const struct tms5100_coeffs *coeff; + + /* need to save state */ + + UINT8 *rom; + int address_mask; + UINT16 address; + UINT8 pin_BSY; + UINT8 pin_ST; + UINT8 pin_VCU; + UINT8 pin_RST; + UINT8 latch_data; + UINT16 vcu_addr_h; + UINT8 parameter; + UINT8 phase; + + /* state of option paramter */ + int frame_size; + int pitch_offset; + UINT8 interp_step; + + UINT8 interp_count; /* number of interp periods */ + UINT8 sample_count; /* sample number within interp */ + UINT8 pitch_count; + + /* these contain data describing the current and previous voice frames */ + UINT16 old_energy; + UINT8 old_pitch; + INT16 old_k[10]; + UINT16 target_energy; + UINT8 target_pitch; + INT16 target_k[10]; + + UINT16 new_energy; + UINT8 new_pitch; + INT16 new_k[10]; + + /* these are all used to contain the current state of the sound generation */ + unsigned int current_energy; + unsigned int current_pitch; + int current_k[10]; + + INT32 x[10]; +}; + +/* phase value */ +enum { + PH_RESET, + PH_IDLE, + PH_SETUP, + PH_WAIT, + PH_RUN, + PH_STOP, + PH_END +}; + +/* Pull in the ROM tables */ +#include "tms5110r.c" + +/* + speed parameter +SPC SPB SPA + 1 0 1 more slow (05h) : 42ms (150%) : 60sample + 1 1 x slow (06h,07h) : 34ms (125%) : 50sample + x 0 0 normal (00h,04h) : 25.6ms (100%) : 40samplme + 0 0 1 fast (01h) : 20.2ms (75%) : 30sample + 0 1 x more fast (02h,03h) : 12.2ms (50%) : 20sample +*/ +static const int vlm5030_speed_table[8] = +{ + IP_SIZE_NORMAL, + IP_SIZE_FAST, + IP_SIZE_FASTER, + IP_SIZE_FASTER, + IP_SIZE_NORMAL, + IP_SIZE_SLOWER, + IP_SIZE_SLOW, + IP_SIZE_SLOW +}; + +static const char VLM_NAME[] = "VLM5030"; + +INLINE vlm5030_state *get_safe_token(device_t *device) +{ + assert(device != NULL); + assert(device->type() == VLM5030); + return (vlm5030_state *)downcast<legacy_device_base *>(device)->token(); +} + +static int get_bits(vlm5030_state *chip, int sbit,int bits) +{ + int offset = chip->address + (sbit>>3); + int data; + + data = chip->rom[offset&chip->address_mask] + + (((int)chip->rom[(offset+1)&chip->address_mask])*256); + data >>= (sbit&7); + data &= (0xff>>(8-bits)); + + return data; +} + +/* get next frame */ +static int parse_frame (vlm5030_state *chip) +{ + unsigned char cmd; + int i; + + /* remember previous frame */ + chip->old_energy = chip->new_energy; + chip->old_pitch = chip->new_pitch; + for(i=0;i<=9;i++) + chip->old_k[i] = chip->new_k[i]; + + /* command byte check */ + cmd = chip->rom[chip->address&chip->address_mask]; + if( cmd & 0x01 ) + { /* extend frame */ + chip->new_energy = chip->new_pitch = 0; + for(i=0;i<=9;i++) + chip->new_k[i] = 0; + chip->address++; + if( cmd & 0x02 ) + { /* end of speech */ + + /* logerror("VLM5030 %04X end \n",chip->address ); */ + return 0; + } + else + { /* silent frame */ + int nums = ( (cmd>>2)+1 )*2; + /* logerror("VLM5030 %04X silent %d frame\n",chip->address,nums ); */ + return nums * FR_SIZE; + } + } + /* pitch */ + chip->new_pitch = ( chip->coeff->pitchtable[get_bits(chip, 1,chip->coeff->pitch_bits)] + chip->pitch_offset )&0xff; + /* energy */ + chip->new_energy = chip->coeff->energytable[get_bits(chip, 6,chip->coeff->energy_bits)]; + + /* 10 K's */ + chip->new_k[9] = chip->coeff->ktable[9][get_bits(chip,11,chip->coeff->kbits[9])]; + chip->new_k[8] = chip->coeff->ktable[8][get_bits(chip,14,chip->coeff->kbits[8])]; + chip->new_k[7] = chip->coeff->ktable[7][get_bits(chip,17,chip->coeff->kbits[7])]; + chip->new_k[6] = chip->coeff->ktable[6][get_bits(chip,20,chip->coeff->kbits[6])]; + chip->new_k[5] = chip->coeff->ktable[5][get_bits(chip,23,chip->coeff->kbits[5])]; + chip->new_k[4] = chip->coeff->ktable[4][get_bits(chip,26,chip->coeff->kbits[4])]; + chip->new_k[3] = chip->coeff->ktable[3][get_bits(chip,29,chip->coeff->kbits[3])]; + chip->new_k[2] = chip->coeff->ktable[2][get_bits(chip,33,chip->coeff->kbits[2])]; + chip->new_k[1] = chip->coeff->ktable[1][get_bits(chip,37,chip->coeff->kbits[1])]; + chip->new_k[0] = chip->coeff->ktable[0][get_bits(chip,42,chip->coeff->kbits[0])]; + + chip->address+=6; + logerror("VLM5030 %04X voice \n",chip->address ); + //fprintf(stderr,"*** target Energy, Pitch, and Ks = %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d, %04d\n",chip->new_energy, chip->new_pitch, chip->new_k[0], chip->new_k[1], chip->new_k[2], chip->new_k[3], chip->new_k[4], chip->new_k[5], chip->new_k[6], chip->new_k[7], chip->new_k[8], chip->new_k[9]); + return FR_SIZE; +} + +/* decode and buffering data */ +static STREAM_UPDATE( vlm5030_update_callback ) +{ + vlm5030_state *chip = (vlm5030_state *)param; + int buf_count=0; + int interp_effect; + int i; + int u[11]; + stream_sample_t *buffer = outputs[0]; + + /* running */ + if( chip->phase == PH_RUN || chip->phase == PH_STOP ) + { + /* playing speech */ + while (samples > 0) + { + int current_val; + + /* check new interpolator or new frame */ + if( chip->sample_count == 0 ) + { + if( chip->phase == PH_STOP ) + { + chip->phase = PH_END; + chip->sample_count = 1; + goto phase_stop; /* continue to end phase */ + } + chip->sample_count = chip->frame_size; + /* interpolator changes */ + if ( chip->interp_count == 0 ) + { + /* change to new frame */ + chip->interp_count = parse_frame(chip); /* with change phase */ + if ( chip->interp_count == 0 ) + { /* end mark found */ + chip->interp_count = FR_SIZE; + chip->sample_count = chip->frame_size; /* end -> stop time */ + chip->phase = PH_STOP; + } + /* Set old target as new start of frame */ + chip->current_energy = chip->old_energy; + chip->current_pitch = chip->old_pitch; + for(i=0;i<=9;i++) + chip->current_k[i] = chip->old_k[i]; + /* is this a zero energy frame? */ + if (chip->current_energy == 0) + { + /*mame_printf_debug("processing frame: zero energy\n");*/ + chip->target_energy = 0; + chip->target_pitch = chip->current_pitch; + for(i=0;i<=9;i++) + chip->target_k[i] = chip->current_k[i]; + } + else + { + /*mame_printf_debug("processing frame: Normal\n");*/ + /*mame_printf_debug("*** Energy = %d\n",chip->current_energy);*/ + /*mame_printf_debug("proc: %d %d\n",last_fbuf_head,fbuf_head);*/ + chip->target_energy = chip->new_energy; + chip->target_pitch = chip->new_pitch; + for(i=0;i<=9;i++) + chip->target_k[i] = chip->new_k[i]; + } + } + /* next interpolator */ + /* Update values based on step values 25% , 50% , 75% , 100% */ + chip->interp_count -= chip->interp_step; + /* 3,2,1,0 -> 1,2,3,4 */ + interp_effect = FR_SIZE - (chip->interp_count%FR_SIZE); + chip->current_energy = chip->old_energy + (chip->target_energy - chip->old_energy) * interp_effect / FR_SIZE; + if (chip->old_pitch > 1) + chip->current_pitch = chip->old_pitch + (chip->target_pitch - chip->old_pitch) * interp_effect / FR_SIZE; + for (i = 0; i <= 9 ; i++) + chip->current_k[i] = chip->old_k[i] + (chip->target_k[i] - chip->old_k[i]) * interp_effect / FR_SIZE; + } + /* calcrate digital filter */ + if (chip->old_energy == 0) + { + /* generate silent samples here */ + current_val = 0x00; + } + else if (chip->old_pitch <= 1) + { /* generate unvoiced samples here */ + current_val = (chip->device->machine().rand()&1) ? chip->current_energy : -chip->current_energy; + } + else + { + /* generate voiced samples here */ + current_val = ( chip->pitch_count == 0) ? chip->current_energy : 0; + } + + /* Lattice filter here */ + u[10] = current_val; + for (i = 9; i >= 0; i--) + u[i] = u[i+1] - ((-chip->current_k[i] * chip->x[i]) / 512); + for (i = 9; i >= 1; i--) + chip->x[i] = chip->x[i-1] + ((-chip->current_k[i-1] * u[i-1]) / 512); + chip->x[0] = u[0]; + + /* clipping, buffering */ + if (u[0] > 511) + buffer[buf_count] = 511<<6; + else if (u[0] < -511) + buffer[buf_count] = -511<<6; + else + buffer[buf_count] = (u[0] << 6); + buf_count++; + + /* sample count */ + chip->sample_count--; + /* pitch */ + chip->pitch_count++; + if (chip->pitch_count >= chip->current_pitch ) + chip->pitch_count = 0; + /* size */ + samples--; + } +/* return;*/ + } + /* stop phase */ +phase_stop: + switch( chip->phase ) + { + case PH_SETUP: + if( chip->sample_count <= samples) + { + chip->sample_count = 0; + /* logerror("VLM5030 BSY=H\n" ); */ + /* pin_BSY = 1; */ + chip->phase = PH_WAIT; + } + else + { + chip->sample_count -= samples; + } + break; + case PH_END: + if( chip->sample_count <= samples) + { + chip->sample_count = 0; + /* logerror("VLM5030 BSY=L\n" ); */ + chip->pin_BSY = 0; + chip->phase = PH_IDLE; + } + else + { + chip->sample_count -= samples; + } + } + /* silent buffering */ + while (samples > 0) + { + buffer[buf_count++] = 0x00; + samples--; + } +} + +/* realtime update */ +static void vlm5030_update(vlm5030_state *chip) +{ + chip->channel->update(); +} + +/* setup parameteroption when RST=H */ +static void vlm5030_setup_parameter(vlm5030_state *chip, UINT8 param) +{ + /* latch parameter value */ + chip->parameter = param; + + /* bit 0,1 : 4800bps / 9600bps , interporator step */ + if(param&2) /* bit 1 = 1 , 9600bps */ + chip->interp_step = 4; /* 9600bps : no interporator */ + else if(param&1) /* bit1 = 0 & bit0 = 1 , 4800bps */ + chip->interp_step = 2; /* 4800bps : 2 interporator */ + else /* bit1 = bit0 = 0 : 2400bps */ + chip->interp_step = 1; /* 2400bps : 4 interporator */ + + /* bit 3,4,5 : speed (frame size) */ + chip->frame_size = vlm5030_speed_table[(param>>3) &7]; + + /* bit 6,7 : low / high pitch */ + if(param&0x80) /* bit7=1 , high pitch */ + chip->pitch_offset = -8; + else if(param&0x40) /* bit6=1 , low pitch */ + chip->pitch_offset = 8; + else + chip->pitch_offset = 0; +} + + +static void vlm5030_restore_state(vlm5030_state *chip) +{ + int i; + + int interp_effect = FR_SIZE - (chip->interp_count%FR_SIZE); + /* restore parameter data */ + vlm5030_setup_parameter(chip, chip->parameter); + + /* restore current energy,pitch & filter */ + chip->current_energy = chip->old_energy + (chip->target_energy - chip->old_energy) * interp_effect / FR_SIZE; + if (chip->old_pitch > 1) + chip->current_pitch = chip->old_pitch + (chip->target_pitch - chip->old_pitch) * interp_effect / FR_SIZE; + for (i = 0; i <= 9 ; i++) + chip->current_k[i] = chip->old_k[i] + (chip->target_k[i] - chip->old_k[i]) * interp_effect / FR_SIZE; +} + + +static void vlm5030_reset(vlm5030_state *chip) +{ + chip->phase = PH_RESET; + chip->address = 0; + chip->vcu_addr_h = 0; + chip->pin_BSY = 0; + + chip->old_energy = chip->old_pitch = 0; + chip->new_energy = chip->new_pitch = 0; + chip->current_energy = chip->current_pitch = 0; + chip->target_energy = chip->target_pitch = 0; + memset(chip->old_k, 0, sizeof(chip->old_k)); + memset(chip->new_k, 0, sizeof(chip->new_k)); + memset(chip->current_k, 0, sizeof(chip->current_k)); + memset(chip->target_k, 0, sizeof(chip->target_k)); + chip->interp_count = chip->sample_count = chip->pitch_count = 0; + memset(chip->x, 0, sizeof(chip->x)); + /* reset parameters */ + vlm5030_setup_parameter(chip, 0x00); +} + +static DEVICE_RESET( vlm5030 ) +{ + vlm5030_reset(get_safe_token(device)); +} + + +/* set speech rom address */ +void vlm5030_set_rom(device_t *device, void *speech_rom) +{ + vlm5030_state *chip = get_safe_token(device); + chip->rom = (UINT8 *)speech_rom; +} + +/* get BSY pin level */ +int vlm5030_bsy(device_t *device) +{ + vlm5030_state *chip = get_safe_token(device); + vlm5030_update(chip); + return chip->pin_BSY; +} + +/* latch contoll data */ +WRITE8_DEVICE_HANDLER( vlm5030_data_w ) +{ + vlm5030_state *chip = get_safe_token(device); + chip->latch_data = (UINT8)data; +} + +/* set RST pin level : reset / set table address A8-A15 */ +void vlm5030_rst (device_t *device, int pin ) +{ + vlm5030_state *chip = get_safe_token(device); + if( chip->pin_RST ) + { + if( !pin ) + { /* H -> L : latch parameters */ + chip->pin_RST = 0; + vlm5030_setup_parameter(chip, chip->latch_data); + } + } + else + { + if( pin ) + { /* L -> H : reset chip */ + chip->pin_RST = 1; + if( chip->pin_BSY ) + { + vlm5030_reset(chip); + } + } + } +} + +/* set VCU pin level : ?? unknown */ +void vlm5030_vcu(device_t *device, int pin) +{ + vlm5030_state *chip = get_safe_token(device); + /* direct mode / indirect mode */ + chip->pin_VCU = pin; + return; +} + +/* set ST pin level : set table address A0-A7 / start speech */ +void vlm5030_st(device_t *device, int pin ) +{ + vlm5030_state *chip = get_safe_token(device); + int table; + + if( chip->pin_ST != pin ) + { + /* pin level is change */ + if( !pin ) + { /* H -> L */ + chip->pin_ST = 0; + + if( chip->pin_VCU ) + { /* direct access mode & address High */ + chip->vcu_addr_h = ((int)chip->latch_data<<8) + 0x01; + } + else + { + /* start speech */ + /* check access mode */ + if( chip->vcu_addr_h ) + { /* direct access mode */ + chip->address = (chip->vcu_addr_h&0xff00) + chip->latch_data; + chip->vcu_addr_h = 0; + } + else + { /* indirect accedd mode */ + table = (chip->latch_data&0xfe) + (((int)chip->latch_data&1)<<8); + chip->address = (((int)chip->rom[table&chip->address_mask])<<8) + | chip->rom[(table+1)&chip->address_mask]; +#if 0 +/* show unsupported parameter message */ +if( chip->interp_step != 1) + popmessage("No %d %dBPS parameter",table/2,chip->interp_step*2400); +#endif + } + vlm5030_update(chip); + /* logerror("VLM5030 %02X start adr=%04X\n",table/2,chip->address ); */ + /* reset process status */ + chip->sample_count = chip->frame_size; + chip->interp_count = FR_SIZE; + /* clear filter */ + /* start after 3 sampling cycle */ + chip->phase = PH_RUN; + } + } + else + { /* L -> H */ + chip->pin_ST = 1; + /* setup speech , BSY on after 30ms? */ + chip->phase = PH_SETUP; + chip->sample_count = 1; /* wait time for busy on */ + chip->pin_BSY = 1; /* */ + } + } +} + +/* start VLM5030 with sound rom */ +/* speech_rom == 0 -> use sampling data mode */ +static DEVICE_START( vlm5030 ) +{ + const vlm5030_interface defintrf = { 0 }; + int emulation_rate; + vlm5030_state *chip = get_safe_token(device); + + chip->device = device; + chip->coeff = &vlm5030_coeff; + chip->intf = (device->static_config() != NULL) ? (const vlm5030_interface *)device->static_config() : &defintrf; + + emulation_rate = device->clock() / 440; + + /* reset input pins */ + chip->pin_RST = chip->pin_ST = chip->pin_VCU= 0; + chip->latch_data = 0; + + vlm5030_reset(chip); + chip->phase = PH_IDLE; + + chip->rom = *device->region(); + /* memory size */ + if( chip->intf->memory_size == 0) + chip->address_mask = device->region()->bytes()-1; + else + chip->address_mask = chip->intf->memory_size-1; + + chip->channel = device->machine().sound().stream_alloc(*device, 0, 1, emulation_rate,chip,vlm5030_update_callback); + + /* don't restore "UINT8 *chip->rom" when use vlm5030_set_rom() */ + + device->save_item(NAME(chip->address)); + device->save_item(NAME(chip->pin_BSY)); + device->save_item(NAME(chip->pin_ST)); + device->save_item(NAME(chip->pin_VCU)); + device->save_item(NAME(chip->pin_RST)); + device->save_item(NAME(chip->latch_data)); + device->save_item(NAME(chip->vcu_addr_h)); + device->save_item(NAME(chip->parameter)); + device->save_item(NAME(chip->phase)); + device->save_item(NAME(chip->interp_count)); + device->save_item(NAME(chip->sample_count)); + device->save_item(NAME(chip->pitch_count)); + device->save_item(NAME(chip->old_energy)); + device->save_item(NAME(chip->old_pitch)); + device->save_item(NAME(chip->old_k)); + device->save_item(NAME(chip->target_energy)); + device->save_item(NAME(chip->target_pitch)); + device->save_item(NAME(chip->target_k)); + device->save_item(NAME(chip->x)); + device->machine().save().register_postload(save_prepost_delegate(FUNC(vlm5030_restore_state), chip)); +} + + +/************************************************************************** + * Generic get_info + **************************************************************************/ + +DEVICE_GET_INFO( vlm5030 ) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(vlm5030_state); break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( vlm5030 ); break; + case DEVINFO_FCT_STOP: /* Nothing */ break; + case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( vlm5030 ); break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "VLM5030"); break; + case DEVINFO_STR_FAMILY: strcpy(info->s, "VLM speech"); break; + case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break; + case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; + case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break; + } +} + + +DEFINE_LEGACY_SOUND_DEVICE(VLM5030, vlm5030); |