trunk/src/mame/drivers/metro.c
r22809 | r22810 | |
437 | 437 | m_portb = data; |
438 | 438 | } |
439 | 439 | |
440 | | static const ymf278b_interface ymf278b_config = |
441 | | { |
442 | | DEVCB_DRIVER_LINE_MEMBER(metro_state,ymf278b_interrupt) |
443 | | }; |
444 | 440 | |
445 | | |
446 | 441 | /*************************************************************************** |
447 | 442 | |
448 | 443 | |
r22809 | r22810 | |
770 | 765 | |
771 | 766 | static ADDRESS_MAP_START( balcube_map, AS_PROGRAM, 16, metro_state ) |
772 | 767 | AM_RANGE(0x000000, 0x07ffff) AM_ROM // ROM |
773 | | AM_RANGE(0x300000, 0x300001) AM_DEVREAD8_LEGACY("ymf", ymf278b_r, 0x00ff) // Sound |
774 | | AM_RANGE(0x300000, 0x30000b) AM_DEVWRITE8_LEGACY("ymf", ymf278b_w, 0x00ff) // Sound |
| 768 | AM_RANGE(0x300000, 0x300001) AM_DEVREAD8("ymf", ymf278b_device, read, 0x00ff) // Sound |
| 769 | AM_RANGE(0x300000, 0x30000b) AM_DEVWRITE8("ymf", ymf278b_device, write, 0x00ff) // Sound |
775 | 770 | AM_RANGE(0x400000, 0x41ffff) AM_READ(balcube_dsw_r) // DSW x 3 |
776 | 771 | AM_RANGE(0x500000, 0x500001) AM_READ_PORT("IN0") // Inputs |
777 | 772 | AM_RANGE(0x500002, 0x500003) AM_READ_PORT("IN1") // |
r22809 | r22810 | |
829 | 824 | AM_RANGE(0x200006, 0x200007) AM_READNOP // |
830 | 825 | AM_RANGE(0x200002, 0x200009) AM_WRITE(metro_coin_lockout_4words_w) // Coin Lockout |
831 | 826 | AM_RANGE(0x300000, 0x31ffff) AM_READ(balcube_dsw_r) // DSW x 3 |
832 | | AM_RANGE(0x400000, 0x400001) AM_DEVREAD8_LEGACY("ymf", ymf278b_r, 0x00ff) // Sound |
833 | | AM_RANGE(0x400000, 0x40000b) AM_DEVWRITE8_LEGACY("ymf", ymf278b_w, 0x00ff) // Sound |
| 827 | AM_RANGE(0x400000, 0x400001) AM_DEVREAD8("ymf", ymf278b_device, read, 0x00ff) // Sound |
| 828 | AM_RANGE(0x400000, 0x40000b) AM_DEVWRITE8("ymf", ymf278b_device, write, 0x00ff) // Sound |
834 | 829 | AM_RANGE(0xf00000, 0xf0ffff) AM_RAM AM_MIRROR(0x0f0000) // RAM (mirrored) |
835 | 830 | ADDRESS_MAP_END |
836 | 831 | |
r22809 | r22810 | |
841 | 836 | |
842 | 837 | static ADDRESS_MAP_START( bangball_map, AS_PROGRAM, 16, metro_state ) |
843 | 838 | AM_RANGE(0x000000, 0x07ffff) AM_ROM // ROM |
844 | | AM_RANGE(0xb00000, 0xb00001) AM_DEVREAD8_LEGACY("ymf", ymf278b_r, 0x00ff) // Sound |
845 | | AM_RANGE(0xb00000, 0xb0000b) AM_DEVWRITE8_LEGACY("ymf", ymf278b_w, 0x00ff) // Sound |
| 839 | AM_RANGE(0xb00000, 0xb00001) AM_DEVREAD8("ymf", ymf278b_device, read, 0x00ff) // Sound |
| 840 | AM_RANGE(0xb00000, 0xb0000b) AM_DEVWRITE8("ymf", ymf278b_device, write, 0x00ff) // Sound |
846 | 841 | AM_RANGE(0xc00000, 0xc1ffff) AM_READ(balcube_dsw_r) // DSW x 3 |
847 | 842 | AM_RANGE(0xd00000, 0xd00001) AM_READ_PORT("IN0") // Inputs |
848 | 843 | AM_RANGE(0xd00002, 0xd00003) AM_READ_PORT("IN1") // |
r22809 | r22810 | |
900 | 895 | AM_RANGE(0x200006, 0x200007) AM_READ_PORT("IN2") // |
901 | 896 | AM_RANGE(0x200002, 0x200009) AM_WRITE(metro_coin_lockout_4words_w) // Coin Lockout |
902 | 897 | AM_RANGE(0x300000, 0x31ffff) AM_READ(balcube_dsw_r) // read but ignored? |
903 | | AM_RANGE(0x400000, 0x400001) AM_DEVREAD8_LEGACY("ymf", ymf278b_r, 0x00ff) // Sound |
904 | | AM_RANGE(0x400000, 0x40000b) AM_DEVWRITE8_LEGACY("ymf", ymf278b_w, 0x00ff) // |
| 898 | AM_RANGE(0x400000, 0x400001) AM_DEVREAD8("ymf", ymf278b_device, read, 0x00ff) // Sound |
| 899 | AM_RANGE(0x400000, 0x40000b) AM_DEVWRITE8("ymf", ymf278b_device, write, 0x00ff) // |
905 | 900 | AM_RANGE(0xf00000, 0xf0ffff) AM_RAM AM_MIRROR(0x0f0000) // RAM (mirrored) |
906 | 901 | ADDRESS_MAP_END |
907 | 902 | |
r22809 | r22810 | |
935 | 930 | AM_RANGE(0x200006, 0x200007) AM_READNOP // |
936 | 931 | AM_RANGE(0x200002, 0x200009) AM_WRITE(metro_coin_lockout_4words_w) // Coin Lockout |
937 | 932 | AM_RANGE(0x300000, 0x31ffff) AM_READ(balcube_dsw_r) // 3 x DSW |
938 | | AM_RANGE(0x400000, 0x400001) AM_DEVREAD8_LEGACY("ymf", ymf278b_r, 0x00ff) // Sound |
939 | | AM_RANGE(0x400000, 0x40000b) AM_DEVWRITE8_LEGACY("ymf", ymf278b_w, 0x00ff) // |
| 933 | AM_RANGE(0x400000, 0x400001) AM_DEVREAD8("ymf", ymf278b_device, read, 0x00ff) // Sound |
| 934 | AM_RANGE(0x400000, 0x40000b) AM_DEVWRITE8("ymf", ymf278b_device, write, 0x00ff) // |
940 | 935 | AM_RANGE(0xf00000, 0xf0ffff) AM_RAM AM_MIRROR(0x0f0000) // RAM (mirrored) |
941 | 936 | ADDRESS_MAP_END |
942 | 937 | |
r22809 | r22810 | |
3593 | 3588 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
3594 | 3589 | |
3595 | 3590 | MCFG_SOUND_ADD("ymf", YMF278B, YMF278B_STD_CLOCK) |
3596 | | MCFG_SOUND_CONFIG(ymf278b_config) |
| 3591 | MCFG_YMF278B_IRQ_HANDLER(WRITELINE(metro_state, ymf278b_interrupt)) |
3597 | 3592 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
3598 | 3593 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
3599 | 3594 | MACHINE_CONFIG_END |
r22809 | r22810 | |
3626 | 3621 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
3627 | 3622 | |
3628 | 3623 | MCFG_SOUND_ADD("ymf", YMF278B, YMF278B_STD_CLOCK) |
3629 | | MCFG_SOUND_CONFIG(ymf278b_config) |
| 3624 | MCFG_YMF278B_IRQ_HANDLER(WRITELINE(metro_state, ymf278b_interrupt)) |
3630 | 3625 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
3631 | 3626 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
3632 | 3627 | MACHINE_CONFIG_END |
r22809 | r22810 | |
3659 | 3654 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
3660 | 3655 | |
3661 | 3656 | MCFG_SOUND_ADD("ymf", YMF278B, YMF278B_STD_CLOCK) |
3662 | | MCFG_SOUND_CONFIG(ymf278b_config) |
| 3657 | MCFG_YMF278B_IRQ_HANDLER(WRITELINE(metro_state, ymf278b_interrupt)) |
3663 | 3658 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
3664 | 3659 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
3665 | 3660 | MACHINE_CONFIG_END |
r22809 | r22810 | |
3692 | 3687 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
3693 | 3688 | |
3694 | 3689 | MCFG_SOUND_ADD("ymf", YMF278B, YMF278B_STD_CLOCK) |
3695 | | MCFG_SOUND_CONFIG(ymf278b_config) |
| 3690 | MCFG_YMF278B_IRQ_HANDLER(WRITELINE(metro_state, ymf278b_interrupt)) |
3696 | 3691 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
3697 | 3692 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
3698 | 3693 | MACHINE_CONFIG_END |
r22809 | r22810 | |
3725 | 3720 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
3726 | 3721 | |
3727 | 3722 | MCFG_SOUND_ADD("ymf", YMF278B, YMF278B_STD_CLOCK) |
3728 | | MCFG_SOUND_CONFIG(ymf278b_config) |
| 3723 | MCFG_YMF278B_IRQ_HANDLER(WRITELINE(metro_state, ymf278b_interrupt)) |
3729 | 3724 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
3730 | 3725 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
3731 | 3726 | MACHINE_CONFIG_END |
trunk/src/emu/sound/ymf278b.c
r22809 | r22810 | |
71 | 71 | #define VERBOSE 0 |
72 | 72 | #define LOG(x) do { if (VERBOSE) logerror x; } while (0) |
73 | 73 | |
74 | | struct YMF278BChip; |
75 | | |
76 | | struct YMF278BSlot |
| 74 | void ymf278b_device::write_memory(UINT32 offset, UINT8 data) |
77 | 75 | { |
78 | | INT16 wave; /* wavetable number */ |
79 | | INT16 F_NUMBER; /* frequency */ |
80 | | INT8 octave; /* octave */ |
81 | | INT8 preverb; /* pseudo-reverb */ |
82 | | INT8 DAMP; /* damping */ |
83 | | INT8 CH; /* output channel */ |
84 | | INT8 LD; /* level direct */ |
85 | | INT8 TL; /* total level */ |
86 | | INT8 pan; /* panpot */ |
87 | | INT8 LFO; /* LFO */ |
88 | | INT8 VIB; /* vibrato */ |
89 | | INT8 AM; /* tremolo */ |
90 | | |
91 | | INT8 AR; /* attack rate */ |
92 | | INT8 D1R; /* decay 1 rate */ |
93 | | INT8 DL; /* decay level */ |
94 | | INT8 D2R; /* decay 2 rate */ |
95 | | INT8 RC; /* rate correction */ |
96 | | INT8 RR; /* release rate */ |
97 | | |
98 | | UINT32 step; /* fixed-point frequency step */ |
99 | | UINT64 stepptr; /* fixed-point pointer into the sample */ |
100 | | |
101 | | INT8 active; /* channel is playing */ |
102 | | INT8 KEY_ON; /* slot keyed on */ |
103 | | INT8 bits; /* width of the samples */ |
104 | | UINT32 startaddr; |
105 | | UINT32 loopaddr; |
106 | | UINT32 endaddr; |
107 | | |
108 | | int env_step; |
109 | | UINT32 env_vol; |
110 | | UINT32 env_vol_step; |
111 | | UINT32 env_vol_lim; |
112 | | INT8 env_preverb; |
113 | | |
114 | | int num; /* slot number (for debug only) */ |
115 | | YMF278BChip *chip; /* pointer back to parent chip */ |
116 | | }; |
117 | | |
118 | | struct YMF278BChip |
119 | | { |
120 | | UINT8 pcmregs[256]; |
121 | | YMF278BSlot slots[24]; |
122 | | INT8 wavetblhdr; |
123 | | INT8 memmode; |
124 | | INT32 memadr; |
125 | | |
126 | | UINT8 status_busy, status_ld; |
127 | | emu_timer *timer_busy; |
128 | | emu_timer *timer_ld; |
129 | | UINT8 exp; |
130 | | |
131 | | INT32 fm_l, fm_r; |
132 | | INT32 pcm_l, pcm_r; |
133 | | |
134 | | attotime timer_base; |
135 | | UINT8 timer_a_count, timer_b_count; |
136 | | UINT8 enable, current_irq; |
137 | | emu_timer *timer_a, *timer_b; |
138 | | int irq_line; |
139 | | |
140 | | UINT8 port_C, port_AB, lastport; |
141 | | devcb_resolved_write_line irq_callback; |
142 | | device_t *device; |
143 | | |
144 | | const UINT8 *rom; |
145 | | UINT32 romsize; |
146 | | int clock; |
147 | | |
148 | | // precomputed tables |
149 | | UINT32 lut_ar[64]; // attack rate |
150 | | UINT32 lut_dr[64]; // decay rate |
151 | | INT32 volume[256*4]; // precalculated attenuation values with some margin for envelope and pan levels |
152 | | int pan_left[16],pan_right[16]; // pan volume offsets |
153 | | INT32 mix_level[8]; |
154 | | |
155 | | sound_stream * stream; |
156 | | }; |
157 | | |
158 | | INLINE YMF278BChip *get_safe_token(device_t *device) |
159 | | { |
160 | | assert(device != NULL); |
161 | | assert(device->type() == YMF278B); |
162 | | return (YMF278BChip *)downcast<ymf278b_device *>(device)->token(); |
163 | | } |
164 | | |
165 | | static void ymf278b_write_memory(YMF278BChip *chip, UINT32 offset, UINT8 data) |
166 | | { |
167 | 76 | logerror("YMF278B: Memory write %02x to %x\n", data, offset); |
168 | 77 | } |
169 | 78 | |
170 | | INLINE UINT8 ymf278b_read_memory(YMF278BChip *chip, UINT32 offset) |
| 79 | UINT8 ymf278b_device::read_memory(UINT32 offset) |
171 | 80 | { |
172 | | if (offset >= chip->romsize) |
| 81 | if (offset >= m_romsize) |
173 | 82 | { |
174 | 83 | // logerror("YMF278B: Memory read overflow %x\n", offset); |
175 | 84 | return 0xff; |
176 | 85 | } |
177 | | return chip->rom[offset]; |
| 86 | return m_rom[offset]; |
178 | 87 | } |
179 | 88 | |
180 | 89 | |
181 | 90 | /**************************************************************************/ |
182 | 91 | |
183 | | static int ymf278b_compute_rate(YMF278BSlot *slot, int val) |
| 92 | int ymf278b_device::compute_rate(YMF278BSlot *slot, int val) |
184 | 93 | { |
185 | 94 | int res, oct; |
186 | 95 | |
r22809 | r22810 | |
206 | 115 | return res; |
207 | 116 | } |
208 | 117 | |
209 | | static UINT32 ymf278_compute_decay_env_vol_step(YMF278BSlot *slot, int val) |
| 118 | UINT32 ymf278b_device::compute_decay_env_vol_step(YMF278BSlot *slot, int val) |
210 | 119 | { |
211 | 120 | int rate; |
212 | 121 | UINT32 res; |
r22809 | r22810 | |
221 | 130 | rate = 5; |
222 | 131 | } |
223 | 132 | else |
224 | | rate = ymf278b_compute_rate(slot, val); |
| 133 | rate = compute_rate(slot, val); |
225 | 134 | |
226 | 135 | if (rate < 4) |
227 | 136 | res = 0; |
228 | 137 | else |
229 | | res = (256U<<23) / slot->chip->lut_dr[rate]; |
| 138 | res = (256U<<23) / m_lut_dr[rate]; |
230 | 139 | |
231 | 140 | return res; |
232 | 141 | } |
233 | 142 | |
234 | | static void ymf278b_compute_freq_step(YMF278BSlot *slot) |
| 143 | void ymf278b_device::compute_freq_step(YMF278BSlot *slot) |
235 | 144 | { |
236 | 145 | UINT32 step; |
237 | 146 | int oct; |
r22809 | r22810 | |
244 | 153 | slot->step = step >> 3; |
245 | 154 | } |
246 | 155 | |
247 | | static void ymf278b_compute_envelope(YMF278BSlot *slot) |
| 156 | void ymf278b_device::compute_envelope(YMF278BSlot *slot) |
248 | 157 | { |
249 | 158 | switch (slot->env_step) |
250 | 159 | { |
r22809 | r22810 | |
252 | 161 | case 0: |
253 | 162 | { |
254 | 163 | // Attack |
255 | | int rate = ymf278b_compute_rate(slot, slot->AR); |
| 164 | int rate = compute_rate(slot, slot->AR); |
256 | 165 | slot->env_vol = 256U<<23; |
257 | 166 | slot->env_vol_lim = (256U<<23) - 1; |
258 | 167 | |
r22809 | r22810 | |
262 | 171 | LOG(("YMF278B: Attack skipped - ")); |
263 | 172 | slot->env_vol = 0; |
264 | 173 | slot->env_step++; |
265 | | ymf278b_compute_envelope(slot); |
| 174 | compute_envelope(slot); |
266 | 175 | } |
267 | 176 | else if (rate<4) |
268 | 177 | { |
r22809 | r22810 | |
271 | 180 | else |
272 | 181 | { |
273 | 182 | // NOTE: attack rate is linear here, but datasheet shows a smooth curve |
274 | | LOG(("YMF278B: Attack, val = %d, rate = %d, delay = %g\n", slot->AR, rate, slot->chip->lut_ar[rate]*1000.0)); |
275 | | slot->env_vol_step = ~((256U<<23) / slot->chip->lut_ar[rate]); |
| 183 | LOG(("YMF278B: Attack, val = %d, rate = %d, delay = %g\n", slot->AR, rate, m_lut_ar[rate]*1000.0)); |
| 184 | slot->env_vol_step = ~((256U<<23) / m_lut_ar[rate]); |
276 | 185 | } |
277 | 186 | |
278 | 187 | break; |
r22809 | r22810 | |
282 | 191 | case 1: |
283 | 192 | if(slot->DL) |
284 | 193 | { |
285 | | LOG(("YMF278B: Decay step 1, dl=%d, val = %d rate = %d, delay = %g, PRVB = %d, DAMP = %d\n", slot->DL, slot->D1R, ymf278b_compute_rate(slot, slot->D1R), slot->chip->lut_dr[ymf278b_compute_rate(slot, slot->D1R)]*1000.0, slot->preverb, slot->DAMP)); |
286 | | slot->env_vol_step = ymf278_compute_decay_env_vol_step(slot, slot->D1R); |
| 194 | LOG(("YMF278B: Decay step 1, dl=%d, val = %d rate = %d, delay = %g, PRVB = %d, DAMP = %d\n", slot->DL, slot->D1R, compute_rate(slot, slot->D1R), m_lut_dr[compute_rate(slot, slot->D1R)]*1000.0, slot->preverb, slot->DAMP)); |
| 195 | slot->env_vol_step = compute_decay_env_vol_step(slot, slot->D1R); |
287 | 196 | slot->env_vol_lim = (slot->DL*8)<<23; |
288 | 197 | } |
289 | 198 | else |
290 | 199 | { |
291 | 200 | LOG(("YMF278B: Decay 1 skipped - ")); |
292 | 201 | slot->env_step++; |
293 | | ymf278b_compute_envelope(slot); |
| 202 | compute_envelope(slot); |
294 | 203 | } |
295 | 204 | |
296 | 205 | break; |
297 | 206 | |
298 | 207 | // Decay 2 |
299 | 208 | case 2: |
300 | | LOG(("YMF278B: Decay step 2, val = %d, rate = %d, delay = %g, , PRVB = %d, DAMP = %d, current vol = %d\n", slot->D2R, ymf278b_compute_rate(slot, slot->D2R), slot->chip->lut_dr[ymf278b_compute_rate(slot, slot->D2R)]*1000.0, slot->preverb, slot->DAMP, slot->env_vol >> 23)); |
301 | | slot->env_vol_step = ymf278_compute_decay_env_vol_step(slot, slot->D2R); |
| 209 | LOG(("YMF278B: Decay step 2, val = %d, rate = %d, delay = %g, , PRVB = %d, DAMP = %d, current vol = %d\n", slot->D2R, compute_rate(slot, slot->D2R), m_lut_dr[compute_rate(slot, slot->D2R)]*1000.0, slot->preverb, slot->DAMP, slot->env_vol >> 23)); |
| 210 | slot->env_vol_step = compute_decay_env_vol_step(slot, slot->D2R); |
302 | 211 | slot->env_vol_lim = 256U<<23; |
303 | 212 | break; |
304 | 213 | |
r22809 | r22810 | |
313 | 222 | |
314 | 223 | // Release |
315 | 224 | case 4: |
316 | | LOG(("YMF278B: Release, val = %d, rate = %d, delay = %g, PRVB = %d, DAMP = %d\n", slot->RR, ymf278b_compute_rate(slot, slot->RR), slot->chip->lut_dr[ymf278b_compute_rate(slot, slot->RR)]*1000.0, slot->preverb, slot->DAMP)); |
317 | | slot->env_vol_step = ymf278_compute_decay_env_vol_step(slot, slot->RR); |
| 225 | LOG(("YMF278B: Release, val = %d, rate = %d, delay = %g, PRVB = %d, DAMP = %d\n", slot->RR, compute_rate(slot, slot->RR), m_lut_dr[compute_rate(slot, slot->RR)]*1000.0, slot->preverb, slot->DAMP)); |
| 226 | slot->env_vol_step = compute_decay_env_vol_step(slot, slot->RR); |
318 | 227 | slot->env_vol_lim = 256U<<23; |
319 | 228 | break; |
320 | 229 | |
r22809 | r22810 | |
331 | 240 | } |
332 | 241 | } |
333 | 242 | |
334 | | static STREAM_UPDATE( ymf278b_pcm_update ) |
| 243 | //------------------------------------------------- |
| 244 | // sound_stream_update - handle a stream update |
| 245 | //------------------------------------------------- |
| 246 | |
| 247 | void ymf278b_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
335 | 248 | { |
336 | | YMF278BChip *chip = (YMF278BChip *)param; |
337 | 249 | int i, j; |
338 | 250 | YMF278BSlot *slot = NULL; |
339 | 251 | INT16 sample = 0; |
r22809 | r22810 | |
345 | 257 | |
346 | 258 | for (i = 0; i < 24; i++) |
347 | 259 | { |
348 | | slot = &chip->slots[i]; |
| 260 | slot = &m_slots[i]; |
349 | 261 | |
350 | 262 | if (slot->active) |
351 | 263 | { |
r22809 | r22810 | |
364 | 276 | { |
365 | 277 | // 8 bit |
366 | 278 | case 0: |
367 | | sample = ymf278b_read_memory(chip, slot->startaddr + (slot->stepptr>>16))<<8; |
| 279 | sample = read_memory(slot->startaddr + (slot->stepptr>>16))<<8; |
368 | 280 | break; |
369 | 281 | |
370 | 282 | // 12 bit |
371 | 283 | case 1: |
372 | 284 | if (slot->stepptr & 0x10000) |
373 | | sample = ymf278b_read_memory(chip, slot->startaddr + (slot->stepptr>>17)*3+2)<<8 | |
374 | | (ymf278b_read_memory(chip, slot->startaddr + (slot->stepptr>>17)*3+1) << 4 & 0xf0); |
| 285 | sample = read_memory(slot->startaddr + (slot->stepptr>>17)*3+2)<<8 | |
| 286 | (read_memory(slot->startaddr + (slot->stepptr>>17)*3+1) << 4 & 0xf0); |
375 | 287 | else |
376 | | sample = ymf278b_read_memory(chip, slot->startaddr + (slot->stepptr>>17)*3)<<8 | |
377 | | (ymf278b_read_memory(chip, slot->startaddr + (slot->stepptr>>17)*3+1) & 0xf0); |
| 288 | sample = read_memory(slot->startaddr + (slot->stepptr>>17)*3)<<8 | |
| 289 | (read_memory(slot->startaddr + (slot->stepptr>>17)*3+1) & 0xf0); |
378 | 290 | break; |
379 | 291 | |
380 | 292 | // 16 bit |
381 | 293 | case 2: |
382 | | sample = ymf278b_read_memory(chip, slot->startaddr + ((slot->stepptr>>16)*2))<<8 | |
383 | | ymf278b_read_memory(chip, slot->startaddr + ((slot->stepptr>>16)*2)+1); |
| 294 | sample = read_memory(slot->startaddr + ((slot->stepptr>>16)*2))<<8 | |
| 295 | read_memory(slot->startaddr + ((slot->stepptr>>16)*2)+1); |
384 | 296 | break; |
385 | 297 | |
386 | 298 | // ?? bit, effect is unknown, datasheet says it's prohibited |
r22809 | r22810 | |
389 | 301 | break; |
390 | 302 | } |
391 | 303 | |
392 | | *mixp++ += (sample * chip->volume[slot->TL+chip->pan_left [slot->pan]+(slot->env_vol>>23)])>>17; |
393 | | *mixp++ += (sample * chip->volume[slot->TL+chip->pan_right[slot->pan]+(slot->env_vol>>23)])>>17; |
| 304 | *mixp++ += (sample * m_volume[slot->TL+m_pan_left [slot->pan]+(slot->env_vol>>23)])>>17; |
| 305 | *mixp++ += (sample * m_volume[slot->TL+m_pan_right[slot->pan]+(slot->env_vol>>23)])>>17; |
394 | 306 | |
395 | 307 | // update frequency |
396 | 308 | slot->stepptr += slot->step; |
r22809 | r22810 | |
400 | 312 | if (((INT32)(slot->env_vol - slot->env_vol_lim)) >= 0) |
401 | 313 | { |
402 | 314 | slot->env_step++; |
403 | | ymf278b_compute_envelope(slot); |
| 315 | compute_envelope(slot); |
404 | 316 | } |
405 | 317 | else if (slot->preverb && !slot->env_preverb && slot->env_step && slot->env_vol > ((6*8)<<23)) |
406 | | ymf278b_compute_envelope(slot); |
| 318 | compute_envelope(slot); |
407 | 319 | } |
408 | 320 | } |
409 | 321 | } |
410 | 322 | |
411 | 323 | mixp = mix; |
412 | | vl = chip->mix_level[chip->pcm_l]; |
413 | | vr = chip->mix_level[chip->pcm_r]; |
| 324 | vl = m_mix_level[m_pcm_l]; |
| 325 | vr = m_mix_level[m_pcm_r]; |
414 | 326 | for (i = 0; i < samples; i++) |
415 | 327 | { |
416 | 328 | outputs[0][i] = (*mixp++ * vl) >> 16; |
r22809 | r22810 | |
418 | 330 | } |
419 | 331 | } |
420 | 332 | |
421 | | static void ymf278b_irq_check(running_machine &machine, YMF278BChip *chip) |
| 333 | void ymf278b_device::irq_check() |
422 | 334 | { |
423 | | int prev_line = chip->irq_line; |
424 | | chip->irq_line = chip->current_irq ? ASSERT_LINE : CLEAR_LINE; |
425 | | if(chip->irq_line != prev_line && !chip->irq_callback.isnull()) |
426 | | chip->irq_callback(chip->irq_line); |
| 335 | int prev_line = m_irq_line; |
| 336 | m_irq_line = m_current_irq ? ASSERT_LINE : CLEAR_LINE; |
| 337 | if(m_irq_line != prev_line && !m_irq_handler.isnull()) |
| 338 | m_irq_handler(m_irq_line); |
427 | 339 | } |
428 | 340 | |
429 | | static TIMER_CALLBACK( ymf278b_timer_a_tick ) |
| 341 | enum |
430 | 342 | { |
431 | | YMF278BChip *chip = (YMF278BChip *)ptr; |
432 | | if(!(chip->enable & 0x40)) |
433 | | { |
434 | | chip->current_irq |= 0x40; |
435 | | ymf278b_irq_check(machine, chip); |
436 | | } |
437 | | } |
| 343 | TIMER_A = 0, |
| 344 | TIMER_B, |
| 345 | TIMER_BUSY_CLEAR, |
| 346 | TIMER_LD_CLEAR |
| 347 | }; |
438 | 348 | |
439 | | static TIMER_CALLBACK( ymf278b_timer_b_tick ) |
| 349 | void ymf278b_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
440 | 350 | { |
441 | | YMF278BChip *chip = (YMF278BChip *)ptr; |
442 | | if(!(chip->enable & 0x20)) |
| 351 | switch(id) |
443 | 352 | { |
444 | | chip->current_irq |= 0x20; |
445 | | ymf278b_irq_check(machine, chip); |
| 353 | case TIMER_A: |
| 354 | if(!(m_enable & 0x40)) |
| 355 | { |
| 356 | m_current_irq |= 0x40; |
| 357 | irq_check(); |
| 358 | } |
| 359 | break; |
| 360 | |
| 361 | case TIMER_B: |
| 362 | if(!(m_enable & 0x20)) |
| 363 | { |
| 364 | m_current_irq |= 0x20; |
| 365 | irq_check(); |
| 366 | } |
| 367 | break; |
| 368 | |
| 369 | case TIMER_BUSY_CLEAR: |
| 370 | m_status_busy = 0; |
| 371 | break; |
| 372 | |
| 373 | case TIMER_LD_CLEAR: |
| 374 | m_status_ld = 0; |
| 375 | break; |
446 | 376 | } |
447 | 377 | } |
448 | 378 | |
449 | 379 | |
450 | 380 | /**************************************************************************/ |
451 | 381 | |
452 | | static void ymf278b_A_w(running_machine &machine, YMF278BChip *chip, UINT8 reg, UINT8 data) |
| 382 | void ymf278b_device::A_w(UINT8 reg, UINT8 data) |
453 | 383 | { |
454 | 384 | // FM register array 0 (compatible with YMF262) |
455 | 385 | switch(reg) |
r22809 | r22810 | |
461 | 391 | |
462 | 392 | // timer a count |
463 | 393 | case 0x02: |
464 | | if (data != chip->timer_a_count) |
| 394 | if (data != m_timer_a_count) |
465 | 395 | { |
466 | | chip->timer_a_count = data; |
| 396 | m_timer_a_count = data; |
467 | 397 | |
468 | 398 | // change period, ~80.8us * t |
469 | | if (chip->enable & 1) |
470 | | chip->timer_a->adjust(chip->timer_a->remaining(), 0, chip->timer_base * (256-data) * 4); |
| 399 | if (m_enable & 1) |
| 400 | m_timer_a->adjust(m_timer_a->remaining(), 0, m_timer_base * (256-data) * 4); |
471 | 401 | } |
472 | 402 | break; |
473 | 403 | |
474 | 404 | // timer b count |
475 | 405 | case 0x03: |
476 | | if (data != chip->timer_b_count) |
| 406 | if (data != m_timer_b_count) |
477 | 407 | { |
478 | | chip->timer_b_count = data; |
| 408 | m_timer_b_count = data; |
479 | 409 | |
480 | 410 | // change period, ~323.1us * t |
481 | | if (chip->enable & 2) |
482 | | chip->timer_b->adjust(chip->timer_b->remaining(), 0, chip->timer_base * (256-data) * 16); |
| 411 | if (m_enable & 2) |
| 412 | m_timer_b->adjust(m_timer_b->remaining(), 0, m_timer_base * (256-data) * 16); |
483 | 413 | } |
484 | 414 | break; |
485 | 415 | |
486 | 416 | // timer control |
487 | 417 | case 0x04: |
488 | 418 | if(data & 0x80) |
489 | | chip->current_irq = 0; |
| 419 | m_current_irq = 0; |
490 | 420 | else |
491 | 421 | { |
492 | 422 | // reset timers |
493 | | if((chip->enable ^ data) & 1) |
| 423 | if((m_enable ^ data) & 1) |
494 | 424 | { |
495 | | attotime period = (data & 1) ? chip->timer_base * (256-chip->timer_a_count) * 4 : attotime::never; |
496 | | chip->timer_a->adjust(period, 0, period); |
| 425 | attotime period = (data & 1) ? m_timer_base * (256-m_timer_a_count) * 4 : attotime::never; |
| 426 | m_timer_a->adjust(period, 0, period); |
497 | 427 | } |
498 | | if((chip->enable ^ data) & 2) |
| 428 | if((m_enable ^ data) & 2) |
499 | 429 | { |
500 | | attotime period = (data & 2) ? chip->timer_base * (256-chip->timer_b_count) * 16 : attotime::never; |
501 | | chip->timer_b->adjust(period, 0, period); |
| 430 | attotime period = (data & 2) ? m_timer_base * (256-m_timer_b_count) * 16 : attotime::never; |
| 431 | m_timer_b->adjust(period, 0, period); |
502 | 432 | } |
503 | 433 | |
504 | | chip->enable = data; |
505 | | chip->current_irq &= ~data; |
| 434 | m_enable = data; |
| 435 | m_current_irq &= ~data; |
506 | 436 | } |
507 | | ymf278b_irq_check(machine, chip); |
| 437 | irq_check(); |
508 | 438 | break; |
509 | 439 | |
510 | 440 | default: |
r22809 | r22810 | |
513 | 443 | } |
514 | 444 | } |
515 | 445 | |
516 | | static void ymf278b_B_w(YMF278BChip *chip, UINT8 reg, UINT8 data) |
| 446 | void ymf278b_device::B_w(UINT8 reg, UINT8 data) |
517 | 447 | { |
518 | 448 | // FM register array 1 (compatible with YMF262) |
519 | 449 | switch(reg) |
r22809 | r22810 | |
525 | 455 | |
526 | 456 | // expansion register (NEW2/NEW) |
527 | 457 | case 0x05: |
528 | | chip->exp = data; |
| 458 | m_exp = data; |
529 | 459 | break; |
530 | 460 | |
531 | 461 | default: |
r22809 | r22810 | |
534 | 464 | } |
535 | 465 | } |
536 | 466 | |
537 | | static TIMER_CALLBACK( ymf278b_timer_ld_clear ) |
| 467 | void ymf278b_device::retrigger_note(YMF278BSlot *slot) |
538 | 468 | { |
539 | | YMF278BChip *chip = (YMF278BChip *)ptr; |
540 | | chip->status_ld = 0; |
541 | | } |
542 | | |
543 | | static void ymf278b_retrigger_note(YMF278BSlot *slot) |
544 | | { |
545 | 469 | // activate channel |
546 | 470 | if (slot->octave != 8) |
547 | 471 | slot->active = 1; |
r22809 | r22810 | |
551 | 475 | slot->env_step = 0; |
552 | 476 | slot->env_preverb = 0; |
553 | 477 | |
554 | | ymf278b_compute_freq_step(slot); |
555 | | ymf278b_compute_envelope(slot); |
| 478 | compute_freq_step(slot); |
| 479 | compute_envelope(slot); |
556 | 480 | } |
557 | 481 | |
558 | | static void ymf278b_C_w(YMF278BChip *chip, UINT8 reg, UINT8 data, int init) |
| 482 | void ymf278b_device::C_w(UINT8 reg, UINT8 data, int init) |
559 | 483 | { |
560 | 484 | if (!init) |
561 | 485 | { |
562 | 486 | // PCM regs are only accessible if NEW2 is set |
563 | | if (~chip->exp & 2) |
| 487 | if (~m_exp & 2) |
564 | 488 | return; |
565 | 489 | |
566 | | chip->stream->update(); |
| 490 | m_stream->update(); |
567 | 491 | } |
568 | 492 | |
569 | 493 | // Handle slot registers specifically |
r22809 | r22810 | |
572 | 496 | YMF278BSlot *slot = NULL; |
573 | 497 | int snum; |
574 | 498 | snum = (reg-8) % 24; |
575 | | slot = &chip->slots[snum]; |
| 499 | slot = &m_slots[snum]; |
576 | 500 | switch((reg-8) / 24) |
577 | 501 | { |
578 | 502 | case 0: |
r22809 | r22810 | |
586 | 510 | slot->wave |= data; |
587 | 511 | |
588 | 512 | // load wavetable header |
589 | | if(slot->wave < 384 || !chip->wavetblhdr) |
| 513 | if(slot->wave < 384 || !m_wavetblhdr) |
590 | 514 | offset = slot->wave * 12; |
591 | 515 | else |
592 | | offset = chip->wavetblhdr*0x80000 + (slot->wave - 384) * 12; |
| 516 | offset = m_wavetblhdr*0x80000 + (slot->wave - 384) * 12; |
593 | 517 | for (i = 0; i < 12; i++) |
594 | | p[i] = ymf278b_read_memory(chip, offset+i); |
| 518 | p[i] = read_memory(offset+i); |
595 | 519 | |
596 | 520 | slot->bits = (p[0]&0xc0)>>6; |
597 | 521 | slot->startaddr = (p[2] | (p[1]<<8) | ((p[0]&0x3f)<<16)); |
r22809 | r22810 | |
602 | 526 | |
603 | 527 | // copy internal registers data |
604 | 528 | for (i = 7; i < 12; i++) |
605 | | ymf278b_C_w(chip, 8 + snum + (i-2) * 24, p[i], 1); |
| 529 | C_w(8 + snum + (i-2) * 24, p[i], 1); |
606 | 530 | |
607 | 531 | // status register LD bit is on for approx 300us |
608 | | chip->status_ld = 1; |
| 532 | m_status_ld = 1; |
609 | 533 | period = attotime::from_usec(300); |
610 | | if (chip->clock != YMF278B_STD_CLOCK) |
611 | | period = (period * chip->clock) / YMF278B_STD_CLOCK; |
612 | | chip->timer_ld->adjust(period); |
| 534 | if (m_clock != YMF278B_STD_CLOCK) |
| 535 | period = (period * m_clock) / YMF278B_STD_CLOCK; |
| 536 | m_timer_ld->adjust(period); |
613 | 537 | |
614 | 538 | // retrigger if key is on |
615 | 539 | if (slot->KEY_ON) |
616 | | ymf278b_retrigger_note(slot); |
| 540 | retrigger_note(slot); |
617 | 541 | else if (slot->active) |
618 | 542 | { |
619 | 543 | // deactivate channel |
620 | 544 | slot->env_step = 5; |
621 | | ymf278b_compute_envelope(slot); |
| 545 | compute_envelope(slot); |
622 | 546 | } |
623 | 547 | |
624 | 548 | break; |
r22809 | r22810 | |
629 | 553 | slot->wave |= ((data&0x1)<<8); |
630 | 554 | slot->F_NUMBER &= 0x380; |
631 | 555 | slot->F_NUMBER |= (data>>1); |
632 | | if (slot->active && (data ^ chip->pcmregs[reg]) & 0xfe) |
| 556 | if (slot->active && (data ^ m_pcmregs[reg]) & 0xfe) |
633 | 557 | { |
634 | | ymf278b_compute_freq_step(slot); |
635 | | ymf278b_compute_envelope(slot); |
| 558 | compute_freq_step(slot); |
| 559 | compute_envelope(slot); |
636 | 560 | } |
637 | 561 | break; |
638 | 562 | |
r22809 | r22810 | |
641 | 565 | slot->F_NUMBER |= ((data&0x07)<<7); |
642 | 566 | slot->preverb = (data&0x8)>>3; |
643 | 567 | slot->octave = (data&0xf0)>>4; |
644 | | if (data != chip->pcmregs[reg]) |
| 568 | if (data != m_pcmregs[reg]) |
645 | 569 | { |
646 | 570 | // channel goes off if octave is set to -8 (datasheet says it's prohibited) |
647 | | // (it is ok if this activates the channel while it was off: ymf278b_compute_envelope will reset it again if needed) |
| 571 | // (it is ok if this activates the channel while it was off: compute_envelope will reset it again if needed) |
648 | 572 | slot->active = (slot->octave != 8); |
649 | 573 | |
650 | 574 | if (slot->active) |
651 | 575 | { |
652 | 576 | slot->env_preverb = 0; |
653 | | ymf278b_compute_freq_step(slot); |
654 | | ymf278b_compute_envelope(slot); |
| 577 | compute_freq_step(slot); |
| 578 | compute_envelope(slot); |
655 | 579 | } |
656 | 580 | } |
657 | 581 | break; |
r22809 | r22810 | |
675 | 599 | // don't retrigger if key was already on |
676 | 600 | if (slot->KEY_ON) |
677 | 601 | { |
678 | | if ((data ^ chip->pcmregs[reg]) & 0x40) |
679 | | ymf278b_compute_envelope(slot); |
| 602 | if ((data ^ m_pcmregs[reg]) & 0x40) |
| 603 | compute_envelope(slot); |
680 | 604 | |
681 | 605 | break; |
682 | 606 | } |
683 | 607 | |
684 | | ymf278b_retrigger_note(slot); |
| 608 | retrigger_note(slot); |
685 | 609 | } |
686 | 610 | else if (slot->active) |
687 | 611 | { |
688 | 612 | // release |
689 | 613 | slot->env_step = 4; |
690 | | ymf278b_compute_envelope(slot); |
| 614 | compute_envelope(slot); |
691 | 615 | } |
692 | 616 | slot->KEY_ON = (data&0x80)>>7; |
693 | 617 | break; |
r22809 | r22810 | |
701 | 625 | case 6: |
702 | 626 | slot->AR = data>>4; |
703 | 627 | slot->D1R = data&0xf; |
704 | | if (slot->active && data != chip->pcmregs[reg]) |
705 | | ymf278b_compute_envelope(slot); |
| 628 | if (slot->active && data != m_pcmregs[reg]) |
| 629 | compute_envelope(slot); |
706 | 630 | break; |
707 | 631 | |
708 | 632 | case 7: |
709 | 633 | slot->DL = data>>4; |
710 | 634 | slot->D2R = data&0xf; |
711 | | if (slot->active && data != chip->pcmregs[reg]) |
712 | | ymf278b_compute_envelope(slot); |
| 635 | if (slot->active && data != m_pcmregs[reg]) |
| 636 | compute_envelope(slot); |
713 | 637 | break; |
714 | 638 | |
715 | 639 | case 8: |
716 | 640 | slot->RC = data>>4; |
717 | 641 | slot->RR = data&0xf; |
718 | | if (slot->active && data != chip->pcmregs[reg]) |
719 | | ymf278b_compute_envelope(slot); |
| 642 | if (slot->active && data != m_pcmregs[reg]) |
| 643 | compute_envelope(slot); |
720 | 644 | break; |
721 | 645 | |
722 | 646 | case 9: |
r22809 | r22810 | |
736 | 660 | break; |
737 | 661 | |
738 | 662 | case 0x02: |
739 | | chip->wavetblhdr = (data>>2)&0x7; |
740 | | chip->memmode = data&3; |
| 663 | m_wavetblhdr = (data>>2)&0x7; |
| 664 | m_memmode = data&3; |
741 | 665 | break; |
742 | 666 | |
743 | 667 | case 0x03: |
r22809 | r22810 | |
745 | 669 | break; |
746 | 670 | case 0x05: |
747 | 671 | // set memory address |
748 | | chip->memadr = (chip->pcmregs[3] & 0x3f) << 16 | chip->pcmregs[4] << 8 | data; |
| 672 | m_memadr = (m_pcmregs[3] & 0x3f) << 16 | m_pcmregs[4] << 8 | data; |
749 | 673 | break; |
750 | 674 | |
751 | 675 | case 0x06: |
752 | 676 | // memory data (ignored, we don't support RAM) |
753 | | ymf278b_write_memory(chip, chip->memadr, data); |
754 | | chip->memadr = (chip->memadr + 1) & 0x3fffff; |
| 677 | write_memory(m_memadr, data); |
| 678 | m_memadr = (m_memadr + 1) & 0x3fffff; |
755 | 679 | break; |
756 | 680 | |
757 | 681 | case 0x07: |
758 | 682 | break; // unused |
759 | 683 | |
760 | 684 | case 0xf8: |
761 | | chip->fm_l = data & 0x7; |
762 | | chip->fm_r = (data>>3)&0x7; |
| 685 | m_fm_l = data & 0x7; |
| 686 | m_fm_r = (data>>3)&0x7; |
763 | 687 | break; |
764 | 688 | |
765 | 689 | case 0xf9: |
766 | | chip->pcm_l = data & 0x7; |
767 | | chip->pcm_r = (data>>3)&0x7; |
| 690 | m_pcm_l = data & 0x7; |
| 691 | m_pcm_r = (data>>3)&0x7; |
768 | 692 | break; |
769 | 693 | |
770 | 694 | default: |
r22809 | r22810 | |
773 | 697 | } |
774 | 698 | } |
775 | 699 | |
776 | | chip->pcmregs[reg] = data; |
| 700 | m_pcmregs[reg] = data; |
777 | 701 | } |
778 | 702 | |
779 | | static TIMER_CALLBACK( ymf278b_timer_busy_clear ) |
| 703 | void ymf278b_device::timer_busy_start(int is_pcm) |
780 | 704 | { |
781 | | YMF278BChip *chip = (YMF278BChip *)ptr; |
782 | | chip->status_busy = 0; |
783 | | } |
784 | | |
785 | | static void ymf278b_timer_busy_start(YMF278BChip *chip, int is_pcm) |
786 | | { |
787 | 705 | // status register BUSY bit is on for 56(FM) or 88(PCM) cycles |
788 | | chip->status_busy = 1; |
789 | | chip->timer_busy->adjust(attotime::from_hz(chip->clock / (is_pcm ? 88 : 56))); |
| 706 | m_status_busy = 1; |
| 707 | m_timer_busy->adjust(attotime::from_hz(m_clock / (is_pcm ? 88 : 56))); |
790 | 708 | } |
791 | 709 | |
792 | | WRITE8_DEVICE_HANDLER( ymf278b_w ) |
| 710 | WRITE8_MEMBER( ymf278b_device::write ) |
793 | 711 | { |
794 | | YMF278BChip *chip = get_safe_token(device); |
795 | | |
796 | 712 | switch (offset) |
797 | 713 | { |
798 | 714 | case 0: |
799 | 715 | case 2: |
800 | | ymf278b_timer_busy_start(chip, 0); |
801 | | chip->port_AB = data; |
802 | | chip->lastport = offset>>1 & 1; |
| 716 | timer_busy_start(0); |
| 717 | m_port_AB = data; |
| 718 | m_lastport = offset>>1 & 1; |
803 | 719 | break; |
804 | 720 | |
805 | 721 | case 1: |
806 | 722 | case 3: |
807 | | ymf278b_timer_busy_start(chip, 0); |
808 | | if (chip->lastport) ymf278b_B_w(chip, chip->port_AB, data); |
809 | | else ymf278b_A_w(device->machine(), chip, chip->port_AB, data); |
| 723 | timer_busy_start(0); |
| 724 | if (m_lastport) B_w(m_port_AB, data); |
| 725 | else A_w(m_port_AB, data); |
810 | 726 | break; |
811 | 727 | |
812 | 728 | case 4: |
813 | | ymf278b_timer_busy_start(chip, 1); |
814 | | chip->port_C = data; |
| 729 | timer_busy_start(1); |
| 730 | m_port_C = data; |
815 | 731 | break; |
816 | 732 | |
817 | 733 | case 5: |
818 | | ymf278b_timer_busy_start(chip, 1); |
819 | | ymf278b_C_w(chip, chip->port_C, data, 0); |
| 734 | timer_busy_start(1); |
| 735 | C_w(m_port_C, data, 0); |
820 | 736 | break; |
821 | 737 | |
822 | 738 | default: |
823 | | logerror("%s: unexpected write at offset %X to ymf278b = %02X\n", device->machine().describe_context(), offset, data); |
| 739 | logerror("%s: unexpected write at offset %X to ymf278b = %02X\n", machine().describe_context(), offset, data); |
824 | 740 | break; |
825 | 741 | } |
826 | 742 | } |
827 | 743 | |
828 | 744 | |
829 | | READ8_DEVICE_HANDLER( ymf278b_r ) |
| 745 | READ8_MEMBER( ymf278b_device::read ) |
830 | 746 | { |
831 | | YMF278BChip *chip = get_safe_token(device); |
832 | 747 | UINT8 ret = 0; |
833 | 748 | |
834 | 749 | switch (offset) |
r22809 | r22810 | |
838 | 753 | { |
839 | 754 | // bits 0 and 1 are only valid if NEW2 is set |
840 | 755 | UINT8 newbits = 0; |
841 | | if (chip->exp & 2) |
842 | | newbits = (chip->status_ld << 1) | chip->status_busy; |
| 756 | if (m_exp & 2) |
| 757 | newbits = (m_status_ld << 1) | m_status_busy; |
843 | 758 | |
844 | | ret = newbits | chip->current_irq | (chip->irq_line == ASSERT_LINE ? 0x80 : 0x00); |
| 759 | ret = newbits | m_current_irq | (m_irq_line == ASSERT_LINE ? 0x80 : 0x00); |
845 | 760 | break; |
846 | 761 | } |
847 | 762 | |
r22809 | r22810 | |
854 | 769 | // PCM regs |
855 | 770 | case 5: |
856 | 771 | // only accessible if NEW2 is set |
857 | | if (~chip->exp & 2) |
| 772 | if (~m_exp & 2) |
858 | 773 | break; |
859 | 774 | |
860 | | switch (chip->port_C) |
| 775 | switch (m_port_C) |
861 | 776 | { |
862 | 777 | // special cases |
863 | 778 | case 2: |
864 | | ret = (chip->pcmregs[chip->port_C] & 0x1f) | 0x20; // device ID in upper bits |
| 779 | ret = (m_pcmregs[m_port_C] & 0x1f) | 0x20; // device ID in upper bits |
865 | 780 | break; |
866 | 781 | case 6: |
867 | | ret = ymf278b_read_memory(chip, chip->memadr); |
868 | | chip->memadr = (chip->memadr + 1) & 0x3fffff; |
| 782 | ret = read_memory(m_memadr); |
| 783 | m_memadr = (m_memadr + 1) & 0x3fffff; |
869 | 784 | break; |
870 | 785 | |
871 | 786 | default: |
872 | | ret = chip->pcmregs[chip->port_C]; |
| 787 | ret = m_pcmregs[m_port_C]; |
873 | 788 | break; |
874 | 789 | } |
875 | 790 | break; |
876 | 791 | |
877 | 792 | default: |
878 | | logerror("%s: unexpected read at offset %X from ymf278b\n", device->machine().describe_context(), offset); |
| 793 | logerror("%s: unexpected read at offset %X from ymf278b\n", machine().describe_context(), offset); |
879 | 794 | break; |
880 | 795 | } |
881 | 796 | |
r22809 | r22810 | |
885 | 800 | |
886 | 801 | /**************************************************************************/ |
887 | 802 | |
888 | | static DEVICE_RESET( ymf278b ) |
| 803 | //------------------------------------------------- |
| 804 | // device_reset - device-specific reset |
| 805 | //------------------------------------------------- |
| 806 | |
| 807 | void ymf278b_device::device_reset() |
889 | 808 | { |
890 | | YMF278BChip *chip = get_safe_token(device); |
891 | 809 | int i; |
892 | 810 | |
893 | 811 | // clear registers |
894 | 812 | for (i = 0; i <= 4; i++) |
895 | | ymf278b_A_w(device->machine(), chip, i, 0); |
896 | | ymf278b_B_w(chip, 5, 0); |
| 813 | A_w(i, 0); |
| 814 | B_w(5, 0); |
897 | 815 | for (i = 0; i < 8; i++) |
898 | | ymf278b_C_w(chip, i, 0, 1); |
| 816 | C_w(i, 0, 1); |
899 | 817 | for (i = 0xff; i >= 8; i--) |
900 | | ymf278b_C_w(chip, i, 0, 1); |
901 | | ymf278b_C_w(chip, 0xf8, 0x1b, 1); |
| 818 | C_w(i, 0, 1); |
| 819 | C_w(0xf8, 0x1b, 1); |
902 | 820 | |
903 | | chip->port_AB = chip->port_C = 0; |
904 | | chip->lastport = 0; |
905 | | chip->memadr = 0; |
| 821 | m_port_AB = m_port_C = 0; |
| 822 | m_lastport = 0; |
| 823 | m_memadr = 0; |
906 | 824 | |
907 | 825 | // init/silence channels |
908 | 826 | for (i = 0; i < 24 ; i++) |
909 | 827 | { |
910 | | YMF278BSlot *slot = &chip->slots[i]; |
| 828 | YMF278BSlot *slot = &m_slots[i]; |
911 | 829 | |
912 | 830 | slot->LFO = 0; |
913 | 831 | slot->VIB = 0; |
r22809 | r22810 | |
924 | 842 | slot->endaddr = 0; |
925 | 843 | |
926 | 844 | slot->env_step = 5; |
927 | | ymf278b_compute_envelope(slot); |
| 845 | compute_envelope(slot); |
928 | 846 | } |
929 | 847 | |
930 | | chip->timer_a->reset(); |
931 | | chip->timer_b->reset(); |
932 | | chip->timer_busy->reset(); chip->status_busy = 0; |
933 | | chip->timer_ld->reset(); chip->status_ld = 0; |
| 848 | m_timer_a->reset(); |
| 849 | m_timer_b->reset(); |
| 850 | m_timer_busy->reset(); m_status_busy = 0; |
| 851 | m_timer_ld->reset(); m_status_ld = 0; |
934 | 852 | |
935 | | chip->irq_line = CLEAR_LINE; |
| 853 | m_irq_line = CLEAR_LINE; |
936 | 854 | } |
937 | 855 | |
938 | | static void ymf278b_init(device_t *device, YMF278BChip *chip, const devcb_write_line *cb) |
| 856 | void ymf278b_device::precompute_rate_tables() |
939 | 857 | { |
940 | 858 | int i; |
941 | 859 | |
942 | | chip->rom = *device->region(); |
943 | | chip->romsize = device->region()->bytes(); |
944 | | chip->clock = device->clock(); |
945 | | chip->irq_callback.resolve(*cb, *device); |
946 | | |
947 | | chip->timer_base = attotime::from_hz(chip->clock) * (19*36); |
948 | | chip->timer_a = device->machine().scheduler().timer_alloc(FUNC(ymf278b_timer_a_tick), chip); |
949 | | chip->timer_b = device->machine().scheduler().timer_alloc(FUNC(ymf278b_timer_b_tick), chip); |
950 | | chip->timer_busy = device->machine().scheduler().timer_alloc(FUNC(ymf278b_timer_busy_clear), chip); |
951 | | chip->timer_ld = device->machine().scheduler().timer_alloc(FUNC(ymf278b_timer_ld_clear), chip); |
952 | | |
953 | | for (i = 0; i < 24; i++) |
954 | | { |
955 | | chip->slots[i].num = i; |
956 | | chip->slots[i].chip = chip; |
957 | | } |
958 | | } |
959 | | |
960 | | static void precompute_rate_tables(YMF278BChip *chip) |
961 | | { |
962 | | int i; |
963 | | |
964 | 860 | // decay rate |
965 | 861 | for (i = 0; i < 64; i++) |
966 | 862 | { |
967 | 863 | if (i <= 3) |
968 | | chip->lut_dr[i] = 0; |
| 864 | m_lut_dr[i] = 0; |
969 | 865 | else if (i >= 60) |
970 | | chip->lut_dr[i] = 15 << 4; |
| 866 | m_lut_dr[i] = 15 << 4; |
971 | 867 | else |
972 | | chip->lut_dr[i] = (15 << (21 - i / 4)) / (4 + i % 4); |
| 868 | m_lut_dr[i] = (15 << (21 - i / 4)) / (4 + i % 4); |
973 | 869 | } |
974 | 870 | |
975 | 871 | // attack rate (manual shows curve instead of linear though, so this is not entirely accurate) |
976 | 872 | for (i = 0; i < 64; i++) |
977 | 873 | { |
978 | 874 | if (i <= 3 || i == 63) |
979 | | chip->lut_ar[i] = 0; |
| 875 | m_lut_ar[i] = 0; |
980 | 876 | else if (i >= 60) |
981 | | chip->lut_ar[i] = 17; |
| 877 | m_lut_ar[i] = 17; |
982 | 878 | else |
983 | | chip->lut_ar[i] = (67 << (15 - i / 4)) / (4 + i % 4); |
| 879 | m_lut_ar[i] = (67 << (15 - i / 4)) / (4 + i % 4); |
984 | 880 | } |
985 | 881 | } |
986 | 882 | |
987 | | static void ymf278b_register_save_state(device_t *device, YMF278BChip *chip) |
| 883 | void ymf278b_device::register_save_state() |
988 | 884 | { |
989 | 885 | int i; |
990 | 886 | |
991 | | device->save_item(NAME(chip->pcmregs)); |
992 | | device->save_item(NAME(chip->wavetblhdr)); |
993 | | device->save_item(NAME(chip->memmode)); |
994 | | device->save_item(NAME(chip->memadr)); |
995 | | device->save_item(NAME(chip->status_busy)); |
996 | | device->save_item(NAME(chip->status_ld)); |
997 | | device->save_item(NAME(chip->exp)); |
998 | | device->save_item(NAME(chip->fm_l)); |
999 | | device->save_item(NAME(chip->fm_r)); |
1000 | | device->save_item(NAME(chip->pcm_l)); |
1001 | | device->save_item(NAME(chip->pcm_r)); |
1002 | | device->save_item(NAME(chip->timer_a_count)); |
1003 | | device->save_item(NAME(chip->timer_b_count)); |
1004 | | device->save_item(NAME(chip->enable)); |
1005 | | device->save_item(NAME(chip->current_irq)); |
1006 | | device->save_item(NAME(chip->irq_line)); |
1007 | | device->save_item(NAME(chip->port_AB)); |
1008 | | device->save_item(NAME(chip->port_C)); |
1009 | | device->save_item(NAME(chip->lastport)); |
| 887 | save_item(NAME(m_pcmregs)); |
| 888 | save_item(NAME(m_wavetblhdr)); |
| 889 | save_item(NAME(m_memmode)); |
| 890 | save_item(NAME(m_memadr)); |
| 891 | save_item(NAME(m_status_busy)); |
| 892 | save_item(NAME(m_status_ld)); |
| 893 | save_item(NAME(m_exp)); |
| 894 | save_item(NAME(m_fm_l)); |
| 895 | save_item(NAME(m_fm_r)); |
| 896 | save_item(NAME(m_pcm_l)); |
| 897 | save_item(NAME(m_pcm_r)); |
| 898 | save_item(NAME(m_timer_a_count)); |
| 899 | save_item(NAME(m_timer_b_count)); |
| 900 | save_item(NAME(m_enable)); |
| 901 | save_item(NAME(m_current_irq)); |
| 902 | save_item(NAME(m_irq_line)); |
| 903 | save_item(NAME(m_port_AB)); |
| 904 | save_item(NAME(m_port_C)); |
| 905 | save_item(NAME(m_lastport)); |
1010 | 906 | |
1011 | 907 | for (i = 0; i < 24; ++i) |
1012 | 908 | { |
1013 | | device->save_item(NAME(chip->slots[i].wave), i); |
1014 | | device->save_item(NAME(chip->slots[i].F_NUMBER), i); |
1015 | | device->save_item(NAME(chip->slots[i].octave), i); |
1016 | | device->save_item(NAME(chip->slots[i].preverb), i); |
1017 | | device->save_item(NAME(chip->slots[i].DAMP), i); |
1018 | | device->save_item(NAME(chip->slots[i].CH), i); |
1019 | | device->save_item(NAME(chip->slots[i].LD), i); |
1020 | | device->save_item(NAME(chip->slots[i].TL), i); |
1021 | | device->save_item(NAME(chip->slots[i].pan), i); |
1022 | | device->save_item(NAME(chip->slots[i].LFO), i); |
1023 | | device->save_item(NAME(chip->slots[i].VIB), i); |
1024 | | device->save_item(NAME(chip->slots[i].AM), i); |
| 909 | save_item(NAME(m_slots[i].wave), i); |
| 910 | save_item(NAME(m_slots[i].F_NUMBER), i); |
| 911 | save_item(NAME(m_slots[i].octave), i); |
| 912 | save_item(NAME(m_slots[i].preverb), i); |
| 913 | save_item(NAME(m_slots[i].DAMP), i); |
| 914 | save_item(NAME(m_slots[i].CH), i); |
| 915 | save_item(NAME(m_slots[i].LD), i); |
| 916 | save_item(NAME(m_slots[i].TL), i); |
| 917 | save_item(NAME(m_slots[i].pan), i); |
| 918 | save_item(NAME(m_slots[i].LFO), i); |
| 919 | save_item(NAME(m_slots[i].VIB), i); |
| 920 | save_item(NAME(m_slots[i].AM), i); |
1025 | 921 | |
1026 | | device->save_item(NAME(chip->slots[i].AR), i); |
1027 | | device->save_item(NAME(chip->slots[i].D1R), i); |
1028 | | device->save_item(NAME(chip->slots[i].DL), i); |
1029 | | device->save_item(NAME(chip->slots[i].D2R), i); |
1030 | | device->save_item(NAME(chip->slots[i].RC), i); |
1031 | | device->save_item(NAME(chip->slots[i].RR), i); |
| 922 | save_item(NAME(m_slots[i].AR), i); |
| 923 | save_item(NAME(m_slots[i].D1R), i); |
| 924 | save_item(NAME(m_slots[i].DL), i); |
| 925 | save_item(NAME(m_slots[i].D2R), i); |
| 926 | save_item(NAME(m_slots[i].RC), i); |
| 927 | save_item(NAME(m_slots[i].RR), i); |
1032 | 928 | |
1033 | | device->save_item(NAME(chip->slots[i].step), i); |
1034 | | device->save_item(NAME(chip->slots[i].stepptr), i); |
| 929 | save_item(NAME(m_slots[i].step), i); |
| 930 | save_item(NAME(m_slots[i].stepptr), i); |
1035 | 931 | |
1036 | | device->save_item(NAME(chip->slots[i].active), i); |
1037 | | device->save_item(NAME(chip->slots[i].KEY_ON), i); |
1038 | | device->save_item(NAME(chip->slots[i].bits), i); |
1039 | | device->save_item(NAME(chip->slots[i].startaddr), i); |
1040 | | device->save_item(NAME(chip->slots[i].loopaddr), i); |
1041 | | device->save_item(NAME(chip->slots[i].endaddr), i); |
| 932 | save_item(NAME(m_slots[i].active), i); |
| 933 | save_item(NAME(m_slots[i].KEY_ON), i); |
| 934 | save_item(NAME(m_slots[i].bits), i); |
| 935 | save_item(NAME(m_slots[i].startaddr), i); |
| 936 | save_item(NAME(m_slots[i].loopaddr), i); |
| 937 | save_item(NAME(m_slots[i].endaddr), i); |
1042 | 938 | |
1043 | | device->save_item(NAME(chip->slots[i].env_step), i); |
1044 | | device->save_item(NAME(chip->slots[i].env_vol), i); |
1045 | | device->save_item(NAME(chip->slots[i].env_vol_step), i); |
1046 | | device->save_item(NAME(chip->slots[i].env_vol_lim), i); |
1047 | | device->save_item(NAME(chip->slots[i].env_preverb), i); |
| 939 | save_item(NAME(m_slots[i].env_step), i); |
| 940 | save_item(NAME(m_slots[i].env_vol), i); |
| 941 | save_item(NAME(m_slots[i].env_vol_step), i); |
| 942 | save_item(NAME(m_slots[i].env_vol_lim), i); |
| 943 | save_item(NAME(m_slots[i].env_preverb), i); |
1048 | 944 | } |
1049 | 945 | } |
1050 | 946 | |
1051 | | static DEVICE_START( ymf278b ) |
| 947 | //------------------------------------------------- |
| 948 | // device_start - device-specific startup |
| 949 | //------------------------------------------------- |
| 950 | |
| 951 | void ymf278b_device::device_start() |
1052 | 952 | { |
1053 | | static const ymf278b_interface defintrf = { DEVCB_NULL }; |
1054 | | const ymf278b_interface *intf; |
1055 | 953 | int i; |
1056 | | YMF278BChip *chip = get_safe_token(device); |
1057 | 954 | |
1058 | | chip->device = device; |
1059 | | intf = (device->static_config() != NULL) ? (const ymf278b_interface *)device->static_config() : &defintrf; |
| 955 | m_rom = *region(); |
| 956 | m_romsize = region()->bytes(); |
| 957 | m_clock = clock(); |
| 958 | m_irq_handler.resolve(); |
1060 | 959 | |
1061 | | ymf278b_init(device, chip, &intf->irq_callback); |
1062 | | chip->stream = device->machine().sound().stream_alloc(*device, 0, 2, device->clock()/768, chip, ymf278b_pcm_update); |
| 960 | m_timer_base = attotime::from_hz(m_clock) * (19*36); |
| 961 | m_timer_a = timer_alloc(TIMER_A); |
| 962 | m_timer_b = timer_alloc(TIMER_B); |
| 963 | m_timer_busy = timer_alloc(TIMER_BUSY_CLEAR); |
| 964 | m_timer_ld = timer_alloc(TIMER_LD_CLEAR); |
1063 | 965 | |
| 966 | for (i = 0; i < 24; i++) |
| 967 | { |
| 968 | m_slots[i].num = i; |
| 969 | } |
| 970 | |
| 971 | m_stream = machine().sound().stream_alloc(*this, 0, 2, clock()/768); |
| 972 | |
1064 | 973 | // rate tables |
1065 | | precompute_rate_tables(chip); |
| 974 | precompute_rate_tables(); |
1066 | 975 | |
1067 | 976 | // Volume table, 1 = -0.375dB, 8 = -3dB, 256 = -96dB |
1068 | 977 | for(i = 0; i < 256; i++) |
1069 | | chip->volume[i] = 65536*pow(2.0, (-0.375/6)*i); |
| 978 | m_volume[i] = 65536*pow(2.0, (-0.375/6)*i); |
1070 | 979 | for(i = 256; i < 256*4; i++) |
1071 | | chip->volume[i] = 0; |
| 980 | m_volume[i] = 0; |
1072 | 981 | |
1073 | 982 | // Pan values, units are -3dB, i.e. 8. |
1074 | 983 | for(i = 0; i < 16; i++) |
1075 | 984 | { |
1076 | | chip->pan_left[i] = i < 7 ? i*8 : i < 9 ? 256 : 0; |
1077 | | chip->pan_right[i] = i < 8 ? 0 : i < 10 ? 256 : (16-i)*8; |
| 985 | m_pan_left[i] = i < 7 ? i*8 : i < 9 ? 256 : 0; |
| 986 | m_pan_right[i] = i < 8 ? 0 : i < 10 ? 256 : (16-i)*8; |
1078 | 987 | } |
1079 | 988 | |
1080 | 989 | // Mixing levels, units are -3dB, and add some margin to avoid clipping |
1081 | 990 | for(i=0; i<7; i++) |
1082 | | chip->mix_level[i] = chip->volume[8*i+13]; |
1083 | | chip->mix_level[7] = 0; |
| 991 | m_mix_level[i] = m_volume[8*i+13]; |
| 992 | m_mix_level[7] = 0; |
1084 | 993 | |
1085 | 994 | // Register state for saving |
1086 | | ymf278b_register_save_state(device, chip); |
| 995 | register_save_state(); |
1087 | 996 | } |
1088 | 997 | |
1089 | 998 | |
r22809 | r22810 | |
1091 | 1000 | |
1092 | 1001 | ymf278b_device::ymf278b_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
1093 | 1002 | : device_t(mconfig, YMF278B, "YMF278B", tag, owner, clock), |
1094 | | device_sound_interface(mconfig, *this) |
| 1003 | device_sound_interface(mconfig, *this), |
| 1004 | m_irq_handler(*this) |
1095 | 1005 | { |
1096 | | m_token = global_alloc_clear(YMF278BChip); |
1097 | 1006 | } |
1098 | 1007 | |
1099 | 1008 | //------------------------------------------------- |
r22809 | r22810 | |
1105 | 1014 | void ymf278b_device::device_config_complete() |
1106 | 1015 | { |
1107 | 1016 | } |
1108 | | |
1109 | | //------------------------------------------------- |
1110 | | // device_start - device-specific startup |
1111 | | //------------------------------------------------- |
1112 | | |
1113 | | void ymf278b_device::device_start() |
1114 | | { |
1115 | | DEVICE_START_NAME( ymf278b )(this); |
1116 | | } |
1117 | | |
1118 | | //------------------------------------------------- |
1119 | | // device_reset - device-specific reset |
1120 | | //------------------------------------------------- |
1121 | | |
1122 | | void ymf278b_device::device_reset() |
1123 | | { |
1124 | | DEVICE_RESET_NAME( ymf278b )(this); |
1125 | | } |
1126 | | |
1127 | | //------------------------------------------------- |
1128 | | // sound_stream_update - handle a stream update |
1129 | | //------------------------------------------------- |
1130 | | |
1131 | | void ymf278b_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
1132 | | { |
1133 | | // should never get here |
1134 | | fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); |
1135 | | } |