trunk/src/emu/sound/ymz280b.c
r22733 | r22734 | |
26 | 26 | |
27 | 27 | |
28 | 28 | #define MAX_SAMPLE_CHUNK 10000 |
29 | | #define MAKE_WAVS 0 |
30 | 29 | |
31 | 30 | #define FRAC_BITS 14 |
32 | 31 | #define FRAC_ONE (1 << FRAC_BITS) |
33 | 32 | #define FRAC_MASK (FRAC_ONE - 1) |
34 | 33 | |
35 | 34 | #define INTERNAL_BUFFER_SIZE (1 << 15) |
36 | | #define INTERNAL_SAMPLE_RATE (chip->master_clock * 2.0) |
| 35 | #define INTERNAL_SAMPLE_RATE (m_master_clock * 2.0) |
37 | 36 | |
38 | 37 | #if MAKE_WAVS |
39 | 38 | #include "wavwrite.h" |
40 | 39 | #endif |
41 | 40 | |
42 | 41 | |
43 | | /* struct describing a single playing ADPCM voice */ |
44 | | struct YMZ280BVoice |
45 | | { |
46 | | UINT8 playing; /* 1 if we are actively playing */ |
47 | 42 | |
48 | | UINT8 keyon; /* 1 if the key is on */ |
49 | | UINT8 looping; /* 1 if looping is enabled */ |
50 | | UINT8 mode; /* current playback mode */ |
51 | | UINT16 fnum; /* frequency */ |
52 | | UINT8 level; /* output level */ |
53 | | UINT8 pan; /* panning */ |
54 | | |
55 | | UINT32 start; /* start address, in nibbles */ |
56 | | UINT32 stop; /* stop address, in nibbles */ |
57 | | UINT32 loop_start; /* loop start address, in nibbles */ |
58 | | UINT32 loop_end; /* loop end address, in nibbles */ |
59 | | UINT32 position; /* current position, in nibbles */ |
60 | | |
61 | | INT32 signal; /* current ADPCM signal */ |
62 | | INT32 step; /* current ADPCM step */ |
63 | | |
64 | | INT32 loop_signal; /* signal at loop start */ |
65 | | INT32 loop_step; /* step at loop start */ |
66 | | UINT32 loop_count; /* number of loops so far */ |
67 | | |
68 | | INT32 output_left; /* output volume (left) */ |
69 | | INT32 output_right; /* output volume (right) */ |
70 | | INT32 output_step; /* step value for frequency conversion */ |
71 | | INT32 output_pos; /* current fractional position */ |
72 | | INT16 last_sample; /* last sample output */ |
73 | | INT16 curr_sample; /* current sample target */ |
74 | | UINT8 irq_schedule; /* 1 if the IRQ state is updated by timer */ |
75 | | }; |
76 | | |
77 | | struct ymz280b_state |
78 | | { |
79 | | sound_stream * stream; /* which stream are we using */ |
80 | | UINT8 *region_base; /* pointer to the base of the region */ |
81 | | UINT32 region_size; |
82 | | UINT8 current_register; /* currently accessible register */ |
83 | | UINT8 status_register; /* current status register */ |
84 | | UINT8 irq_state; /* current IRQ state */ |
85 | | UINT8 irq_mask; /* current IRQ mask */ |
86 | | UINT8 irq_enable; /* current IRQ enable */ |
87 | | UINT8 keyon_enable; /* key on enable */ |
88 | | UINT8 ext_mem_enable; /* external memory enable */ |
89 | | double master_clock; /* master clock frequency */ |
90 | | devcb_resolved_write_line irq_callback; /* IRQ callback */ |
91 | | struct YMZ280BVoice voice[8]; /* the 8 voices */ |
92 | | UINT32 rom_addr_hi; |
93 | | UINT32 rom_addr_mid; |
94 | | UINT32 rom_readback_addr; /* where the CPU can read the ROM */ |
95 | | devcb_resolved_read8 ext_ram_read; /* external RAM read handler */ |
96 | | devcb_resolved_write8 ext_ram_write; /* external RAM write handler */ |
97 | | |
98 | | #if MAKE_WAVS |
99 | | void * wavresample; /* resampled waveform */ |
100 | | #endif |
101 | | |
102 | | INT16 *scratch; |
103 | | device_t *device; |
104 | | }; |
105 | | |
106 | | static void write_to_register(ymz280b_state *, int); |
107 | | |
108 | | |
109 | 43 | /* step size index shift table */ |
110 | 44 | static const int index_scale[8] = { 0x0e6, 0x0e6, 0x0e6, 0x0e6, 0x133, 0x199, 0x200, 0x266 }; |
111 | 45 | |
112 | 46 | /* lookup table for the precomputed difference */ |
113 | 47 | static int diff_lookup[16]; |
114 | 48 | |
115 | | /* timer callback */ |
116 | | static TIMER_CALLBACK( update_irq_state_timer_0 ); |
117 | | static TIMER_CALLBACK( update_irq_state_timer_1 ); |
118 | | static TIMER_CALLBACK( update_irq_state_timer_2 ); |
119 | | static TIMER_CALLBACK( update_irq_state_timer_3 ); |
120 | | static TIMER_CALLBACK( update_irq_state_timer_4 ); |
121 | | static TIMER_CALLBACK( update_irq_state_timer_5 ); |
122 | | static TIMER_CALLBACK( update_irq_state_timer_6 ); |
123 | | static TIMER_CALLBACK( update_irq_state_timer_7 ); |
124 | 49 | |
125 | | static const struct { timer_expired_func func; const char *name; } update_irq_state_cb[] = |
| 50 | UINT8 ymz280b_device::ymz280b_read_memory(UINT32 offset) |
126 | 51 | { |
127 | | { FUNC(update_irq_state_timer_0) }, |
128 | | { FUNC(update_irq_state_timer_1) }, |
129 | | { FUNC(update_irq_state_timer_2) }, |
130 | | { FUNC(update_irq_state_timer_3) }, |
131 | | { FUNC(update_irq_state_timer_4) }, |
132 | | { FUNC(update_irq_state_timer_5) }, |
133 | | { FUNC(update_irq_state_timer_6) }, |
134 | | { FUNC(update_irq_state_timer_7) } |
135 | | }; |
136 | | |
137 | | |
138 | | INLINE ymz280b_state *get_safe_token(device_t *device) |
139 | | { |
140 | | assert(device != NULL); |
141 | | assert(device->type() == YMZ280B); |
142 | | return (ymz280b_state *)downcast<ymz280b_device *>(device)->token(); |
143 | | } |
144 | | |
145 | | |
146 | | INLINE UINT8 ymz280b_read_memory(ymz280b_state *chip, UINT32 offset) |
147 | | { |
148 | | if (chip->ext_ram_read.isnull()) |
| 52 | if (m_ext_read_handler.isnull()) |
149 | 53 | { |
150 | | if (offset < chip->region_size) |
151 | | return chip->region_base[offset]; |
| 54 | if (offset < m_region_size) |
| 55 | return m_region_base[offset]; |
152 | 56 | |
153 | 57 | /* 16MB chip limit (shouldn't happen) */ |
154 | 58 | else if (offset > 0xffffff) |
155 | | return chip->region_base[offset & 0xffffff]; |
| 59 | return m_region_base[offset & 0xffffff]; |
156 | 60 | |
157 | 61 | else |
158 | 62 | return 0; |
159 | 63 | } |
160 | 64 | else |
161 | | return chip->ext_ram_read(offset); |
| 65 | return m_ext_read_handler(offset); |
162 | 66 | } |
163 | 67 | |
164 | 68 | |
165 | | INLINE void update_irq_state(ymz280b_state *chip) |
| 69 | void ymz280b_device::update_irq_state() |
166 | 70 | { |
167 | | int irq_bits = chip->status_register & chip->irq_mask; |
| 71 | int irq_bits = m_status_register & m_irq_mask; |
168 | 72 | |
169 | 73 | /* always off if the enable is off */ |
170 | | if (!chip->irq_enable) |
| 74 | if (!m_irq_enable) |
171 | 75 | irq_bits = 0; |
172 | 76 | |
173 | 77 | /* update the state if changed */ |
174 | | if (irq_bits && !chip->irq_state) |
| 78 | if (irq_bits && !m_irq_state) |
175 | 79 | { |
176 | | chip->irq_state = 1; |
177 | | if (!chip->irq_callback.isnull()) |
178 | | chip->irq_callback(1); |
| 80 | m_irq_state = 1; |
| 81 | if (!m_irq_handler.isnull()) |
| 82 | m_irq_handler(1); |
179 | 83 | else logerror("YMZ280B: IRQ generated, but no callback specified!"); |
180 | 84 | } |
181 | | else if (!irq_bits && chip->irq_state) |
| 85 | else if (!irq_bits && m_irq_state) |
182 | 86 | { |
183 | | chip->irq_state = 0; |
184 | | if (!chip->irq_callback.isnull()) |
185 | | chip->irq_callback(0); |
| 87 | m_irq_state = 0; |
| 88 | if (!m_irq_handler.isnull()) |
| 89 | m_irq_handler(0); |
186 | 90 | else logerror("YMZ280B: IRQ generated, but no callback specified!"); |
187 | 91 | } |
188 | 92 | } |
189 | 93 | |
190 | 94 | |
191 | | INLINE void update_step(ymz280b_state *chip, struct YMZ280BVoice *voice) |
| 95 | void ymz280b_device::update_step(struct YMZ280BVoice *voice) |
192 | 96 | { |
193 | 97 | double frequency; |
194 | 98 | |
195 | 99 | /* compute the frequency */ |
196 | 100 | if (voice->mode == 1) |
197 | | frequency = chip->master_clock * (double)((voice->fnum & 0x0ff) + 1) * (1.0 / 256.0); |
| 101 | frequency = m_master_clock * (double)((voice->fnum & 0x0ff) + 1) * (1.0 / 256.0); |
198 | 102 | else |
199 | | frequency = chip->master_clock * (double)((voice->fnum & 0x1ff) + 1) * (1.0 / 256.0); |
| 103 | frequency = m_master_clock * (double)((voice->fnum & 0x1ff) + 1) * (1.0 / 256.0); |
200 | 104 | voice->output_step = (UINT32)(frequency * (double)FRAC_ONE / INTERNAL_SAMPLE_RATE); |
201 | 105 | } |
202 | 106 | |
203 | 107 | |
204 | | INLINE void update_volumes(struct YMZ280BVoice *voice) |
| 108 | void ymz280b_device::update_volumes(struct YMZ280BVoice *voice) |
205 | 109 | { |
206 | 110 | if (voice->pan == 8) |
207 | 111 | { |
r22733 | r22734 | |
223 | 127 | } |
224 | 128 | |
225 | 129 | |
226 | | static void YMZ280B_state_save_update_step(ymz280b_state *chip) |
| 130 | void ymz280b_device::post_load() |
227 | 131 | { |
228 | 132 | for (int j = 0; j < 8; j++) |
229 | 133 | { |
230 | | struct YMZ280BVoice *voice = &chip->voice[j]; |
231 | | update_step(chip, voice); |
| 134 | struct YMZ280BVoice *voice = &m_voice[j]; |
| 135 | update_step(voice); |
232 | 136 | if(voice->irq_schedule) |
233 | | chip->device->machine().scheduler().timer_set(attotime::zero, update_irq_state_cb[j].func, update_irq_state_cb[j].name, 0, chip); |
| 137 | voice->timer->adjust(attotime::zero); |
234 | 138 | } |
235 | 139 | } |
236 | 140 | |
237 | 141 | |
238 | | static void update_irq_state_timer_common(void *param, int voicenum) |
| 142 | void ymz280b_device::update_irq_state_timer_common(int voicenum) |
239 | 143 | { |
240 | | ymz280b_state *chip = (ymz280b_state *)param; |
241 | | struct YMZ280BVoice *voice = &chip->voice[voicenum]; |
| 144 | struct YMZ280BVoice *voice = &m_voice[voicenum]; |
242 | 145 | |
243 | 146 | if(!voice->irq_schedule) return; |
244 | 147 | |
245 | 148 | voice->playing = 0; |
246 | | chip->status_register |= 1 << voicenum; |
247 | | update_irq_state(chip); |
| 149 | m_status_register |= 1 << voicenum; |
| 150 | update_irq_state(); |
248 | 151 | voice->irq_schedule = 0; |
249 | 152 | } |
250 | 153 | |
251 | | static TIMER_CALLBACK( update_irq_state_timer_0 ) { update_irq_state_timer_common(ptr, 0); } |
252 | | static TIMER_CALLBACK( update_irq_state_timer_1 ) { update_irq_state_timer_common(ptr, 1); } |
253 | | static TIMER_CALLBACK( update_irq_state_timer_2 ) { update_irq_state_timer_common(ptr, 2); } |
254 | | static TIMER_CALLBACK( update_irq_state_timer_3 ) { update_irq_state_timer_common(ptr, 3); } |
255 | | static TIMER_CALLBACK( update_irq_state_timer_4 ) { update_irq_state_timer_common(ptr, 4); } |
256 | | static TIMER_CALLBACK( update_irq_state_timer_5 ) { update_irq_state_timer_common(ptr, 5); } |
257 | | static TIMER_CALLBACK( update_irq_state_timer_6 ) { update_irq_state_timer_common(ptr, 6); } |
258 | | static TIMER_CALLBACK( update_irq_state_timer_7 ) { update_irq_state_timer_common(ptr, 7); } |
259 | | |
260 | | |
261 | 154 | /********************************************************************************************** |
262 | 155 | |
263 | 156 | compute_tables -- compute the difference tables |
r22733 | r22734 | |
282 | 175 | |
283 | 176 | ***********************************************************************************************/ |
284 | 177 | |
285 | | static int generate_adpcm(ymz280b_state *chip, struct YMZ280BVoice *voice, INT16 *buffer, int samples) |
| 178 | int ymz280b_device::generate_adpcm(struct YMZ280BVoice *voice, INT16 *buffer, int samples) |
286 | 179 | { |
287 | 180 | int position = voice->position; |
288 | 181 | int signal = voice->signal; |
r22733 | r22734 | |
296 | 189 | while (samples) |
297 | 190 | { |
298 | 191 | /* compute the new amplitude and update the current step */ |
299 | | val = ymz280b_read_memory(chip, position / 2) >> ((~position & 1) << 2); |
| 192 | val = ymz280b_read_memory(position / 2) >> ((~position & 1) << 2); |
300 | 193 | signal += (step * diff_lookup[val & 15]) / 8; |
301 | 194 | |
302 | 195 | /* clamp to the maximum */ |
r22733 | r22734 | |
335 | 228 | while (samples) |
336 | 229 | { |
337 | 230 | /* compute the new amplitude and update the current step */ |
338 | | val = ymz280b_read_memory(chip, position / 2) >> ((~position & 1) << 2); |
| 231 | val = ymz280b_read_memory(position / 2) >> ((~position & 1) << 2); |
339 | 232 | signal += (step * diff_lookup[val & 15]) / 8; |
340 | 233 | |
341 | 234 | /* clamp to the maximum */ |
r22733 | r22734 | |
398 | 291 | |
399 | 292 | ***********************************************************************************************/ |
400 | 293 | |
401 | | static int generate_pcm8(ymz280b_state *chip, struct YMZ280BVoice *voice, INT16 *buffer, int samples) |
| 294 | int ymz280b_device::generate_pcm8(struct YMZ280BVoice *voice, INT16 *buffer, int samples) |
402 | 295 | { |
403 | 296 | int position = voice->position; |
404 | 297 | int val; |
r22733 | r22734 | |
410 | 303 | while (samples) |
411 | 304 | { |
412 | 305 | /* fetch the current value */ |
413 | | val = ymz280b_read_memory(chip, position / 2); |
| 306 | val = ymz280b_read_memory(position / 2); |
414 | 307 | |
415 | 308 | /* output to the buffer, scaling by the volume */ |
416 | 309 | *buffer++ = (INT8)val * 256; |
r22733 | r22734 | |
435 | 328 | while (samples) |
436 | 329 | { |
437 | 330 | /* fetch the current value */ |
438 | | val = ymz280b_read_memory(chip, position / 2); |
| 331 | val = ymz280b_read_memory(position / 2); |
439 | 332 | |
440 | 333 | /* output to the buffer, scaling by the volume */ |
441 | 334 | *buffer++ = (INT8)val * 256; |
r22733 | r22734 | |
472 | 365 | |
473 | 366 | ***********************************************************************************************/ |
474 | 367 | |
475 | | static int generate_pcm16(ymz280b_state *chip, struct YMZ280BVoice *voice, INT16 *buffer, int samples) |
| 368 | int ymz280b_device::generate_pcm16(struct YMZ280BVoice *voice, INT16 *buffer, int samples) |
476 | 369 | { |
477 | 370 | int position = voice->position; |
478 | 371 | int val; |
r22733 | r22734 | |
484 | 377 | while (samples) |
485 | 378 | { |
486 | 379 | /* fetch the current value */ |
487 | | val = (INT16)((ymz280b_read_memory(chip, position / 2 + 0) << 8) + ymz280b_read_memory(chip, position / 2 + 1)); |
| 380 | val = (INT16)((ymz280b_read_memory(position / 2 + 0) << 8) + ymz280b_read_memory(position / 2 + 1)); |
488 | 381 | |
489 | 382 | /* output to the buffer, scaling by the volume */ |
490 | 383 | *buffer++ = val; |
r22733 | r22734 | |
509 | 402 | while (samples) |
510 | 403 | { |
511 | 404 | /* fetch the current value */ |
512 | | val = (INT16)((ymz280b_read_memory(chip, position / 2 + 0) << 8) + ymz280b_read_memory(chip, position / 2 + 1)); |
| 405 | val = (INT16)((ymz280b_read_memory(position / 2 + 0) << 8) + ymz280b_read_memory(position / 2 + 1)); |
513 | 406 | |
514 | 407 | /* output to the buffer, scaling by the volume */ |
515 | 408 | *buffer++ = val; |
r22733 | r22734 | |
540 | 433 | |
541 | 434 | |
542 | 435 | |
543 | | /********************************************************************************************** |
544 | 436 | |
545 | | ymz280b_update -- update the sound chip so that it is in sync with CPU execution |
| 437 | //------------------------------------------------- |
| 438 | // sound_stream_update - handle a stream update |
| 439 | //------------------------------------------------- |
546 | 440 | |
547 | | ***********************************************************************************************/ |
548 | | |
549 | | static STREAM_UPDATE( ymz280b_update ) |
| 441 | void ymz280b_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
550 | 442 | { |
551 | | ymz280b_state *chip = (ymz280b_state *)param; |
552 | 443 | stream_sample_t *lacc = outputs[0]; |
553 | 444 | stream_sample_t *racc = outputs[1]; |
554 | 445 | int v; |
r22733 | r22734 | |
560 | 451 | /* loop over voices */ |
561 | 452 | for (v = 0; v < 8; v++) |
562 | 453 | { |
563 | | struct YMZ280BVoice *voice = &chip->voice[v]; |
| 454 | struct YMZ280BVoice *voice = &m_voice[v]; |
564 | 455 | INT16 prev = voice->last_sample; |
565 | 456 | INT16 curr = voice->curr_sample; |
566 | | INT16 *curr_data = chip->scratch; |
| 457 | INT16 *curr_data = m_scratch; |
567 | 458 | INT32 *ldest = lacc; |
568 | 459 | INT32 *rdest = racc; |
569 | 460 | UINT32 new_samples, samples_left; |
r22733 | r22734 | |
608 | 499 | /* generate them into our buffer */ |
609 | 500 | switch (voice->playing << 7 | voice->mode) |
610 | 501 | { |
611 | | case 0x81: samples_left = generate_adpcm(chip, voice, chip->scratch, new_samples); break; |
612 | | case 0x82: samples_left = generate_pcm8(chip, voice, chip->scratch, new_samples); break; |
613 | | case 0x83: samples_left = generate_pcm16(chip, voice, chip->scratch, new_samples); break; |
614 | | default: samples_left = 0; memset(chip->scratch, 0, new_samples * sizeof(chip->scratch[0])); break; |
| 502 | case 0x81: samples_left = generate_adpcm(voice, m_scratch, new_samples); break; |
| 503 | case 0x82: samples_left = generate_pcm8(voice, m_scratch, new_samples); break; |
| 504 | case 0x83: samples_left = generate_pcm16(voice, m_scratch, new_samples); break; |
| 505 | default: samples_left = 0; memset(m_scratch, 0, new_samples * sizeof(m_scratch[0])); break; |
615 | 506 | } |
616 | 507 | |
617 | 508 | /* if there are leftovers, ramp back to 0 */ |
r22733 | r22734 | |
619 | 510 | { |
620 | 511 | /* note: samples_left bit 16 is set if the voice was finished at the same time the function ended */ |
621 | 512 | int base = new_samples - (samples_left & 0xffff); |
622 | | int i, t = (base == 0) ? curr : chip->scratch[base - 1]; |
| 513 | int i, t = (base == 0) ? curr : m_scratch[base - 1]; |
623 | 514 | for (i = 0; i < (samples_left & 0xffff); i++) |
624 | 515 | { |
625 | 516 | if (t < 0) t = -((-t * 15) >> 4); |
626 | 517 | else if (t > 0) t = (t * 15) >> 4; |
627 | | chip->scratch[base + i] = t; |
| 518 | m_scratch[base + i] = t; |
628 | 519 | } |
629 | 520 | |
630 | 521 | /* if we hit the end and IRQs are enabled, signal it */ |
r22733 | r22734 | |
633 | 524 | voice->playing = 0; |
634 | 525 | |
635 | 526 | /* set update_irq_state_timer. IRQ is signaled on next CPU execution. */ |
636 | | chip->device->machine().scheduler().timer_set(attotime::zero, update_irq_state_cb[v].func, update_irq_state_cb[v].name, 0, chip); |
| 527 | voice->timer->adjust(attotime::zero); |
637 | 528 | voice->irq_schedule = 1; |
638 | 529 | } |
639 | 530 | } |
r22733 | r22734 | |
678 | 569 | |
679 | 570 | |
680 | 571 | |
681 | | /********************************************************************************************** |
| 572 | //------------------------------------------------- |
| 573 | // device_start - device-specific startup |
| 574 | //------------------------------------------------- |
682 | 575 | |
683 | | DEVICE_START/RESET( ymz280b ) -- start/reset emulation of the YMZ280B |
684 | | |
685 | | ***********************************************************************************************/ |
686 | | |
687 | | static DEVICE_START( ymz280b ) |
| 576 | void ymz280b_device::device_start() |
688 | 577 | { |
689 | | static const ymz280b_interface defintrf = { DEVCB_NULL }; |
690 | | const ymz280b_interface *intf = (device->static_config() != NULL) ? (const ymz280b_interface *)device->static_config() : &defintrf; |
691 | | ymz280b_state *chip = get_safe_token(device); |
| 578 | m_ext_read_handler.resolve(); |
| 579 | m_ext_write_handler.resolve(); |
692 | 580 | |
693 | | chip->device = device; |
694 | | chip->ext_ram_read.resolve(intf->ext_read, *device); |
695 | | chip->ext_ram_write.resolve(intf->ext_write, *device); |
696 | | |
697 | 581 | /* compute ADPCM tables */ |
698 | 582 | compute_tables(); |
699 | 583 | |
700 | 584 | /* initialize the rest of the structure */ |
701 | | chip->master_clock = (double)device->clock() / 384.0; |
702 | | chip->region_base = *device->region(); |
703 | | chip->region_size = device->region()->bytes(); |
704 | | chip->irq_callback.resolve(intf->irq_callback, *device); |
| 585 | m_master_clock = (double)clock() / 384.0; |
| 586 | m_region_base = *region(); |
| 587 | m_region_size = region()->bytes(); |
| 588 | m_irq_handler.resolve(); |
705 | 589 | |
| 590 | for (int i = 0; i < 8; i++) |
| 591 | { |
| 592 | m_voice[i].timer = timer_alloc(i); |
| 593 | } |
| 594 | |
706 | 595 | /* create the stream */ |
707 | | chip->stream = device->machine().sound().stream_alloc(*device, 0, 2, INTERNAL_SAMPLE_RATE, chip, ymz280b_update); |
| 596 | m_stream = machine().sound().stream_alloc(*this, 0, 2, INTERNAL_SAMPLE_RATE); |
708 | 597 | |
709 | 598 | /* allocate memory */ |
710 | 599 | assert(MAX_SAMPLE_CHUNK < 0x10000); |
711 | | chip->scratch = auto_alloc_array(device->machine(), INT16, MAX_SAMPLE_CHUNK); |
| 600 | m_scratch = auto_alloc_array(machine(), INT16, MAX_SAMPLE_CHUNK); |
712 | 601 | |
713 | 602 | /* state save */ |
| 603 | save_item(NAME(m_current_register)); |
| 604 | save_item(NAME(m_status_register)); |
| 605 | save_item(NAME(m_irq_state)); |
| 606 | save_item(NAME(m_irq_mask)); |
| 607 | save_item(NAME(m_irq_enable)); |
| 608 | save_item(NAME(m_keyon_enable)); |
| 609 | save_item(NAME(m_ext_mem_enable)); |
| 610 | save_item(NAME(m_rom_readback_addr)); |
| 611 | save_item(NAME(m_rom_addr_hi)); |
| 612 | save_item(NAME(m_rom_addr_mid)); |
| 613 | for (int j = 0; j < 8; j++) |
714 | 614 | { |
715 | | int j; |
716 | | device->save_item(NAME(chip->current_register)); |
717 | | device->save_item(NAME(chip->status_register)); |
718 | | device->save_item(NAME(chip->irq_state)); |
719 | | device->save_item(NAME(chip->irq_mask)); |
720 | | device->save_item(NAME(chip->irq_enable)); |
721 | | device->save_item(NAME(chip->keyon_enable)); |
722 | | device->save_item(NAME(chip->ext_mem_enable)); |
723 | | device->save_item(NAME(chip->rom_readback_addr)); |
724 | | device->save_item(NAME(chip->rom_addr_hi)); |
725 | | device->save_item(NAME(chip->rom_addr_mid)); |
726 | | for (j = 0; j < 8; j++) |
727 | | { |
728 | | device->save_item(NAME(chip->voice[j].playing), j); |
729 | | device->save_item(NAME(chip->voice[j].keyon), j); |
730 | | device->save_item(NAME(chip->voice[j].looping), j); |
731 | | device->save_item(NAME(chip->voice[j].mode), j); |
732 | | device->save_item(NAME(chip->voice[j].fnum), j); |
733 | | device->save_item(NAME(chip->voice[j].level), j); |
734 | | device->save_item(NAME(chip->voice[j].pan), j); |
735 | | device->save_item(NAME(chip->voice[j].start), j); |
736 | | device->save_item(NAME(chip->voice[j].stop), j); |
737 | | device->save_item(NAME(chip->voice[j].loop_start), j); |
738 | | device->save_item(NAME(chip->voice[j].loop_end), j); |
739 | | device->save_item(NAME(chip->voice[j].position), j); |
740 | | device->save_item(NAME(chip->voice[j].signal), j); |
741 | | device->save_item(NAME(chip->voice[j].step), j); |
742 | | device->save_item(NAME(chip->voice[j].loop_signal), j); |
743 | | device->save_item(NAME(chip->voice[j].loop_step), j); |
744 | | device->save_item(NAME(chip->voice[j].loop_count), j); |
745 | | device->save_item(NAME(chip->voice[j].output_left), j); |
746 | | device->save_item(NAME(chip->voice[j].output_right), j); |
747 | | device->save_item(NAME(chip->voice[j].output_pos), j); |
748 | | device->save_item(NAME(chip->voice[j].last_sample), j); |
749 | | device->save_item(NAME(chip->voice[j].curr_sample), j); |
750 | | device->save_item(NAME(chip->voice[j].irq_schedule), j); |
751 | | } |
| 615 | save_item(NAME(m_voice[j].playing), j); |
| 616 | save_item(NAME(m_voice[j].keyon), j); |
| 617 | save_item(NAME(m_voice[j].looping), j); |
| 618 | save_item(NAME(m_voice[j].mode), j); |
| 619 | save_item(NAME(m_voice[j].fnum), j); |
| 620 | save_item(NAME(m_voice[j].level), j); |
| 621 | save_item(NAME(m_voice[j].pan), j); |
| 622 | save_item(NAME(m_voice[j].start), j); |
| 623 | save_item(NAME(m_voice[j].stop), j); |
| 624 | save_item(NAME(m_voice[j].loop_start), j); |
| 625 | save_item(NAME(m_voice[j].loop_end), j); |
| 626 | save_item(NAME(m_voice[j].position), j); |
| 627 | save_item(NAME(m_voice[j].signal), j); |
| 628 | save_item(NAME(m_voice[j].step), j); |
| 629 | save_item(NAME(m_voice[j].loop_signal), j); |
| 630 | save_item(NAME(m_voice[j].loop_step), j); |
| 631 | save_item(NAME(m_voice[j].loop_count), j); |
| 632 | save_item(NAME(m_voice[j].output_left), j); |
| 633 | save_item(NAME(m_voice[j].output_right), j); |
| 634 | save_item(NAME(m_voice[j].output_pos), j); |
| 635 | save_item(NAME(m_voice[j].last_sample), j); |
| 636 | save_item(NAME(m_voice[j].curr_sample), j); |
| 637 | save_item(NAME(m_voice[j].irq_schedule), j); |
752 | 638 | } |
753 | 639 | |
754 | | device->machine().save().register_postload(save_prepost_delegate(FUNC(YMZ280B_state_save_update_step), chip)); |
755 | | |
756 | 640 | #if MAKE_WAVS |
757 | | chip->wavresample = wav_open("resamp.wav", INTERNAL_SAMPLE_RATE, 2); |
| 641 | m_wavresample = wav_open("resamp.wav", INTERNAL_SAMPLE_RATE, 2); |
758 | 642 | #endif |
759 | 643 | } |
760 | 644 | |
761 | | static DEVICE_RESET( ymz280b ) |
| 645 | //------------------------------------------------- |
| 646 | // device_reset - device-specific reset |
| 647 | //------------------------------------------------- |
| 648 | |
| 649 | void ymz280b_device::device_reset() |
762 | 650 | { |
763 | 651 | int i; |
764 | | ymz280b_state *chip = get_safe_token(device); |
765 | 652 | |
766 | 653 | /* initial clear registers */ |
767 | 654 | for (i = 0xff; i >= 0; i--) |
768 | 655 | { |
769 | | chip->current_register = i; |
770 | | write_to_register(chip, 0); |
| 656 | m_current_register = i; |
| 657 | write_to_register(0); |
771 | 658 | } |
772 | 659 | |
773 | | chip->current_register = 0; |
774 | | chip->status_register = 0; |
775 | | chip->rom_readback_addr = 0; |
| 660 | m_current_register = 0; |
| 661 | m_status_register = 0; |
| 662 | m_rom_readback_addr = 0; |
776 | 663 | |
777 | 664 | /* clear other voice parameters */ |
778 | 665 | for (i = 0; i < 8; i++) |
779 | 666 | { |
780 | | struct YMZ280BVoice *voice = &chip->voice[i]; |
| 667 | struct YMZ280BVoice *voice = &m_voice[i]; |
781 | 668 | |
782 | 669 | voice->curr_sample = 0; |
783 | 670 | voice->last_sample = 0; |
r22733 | r22734 | |
787 | 674 | } |
788 | 675 | |
789 | 676 | |
| 677 | void ymz280b_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
| 678 | { |
| 679 | update_irq_state_timer_common( param ); |
| 680 | } |
790 | 681 | |
| 682 | |
791 | 683 | /********************************************************************************************** |
792 | 684 | |
793 | 685 | write_to_register -- handle a write to the current register |
794 | 686 | |
795 | 687 | ***********************************************************************************************/ |
796 | 688 | |
797 | | static void write_to_register(ymz280b_state *chip, int data) |
| 689 | void ymz280b_device::write_to_register(int data) |
798 | 690 | { |
799 | 691 | struct YMZ280BVoice *voice; |
800 | 692 | int i; |
801 | 693 | |
802 | 694 | /* lower registers follow a pattern */ |
803 | | if (chip->current_register < 0x80) |
| 695 | if (m_current_register < 0x80) |
804 | 696 | { |
805 | | voice = &chip->voice[(chip->current_register >> 2) & 7]; |
| 697 | voice = &m_voice[(m_current_register >> 2) & 7]; |
806 | 698 | |
807 | | switch (chip->current_register & 0xe3) |
| 699 | switch (m_current_register & 0xe3) |
808 | 700 | { |
809 | 701 | case 0x00: /* pitch low 8 bits */ |
810 | 702 | voice->fnum = (voice->fnum & 0x100) | (data & 0xff); |
811 | | update_step(chip, voice); |
| 703 | update_step(voice); |
812 | 704 | break; |
813 | 705 | |
814 | 706 | case 0x01: /* pitch upper 1 bit, loop, key on, mode */ |
r22733 | r22734 | |
816 | 708 | voice->looping = (data & 0x10) >> 4; |
817 | 709 | if ((data & 0x60) == 0) data &= 0x7f; /* ignore mode setting and set to same state as KON=0 */ |
818 | 710 | else voice->mode = (data & 0x60) >> 5; |
819 | | if (!voice->keyon && (data & 0x80) && chip->keyon_enable) |
| 711 | if (!voice->keyon && (data & 0x80) && m_keyon_enable) |
820 | 712 | { |
821 | 713 | voice->playing = 1; |
822 | 714 | voice->position = voice->start; |
r22733 | r22734 | |
835 | 727 | voice->irq_schedule = 0; |
836 | 728 | } |
837 | 729 | voice->keyon = (data & 0x80) >> 7; |
838 | | update_step(chip, voice); |
| 730 | update_step(voice); |
839 | 731 | break; |
840 | 732 | |
841 | 733 | case 0x02: /* total level */ |
r22733 | r22734 | |
897 | 789 | break; |
898 | 790 | |
899 | 791 | default: |
900 | | logerror("YMZ280B: unknown register write %02X = %02X\n", chip->current_register, data); |
| 792 | logerror("YMZ280B: unknown register write %02X = %02X\n", m_current_register, data); |
901 | 793 | break; |
902 | 794 | } |
903 | 795 | } |
r22733 | r22734 | |
905 | 797 | /* upper registers are special */ |
906 | 798 | else |
907 | 799 | { |
908 | | switch (chip->current_register) |
| 800 | switch (m_current_register) |
909 | 801 | { |
910 | 802 | /* DSP related (not implemented yet) */ |
911 | 803 | case 0x80: // d0-2: DSP Rch, d3: enable Rch (0: yes, 1: no), d4-6: DSP Lch, d7: enable Lch (0: yes, 1: no) |
912 | 804 | case 0x81: // d0: enable control of $82 (0: yes, 1: no) |
913 | 805 | case 0x82: // DSP data |
914 | | logerror("YMZ280B: DSP register write %02X = %02X\n", chip->current_register, data); |
| 806 | logerror("YMZ280B: DSP register write %02X = %02X\n", m_current_register, data); |
915 | 807 | break; |
916 | 808 | |
917 | 809 | case 0x84: /* ROM readback / RAM write (high) */ |
918 | | chip->rom_addr_hi = data << 16; |
| 810 | m_rom_addr_hi = data << 16; |
919 | 811 | break; |
920 | 812 | |
921 | 813 | case 0x85: /* ROM readback / RAM write (middle) */ |
922 | | chip->rom_addr_mid = data << 8; |
| 814 | m_rom_addr_mid = data << 8; |
923 | 815 | break; |
924 | 816 | |
925 | 817 | case 0x86: /* ROM readback / RAM write (low) -> update latch */ |
926 | | chip->rom_readback_addr = chip->rom_addr_hi | chip->rom_addr_mid | data; |
| 818 | m_rom_readback_addr = m_rom_addr_hi | m_rom_addr_mid | data; |
927 | 819 | break; |
928 | 820 | |
929 | 821 | case 0x87: /* RAM write */ |
930 | | if (chip->ext_mem_enable) |
| 822 | if (m_ext_mem_enable) |
931 | 823 | { |
932 | | if (!chip->ext_ram_write.isnull()) |
933 | | chip->ext_ram_write(chip->rom_readback_addr, data); |
| 824 | if (!m_ext_write_handler.isnull()) |
| 825 | m_ext_write_handler(m_rom_readback_addr, data); |
934 | 826 | else |
935 | | logerror("YMZ280B attempted RAM write to %X\n", chip->rom_readback_addr); |
936 | | chip->rom_readback_addr = (chip->rom_readback_addr + 1) & 0xffffff; |
| 827 | logerror("YMZ280B attempted RAM write to %X\n", m_rom_readback_addr); |
| 828 | m_rom_readback_addr = (m_rom_readback_addr + 1) & 0xffffff; |
937 | 829 | } |
938 | 830 | break; |
939 | 831 | |
940 | 832 | case 0xfe: /* IRQ mask */ |
941 | | chip->irq_mask = data; |
942 | | update_irq_state(chip); |
| 833 | m_irq_mask = data; |
| 834 | update_irq_state(); |
943 | 835 | break; |
944 | 836 | |
945 | 837 | case 0xff: /* IRQ enable, test, etc */ |
946 | | chip->ext_mem_enable = (data & 0x40) >> 6; |
947 | | chip->irq_enable = (data & 0x10) >> 4; |
948 | | update_irq_state(chip); |
| 838 | m_ext_mem_enable = (data & 0x40) >> 6; |
| 839 | m_irq_enable = (data & 0x10) >> 4; |
| 840 | update_irq_state(); |
949 | 841 | |
950 | | if (chip->keyon_enable && !(data & 0x80)) |
| 842 | if (m_keyon_enable && !(data & 0x80)) |
951 | 843 | { |
952 | 844 | for (i = 0; i < 8; i++) |
953 | 845 | { |
954 | | chip->voice[i].playing = 0; |
| 846 | m_voice[i].playing = 0; |
955 | 847 | |
956 | 848 | /* if update_irq_state_timer is set, cancel it. */ |
957 | | chip->voice[i].irq_schedule = 0; |
| 849 | m_voice[i].irq_schedule = 0; |
958 | 850 | } |
959 | 851 | } |
960 | | else if (!chip->keyon_enable && (data & 0x80)) |
| 852 | else if (!m_keyon_enable && (data & 0x80)) |
961 | 853 | { |
962 | 854 | for (i = 0; i < 8; i++) |
963 | 855 | { |
964 | | if (chip->voice[i].keyon && chip->voice[i].looping) |
965 | | chip->voice[i].playing = 1; |
| 856 | if (m_voice[i].keyon && m_voice[i].looping) |
| 857 | m_voice[i].playing = 1; |
966 | 858 | } |
967 | 859 | } |
968 | | chip->keyon_enable = (data & 0x80) >> 7; |
| 860 | m_keyon_enable = (data & 0x80) >> 7; |
969 | 861 | break; |
970 | 862 | |
971 | 863 | default: |
972 | | logerror("YMZ280B: unknown register write %02X = %02X\n", chip->current_register, data); |
| 864 | logerror("YMZ280B: unknown register write %02X = %02X\n", m_current_register, data); |
973 | 865 | break; |
974 | 866 | } |
975 | 867 | } |
r22733 | r22734 | |
983 | 875 | |
984 | 876 | ***********************************************************************************************/ |
985 | 877 | |
986 | | static int compute_status(ymz280b_state *chip) |
| 878 | int ymz280b_device::compute_status() |
987 | 879 | { |
988 | 880 | UINT8 result; |
989 | 881 | |
990 | 882 | /* force an update */ |
991 | | chip->stream->update(); |
| 883 | m_stream->update(); |
992 | 884 | |
993 | | result = chip->status_register; |
| 885 | result = m_status_register; |
994 | 886 | |
995 | 887 | /* clear the IRQ state */ |
996 | | chip->status_register = 0; |
997 | | update_irq_state(chip); |
| 888 | m_status_register = 0; |
| 889 | update_irq_state(); |
998 | 890 | |
999 | 891 | return result; |
1000 | 892 | } |
r22733 | r22734 | |
1007 | 899 | |
1008 | 900 | ***********************************************************************************************/ |
1009 | 901 | |
1010 | | READ8_DEVICE_HANDLER( ymz280b_r ) |
| 902 | READ8_MEMBER( ymz280b_device::read ) |
1011 | 903 | { |
1012 | | ymz280b_state *chip = get_safe_token(device); |
1013 | | |
1014 | 904 | if ((offset & 1) == 0) |
1015 | 905 | { |
1016 | | if (!chip->ext_mem_enable) |
| 906 | if (!m_ext_mem_enable) |
1017 | 907 | return 0xff; |
1018 | 908 | |
1019 | 909 | /* read from external memory */ |
1020 | | UINT8 result = ymz280b_read_memory(chip, chip->rom_readback_addr); |
1021 | | chip->rom_readback_addr = (chip->rom_readback_addr + 1) & 0xffffff; |
| 910 | UINT8 result = ymz280b_read_memory(m_rom_readback_addr); |
| 911 | m_rom_readback_addr = (m_rom_readback_addr + 1) & 0xffffff; |
1022 | 912 | return result; |
1023 | 913 | } |
1024 | 914 | else |
1025 | | return compute_status(chip); |
| 915 | return compute_status(); |
1026 | 916 | } |
1027 | 917 | |
1028 | 918 | |
1029 | | WRITE8_DEVICE_HANDLER( ymz280b_w ) |
| 919 | WRITE8_MEMBER( ymz280b_device::write ) |
1030 | 920 | { |
1031 | | ymz280b_state *chip = get_safe_token(device); |
1032 | | |
1033 | 921 | if ((offset & 1) == 0) |
1034 | | chip->current_register = data; |
| 922 | m_current_register = data; |
1035 | 923 | else |
1036 | 924 | { |
1037 | 925 | /* force an update */ |
1038 | | chip->stream->update(); |
| 926 | m_stream->update(); |
1039 | 927 | |
1040 | | write_to_register(chip, data); |
| 928 | write_to_register(data); |
1041 | 929 | } |
1042 | 930 | } |
1043 | 931 | |
r22733 | r22734 | |
1046 | 934 | |
1047 | 935 | ymz280b_device::ymz280b_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
1048 | 936 | : device_t(mconfig, YMZ280B, "YMZ280B", tag, owner, clock), |
1049 | | device_sound_interface(mconfig, *this) |
| 937 | device_sound_interface(mconfig, *this), |
| 938 | m_irq_handler(*this), |
| 939 | m_ext_read_handler(*this), |
| 940 | m_ext_write_handler(*this) |
1050 | 941 | { |
1051 | | m_token = global_alloc_clear(ymz280b_state); |
1052 | 942 | } |
1053 | 943 | |
1054 | 944 | //------------------------------------------------- |
r22733 | r22734 | |
1060 | 950 | void ymz280b_device::device_config_complete() |
1061 | 951 | { |
1062 | 952 | } |
1063 | | |
1064 | | //------------------------------------------------- |
1065 | | // device_start - device-specific startup |
1066 | | //------------------------------------------------- |
1067 | | |
1068 | | void ymz280b_device::device_start() |
1069 | | { |
1070 | | DEVICE_START_NAME( ymz280b )(this); |
1071 | | } |
1072 | | |
1073 | | //------------------------------------------------- |
1074 | | // device_reset - device-specific reset |
1075 | | //------------------------------------------------- |
1076 | | |
1077 | | void ymz280b_device::device_reset() |
1078 | | { |
1079 | | DEVICE_RESET_NAME( ymz280b )(this); |
1080 | | } |
1081 | | |
1082 | | //------------------------------------------------- |
1083 | | // sound_stream_update - handle a stream update |
1084 | | //------------------------------------------------- |
1085 | | |
1086 | | void ymz280b_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
1087 | | { |
1088 | | // should never get here |
1089 | | fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); |
1090 | | } |
trunk/src/mame/drivers/cave.c
r22733 | r22734 | |
423 | 423 | static ADDRESS_MAP_START( dfeveron_map, AS_PROGRAM, 16, cave_state ) |
424 | 424 | AM_RANGE(0x000000, 0x0fffff) AM_ROM // ROM |
425 | 425 | AM_RANGE(0x100000, 0x10ffff) AM_RAM // RAM |
426 | | AM_RANGE(0x300000, 0x300003) AM_DEVREADWRITE8_LEGACY("ymz", ymz280b_r, ymz280b_w, 0x00ff) // YMZ280 |
| 426 | AM_RANGE(0x300000, 0x300003) AM_DEVREADWRITE8("ymz", ymz280b_device, read, write, 0x00ff) // YMZ280 |
427 | 427 | /**/AM_RANGE(0x400000, 0x407fff) AM_RAM AM_SHARE("spriteram") // Sprites |
428 | 428 | /**/AM_RANGE(0x408000, 0x40ffff) AM_RAM AM_SHARE("spriteram_2") // Sprites? |
429 | 429 | /**/AM_RANGE(0x500000, 0x507fff) AM_RAM_WRITE(cave_vram_0_w) AM_SHARE("vram.0") // Layer 0 |
r22733 | r22734 | |
448 | 448 | static ADDRESS_MAP_START( ddonpach_map, AS_PROGRAM, 16, cave_state ) |
449 | 449 | AM_RANGE(0x000000, 0x0fffff) AM_ROM // ROM |
450 | 450 | AM_RANGE(0x100000, 0x10ffff) AM_RAM // RAM |
451 | | AM_RANGE(0x300000, 0x300003) AM_DEVREADWRITE8_LEGACY("ymz", ymz280b_r, ymz280b_w, 0x00ff) // YMZ280 |
| 451 | AM_RANGE(0x300000, 0x300003) AM_DEVREADWRITE8("ymz", ymz280b_device, read, write, 0x00ff) // YMZ280 |
452 | 452 | /**/AM_RANGE(0x400000, 0x407fff) AM_RAM AM_SHARE("spriteram") // Sprites |
453 | 453 | /**/AM_RANGE(0x408000, 0x40ffff) AM_RAM AM_SHARE("spriteram_2") // Sprites? |
454 | 454 | /**/AM_RANGE(0x500000, 0x507fff) AM_RAM_WRITE(cave_vram_0_w) AM_SHARE("vram.0") // Layer 0 |
r22733 | r22734 | |
524 | 524 | static ADDRESS_MAP_START( esprade_map, AS_PROGRAM, 16, cave_state ) |
525 | 525 | AM_RANGE(0x000000, 0x0fffff) AM_ROM // ROM |
526 | 526 | AM_RANGE(0x100000, 0x10ffff) AM_RAM // RAM |
527 | | AM_RANGE(0x300000, 0x300003) AM_DEVREADWRITE8_LEGACY("ymz", ymz280b_r, ymz280b_w, 0x00ff) // YMZ280 |
| 527 | AM_RANGE(0x300000, 0x300003) AM_DEVREADWRITE8("ymz", ymz280b_device, read, write, 0x00ff) // YMZ280 |
528 | 528 | /**/AM_RANGE(0x400000, 0x407fff) AM_RAM AM_SHARE("spriteram") // Sprites |
529 | 529 | /**/AM_RANGE(0x408000, 0x40ffff) AM_RAM AM_SHARE("spriteram_2") // Sprites? |
530 | 530 | /**/AM_RANGE(0x500000, 0x507fff) AM_RAM_WRITE(cave_vram_0_w) AM_SHARE("vram.0") // Layer 0 |
r22733 | r22734 | |
549 | 549 | static ADDRESS_MAP_START( gaia_map, AS_PROGRAM, 16, cave_state ) |
550 | 550 | AM_RANGE(0x000000, 0x0fffff) AM_ROM // ROM |
551 | 551 | AM_RANGE(0x100000, 0x10ffff) AM_RAM // RAM |
552 | | AM_RANGE(0x300000, 0x300003) AM_DEVREADWRITE8_LEGACY("ymz", ymz280b_r, ymz280b_w, 0x00ff) // YMZ280 |
| 552 | AM_RANGE(0x300000, 0x300003) AM_DEVREADWRITE8("ymz", ymz280b_device, read, write, 0x00ff) // YMZ280 |
553 | 553 | AM_RANGE(0x400000, 0x407fff) AM_RAM AM_SHARE("spriteram") // Sprite bank 1 |
554 | 554 | AM_RANGE(0x408000, 0x40ffff) AM_RAM AM_SHARE("spriteram_2") // Sprite bank 2 |
555 | 555 | AM_RANGE(0x500000, 0x507fff) AM_RAM_WRITE(cave_vram_0_w) AM_SHARE("vram.0") // Layer 0 |
r22733 | r22734 | |
586 | 586 | /**/AM_RANGE(0x500000, 0x507fff) AM_RAM_WRITE(cave_vram_0_w) AM_SHARE("vram.0") // Layer 0 |
587 | 587 | /**/AM_RANGE(0x600000, 0x607fff) AM_RAM_WRITE(cave_vram_1_w) AM_SHARE("vram.1") // Layer 1 |
588 | 588 | /**/AM_RANGE(0x700000, 0x707fff) AM_RAM_WRITE(cave_vram_2_w) AM_SHARE("vram.2") // Layer 2 |
589 | | AM_RANGE(0x800000, 0x800003) AM_DEVREADWRITE8_LEGACY("ymz", ymz280b_r, ymz280b_w, 0x00ff) // YMZ280 |
| 589 | AM_RANGE(0x800000, 0x800003) AM_DEVREADWRITE8("ymz", ymz280b_device, read, write, 0x00ff) // YMZ280 |
590 | 590 | /**/AM_RANGE(0x900000, 0x900005) AM_RAM AM_SHARE("vctrl.0") // Layer 0 Control |
591 | 591 | /**/AM_RANGE(0xa00000, 0xa00005) AM_RAM AM_SHARE("vctrl.1") // Layer 1 Control |
592 | 592 | /**/AM_RANGE(0xb00000, 0xb00005) AM_RAM AM_SHARE("vctrl.2") // Layer 2 Control |
r22733 | r22734 | |
700 | 700 | AM_RANGE(0x1c0000, 0x1c0007) AM_READ(cave_irq_cause_r) // IRQ Cause |
701 | 701 | AM_RANGE(0x1c0000, 0x1c007f) AM_WRITEONLY AM_SHARE("videoregs") // Video Regs |
702 | 702 | AM_RANGE(0x200000, 0x207fff) AM_WRITEONLY AM_SHARE("paletteram") // Palette |
703 | | // AM_RANGE(0x240000, 0x240003) AM_DEVREAD8_LEGACY("ymz", ymz280b_r, 0x00ff) // YMZ280 |
704 | | AM_RANGE(0x240000, 0x240003) AM_DEVWRITE8_LEGACY("ymz", ymz280b_w, 0x00ff) // YMZ280 |
| 703 | // AM_RANGE(0x240000, 0x240003) AM_DEVREAD8("ymz", ymz280b_device, read, 0x00ff) // YMZ280 |
| 704 | AM_RANGE(0x240000, 0x240003) AM_DEVWRITE8("ymz", ymz280b_device, write, 0x00ff) // YMZ280 |
705 | 705 | AM_RANGE(0x280000, 0x280001) AM_READ_PORT("IN0") // Inputs + ??? |
706 | 706 | AM_RANGE(0x280002, 0x280003) AM_READ_PORT("IN1") // Inputs + EEPROM |
707 | 707 | AM_RANGE(0x280008, 0x280009) AM_WRITE(korokoro_leds_w) // Leds |
r22733 | r22734 | |
716 | 716 | AM_RANGE(0x140000, 0x140005) AM_WRITEONLY AM_SHARE("vctrl.0") // Layer 0 Control |
717 | 717 | AM_RANGE(0x180000, 0x187fff) AM_WRITEONLY AM_SHARE("spriteram") // Sprites |
718 | 718 | AM_RANGE(0x200000, 0x207fff) AM_WRITEONLY AM_SHARE("paletteram") // Palette |
719 | | AM_RANGE(0x240000, 0x240003) AM_DEVWRITE8_LEGACY("ymz", ymz280b_w, 0x00ff) // YMZ280 |
| 719 | AM_RANGE(0x240000, 0x240003) AM_DEVWRITE8("ymz", ymz280b_device, write, 0x00ff) // YMZ280 |
720 | 720 | AM_RANGE(0x280000, 0x280001) AM_READ_PORT("IN0") // Inputs + ??? |
721 | 721 | AM_RANGE(0x280002, 0x280003) AM_READ_PORT("IN1") // Inputs + EEPROM |
722 | 722 | AM_RANGE(0x280008, 0x280009) AM_WRITE(korokoro_leds_w) // Leds |
r22733 | r22734 | |
991 | 991 | static ADDRESS_MAP_START( uopoko_map, AS_PROGRAM, 16, cave_state ) |
992 | 992 | AM_RANGE(0x000000, 0x0fffff) AM_ROM // ROM |
993 | 993 | AM_RANGE(0x100000, 0x10ffff) AM_RAM // RAM |
994 | | AM_RANGE(0x300000, 0x300003) AM_DEVREADWRITE8_LEGACY("ymz", ymz280b_r, ymz280b_w, 0x00ff) // YMZ280 |
| 994 | AM_RANGE(0x300000, 0x300003) AM_DEVREADWRITE8("ymz", ymz280b_device, read, write, 0x00ff) // YMZ280 |
995 | 995 | /**/AM_RANGE(0x400000, 0x407fff) AM_RAM AM_SHARE("spriteram") // Sprites |
996 | 996 | /**/AM_RANGE(0x408000, 0x40ffff) AM_RAM AM_SHARE("spriteram_2") // Sprites? |
997 | 997 | /**/AM_RANGE(0x500000, 0x507fff) AM_RAM_WRITE(cave_vram_0_w) AM_SHARE("vram.0") // Layer 0 |
r22733 | r22734 | |
1797 | 1797 | m_agallet_vblank_irq = 0; |
1798 | 1798 | } |
1799 | 1799 | |
1800 | | static const ymz280b_interface ymz280b_intf = |
1801 | | { |
1802 | | DEVCB_DRIVER_LINE_MEMBER(cave_state,sound_irq_gen) |
1803 | | }; |
1804 | | |
1805 | 1800 | WRITE_LINE_MEMBER(cave_state::irqhandler) |
1806 | 1801 | { |
1807 | 1802 | m_audiocpu->set_input_line(0, state ? ASSERT_LINE : CLEAR_LINE); |
r22733 | r22734 | |
1852 | 1847 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
1853 | 1848 | |
1854 | 1849 | MCFG_SOUND_ADD("ymz", YMZ280B, XTAL_16_9344MHz) |
1855 | | MCFG_SOUND_CONFIG(ymz280b_intf) |
| 1850 | MCFG_YMZ280B_IRQ_HANDLER(WRITELINE(cave_state, sound_irq_gen)) |
1856 | 1851 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
1857 | 1852 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
1858 | 1853 | MACHINE_CONFIG_END |
r22733 | r22734 | |
1894 | 1889 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
1895 | 1890 | |
1896 | 1891 | MCFG_SOUND_ADD("ymz", YMZ280B, XTAL_16_9344MHz) |
1897 | | MCFG_SOUND_CONFIG(ymz280b_intf) |
| 1892 | MCFG_YMZ280B_IRQ_HANDLER(WRITELINE(cave_state, sound_irq_gen)) |
1898 | 1893 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
1899 | 1894 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
1900 | 1895 | MACHINE_CONFIG_END |
r22733 | r22734 | |
1986 | 1981 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
1987 | 1982 | |
1988 | 1983 | MCFG_SOUND_ADD("ymz", YMZ280B, XTAL_16_9344MHz) |
1989 | | MCFG_SOUND_CONFIG(ymz280b_intf) |
| 1984 | MCFG_YMZ280B_IRQ_HANDLER(WRITELINE(cave_state, sound_irq_gen)) |
1990 | 1985 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
1991 | 1986 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
1992 | 1987 | MACHINE_CONFIG_END |
r22733 | r22734 | |
2026 | 2021 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
2027 | 2022 | |
2028 | 2023 | MCFG_SOUND_ADD("ymz", YMZ280B, XTAL_16_9344MHz) |
2029 | | MCFG_SOUND_CONFIG(ymz280b_intf) |
| 2024 | MCFG_YMZ280B_IRQ_HANDLER(WRITELINE(cave_state, sound_irq_gen)) |
2030 | 2025 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
2031 | 2026 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
2032 | 2027 | MACHINE_CONFIG_END |
r22733 | r22734 | |
2067 | 2062 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
2068 | 2063 | |
2069 | 2064 | MCFG_SOUND_ADD("ymz", YMZ280B, XTAL_16_9344MHz) |
2070 | | MCFG_SOUND_CONFIG(ymz280b_intf) |
| 2065 | MCFG_YMZ280B_IRQ_HANDLER(WRITELINE(cave_state, sound_irq_gen)) |
2071 | 2066 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
2072 | 2067 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
2073 | 2068 | MACHINE_CONFIG_END |
r22733 | r22734 | |
2163 | 2158 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
2164 | 2159 | |
2165 | 2160 | MCFG_SOUND_ADD("ymz", YMZ280B, XTAL_16_9344MHz) |
2166 | | MCFG_SOUND_CONFIG(ymz280b_intf) |
| 2161 | MCFG_YMZ280B_IRQ_HANDLER(WRITELINE(cave_state, sound_irq_gen)) |
2167 | 2162 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
2168 | 2163 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
2169 | 2164 | MACHINE_CONFIG_END |
r22733 | r22734 | |
2544 | 2539 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
2545 | 2540 | |
2546 | 2541 | MCFG_SOUND_ADD("ymz", YMZ280B, XTAL_16_9344MHz) |
2547 | | MCFG_SOUND_CONFIG(ymz280b_intf) |
| 2542 | MCFG_YMZ280B_IRQ_HANDLER(WRITELINE(cave_state, sound_irq_gen)) |
2548 | 2543 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
2549 | 2544 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
2550 | 2545 | MACHINE_CONFIG_END |