📄 es5506.c
字号:
//update_irq_state(chip); //} // (LOG_COMMANDS && eslog) //fprintf(eslog, "%06x:voice %d, loop end=%08x\n", cpu_getpreviouspc(), chip->current_page & 0x1f, voice->end); break; case 0x06: /* K2 */ voice->k2 = (voice->k2 & ~0x00f0) | (data & 0x00f0); voice->k2 = (voice->k2 & ~0xff00) | (data & 0xff00); break; case 0x07: /* K1 */ voice->k1 = (voice->k1 & ~0x00f0) | (data & 0x00f0); voice->k1 = (voice->k1 & ~0xff00) | (data & 0xff00); break; case 0x08: /* LVOL */ voice->lvol = (voice->lvol & ~0xff00) | (data & 0xff00); break; case 0x09: /* RVOL */ voice->rvol = (voice->rvol & ~0xff00) | (data & 0xff00); break; case 0x0a: /* ACC (hi) */ voice->accum = (voice->accum & ~0x03fc0000) | ((data & 0x00ff) << 18); voice->accum = (voice->accum & ~0x7c000000) | ((data & 0x1f00) << 18); if (!(voice->control & CONTROL_STOPMASK)) fprintf(stderr,"got it accum2\n"); break; case 0x0b: /* ACC (lo) */ voice->accum = (voice->accum & ~0x000003fc) | ((data & 0x00ff) << 2); voice->accum = (voice->accum & ~0x0003fc00) | ((data & 0xff00) << 2); if (!(voice->control & CONTROL_STOPMASK)) fprintf(stderr,"got it accum2bzz\n"); break; case 0x0c: /* unused */ break; case 0x0d: /* ACT */ { double sample_rate = chip->master_clock / (double)(16 * ((data & 0x1f) + 1)); if (audio_sample_rate) chip->output_step = (int)(sample_rate * (double)(1 << FRAC_BITS) / (double)audio_sample_rate); chip->active_voices = data & 0x1f; if (LOG_COMMANDS && eslog) fprintf(eslog, "active voices=%d, sample_rate=%d, output_step=%08x\n", chip->active_voices, (int)sample_rate, chip->output_step); } break; case 0x0e: /* IRQV - read only */ break; case 0x0f: /* PAGE */ chip->current_page = data & 0x7f; break; }}INLINE void es5505_reg_write_high(struct ES5506Chip *chip, struct ES5506Voice *voice, offs_t offset, UINT16 data, UINT16 mem_mask){ //fprintf(stderr,"reg_write_high %x\n",offset); switch (offset) { case 0x00: /* CR */ voice->control &= ~(CONTROL_STOPMASK | CONTROL_BS0 | CONTROL_LOOPMASK | CONTROL_IRQE | CONTROL_DIR | CONTROL_IRQ); voice->control |= (data & (CONTROL_STOPMASK | CONTROL_LOOPMASK | CONTROL_IRQE | CONTROL_DIR | CONTROL_IRQ)) | ((data << 12) & CONTROL_BS0); voice->control &= ~(CONTROL_CA0 | CONTROL_CA1 | CONTROL_LPMASK); voice->control |= ((data >> 2) & CONTROL_LPMASK) | ((data << 2) & (CONTROL_CA0 | CONTROL_CA1)); update_irq_state(chip); break; case 0x01: /* O4(n-1) */ voice->o4n1 = (voice->o4n1 & ~0x00ff) | (data & 0x00ff); voice->o4n1 = (INT16)((voice->o4n1 & ~0xff00) | (data & 0xff00)); break; case 0x02: /* O3(n-1) */ voice->o3n1 = (voice->o3n1 & ~0x00ff) | (data & 0x00ff); voice->o3n1 = (INT16)((voice->o3n1 & ~0xff00) | (data & 0xff00)); break; case 0x03: /* O3(n-2) */ voice->o3n2 = (voice->o3n2 & ~0x00ff) | (data & 0x00ff); voice->o3n2 = (INT16)((voice->o3n2 & ~0xff00) | (data & 0xff00)); break; case 0x04: /* O2(n-1) */ voice->o2n1 = (voice->o2n1 & ~0x00ff) | (data & 0x00ff); voice->o2n1 = (INT16)((voice->o2n1 & ~0xff00) | (data & 0xff00)); break; case 0x05: /* O2(n-2) */ voice->o2n2 = (voice->o2n2 & ~0x00ff) | (data & 0x00ff); voice->o2n2 = (INT16)((voice->o2n2 & ~0xff00) | (data & 0xff00)); break; case 0x06: /* O1(n-1) */ voice->o1n1 = (voice->o1n1 & ~0x00ff) | (data & 0x00ff); voice->o1n1 = (INT16)((voice->o1n1 & ~0xff00) | (data & 0xff00)); break; case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: /* unused */ break; case 0x0d: /* ACT */ { double sample_rate = chip->master_clock / (double)(16 * ((data & 0x1f) + 1)); if (audio_sample_rate) chip->output_step = (int)(sample_rate * (double)(1 << FRAC_BITS) / (double)audio_sample_rate); chip->active_voices = data & 0x1f; if (LOG_COMMANDS && eslog) fprintf(eslog, "active voices=%d, sample_rate=%d, output_step=%08x\n", chip->active_voices, (int)sample_rate, chip->output_step); } break; case 0x0e: /* IRQV - read only */ break; case 0x0f: /* PAGE */ chip->current_page = data & 0x7f; break; }}INLINE void es5505_reg_write_test(struct ES5506Chip *chip, struct ES5506Voice *voice, offs_t offset, UINT16 data, UINT16 mem_mask){ //fprintf(stderr,"writetest offset %x data %x\n",offset,data); switch (offset) { case 0x00: /* CH0L */ case 0x01: /* CH0R */ case 0x02: /* CH1L */ case 0x03: /* CH1R */ case 0x04: /* CH2L */ case 0x05: /* CH2R */ case 0x06: /* CH3L */ case 0x07: /* CH3R */ break; case 0x08: /* SERMODE */ chip->mode = data & 0x0007; break; case 0x09: /* PAR */ break; case 0x0d: /* ACT */ if (ACCESSING_LSB) { double sample_rate = chip->master_clock / (double)(16 * ((data & 0x1f) + 1)); if (audio_sample_rate) chip->output_step = (int)(sample_rate * (double)(1 << FRAC_BITS) / (double)audio_sample_rate); chip->active_voices = data & 0x1f; if (LOG_COMMANDS && eslog) fprintf(eslog, "active voices=%d, sample_rate=%d, output_step=%08x\n", chip->active_voices, (int)sample_rate, chip->output_step); } break; case 0x0e: /* IRQV - read only */ break; case 0x0f: /* PAGE */ if (ACCESSING_LSB) chip->current_page = data & 0x7f; break; }}static void es5505_reg_write(struct ES5506Chip *chip, offs_t offset, data16_t data, data16_t mem_mask){ struct ES5506Voice *voice = &chip->voice[chip->current_page & 0x1f]; //fprintf(stderr,"reg_write %x\n",offset); // logerror("%04x:ES5505 write %02x/%02x = %04x & %04x\n", cpu_getpreviouspc(), chip->current_page, offset, data, mem_mask ^ 0xffff); /* force an update */ stream_update(chip->stream, 0); /* switch off the page and register */ if (chip->current_page < 0x20) es5505_reg_write_low(chip, voice, offset, data, mem_mask); else if (chip->current_page < 0x40) es5505_reg_write_high(chip, voice, offset, data, mem_mask); else es5505_reg_write_test(chip, voice, offset, data, mem_mask);}/********************************************************************************************** es5505_reg_read -- read from the specified ES5505 register***********************************************************************************************/INLINE UINT16 es5505_reg_read_low(struct ES5506Chip *chip, struct ES5506Voice *voice, offs_t offset){ UINT16 result = 0; switch (offset) { case 0x00: /* CR */ result = (voice->control & (CONTROL_STOPMASK | CONTROL_LOOPMASK | CONTROL_IRQE | CONTROL_DIR | CONTROL_IRQ)) | ((voice->control & CONTROL_BS0) >> 12) | ((voice->control & CONTROL_LPMASK) << 2) | ((voice->control & (CONTROL_CA0 | CONTROL_CA1)) >> 2) | 0xf000; voice->control &= ~CONTROL_IRQ; update_irq_state(chip); break; case 0x01: /* FC */ result = voice->freqcount >> 1; break; case 0x02: /* STRT (hi) */ result = voice->start >> 18; break; case 0x03: /* STRT (lo) */ result = voice->start >> 2; break; case 0x04: /* END (hi) */ result = voice->end >> 18; break; case 0x05: /* END (lo) */ result = voice->end >> 2; break; case 0x06: /* K2 */ result = voice->k2; break; case 0x07: /* K1 */ result = voice->k1; break; case 0x08: /* LVOL */ result = voice->lvol; break; case 0x09: /* RVOL */ result = voice->rvol; break; case 0x0a: /* ACC (hi) */ result = voice->accum >> 18; break; case 0x0b: /* ACC (lo) */ result = voice->accum >> 2; break; case 0x0c: /* unused */ break; case 0x0d: /* ACT */ result = chip->active_voices; break; case 0x0e: /* IRQV */ result = chip->irqv; break; case 0x0f: /* PAGE */ result = chip->current_page; break; } return result;}INLINE UINT16 es5505_reg_read_high(struct ES5506Chip *chip, struct ES5506Voice *voice, offs_t offset){ UINT16 result = 0; switch (offset) { case 0x00: /* CR */ result = (voice->control & (CONTROL_STOPMASK | CONTROL_LOOPMASK | CONTROL_IRQE | CONTROL_DIR | CONTROL_IRQ)) | ((voice->control & CONTROL_BS0) >> 12) | ((voice->control & CONTROL_LPMASK) << 2) | ((voice->control & (CONTROL_CA0 | CONTROL_CA1)) >> 2) | 0xf000; voice->control &= ~CONTROL_IRQ; update_irq_state(chip); break; case 0x01: /* O4(n-1) */ result = voice->o4n1; break; case 0x02: /* O3(n-1) */ result = voice->o3n1; break; case 0x03: /* O3(n-2) */ result = voice->o3n2; break; case 0x04: /* O2(n-1) */ result = voice->o2n1; break; case 0x05: /* O2(n-2) */ result = voice->o2n2; break; case 0x06: /* O1(n-1) */ /* special case for the Taito F3 games: they set the accumulator on a stopped */ /* voice and assume the filters continue to process the data. They then read */ /* the O1(n-1) in order to extract raw data from the sound ROMs. Since we don't */ /* want to waste time filtering stopped channels, we just look for a read from */ /* this register on a stopped voice, and return the raw sample data at the */ /* accumulator */ if ((voice->control & CONTROL_STOPMASK) && chip->region_base[voice->control >> 14]) voice->o1n1 = chip->region_base[voice->control >> 14][voice->exbank + (voice->accum >> 11)]; result = voice->o1n1; break; case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: /* unused */ break; case 0x0d: /* ACT */ result = chip->active_voices; break; case 0x0e: /* IRQV */ result = chip->irqv; break; case 0x0f: /* PAGE */ result = chip->current_page; break; } return result;}INLINE UINT16 es5505_reg_read_test(struct ES5506Chip *chip, struct ES5506Voice *voice, offs_t offset){ UINT16 result = 0; switch (offset) { case 0x00: /* CH0L */ case 0x01: /* CH0R */ case 0x02: /* CH1L */ case 0x03: /* CH1R */ case 0x04: /* CH2L */ case 0x05: /* CH2R */ case 0x06: /* CH3L */ case 0x07: /* CH3R */ break; case 0x08: /* SERMODE */ result = chip->mode; break; case 0x09: /* PAR */ if (chip->port_read) result = (*chip->port_read)(); break; case 0x0f: /* PAGE */ result = chip->current_page; break; } return result;}static data16_t es5505_reg_read(struct ES5506Chip *chip, offs_t offset){ struct ES5506Voice *voice = &chip->voice[chip->current_page & 0x1f]; data16_t result = 0; if (LOG_COMMANDS && eslog) fprintf(eslog, "read from %02x/%02x -> ", chip->current_page, offset); /* force an update */ stream_update(chip->stream, 0); /* switch off the page and register */ if (chip->current_page < 0x20) result = es5505_reg_read_low(chip, voice, offset); else if (chip->current_page < 0x40) result = es5505_reg_read_high(chip, voice, offset); else result = es5505_reg_read_test(chip, voice, offset); if (LOG_COMMANDS && eslog) fprintf(eslog, "%04x (accum=%08x)\n", result, voice->accum); /* return the high byte */ return result;}/********************************************************************************************** ES5505_data_0_r/ES5505_data_1_r -- handle a read from the status register***********************************************************************************************/READ16_HANDLER( ES5505_data_0_r ){ int res; offset &= 0x3f; res=es5505_reg_read(&es5506[0], offset>>1);#ifdef DUMP fprintf(stderr,"ess %x -> %x (pc:%6x)\n",offset>>1,res,s68000readPC());#endif return res;}READ16_HANDLER( ES5505_data_1_r ){ offset &= 0x3f; return es5505_reg_read(&es5506[1], offset>>1);}/********************************************************************************************** ES5505_data_0_w/ES5505_data_1_w -- handle a write to the current register***********************************************************************************************/WRITE16_HANDLER( ES5505_data_0_ww ){ offset &= 0x3f;#ifdef DUMP fprintf(stderr,"es5505_data_0_w %x,%x (%x)\n",offset>>1,data,s68000readPC());#endif es5505_reg_write(&es5506[0], offset>>1, data, 0);}WRITE_HANDLER( ES5505_data_0_wb ){ int mem_mask; offset &= 0x3f;#ifdef DUMP fprintf(stderr,"es5505_data_0_w %x,%d\n",offset>>1,data);#endif if (offset & 1) { mem_mask = 0xff00; } else { mem_mask = 0x00ff; } fprintf(stderr,"mem_mask bad\n"); exit(1); es5505_reg_write(&es5506[0], offset>>1, data, mem_mask);}WRITE16_HANDLER( ES5505_data_1_ww ){ offset &= 0x1f; es5505_reg_write(&es5506[1], offset>>1, data, 0);}WRITE_HANDLER( ES5505_data_1_wb ){ int mem_mask; offset &= 0x1f; if (offset & 1) { mem_mask = 0xff00; } else { mem_mask = 0x00ff; } es5505_reg_write(&es5506[1], offset>>1, data, mem_mask);}void ES5506_voice_bank_0_w(int voice, int bank){ es5506[0].voice[voice].control = CONTROL_STOPMASK; es5506[0].voice[voice].exbank=bank;}void ES5506_voice_bank_1_w(int voice, int bank){ es5506[1].voice[voice].control = CONTROL_STOPMASK; es5506[1].voice[voice].exbank=bank;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -