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 |