diff options
Diffstat (limited to 'trunk/src/emu/sound/vlm5030.c')
-rw-r--r-- | trunk/src/emu/sound/vlm5030.c | 758 |
1 files changed, 758 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..471ed81594b --- /dev/null +++ b/trunk/src/emu/sound/vlm5030.c @@ -0,0 +1,758 @@ +/* + 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; + + /* 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 +}; + +/* + 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"; + +/* ROM Tables */ + +/* This is the energy lookup table */ + +/* sampled from real chip */ +static const unsigned short energytable[0x20] = +{ + 0, 2, 4, 6, 10, 12, 14, 18, /* 0-7 */ + 22, 26, 30, 34, 38, 44, 48, 54, /* 8-15 */ + 62, 68, 76, 84, 94,102,114,124, /* 16-23 */ + 136,150,164,178,196,214,232,254 /* 24-31 */ +}; + +/* This is the pitch lookup table */ +static const unsigned char pitchtable [0x20]= +{ + 1, /* 0 : random mode */ + 22, /* 1 : start=22 */ + 23, 24, 25, 26, 27, 28, 29, 30, /* 2- 9 : 1step */ + 32, 34, 36, 38, 40, 42, 44, 46, /* 10-17 : 2step */ + 50, 54, 58, 62, 66, 70, 74, 78, /* 18-25 : 4step */ + 86, 94, 102,110,118,126 /* 26-31 : 8step */ +}; + +static const INT16 K1_table[] = { + -24898, -25672, -26446, -27091, -27736, -28252, -28768, -29155, + -29542, -29929, -30316, -30574, -30832, -30961, -31219, -31348, + -31606, -31735, -31864, -31864, -31993, -32122, -32122, -32251, + -32251, -32380, -32380, -32380, -32509, -32509, -32509, -32509, + 24898, 23995, 22963, 21931, 20770, 19480, 18061, 16642, + 15093, 13416, 11610, 9804, 7998, 6063, 3999, 1935, + 0, -1935, -3999, -6063, -7998, -9804, -11610, -13416, + -15093, -16642, -18061, -19480, -20770, -21931, -22963, -23995 +}; +static const INT16 K2_table[] = { + 0, -3096, -6321, -9417, -12513, -15351, -18061, -20770, + -23092, -25285, -27220, -28897, -30187, -31348, -32122, -32638, + 0, 32638, 32122, 31348, 30187, 28897, 27220, 25285, + 23092, 20770, 18061, 15351, 12513, 9417, 6321, 3096 +}; +static const INT16 K3_table[] = { + 0, -3999, -8127, -12255, -16384, -20383, -24511, -28639, + 32638, 28639, 24511, 20383, 16254, 12255, 8127, 3999 +}; +static const INT16 K5_table[] = { + 0, -8127, -16384, -24511, 32638, 24511, 16254, 8127 +}; + +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 = ( pitchtable[get_bits(chip, 1,5)] + chip->pitch_offset )&0xff; + /* energy */ + chip->new_energy = energytable[get_bits(chip, 6,5)]; + + /* 10 K's */ + chip->new_k[9] = K5_table[get_bits(chip,11,3)]; + chip->new_k[8] = K5_table[get_bits(chip,14,3)]; + chip->new_k[7] = K5_table[get_bits(chip,17,3)]; + chip->new_k[6] = K5_table[get_bits(chip,20,3)]; + chip->new_k[5] = K5_table[get_bits(chip,23,3)]; + chip->new_k[4] = K5_table[get_bits(chip,26,3)]; + chip->new_k[3] = K3_table[get_bits(chip,29,4)]; + chip->new_k[2] = K3_table[get_bits(chip,33,4)]; + chip->new_k[1] = K2_table[get_bits(chip,37,5)]; + chip->new_k[0] = K1_table[get_bits(chip,42,6)]; + + chip->address+=6; + logerror("VLM5030 %04X voice \n",chip->address ); + 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]) / 32768); + for (i = 9; i >= 1; i--) + chip->x[i] = chip->x[i-1] + ((chip->current_k[i-1] * u[i-1]) / 32768); + 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->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); |