trunk/src/emu/sound/k005289.c
| r20748 | r20749 | |
| 30 | 30 | |
| 31 | 31 | #define FREQBASEBITS 16 |
| 32 | 32 | |
| 33 | | /* this structure defines the parameters for a channel */ |
| 34 | | struct k005289_sound_channel |
| 35 | | { |
| 36 | | int frequency; |
| 37 | | int counter; |
| 38 | | int volume; |
| 39 | | const unsigned char *wave; |
| 40 | | }; |
| 41 | 33 | |
| 42 | | struct k005289_state |
| 43 | | { |
| 44 | | k005289_sound_channel channel_list[2]; |
| 34 | // device type definition |
| 35 | const device_type K005289 = &device_creator<k005289_device>; |
| 45 | 36 | |
| 46 | | /* global sound parameters */ |
| 47 | | const unsigned char *sound_prom; |
| 48 | | sound_stream * stream; |
| 49 | | int mclock,rate; |
| 50 | 37 | |
| 51 | | /* mixer tables and internal buffers */ |
| 52 | | INT16 *mixer_table; |
| 53 | | INT16 *mixer_lookup; |
| 54 | | short *mixer_buffer; |
| 38 | //************************************************************************** |
| 39 | // LIVE DEVICE |
| 40 | //************************************************************************** |
| 55 | 41 | |
| 56 | | int k005289_A_frequency,k005289_B_frequency; |
| 57 | | int k005289_A_volume,k005289_B_volume; |
| 58 | | int k005289_A_waveform,k005289_B_waveform; |
| 59 | | int k005289_A_latch,k005289_B_latch; |
| 60 | | }; |
| 42 | //------------------------------------------------- |
| 43 | // k005289_device - constructor |
| 44 | //------------------------------------------------- |
| 61 | 45 | |
| 62 | | INLINE k005289_state *get_safe_token(device_t *device) |
| 46 | k005289_device::k005289_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 47 | : device_t(mconfig, K005289, "K005289", tag, owner, clock), |
| 48 | device_sound_interface(mconfig, *this), |
| 49 | m_sound_prom(NULL), |
| 50 | m_stream(NULL), |
| 51 | m_mclock(0), |
| 52 | m_rate(0), |
| 53 | m_mixer_table(NULL), |
| 54 | m_mixer_lookup(NULL), |
| 55 | m_mixer_buffer(NULL), |
| 56 | m_k005289_A_frequency(0), |
| 57 | m_k005289_B_frequency(0), |
| 58 | m_k005289_A_volume(0), |
| 59 | m_k005289_B_volume(0), |
| 60 | m_k005289_A_waveform(0), |
| 61 | m_k005289_B_waveform(0), |
| 62 | m_k005289_A_latch(0), |
| 63 | m_k005289_B_latch(0) |
| 63 | 64 | { |
| 64 | | assert(device != NULL); |
| 65 | | assert(device->type() == K005289); |
| 66 | | return (k005289_state *)downcast<k005289_device *>(device)->token(); |
| 67 | 65 | } |
| 68 | 66 | |
| 69 | | /* build a table to divide by the number of voices */ |
| 70 | | static void make_mixer_table(running_machine &machine, k005289_state *info, int voices) |
| 67 | |
| 68 | //------------------------------------------------- |
| 69 | // device_start - device-specific startup |
| 70 | //------------------------------------------------- |
| 71 | |
| 72 | void k005289_device::device_start() |
| 71 | 73 | { |
| 72 | | int count = voices * 128; |
| 73 | | int i; |
| 74 | | int gain = 16; |
| 74 | k005289_sound_channel *voice; |
| 75 | 75 | |
| 76 | | /* allocate memory */ |
| 77 | | info->mixer_table = auto_alloc_array(machine, INT16, 256 * voices); |
| 76 | voice = m_channel_list; |
| 78 | 77 | |
| 79 | | /* find the middle of the table */ |
| 80 | | info->mixer_lookup = info->mixer_table + (128 * voices); |
| 78 | /* get stream channels */ |
| 79 | m_rate = clock()/16; |
| 80 | m_stream = stream_alloc(0, 1, m_rate); |
| 81 | m_mclock = clock(); |
| 81 | 82 | |
| 82 | | /* fill in the table - 16 bit case */ |
| 83 | | for (i = 0; i < count; i++) |
| 84 | | { |
| 85 | | int val = i * gain * 16 / voices; |
| 86 | | if (val > 32767) val = 32767; |
| 87 | | info->mixer_lookup[ i] = val; |
| 88 | | info->mixer_lookup[-i] = -val; |
| 89 | | } |
| 83 | /* allocate a pair of buffers to mix into - 1 second's worth should be more than enough */ |
| 84 | m_mixer_buffer = auto_alloc_array(machine(), short, 2 * m_rate); |
| 85 | |
| 86 | /* build the mixer table */ |
| 87 | make_mixer_table(2); |
| 88 | |
| 89 | m_sound_prom = m_region->base(); |
| 90 | |
| 91 | /* reset all the voices */ |
| 92 | voice[0].frequency = 0; |
| 93 | voice[0].volume = 0; |
| 94 | voice[0].wave = &m_sound_prom[0]; |
| 95 | voice[0].counter = 0; |
| 96 | voice[1].frequency = 0; |
| 97 | voice[1].volume = 0; |
| 98 | voice[1].wave = &m_sound_prom[0x100]; |
| 99 | voice[1].counter = 0; |
| 90 | 100 | } |
| 91 | 101 | |
| 92 | 102 | |
| 93 | | /* generate sound to the mix buffer */ |
| 94 | | static STREAM_UPDATE( K005289_update ) |
| 103 | //------------------------------------------------- |
| 104 | // sound_stream_update - handle a stream update |
| 105 | //------------------------------------------------- |
| 106 | |
| 107 | void k005289_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 95 | 108 | { |
| 96 | | k005289_state *info = (k005289_state *)param; |
| 97 | | k005289_sound_channel *voice=info->channel_list; |
| 109 | k005289_sound_channel *voice=m_channel_list; |
| 98 | 110 | stream_sample_t *buffer = outputs[0]; |
| 99 | 111 | short *mix; |
| 100 | 112 | int i,v,f; |
| 101 | 113 | |
| 102 | 114 | /* zap the contents of the mixer buffer */ |
| 103 | | memset(info->mixer_buffer, 0, samples * sizeof(INT16)); |
| 115 | memset(m_mixer_buffer, 0, samples * sizeof(INT16)); |
| 104 | 116 | |
| 105 | 117 | v=voice[0].volume; |
| 106 | 118 | f=voice[0].frequency; |
| r20748 | r20749 | |
| 109 | 121 | const unsigned char *w = voice[0].wave; |
| 110 | 122 | int c = voice[0].counter; |
| 111 | 123 | |
| 112 | | mix = info->mixer_buffer; |
| 124 | mix = m_mixer_buffer; |
| 113 | 125 | |
| 114 | 126 | /* add our contribution */ |
| 115 | 127 | for (i = 0; i < samples; i++) |
| 116 | 128 | { |
| 117 | 129 | int offs; |
| 118 | 130 | |
| 119 | | c+=(long)((((float)info->mclock / (float)(f * 16))*(float)(1<<FREQBASEBITS)) / (float)(info->rate / 32)); |
| 131 | c+=(long)((((float)m_mclock / (float)(f * 16))*(float)(1<<FREQBASEBITS)) / (float)(m_rate / 32)); |
| 120 | 132 | offs = (c >> 16) & 0x1f; |
| 121 | 133 | *mix++ += ((w[offs] & 0x0f) - 8) * v; |
| 122 | 134 | } |
| r20748 | r20749 | |
| 132 | 144 | const unsigned char *w = voice[1].wave; |
| 133 | 145 | int c = voice[1].counter; |
| 134 | 146 | |
| 135 | | mix = info->mixer_buffer; |
| 147 | mix = m_mixer_buffer; |
| 136 | 148 | |
| 137 | 149 | /* add our contribution */ |
| 138 | 150 | for (i = 0; i < samples; i++) |
| 139 | 151 | { |
| 140 | 152 | int offs; |
| 141 | 153 | |
| 142 | | c+=(long)((((float)info->mclock / (float)(f * 16))*(float)(1<<FREQBASEBITS)) / (float)(info->rate / 32)); |
| 154 | c+=(long)((((float)m_mclock / (float)(f * 16))*(float)(1<<FREQBASEBITS)) / (float)(m_rate / 32)); |
| 143 | 155 | offs = (c >> 16) & 0x1f; |
| 144 | 156 | *mix++ += ((w[offs] & 0x0f) - 8) * v; |
| 145 | 157 | } |
| r20748 | r20749 | |
| 149 | 161 | } |
| 150 | 162 | |
| 151 | 163 | /* mix it down */ |
| 152 | | mix = info->mixer_buffer; |
| 164 | mix = m_mixer_buffer; |
| 153 | 165 | for (i = 0; i < samples; i++) |
| 154 | | *buffer++ = info->mixer_lookup[*mix++]; |
| 166 | *buffer++ = m_mixer_lookup[*mix++]; |
| 155 | 167 | } |
| 156 | 168 | |
| 157 | | static DEVICE_START( k005289 ) |
| 158 | | { |
| 159 | | k005289_sound_channel *voice; |
| 160 | | k005289_state *info = get_safe_token(device); |
| 161 | 169 | |
| 162 | | voice = info->channel_list; |
| 163 | 170 | |
| 164 | | /* get stream channels */ |
| 165 | | info->rate = device->clock()/16; |
| 166 | | info->stream = device->machine().sound().stream_alloc(*device, 0, 1, info->rate, info, K005289_update); |
| 167 | | info->mclock = device->clock(); |
| 168 | 171 | |
| 169 | | /* allocate a pair of buffers to mix into - 1 second's worth should be more than enough */ |
| 170 | | info->mixer_buffer = auto_alloc_array(device->machine(), short, 2 * info->rate); |
| 172 | /********************************************************************************/ |
| 171 | 173 | |
| 172 | | /* build the mixer table */ |
| 173 | | make_mixer_table(device->machine(), info, 2); |
| 174 | /* build a table to divide by the number of voices */ |
| 175 | void k005289_device::make_mixer_table(int voices) |
| 176 | { |
| 177 | int count = voices * 128; |
| 178 | int i; |
| 179 | int gain = 16; |
| 174 | 180 | |
| 175 | | info->sound_prom = *device->region(); |
| 181 | /* allocate memory */ |
| 182 | m_mixer_table = auto_alloc_array(machine(), INT16, 256 * voices); |
| 176 | 183 | |
| 177 | | /* reset all the voices */ |
| 178 | | voice[0].frequency = 0; |
| 179 | | voice[0].volume = 0; |
| 180 | | voice[0].wave = &info->sound_prom[0]; |
| 181 | | voice[0].counter = 0; |
| 182 | | voice[1].frequency = 0; |
| 183 | | voice[1].volume = 0; |
| 184 | | voice[1].wave = &info->sound_prom[0x100]; |
| 185 | | voice[1].counter = 0; |
| 184 | /* find the middle of the table */ |
| 185 | m_mixer_lookup = m_mixer_table + (128 * voices); |
| 186 | |
| 187 | /* fill in the table - 16 bit case */ |
| 188 | for (i = 0; i < count; i++) |
| 189 | { |
| 190 | int val = i * gain * 16 / voices; |
| 191 | if (val > 32767) val = 32767; |
| 192 | m_mixer_lookup[ i] = val; |
| 193 | m_mixer_lookup[-i] = -val; |
| 194 | } |
| 186 | 195 | } |
| 187 | 196 | |
| 188 | 197 | |
| 189 | | /********************************************************************************/ |
| 190 | | |
| 191 | | static void k005289_recompute(k005289_state *info) |
| 198 | void k005289_device::k005289_recompute() |
| 192 | 199 | { |
| 193 | | k005289_sound_channel *voice = info->channel_list; |
| 200 | k005289_sound_channel *voice = m_channel_list; |
| 194 | 201 | |
| 195 | | info->stream->update(); /* update the streams */ |
| 202 | m_stream->update(); /* update the streams */ |
| 196 | 203 | |
| 197 | | voice[0].frequency = info->k005289_A_frequency; |
| 198 | | voice[1].frequency = info->k005289_B_frequency; |
| 199 | | voice[0].volume = info->k005289_A_volume; |
| 200 | | voice[1].volume = info->k005289_B_volume; |
| 201 | | voice[0].wave = &info->sound_prom[32 * info->k005289_A_waveform]; |
| 202 | | voice[1].wave = &info->sound_prom[32 * info->k005289_B_waveform + 0x100]; |
| 204 | voice[0].frequency = m_k005289_A_frequency; |
| 205 | voice[1].frequency = m_k005289_B_frequency; |
| 206 | voice[0].volume = m_k005289_A_volume; |
| 207 | voice[1].volume = m_k005289_B_volume; |
| 208 | voice[0].wave = &m_sound_prom[32 * m_k005289_A_waveform]; |
| 209 | voice[1].wave = &m_sound_prom[32 * m_k005289_B_waveform + 0x100]; |
| 203 | 210 | } |
| 204 | 211 | |
| 205 | | WRITE8_DEVICE_HANDLER( k005289_control_A_w ) |
| 206 | | { |
| 207 | | k005289_state *info = get_safe_token(device); |
| 208 | | info->k005289_A_volume=data&0xf; |
| 209 | | info->k005289_A_waveform=data>>5; |
| 210 | | k005289_recompute(info); |
| 211 | | } |
| 212 | 212 | |
| 213 | | WRITE8_DEVICE_HANDLER( k005289_control_B_w ) |
| 213 | WRITE8_MEMBER( k005289_device::k005289_control_A_w ) |
| 214 | 214 | { |
| 215 | | k005289_state *info = get_safe_token(device); |
| 216 | | info->k005289_B_volume=data&0xf; |
| 217 | | info->k005289_B_waveform=data>>5; |
| 218 | | k005289_recompute(info); |
| 215 | m_k005289_A_volume=data&0xf; |
| 216 | m_k005289_A_waveform=data>>5; |
| 217 | k005289_recompute(); |
| 219 | 218 | } |
| 220 | 219 | |
| 221 | | WRITE8_DEVICE_HANDLER( k005289_pitch_A_w ) |
| 222 | | { |
| 223 | | k005289_state *info = get_safe_token(device); |
| 224 | | info->k005289_A_latch = 0x1000 - offset; |
| 225 | | } |
| 226 | 220 | |
| 227 | | WRITE8_DEVICE_HANDLER( k005289_pitch_B_w ) |
| 221 | WRITE8_MEMBER( k005289_device::k005289_control_B_w ) |
| 228 | 222 | { |
| 229 | | k005289_state *info = get_safe_token(device); |
| 230 | | info->k005289_B_latch = 0x1000 - offset; |
| 223 | m_k005289_B_volume=data&0xf; |
| 224 | m_k005289_B_waveform=data>>5; |
| 225 | k005289_recompute(); |
| 231 | 226 | } |
| 232 | 227 | |
| 233 | | WRITE8_DEVICE_HANDLER( k005289_keylatch_A_w ) |
| 234 | | { |
| 235 | | k005289_state *info = get_safe_token(device); |
| 236 | | info->k005289_A_frequency = info->k005289_A_latch; |
| 237 | | k005289_recompute(info); |
| 238 | | } |
| 239 | 228 | |
| 240 | | WRITE8_DEVICE_HANDLER( k005289_keylatch_B_w ) |
| 229 | WRITE8_MEMBER( k005289_device::k005289_pitch_A_w ) |
| 241 | 230 | { |
| 242 | | k005289_state *info = get_safe_token(device); |
| 243 | | info->k005289_B_frequency = info->k005289_B_latch; |
| 244 | | k005289_recompute(info); |
| 231 | m_k005289_A_latch = 0x1000 - offset; |
| 245 | 232 | } |
| 246 | 233 | |
| 247 | | const device_type K005289 = &device_creator<k005289_device>; |
| 248 | 234 | |
| 249 | | k005289_device::k005289_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 250 | | : device_t(mconfig, K005289, "K005289", tag, owner, clock), |
| 251 | | device_sound_interface(mconfig, *this) |
| 235 | WRITE8_MEMBER( k005289_device::k005289_pitch_B_w ) |
| 252 | 236 | { |
| 253 | | m_token = global_alloc_clear(k005289_state); |
| 237 | m_k005289_B_latch = 0x1000 - offset; |
| 254 | 238 | } |
| 255 | 239 | |
| 256 | | //------------------------------------------------- |
| 257 | | // device_config_complete - perform any |
| 258 | | // operations now that the configuration is |
| 259 | | // complete |
| 260 | | //------------------------------------------------- |
| 261 | 240 | |
| 262 | | void k005289_device::device_config_complete() |
| 241 | WRITE8_MEMBER( k005289_device::k005289_keylatch_A_w ) |
| 263 | 242 | { |
| 243 | m_k005289_A_frequency = m_k005289_A_latch; |
| 244 | k005289_recompute(); |
| 264 | 245 | } |
| 265 | 246 | |
| 266 | | //------------------------------------------------- |
| 267 | | // device_start - device-specific startup |
| 268 | | //------------------------------------------------- |
| 269 | 247 | |
| 270 | | void k005289_device::device_start() |
| 248 | WRITE8_MEMBER( k005289_device::k005289_keylatch_B_w ) |
| 271 | 249 | { |
| 272 | | DEVICE_START_NAME( k005289 )(this); |
| 250 | m_k005289_B_frequency = m_k005289_B_latch; |
| 251 | k005289_recompute(); |
| 273 | 252 | } |
| 274 | | |
| 275 | | //------------------------------------------------- |
| 276 | | // sound_stream_update - handle a stream update |
| 277 | | //------------------------------------------------- |
| 278 | | |
| 279 | | void k005289_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 280 | | { |
| 281 | | // should never get here |
| 282 | | fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); |
| 283 | | } |
trunk/src/emu/sound/k005289.h
| r20748 | r20749 | |
| 3 | 3 | #ifndef __K005289_H__ |
| 4 | 4 | #define __K005289_H__ |
| 5 | 5 | |
| 6 | | #include "devlegcy.h" |
| 7 | 6 | |
| 8 | | DECLARE_WRITE8_DEVICE_HANDLER( k005289_control_A_w ); |
| 9 | | DECLARE_WRITE8_DEVICE_HANDLER( k005289_control_B_w ); |
| 10 | | DECLARE_WRITE8_DEVICE_HANDLER( k005289_pitch_A_w ); |
| 11 | | DECLARE_WRITE8_DEVICE_HANDLER( k005289_pitch_B_w ); |
| 12 | | DECLARE_WRITE8_DEVICE_HANDLER( k005289_keylatch_A_w ); |
| 13 | | DECLARE_WRITE8_DEVICE_HANDLER( k005289_keylatch_B_w ); |
| 7 | //************************************************************************** |
| 8 | // INTERFACE CONFIGURATION MACROS |
| 9 | //************************************************************************** |
| 14 | 10 | |
| 11 | #define MCFG_K005289_ADD(_tag, _clock) \ |
| 12 | MCFG_DEVICE_ADD(_tag, K005289, _clock) |
| 13 | #define MCFG_K005289_REPLACE(_tag, _clock) \ |
| 14 | MCFG_DEVICE_REPLACE(_tag, K005289, _clock) |
| 15 | |
| 16 | |
| 17 | //************************************************************************** |
| 18 | // TYPE DEFINITIONS |
| 19 | //************************************************************************** |
| 20 | |
| 21 | struct k005289_sound_channel |
| 22 | { |
| 23 | int frequency; |
| 24 | int counter; |
| 25 | int volume; |
| 26 | const unsigned char *wave; |
| 27 | }; |
| 28 | |
| 29 | |
| 30 | // ======================> k005289_device |
| 31 | |
| 15 | 32 | class k005289_device : public device_t, |
| 16 | | public device_sound_interface |
| 33 | public device_sound_interface |
| 17 | 34 | { |
| 18 | 35 | public: |
| 19 | 36 | k005289_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 20 | | ~k005289_device() { global_free(m_token); } |
| 37 | ~k005289_device() { } |
| 21 | 38 | |
| 22 | | // access to legacy token |
| 23 | | void *token() const { assert(m_token != NULL); return m_token; } |
| 24 | 39 | protected: |
| 25 | 40 | // device-level overrides |
| 26 | | virtual void device_config_complete(); |
| 27 | 41 | virtual void device_start(); |
| 28 | 42 | |
| 29 | 43 | // sound stream update overrides |
| 30 | 44 | virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); |
| 45 | |
| 46 | public: |
| 47 | DECLARE_WRITE8_MEMBER( k005289_control_A_w ); |
| 48 | DECLARE_WRITE8_MEMBER( k005289_control_B_w ); |
| 49 | DECLARE_WRITE8_MEMBER( k005289_pitch_A_w ); |
| 50 | DECLARE_WRITE8_MEMBER( k005289_pitch_B_w ); |
| 51 | DECLARE_WRITE8_MEMBER( k005289_keylatch_A_w ); |
| 52 | DECLARE_WRITE8_MEMBER( k005289_keylatch_B_w ); |
| 53 | |
| 31 | 54 | private: |
| 32 | | // internal state |
| 33 | | void *m_token; |
| 55 | void make_mixer_table(int voices); |
| 56 | void k005289_recompute(); |
| 57 | |
| 58 | private: |
| 59 | k005289_sound_channel m_channel_list[2]; |
| 60 | |
| 61 | const unsigned char *m_sound_prom; |
| 62 | sound_stream *m_stream; |
| 63 | int m_mclock; |
| 64 | int m_rate; |
| 65 | |
| 66 | /* mixer tables and internal buffers */ |
| 67 | INT16 *m_mixer_table; |
| 68 | INT16 *m_mixer_lookup; |
| 69 | short *m_mixer_buffer; |
| 70 | |
| 71 | int m_k005289_A_frequency; |
| 72 | int m_k005289_B_frequency; |
| 73 | int m_k005289_A_volume; |
| 74 | int m_k005289_B_volume; |
| 75 | int m_k005289_A_waveform; |
| 76 | int m_k005289_B_waveform; |
| 77 | int m_k005289_A_latch; |
| 78 | int m_k005289_B_latch; |
| 34 | 79 | }; |
| 35 | 80 | |
| 36 | 81 | extern const device_type K005289; |
trunk/src/emu/sound/iremga20.c
| r20748 | r20749 | |
| 31 | 31 | |
| 32 | 32 | #define MAX_VOL 256 |
| 33 | 33 | |
| 34 | | struct IremGA20_channel_def |
| 34 | |
| 35 | // device type definition |
| 36 | const device_type IREMGA20 = &device_creator<iremga20_device>; |
| 37 | |
| 38 | |
| 39 | //************************************************************************** |
| 40 | // LIVE DEVICE |
| 41 | //************************************************************************** |
| 42 | |
| 43 | //------------------------------------------------- |
| 44 | // iremga20_device - constructor |
| 45 | //------------------------------------------------- |
| 46 | |
| 47 | iremga20_device::iremga20_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 48 | : device_t(mconfig, IREMGA20, "Irem GA20", tag, owner, clock), |
| 49 | device_sound_interface(mconfig, *this), |
| 50 | m_rom(NULL), |
| 51 | m_rom_size(0), |
| 52 | m_stream(NULL) |
| 35 | 53 | { |
| 36 | | UINT32 rate; |
| 37 | | UINT32 size; |
| 38 | | UINT32 start; |
| 39 | | UINT32 pos; |
| 40 | | UINT32 frac; |
| 41 | | UINT32 end; |
| 42 | | UINT32 volume; |
| 43 | | UINT32 pan; |
| 44 | | UINT32 effect; |
| 45 | | UINT32 play; |
| 46 | | }; |
| 54 | } |
| 47 | 55 | |
| 48 | | struct ga20_state |
| 56 | |
| 57 | //------------------------------------------------- |
| 58 | // device_start - device-specific startup |
| 59 | //------------------------------------------------- |
| 60 | |
| 61 | void iremga20_device::device_start() |
| 49 | 62 | { |
| 50 | | UINT8 *rom; |
| 51 | | INT32 rom_size; |
| 52 | | sound_stream * stream; |
| 53 | | UINT16 regs[0x40]; |
| 54 | | struct IremGA20_channel_def channel[4]; |
| 55 | | }; |
| 63 | int i; |
| 56 | 64 | |
| 65 | /* Initialize our chip structure */ |
| 66 | m_rom = m_region->base(); |
| 67 | m_rom_size = m_region->bytes(); |
| 57 | 68 | |
| 58 | | INLINE ga20_state *get_safe_token(device_t *device) |
| 69 | iremga20_reset(); |
| 70 | |
| 71 | for ( i = 0; i < 0x40; i++ ) |
| 72 | m_regs[i] = 0; |
| 73 | |
| 74 | m_stream = stream_alloc(0, 2, clock()/4); |
| 75 | |
| 76 | save_item(NAME(m_regs)); |
| 77 | for (i = 0; i < 4; i++) |
| 78 | { |
| 79 | save_item(NAME(m_channel[i].rate), i); |
| 80 | save_item(NAME(m_channel[i].size), i); |
| 81 | save_item(NAME(m_channel[i].start), i); |
| 82 | save_item(NAME(m_channel[i].pos), i); |
| 83 | save_item(NAME(m_channel[i].end), i); |
| 84 | save_item(NAME(m_channel[i].volume), i); |
| 85 | save_item(NAME(m_channel[i].pan), i); |
| 86 | save_item(NAME(m_channel[i].effect), i); |
| 87 | save_item(NAME(m_channel[i].play), i); |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | |
| 92 | //------------------------------------------------- |
| 93 | // device_reset - device-specific reset |
| 94 | //------------------------------------------------- |
| 95 | |
| 96 | void iremga20_device::device_reset() |
| 59 | 97 | { |
| 60 | | assert(device != NULL); |
| 61 | | assert(device->type() == IREMGA20); |
| 62 | | return (ga20_state *)downcast<iremga20_device *>(device)->token(); |
| 98 | iremga20_reset(); |
| 63 | 99 | } |
| 64 | 100 | |
| 65 | 101 | |
| 66 | | static STREAM_UPDATE( IremGA20_update ) |
| 102 | //------------------------------------------------- |
| 103 | // sound_stream_update - handle a stream update |
| 104 | //------------------------------------------------- |
| 105 | |
| 106 | void iremga20_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 67 | 107 | { |
| 68 | | ga20_state *chip = (ga20_state *)param; |
| 69 | 108 | UINT32 rate[4], pos[4], frac[4], end[4], vol[4], play[4]; |
| 70 | 109 | UINT8 *pSamples; |
| 71 | 110 | stream_sample_t *outL, *outR; |
| r20748 | r20749 | |
| 74 | 113 | /* precache some values */ |
| 75 | 114 | for (i=0; i < 4; i++) |
| 76 | 115 | { |
| 77 | | rate[i] = chip->channel[i].rate; |
| 78 | | pos[i] = chip->channel[i].pos; |
| 79 | | frac[i] = chip->channel[i].frac; |
| 80 | | end[i] = chip->channel[i].end - 0x20; |
| 81 | | vol[i] = chip->channel[i].volume; |
| 82 | | play[i] = chip->channel[i].play; |
| 116 | rate[i] = m_channel[i].rate; |
| 117 | pos[i] = m_channel[i].pos; |
| 118 | frac[i] = m_channel[i].frac; |
| 119 | end[i] = m_channel[i].end - 0x20; |
| 120 | vol[i] = m_channel[i].volume; |
| 121 | play[i] = m_channel[i].play; |
| 83 | 122 | } |
| 84 | 123 | |
| 85 | 124 | i = samples; |
| 86 | | pSamples = chip->rom; |
| 125 | pSamples = m_rom; |
| 87 | 126 | outL = outputs[0]; |
| 88 | 127 | outR = outputs[1]; |
| 89 | 128 | |
| r20748 | r20749 | |
| 133 | 172 | /* update the regs now */ |
| 134 | 173 | for (i=0; i < 4; i++) |
| 135 | 174 | { |
| 136 | | chip->channel[i].pos = pos[i]; |
| 137 | | chip->channel[i].frac = frac[i]; |
| 138 | | chip->channel[i].play = play[i]; |
| 175 | m_channel[i].pos = pos[i]; |
| 176 | m_channel[i].frac = frac[i]; |
| 177 | m_channel[i].play = play[i]; |
| 139 | 178 | } |
| 140 | 179 | } |
| 141 | 180 | |
| 142 | | WRITE8_DEVICE_HANDLER( irem_ga20_w ) |
| 181 | WRITE8_MEMBER( iremga20_device::irem_ga20_w ) |
| 143 | 182 | { |
| 144 | | ga20_state *chip = get_safe_token(device); |
| 145 | 183 | int channel; |
| 146 | 184 | |
| 147 | 185 | //logerror("GA20: Offset %02x, data %04x\n",offset,data); |
| 148 | 186 | |
| 149 | | chip->stream->update(); |
| 187 | m_stream->update(); |
| 150 | 188 | |
| 151 | 189 | channel = offset >> 3; |
| 152 | 190 | |
| 153 | | chip->regs[offset] = data; |
| 191 | m_regs[offset] = data; |
| 154 | 192 | |
| 155 | 193 | switch (offset & 0x7) |
| 156 | 194 | { |
| 157 | 195 | case 0: /* start address low */ |
| 158 | | chip->channel[channel].start = ((chip->channel[channel].start)&0xff000) | (data<<4); |
| 196 | m_channel[channel].start = ((m_channel[channel].start)&0xff000) | (data<<4); |
| 159 | 197 | break; |
| 160 | 198 | |
| 161 | 199 | case 1: /* start address high */ |
| 162 | | chip->channel[channel].start = ((chip->channel[channel].start)&0x00ff0) | (data<<12); |
| 200 | m_channel[channel].start = ((m_channel[channel].start)&0x00ff0) | (data<<12); |
| 163 | 201 | break; |
| 164 | 202 | |
| 165 | 203 | case 2: /* end address low */ |
| 166 | | chip->channel[channel].end = ((chip->channel[channel].end)&0xff000) | (data<<4); |
| 204 | m_channel[channel].end = ((m_channel[channel].end)&0xff000) | (data<<4); |
| 167 | 205 | break; |
| 168 | 206 | |
| 169 | 207 | case 3: /* end address high */ |
| 170 | | chip->channel[channel].end = ((chip->channel[channel].end)&0x00ff0) | (data<<12); |
| 208 | m_channel[channel].end = ((m_channel[channel].end)&0x00ff0) | (data<<12); |
| 171 | 209 | break; |
| 172 | 210 | |
| 173 | 211 | case 4: |
| 174 | | chip->channel[channel].rate = 0x1000000 / (256 - data); |
| 212 | m_channel[channel].rate = 0x1000000 / (256 - data); |
| 175 | 213 | break; |
| 176 | 214 | |
| 177 | 215 | case 5: //AT: gain control |
| 178 | | chip->channel[channel].volume = (data * MAX_VOL) / (data + 10); |
| 216 | m_channel[channel].volume = (data * MAX_VOL) / (data + 10); |
| 179 | 217 | break; |
| 180 | 218 | |
| 181 | 219 | case 6: //AT: this is always written 2(enabling both channels?) |
| 182 | | chip->channel[channel].play = data; |
| 183 | | chip->channel[channel].pos = chip->channel[channel].start; |
| 184 | | chip->channel[channel].frac = 0; |
| 220 | m_channel[channel].play = data; |
| 221 | m_channel[channel].pos = m_channel[channel].start; |
| 222 | m_channel[channel].frac = 0; |
| 185 | 223 | break; |
| 186 | 224 | } |
| 187 | 225 | } |
| 188 | 226 | |
| 189 | | READ8_DEVICE_HANDLER( irem_ga20_r ) |
| 227 | READ8_MEMBER( iremga20_device::irem_ga20_r ) |
| 190 | 228 | { |
| 191 | | ga20_state *chip = get_safe_token(device); |
| 192 | 229 | int channel; |
| 193 | 230 | |
| 194 | | chip->stream->update(); |
| 231 | m_stream->update(); |
| 195 | 232 | |
| 196 | 233 | channel = offset >> 3; |
| 197 | 234 | |
| 198 | 235 | switch (offset & 0x7) |
| 199 | 236 | { |
| 200 | 237 | case 7: // voice status. bit 0 is 1 if active. (routine around 0xccc in rtypeleo) |
| 201 | | return chip->channel[channel].play ? 1 : 0; |
| 238 | return m_channel[channel].play ? 1 : 0; |
| 202 | 239 | |
| 203 | 240 | default: |
| 204 | 241 | logerror("GA20: read unk. register %d, channel %d\n", offset & 0xf, channel); |
| r20748 | r20749 | |
| 208 | 245 | return 0; |
| 209 | 246 | } |
| 210 | 247 | |
| 211 | | static void iremga20_reset(ga20_state *chip) |
| 248 | |
| 249 | void iremga20_device::iremga20_reset() |
| 212 | 250 | { |
| 213 | 251 | int i; |
| 214 | 252 | |
| 215 | 253 | for( i = 0; i < 4; i++ ) { |
| 216 | | chip->channel[i].rate = 0; |
| 217 | | chip->channel[i].size = 0; |
| 218 | | chip->channel[i].start = 0; |
| 219 | | chip->channel[i].pos = 0; |
| 220 | | chip->channel[i].frac = 0; |
| 221 | | chip->channel[i].end = 0; |
| 222 | | chip->channel[i].volume = 0; |
| 223 | | chip->channel[i].pan = 0; |
| 224 | | chip->channel[i].effect = 0; |
| 225 | | chip->channel[i].play = 0; |
| 254 | m_channel[i].rate = 0; |
| 255 | m_channel[i].size = 0; |
| 256 | m_channel[i].start = 0; |
| 257 | m_channel[i].pos = 0; |
| 258 | m_channel[i].frac = 0; |
| 259 | m_channel[i].end = 0; |
| 260 | m_channel[i].volume = 0; |
| 261 | m_channel[i].pan = 0; |
| 262 | m_channel[i].effect = 0; |
| 263 | m_channel[i].play = 0; |
| 226 | 264 | } |
| 227 | 265 | } |
| 228 | | |
| 229 | | |
| 230 | | static DEVICE_RESET( iremga20 ) |
| 231 | | { |
| 232 | | iremga20_reset(get_safe_token(device)); |
| 233 | | } |
| 234 | | |
| 235 | | static DEVICE_START( iremga20 ) |
| 236 | | { |
| 237 | | ga20_state *chip = get_safe_token(device); |
| 238 | | int i; |
| 239 | | |
| 240 | | /* Initialize our chip structure */ |
| 241 | | chip->rom = *device->region(); |
| 242 | | chip->rom_size = device->region()->bytes(); |
| 243 | | |
| 244 | | iremga20_reset(chip); |
| 245 | | |
| 246 | | for ( i = 0; i < 0x40; i++ ) |
| 247 | | chip->regs[i] = 0; |
| 248 | | |
| 249 | | chip->stream = device->machine().sound().stream_alloc( *device, 0, 2, device->clock()/4, chip, IremGA20_update ); |
| 250 | | |
| 251 | | device->save_item(NAME(chip->regs)); |
| 252 | | for (i = 0; i < 4; i++) |
| 253 | | { |
| 254 | | device->save_item(NAME(chip->channel[i].rate), i); |
| 255 | | device->save_item(NAME(chip->channel[i].size), i); |
| 256 | | device->save_item(NAME(chip->channel[i].start), i); |
| 257 | | device->save_item(NAME(chip->channel[i].pos), i); |
| 258 | | device->save_item(NAME(chip->channel[i].end), i); |
| 259 | | device->save_item(NAME(chip->channel[i].volume), i); |
| 260 | | device->save_item(NAME(chip->channel[i].pan), i); |
| 261 | | device->save_item(NAME(chip->channel[i].effect), i); |
| 262 | | device->save_item(NAME(chip->channel[i].play), i); |
| 263 | | } |
| 264 | | } |
| 265 | | |
| 266 | | const device_type IREMGA20 = &device_creator<iremga20_device>; |
| 267 | | |
| 268 | | iremga20_device::iremga20_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 269 | | : device_t(mconfig, IREMGA20, "Irem GA20", tag, owner, clock), |
| 270 | | device_sound_interface(mconfig, *this) |
| 271 | | { |
| 272 | | m_token = global_alloc_clear(ga20_state); |
| 273 | | } |
| 274 | | |
| 275 | | //------------------------------------------------- |
| 276 | | // device_config_complete - perform any |
| 277 | | // operations now that the configuration is |
| 278 | | // complete |
| 279 | | //------------------------------------------------- |
| 280 | | |
| 281 | | void iremga20_device::device_config_complete() |
| 282 | | { |
| 283 | | } |
| 284 | | |
| 285 | | //------------------------------------------------- |
| 286 | | // device_start - device-specific startup |
| 287 | | //------------------------------------------------- |
| 288 | | |
| 289 | | void iremga20_device::device_start() |
| 290 | | { |
| 291 | | DEVICE_START_NAME( iremga20 )(this); |
| 292 | | } |
| 293 | | |
| 294 | | //------------------------------------------------- |
| 295 | | // device_reset - device-specific reset |
| 296 | | //------------------------------------------------- |
| 297 | | |
| 298 | | void iremga20_device::device_reset() |
| 299 | | { |
| 300 | | DEVICE_RESET_NAME( iremga20 )(this); |
| 301 | | } |
| 302 | | |
| 303 | | //------------------------------------------------- |
| 304 | | // sound_stream_update - handle a stream update |
| 305 | | //------------------------------------------------- |
| 306 | | |
| 307 | | void iremga20_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 308 | | { |
| 309 | | // should never get here |
| 310 | | fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); |
| 311 | | } |
trunk/src/mame/drivers/nemesis.c
| r20748 | r20749 | |
| 392 | 392 | static ADDRESS_MAP_START( sound_map, AS_PROGRAM, 8, nemesis_state ) |
| 393 | 393 | AM_RANGE(0x0000, 0x3fff) AM_ROM |
| 394 | 394 | AM_RANGE(0x4000, 0x47ff) AM_RAM |
| 395 | | AM_RANGE(0xa000, 0xafff) AM_DEVWRITE_LEGACY("k007232", k005289_pitch_A_w) |
| 396 | | AM_RANGE(0xc000, 0xcfff) AM_DEVWRITE_LEGACY("k007232", k005289_pitch_B_w) |
| 395 | AM_RANGE(0xa000, 0xafff) AM_DEVWRITE("k007232", k005289_device, k005289_pitch_A_w) |
| 396 | AM_RANGE(0xc000, 0xcfff) AM_DEVWRITE("k007232", k005289_device, k005289_pitch_B_w) |
| 397 | 397 | AM_RANGE(0xe001, 0xe001) AM_READ(soundlatch_byte_r) |
| 398 | | AM_RANGE(0xe003, 0xe003) AM_DEVWRITE_LEGACY("k007232", k005289_keylatch_A_w) |
| 399 | | AM_RANGE(0xe004, 0xe004) AM_DEVWRITE_LEGACY("k007232", k005289_keylatch_B_w) |
| 398 | AM_RANGE(0xe003, 0xe003) AM_DEVWRITE("k007232", k005289_device, k005289_keylatch_A_w) |
| 399 | AM_RANGE(0xe004, 0xe004) AM_DEVWRITE("k007232", k005289_device, k005289_keylatch_B_w) |
| 400 | 400 | AM_RANGE(0xe005, 0xe005) AM_DEVWRITE_LEGACY("ay2", ay8910_address_w) |
| 401 | 401 | AM_RANGE(0xe006, 0xe006) AM_DEVWRITE_LEGACY("ay1", ay8910_address_w) |
| 402 | 402 | AM_RANGE(0xe086, 0xe086) AM_DEVREAD_LEGACY("ay1", ay8910_r) |
| r20748 | r20749 | |
| 408 | 408 | static ADDRESS_MAP_START( gx400_sound_map, AS_PROGRAM, 8, nemesis_state ) |
| 409 | 409 | AM_RANGE(0x0000, 0x1fff) AM_ROM |
| 410 | 410 | AM_RANGE(0x4000, 0x87ff) AM_RAM AM_SHARE("gx400_shared") |
| 411 | | AM_RANGE(0xa000, 0xafff) AM_DEVWRITE_LEGACY("k007232", k005289_pitch_A_w) |
| 412 | | AM_RANGE(0xc000, 0xcfff) AM_DEVWRITE_LEGACY("k007232", k005289_pitch_B_w) |
| 411 | AM_RANGE(0xa000, 0xafff) AM_DEVWRITE("k007232", k005289_device, k005289_pitch_A_w) |
| 412 | AM_RANGE(0xc000, 0xcfff) AM_DEVWRITE("k007232", k005289_device, k005289_pitch_B_w) |
| 413 | 413 | AM_RANGE(0xe000, 0xe000) AM_DEVWRITE_LEGACY("vlm", vlm5030_data_w) |
| 414 | 414 | AM_RANGE(0xe001, 0xe001) AM_READ(soundlatch_byte_r) |
| 415 | | AM_RANGE(0xe003, 0xe003) AM_DEVWRITE_LEGACY("k007232", k005289_keylatch_A_w) |
| 416 | | AM_RANGE(0xe004, 0xe004) AM_DEVWRITE_LEGACY("k007232", k005289_keylatch_B_w) |
| 415 | AM_RANGE(0xe003, 0xe003) AM_DEVWRITE("k007232", k005289_device, k005289_keylatch_A_w) |
| 416 | AM_RANGE(0xe004, 0xe004) AM_DEVWRITE("k007232", k005289_device, k005289_keylatch_B_w) |
| 417 | 417 | AM_RANGE(0xe005, 0xe005) AM_DEVWRITE_LEGACY("ay2", ay8910_address_w) |
| 418 | 418 | AM_RANGE(0xe006, 0xe006) AM_DEVWRITE_LEGACY("ay1", ay8910_address_w) |
| 419 | 419 | AM_RANGE(0xe030, 0xe030) AM_WRITE(gx400_speech_start_w) |
| r20748 | r20749 | |
| 1476 | 1476 | AY8910_DEFAULT_LOADS, |
| 1477 | 1477 | DEVCB_NULL, |
| 1478 | 1478 | DEVCB_NULL, |
| 1479 | | DEVCB_DEVICE_HANDLER("k007232", k005289_control_A_w), |
| 1480 | | DEVCB_DEVICE_HANDLER("k007232", k005289_control_B_w) |
| 1479 | DEVCB_DEVICE_MEMBER("k007232", k005289_device, k005289_control_A_w), |
| 1480 | DEVCB_DEVICE_MEMBER("k007232", k005289_device, k005289_control_B_w) |
| 1481 | 1481 | }; |
| 1482 | 1482 | |
| 1483 | 1483 | static void sound_irq(device_t *device, int state) |
| r20748 | r20749 | |
| 1574 | 1574 | MCFG_SOUND_CONFIG(ay8910_interface_2) /* fixed */ |
| 1575 | 1575 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00) /* verified with OST */ |
| 1576 | 1576 | |
| 1577 | | MCFG_SOUND_ADD("k007232", K005289, 3579545/2) |
| 1577 | MCFG_K005289_ADD("k007232", 3579545/2) |
| 1578 | 1578 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.35) /* verified with OST */ |
| 1579 | 1579 | |
| 1580 | 1580 | MCFG_SOUND_ADD("vlm", VLM5030, 3579545) |
| r20748 | r20749 | |
| 1617 | 1617 | MCFG_SOUND_CONFIG(ay8910_interface_2) |
| 1618 | 1618 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00) /* verified with OST */ |
| 1619 | 1619 | |
| 1620 | | MCFG_SOUND_ADD("k007232", K005289, 3579545/2) |
| 1620 | MCFG_K005289_ADD("k007232", 3579545/2) |
| 1621 | 1621 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.35) /* verified with OST */ |
| 1622 | 1622 | |
| 1623 | 1623 | MCFG_SOUND_ADD("vlm", VLM5030, 3579545) |
| r20748 | r20749 | |
| 1659 | 1659 | MCFG_SOUND_CONFIG(ay8910_interface_2) |
| 1660 | 1660 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.80) |
| 1661 | 1661 | |
| 1662 | | MCFG_SOUND_ADD("k007232", K005289, 3579545/2) |
| 1662 | MCFG_K005289_ADD("k007232", 3579545/2) |
| 1663 | 1663 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.60) |
| 1664 | 1664 | MACHINE_CONFIG_END |
| 1665 | 1665 | |
| r20748 | r20749 | |
| 1699 | 1699 | MCFG_SOUND_CONFIG(ay8910_interface_2) |
| 1700 | 1700 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.80) |
| 1701 | 1701 | |
| 1702 | | MCFG_SOUND_ADD("k007232", K005289, 3579545/2) |
| 1702 | MCFG_K005289_ADD("k007232", 3579545/2) |
| 1703 | 1703 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.60) |
| 1704 | 1704 | |
| 1705 | 1705 | MCFG_SOUND_ADD("vlm", VLM5030, 3579545) |