static void saa1099_control_port_w( int chip, int reg, int data ) { struct SAA1099 *saa = sndti_token(SOUND_SAA1099, chip); if ((data & 0xff) > 0x1c) { /* Error! */ logerror("%04x: (SAA1099 #%d) Unknown register selected\n",activecpu_get_pc(), chip); } saa->selected_reg = data & 0x1f; if (saa->selected_reg == 0x18 || saa->selected_reg == 0x19) { /* clock the envelope channels */ if (saa->env_clock[0]) saa1099_envelope(saa,0); if (saa->env_clock[1]) saa1099_envelope(saa,1); } }
void saa1099ControlWrite(INT32 chip, INT32 data) { #if defined FBA_DEBUG if (!DebugSnd_SAA1099Initted) bprintf(PRINT_ERROR, _T("saa1099ControlWrite called without init\n")); if (chip > nNumChips) bprintf(PRINT_ERROR, _T("saa1099ControlWrite called with invalid chip %x\n"), chip); #endif saa1099_state *saa = &chips[chip]; saa->selected_reg = data & 0x1f; if (saa->selected_reg == 0x18 || saa->selected_reg == 0x19) { /* clock the envelope channels */ if (saa->env_clock[0]) saa1099_envelope(saa,0); if (saa->env_clock[1]) saa1099_envelope(saa,1); } }
//WRITE8_DEVICE_HANDLER( saa1099_control_w ) void saa1099_control_w(UINT8 ChipID, offs_t offset, UINT8 data) { //saa1099_state *saa = get_safe_token(device); saa1099_state *saa = &SAA1099Data[ChipID]; if ((data & 0xff) > 0x1c) { /* Error! */ //logerror("%s: (SAA1099 '%s') Unknown register selected\n",device->machine().describe_context(), device->tag()); logerror("SAA1099: Unknown register selected\n"); } saa->selected_reg = data & 0x1f; if (saa->selected_reg == 0x18 || saa->selected_reg == 0x19) { /* clock the envelope channels */ if (saa->env_clock[0]) saa1099_envelope(saa,0); if (saa->env_clock[1]) saa1099_envelope(saa,1); } }
static void saa1099_update(void *param, stream_sample_t **inputs, stream_sample_t **buffer, int length) { struct SAA1099 *saa = param; int j, ch; /* if the channels are disabled we're done */ if (!saa->all_ch_enable) { /* init output data */ memset(buffer[LEFT],0,length*sizeof(*buffer[LEFT])); memset(buffer[RIGHT],0,length*sizeof(*buffer[RIGHT])); return; } for (ch = 0; ch < 2; ch++) { switch (saa->noise_params[ch]) { case 0: saa->noise[ch].freq = 31250.0 * 2; break; case 1: saa->noise[ch].freq = 15625.0 * 2; break; case 2: saa->noise[ch].freq = 7812.5 * 2; break; case 3: saa->noise[ch].freq = saa->channels[ch * 3].freq; break; } } /* fill all data needed */ for( j = 0; j < length; j++ ) { int output_l = 0, output_r = 0; /* for each channel */ for (ch = 0; ch < 6; ch++) { if (saa->channels[ch].freq == 0.0) saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) / (511.0 - (double)saa->channels[ch].frequency); /* check the actual position in the square wave */ saa->channels[ch].counter -= saa->channels[ch].freq; while (saa->channels[ch].counter < 0) { /* calculate new frequency now after the half wave is updated */ saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) / (511.0 - (double)saa->channels[ch].frequency); saa->channels[ch].counter += saa->sample_rate; saa->channels[ch].level ^= 1; /* eventually clock the envelope counters */ if (ch == 1 && saa->env_clock[0] == 0) saa1099_envelope(saa, 0); if (ch == 4 && saa->env_clock[1] == 0) saa1099_envelope(saa, 1); } /* if the noise is enabled */ if (saa->channels[ch].noise_enable) { /* if the noise level is high (noise 0: chan 0-2, noise 1: chan 3-5) */ if (saa->noise[ch/3].level & 1) { /* subtract to avoid overflows, also use only half amplitude */ output_l -= saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16 / 2; output_r -= saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16 / 2; } } /* if the square wave is enabled */ if (saa->channels[ch].freq_enable) { /* if the channel level is high */ if (saa->channels[ch].level & 1) { output_l += saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16; output_r += saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16; } } } for (ch = 0; ch < 2; ch++) { /* check the actual position in noise generator */ saa->noise[ch].counter -= saa->noise[ch].freq; while (saa->noise[ch].counter < 0) { saa->noise[ch].counter += saa->sample_rate; if( ((saa->noise[ch].level & 0x4000) == 0) == ((saa->noise[ch].level & 0x0040) == 0) ) saa->noise[ch].level = (saa->noise[ch].level << 1) | 1; else saa->noise[ch].level <<= 1; } } /* write sound data to the buffer */ buffer[LEFT][j] = output_l / 6; buffer[RIGHT][j] = output_r / 6; } }
//static STREAM_UPDATE( saa1099_update ) void saa1099_update(UINT8 ChipID, stream_sample_t **outputs, int samples) { //saa1099_state *saa = (saa1099_state *)param; saa1099_state *saa = &SAA1099Data[ChipID]; int j, ch; int clk2div512; /* if the channels are disabled we're done */ if (!saa->all_ch_enable) { /* init output data */ memset(outputs[LEFT],0,samples*sizeof(*outputs[LEFT])); memset(outputs[RIGHT],0,samples*sizeof(*outputs[RIGHT])); return; } for (ch = 0; ch < 2; ch++) { switch (saa->noise_params[ch]) { case 0: saa->noise[ch].freq = saa->master_clock/ 256.0 * 2; break; case 1: saa->noise[ch].freq = saa->master_clock/ 512.0 * 2; break; case 2: saa->noise[ch].freq = saa->master_clock/1024.0 * 2; break; case 3: saa->noise[ch].freq = saa->channels[ch * 3].freq; break; } } // clock fix thanks to http://www.vogons.org/viewtopic.php?p=344227#p344227 //clk2div512 = 2 * saa->master_clock / 512; clk2div512 = (saa->master_clock + 128) / 256; /* fill all data needed */ for( j = 0; j < samples; j++ ) { int output_l = 0, output_r = 0; /* for each channel */ for (ch = 0; ch < 6; ch++) { if (saa->channels[ch].freq == 0.0) saa->channels[ch].freq = (double)(clk2div512 << saa->channels[ch].octave) / (511.0 - (double)saa->channels[ch].frequency); /* check the actual position in the square wave */ saa->channels[ch].counter -= saa->channels[ch].freq; while (saa->channels[ch].counter < 0) { /* calculate new frequency now after the half wave is updated */ saa->channels[ch].freq = (double)(clk2div512 << saa->channels[ch].octave) / (511.0 - (double)saa->channels[ch].frequency); saa->channels[ch].counter += saa->sample_rate; saa->channels[ch].level ^= 1; /* eventually clock the envelope counters */ if (ch == 1 && saa->env_clock[0] == 0) saa1099_envelope(saa, 0); if (ch == 4 && saa->env_clock[1] == 0) saa1099_envelope(saa, 1); } if (saa->channels[ch].Muted) continue; // placed here to ensure that envelopes are updated #if 0 // if the noise is enabled if (saa->channels[ch].noise_enable) { // if the noise level is high (noise 0: chan 0-2, noise 1: chan 3-5) if (saa->noise[ch/3].level & 1) { // subtract to avoid overflows, also use only half amplitude output_l -= saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16 / 2; output_r -= saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16 / 2; } } // if the square wave is enabled if (saa->channels[ch].freq_enable) { // if the channel level is high if (saa->channels[ch].level & 1) { output_l += saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16; output_r += saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16; } } #else // Now with bipolar output. -Valley Bell if (saa->channels[ch].noise_enable) { if (saa->noise[ch/3].level & 1) { output_l += saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 32 / 2; output_r += saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 32 / 2; } else { output_l -= saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 32 / 2; output_r -= saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 32 / 2; } } if (saa->channels[ch].freq_enable) { if (saa->channels[ch].level & 1) { output_l += saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 32; output_r += saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 32; } else { output_l -= saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 32; output_r -= saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 32; } } #endif } for (ch = 0; ch < 2; ch++) { /* check the actual position in noise generator */ saa->noise[ch].counter -= saa->noise[ch].freq; while (saa->noise[ch].counter < 0) { saa->noise[ch].counter += saa->sample_rate; if( ((saa->noise[ch].level & 0x4000) == 0) == ((saa->noise[ch].level & 0x0040) == 0) ) saa->noise[ch].level = (saa->noise[ch].level << 1) | 1; else saa->noise[ch].level <<= 1; } } /* write sound data to the buffer */ outputs[LEFT][j] = output_l / 6; outputs[RIGHT][j] = output_r / 6; } }
void saa1099_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) { int j, ch; /* if the channels are disabled we're done */ if (!m_all_ch_enable) { /* init output data */ memset(outputs[LEFT],0,samples*sizeof(*outputs[LEFT])); memset(outputs[RIGHT],0,samples*sizeof(*outputs[RIGHT])); return; } for (ch = 0; ch < 2; ch++) { switch (m_noise_params[ch]) { case 0: m_noise[ch].freq = 31250.0 * 2; break; case 1: m_noise[ch].freq = 15625.0 * 2; break; case 2: m_noise[ch].freq = 7812.5 * 2; break; case 3: m_noise[ch].freq = m_channels[ch * 3].freq; break; } } /* fill all data needed */ for( j = 0; j < samples; j++ ) { int output_l = 0, output_r = 0; /* for each channel */ for (ch = 0; ch < 6; ch++) { if (m_channels[ch].freq == 0.0) m_channels[ch].freq = (double)((2 * 15625) << m_channels[ch].octave) / (511.0 - (double)m_channels[ch].frequency); /* check the actual position in the square wave */ m_channels[ch].counter -= m_channels[ch].freq; while (m_channels[ch].counter < 0) { /* calculate new frequency now after the half wave is updated */ m_channels[ch].freq = (double)((2 * 15625) << m_channels[ch].octave) / (511.0 - (double)m_channels[ch].frequency); m_channels[ch].counter += m_sample_rate; m_channels[ch].level ^= 1; /* eventually clock the envelope counters */ if (ch == 1 && m_env_clock[0] == 0) saa1099_envelope(0); if (ch == 4 && m_env_clock[1] == 0) saa1099_envelope(1); } /* if the noise is enabled */ if (m_channels[ch].noise_enable) { /* if the noise level is high (noise 0: chan 0-2, noise 1: chan 3-5) */ if (m_noise[ch/3].level & 1) { /* subtract to avoid overflows, also use only half amplitude */ output_l -= m_channels[ch].amplitude[ LEFT] * m_channels[ch].envelope[ LEFT] / 16 / 2; output_r -= m_channels[ch].amplitude[RIGHT] * m_channels[ch].envelope[RIGHT] / 16 / 2; } } /* if the square wave is enabled */ if (m_channels[ch].freq_enable) { /* if the channel level is high */ if (m_channels[ch].level & 1) { output_l += m_channels[ch].amplitude[ LEFT] * m_channels[ch].envelope[ LEFT] / 16; output_r += m_channels[ch].amplitude[RIGHT] * m_channels[ch].envelope[RIGHT] / 16; } } } for (ch = 0; ch < 2; ch++) { /* check the actual position in noise generator */ m_noise[ch].counter -= m_noise[ch].freq; while (m_noise[ch].counter < 0) { m_noise[ch].counter += m_sample_rate; if( ((m_noise[ch].level & 0x4000) == 0) == ((m_noise[ch].level & 0x0040) == 0) ) m_noise[ch].level = (m_noise[ch].level << 1) | 1; else m_noise[ch].level <<= 1; } } /* write sound data to the buffer */ outputs[LEFT][j] = output_l / 6; outputs[RIGHT][j] = output_r / 6; } }
void saa1099Update(INT32 chip, INT16 *output, INT32 samples) { #if defined FBA_DEBUG if (!DebugSnd_SAA1099Initted) bprintf(PRINT_ERROR, _T("saa1099Update called without init\n")); if (chip > nNumChips) bprintf(PRINT_ERROR, _T("saa1099Update called with invalid chip %x\n"), chip); #endif saa1099_state *saa = &chips[chip]; INT32 j, ch; /* if the channels are disabled we're done */ if (!saa->all_ch_enable) { /* init output data */ memset (output, 0, samples * sizeof(INT16) * 2); return; } for (ch = 0; ch < 2; ch++) { switch (saa->noise_params[ch]) { case 0: saa->noise[ch].freq = 31250.0 * 2; break; case 1: saa->noise[ch].freq = 15625.0 * 2; break; case 2: saa->noise[ch].freq = 7812.5 * 2; break; case 3: saa->noise[ch].freq = saa->channels[ch * 3].freq; break; } } /* fill all data needed */ for( j = 0; j < samples; j++, output+=2) { INT32 output_l = 0, output_r = 0; /* for each channel */ for (ch = 0; ch < 6; ch++) { if (saa->channels[ch].freq == 0.0) saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) / (511.0 - (double)saa->channels[ch].frequency); /* check the actual position in the square wave */ saa->channels[ch].counter -= saa->channels[ch].freq; while (saa->channels[ch].counter < 0) { /* calculate new frequency now after the half wave is updated */ saa->channels[ch].freq = (double)((2 * 15625) << saa->channels[ch].octave) / (511.0 - (double)saa->channels[ch].frequency); saa->channels[ch].counter += saa->sample_rate; saa->channels[ch].level ^= 1; /* eventually clock the envelope counters */ if (ch == 1 && saa->env_clock[0] == 0) saa1099_envelope(saa, 0); if (ch == 4 && saa->env_clock[1] == 0) saa1099_envelope(saa, 1); } /* if the noise is enabled */ if (saa->channels[ch].noise_enable) { /* if the noise level is high (noise 0: chan 0-2, noise 1: chan 3-5) */ if (saa->noise[ch/3].level & 1) { /* subtract to avoid overflows, also use only half amplitude */ output_l -= saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16 / 2; output_r -= saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16 / 2; } } /* if the square wave is enabled */ if (saa->channels[ch].freq_enable) { /* if the channel level is high */ if (saa->channels[ch].level & 1) { output_l += saa->channels[ch].amplitude[ LEFT] * saa->channels[ch].envelope[ LEFT] / 16; output_r += saa->channels[ch].amplitude[RIGHT] * saa->channels[ch].envelope[RIGHT] / 16; } } } for (ch = 0; ch < 2; ch++) { /* check the actual position in noise generator */ saa->noise[ch].counter -= saa->noise[ch].freq; while (saa->noise[ch].counter < 0) { saa->noise[ch].counter += saa->sample_rate; if( ((saa->noise[ch].level & 0x4000) == 0) == ((saa->noise[ch].level & 0x0040) == 0) ) saa->noise[ch].level = (saa->noise[ch].level << 1) | 1; else saa->noise[ch].level <<= 1; } } /* write sound data to the buffer */ INT32 nLeftSample = 0, nRightSample = 0; if ((saa->output_dir[BURN_SND_SAA1099_ROUTE_1] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) { nLeftSample += (INT32)((output_l / 6) * saa->gain[BURN_SND_SAA1099_ROUTE_1]); } if ((saa->output_dir[BURN_SND_SAA1099_ROUTE_1] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) { nRightSample += (INT32)((output_l / 6) * saa->gain[BURN_SND_SAA1099_ROUTE_1]); } if ((saa->output_dir[BURN_SND_SAA1099_ROUTE_2] & BURN_SND_ROUTE_LEFT) == BURN_SND_ROUTE_LEFT) { nLeftSample += (INT32)((output_r / 6) * saa->gain[BURN_SND_SAA1099_ROUTE_2]); } if ((saa->output_dir[BURN_SND_SAA1099_ROUTE_2] & BURN_SND_ROUTE_RIGHT) == BURN_SND_ROUTE_RIGHT) { nRightSample += (INT32)((output_r / 6) * saa->gain[BURN_SND_SAA1099_ROUTE_2]); } nLeftSample = BURN_SND_CLIP(nLeftSample); nRightSample = BURN_SND_CLIP(nRightSample); output[LEFT] = nLeftSample; output[RIGHT] = nRightSample; } }
static void saa1099_write_port_w( int chip, int offset, int data ) { struct SAA1099 *saa = &saa1099[chip]; if(offset == 1) { // address port saa->selected_reg = data & 0x1f; if (saa->selected_reg == 0x18 || saa->selected_reg == 0x19) { /* clock the envelope channels */ if (saa->env_clock[0]) saa1099_envelope(chip,0); if (saa->env_clock[1]) saa1099_envelope(chip,1); } return; } int reg = saa->selected_reg; int ch; switch (reg) { /* channel i amplitude */ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: ch = reg & 7; saa->channels[ch].amplitude[LEFT] = amplitude_lookup[data & 0x0f]; saa->channels[ch].amplitude[RIGHT] = amplitude_lookup[(data >> 4) & 0x0f]; break; /* channel i frequency */ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: ch = reg & 7; saa->channels[ch].frequency = data & 0xff; break; /* channel i octave */ case 0x10: case 0x11: case 0x12: ch = (reg - 0x10) << 1; saa->channels[ch + 0].octave = data & 0x07; saa->channels[ch + 1].octave = (data >> 4) & 0x07; break; /* channel i frequency enable */ case 0x14: saa->channels[0].freq_enable = data & 0x01; saa->channels[1].freq_enable = data & 0x02; saa->channels[2].freq_enable = data & 0x04; saa->channels[3].freq_enable = data & 0x08; saa->channels[4].freq_enable = data & 0x10; saa->channels[5].freq_enable = data & 0x20; break; /* channel i noise enable */ case 0x15: saa->channels[0].noise_enable = data & 0x01; saa->channels[1].noise_enable = data & 0x02; saa->channels[2].noise_enable = data & 0x04; saa->channels[3].noise_enable = data & 0x08; saa->channels[4].noise_enable = data & 0x10; saa->channels[5].noise_enable = data & 0x20; break; /* noise generators parameters */ case 0x16: saa->noise_params[0] = data & 0x03; saa->noise_params[1] = (data >> 4) & 0x03; break; /* envelope generators parameters */ case 0x18: case 0x19: ch = reg - 0x18; saa->env_reverse_right[ch] = data & 0x01; saa->env_mode[ch] = (data >> 1) & 0x07; saa->env_bits[ch] = data & 0x10; saa->env_clock[ch] = data & 0x20; saa->env_enable[ch] = data & 0x80; /* reset the envelope */ saa->env_step[ch] = 0; break; /* channels enable & reset generators */ case 0x1c: saa->all_ch_enable = data & 0x01; saa->sync_state = data & 0x02; if (data & 0x02) { int i; // logerror("%04x: (SAA1099 #%d) -reg 0x1c- Chip reset\n",activecpu_get_pc(), chip); /* Synch & Reset generators */ for (i = 0; i < 6; i++) { saa->channels[i].level = 0; saa->channels[i].counter = 0.0; } } break; default: /* Error! */ // logerror("%04x: (SAA1099 #%d) Unknown operation (reg:%02x, data:%02x)\n",activecpu_get_pc(), chip, reg, data); LOG(LOG_MISC,LOG_ERROR)("CMS Unkown write to reg %x with %x",reg, data); } }