📄 es5506.c
字号:
fprintf(eslog, "voice %d, K2 ramp=%04x\n", chip->current_page & 0x1f, voice->k2ramp); break; case 0x48/8: /* K1 */ voice->k1 = data & 0xffff; if (LOG_COMMANDS && eslog) fprintf(eslog, "voice %d, K1=%04x\n", chip->current_page & 0x1f, voice->k1); break; case 0x50/8: /* K1RAMP */ voice->k1ramp = ((data & 0xff00) >> 8) | ((data & 0x0001) << 31); if (LOG_COMMANDS && eslog) fprintf(eslog, "voice %d, K1 ramp=%04x\n", chip->current_page & 0x1f, voice->k1ramp); break; case 0x58/8: /* ACTV */ { 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 0x60/8: /* MODE */ chip->mode = data & 0x1f; break; case 0x68/8: /* PAR - read only */ case 0x70/8: /* IRQV - read only */ break; case 0x78/8: /* PAGE */ chip->current_page = data & 0x7f; break; }}INLINE void es5506_reg_write_high(struct ES5506Chip *chip, struct ES5506Voice *voice, offs_t offset, UINT32 data){ //fprintf(stderr,"ess_reg_write_high %x %d\n",offset,data); switch (offset) { case 0x00/8: /* CR */ //if (!(voice->control & CONTROL_IRQ)){ voice->control = data & 0xffff; update_irq_state(chip); //} break; case 0x08/8: /* START */ voice->start = data & 0x7ffff800; if (!(voice->control & CONTROL_STOPMASK)) fprintf(stderr,"got it start\n"); break; case 0x10/8: /* END */ voice->end = data & 0x7fffff80; if (!(voice->control & CONTROL_STOPMASK)) fprintf(stderr,"got it end\n"); break; case 0x18/8: /* ACCUM */ voice->accum = data & 0x7fffff80; if (!(voice->control & CONTROL_STOPMASK)) fprintf(stderr,"got it accum\n"); break; case 0x20/8: /* O4(n-1) */ voice->o4n1 = (INT32)(data << 14) >> 14; if (LOG_COMMANDS && eslog) fprintf(eslog, "voice %d, O4(n-1)=%05x\n", chip->current_page & 0x1f, voice->o4n1 & 0x3ffff); break; case 0x28/8: /* O3(n-1) */ voice->o3n1 = (INT32)(data << 14) >> 14; if (LOG_COMMANDS && eslog) fprintf(eslog, "voice %d, O3(n-1)=%05x\n", chip->current_page & 0x1f, voice->o3n1 & 0x3ffff); break; case 0x30/8: /* O3(n-2) */ voice->o3n2 = (INT32)(data << 14) >> 14; if (LOG_COMMANDS && eslog) fprintf(eslog, "voice %d, O3(n-2)=%05x\n", chip->current_page & 0x1f, voice->o3n2 & 0x3ffff); break; case 0x38/8: /* O2(n-1) */ voice->o2n1 = (INT32)(data << 14) >> 14; if (LOG_COMMANDS && eslog) fprintf(eslog, "voice %d, O2(n-1)=%05x\n", chip->current_page & 0x1f, voice->o2n1 & 0x3ffff); break; case 0x40/8: /* O2(n-2) */ voice->o2n2 = (INT32)(data << 14) >> 14; if (LOG_COMMANDS && eslog) fprintf(eslog, "voice %d, O2(n-2)=%05x\n", chip->current_page & 0x1f, voice->o2n2 & 0x3ffff); break; case 0x48/8: /* O1(n-1) */ voice->o1n1 = (INT32)(data << 14) >> 14; if (LOG_COMMANDS && eslog) fprintf(eslog, "voice %d, O1(n-1)=%05x\n", chip->current_page & 0x1f, voice->o1n1 & 0x3ffff); break; case 0x50/8: /* W_ST */ chip->wst = data & 0x7f; break; case 0x58/8: /* W_END */ chip->wend = data & 0x7f; break; case 0x60/8: /* LR_END */ chip->lrend = data & 0x7f; break; case 0x68/8: /* PAR - read only */ case 0x70/8: /* IRQV - read only */ break; case 0x78/8: /* PAGE */ chip->current_page = data & 0x7f; break; }}static void es5506_reg_write(struct ES5506Chip *chip, offs_t offset, data8_t data){ struct ES5506Voice *voice = &chip->voice[chip->current_page & 0x1f]; int shift = 8 * (offset & 3); //fprintf(stderr,"ess_reg_write %x %d\n",offset,data); /* accumulate the data */ chip->write_latch = (chip->write_latch & ~(0xff000000 >> shift)) | (data << (24 - shift)); /* wait for a write to complete */ if (shift != 24) return;/* logerror("%04x:ES5506 write %02x/%02x = %08x\n", cpu_getpreviouspc(), chip->current_page, offset / 4 * 8, chip->write_latch);*/ /* force an update */ stream_update(chip->stream, 0); /* switch off the page and register */ if (chip->current_page < 0x20) es5506_reg_write_low(chip, voice, offset / 4, chip->write_latch); else if (chip->current_page < 0x40) es5506_reg_write_high(chip, voice, offset / 4, chip->write_latch); /* clear the write latch when done */ chip->write_latch = 0;}/********************************************************************************************** es5506_reg_read -- read from the specified ES5506 register***********************************************************************************************/INLINE UINT32 es5506_reg_read_low(struct ES5506Chip *chip, struct ES5506Voice *voice, offs_t offset){ UINT32 result = 0; switch (offset) { case 0x00/8: /* CR */ result = voice->control; voice->control &= ~CONTROL_IRQ; update_irq_state(chip); break; case 0x08/8: /* FC */ result = voice->freqcount; break; case 0x10/8: /* LVOL */ result = voice->lvol; break; case 0x18/8: /* LVRAMP */ result = voice->lvramp << 8; break; case 0x20/8: /* RVOL */ result = voice->rvol; break; case 0x28/8: /* RVRAMP */ result = voice->rvramp << 8; break; case 0x30/8: /* ECOUNT */ result = voice->ecount; break; case 0x38/8: /* K2 */ result = voice->k2; break; case 0x40/8: /* K2RAMP */ result = (voice->k2ramp << 8) | (voice->k2ramp >> 31); break; case 0x48/8: /* K1 */ result = voice->k1; break; case 0x50/8: /* K1RAMP */ result = (voice->k1ramp << 8) | (voice->k1ramp >> 31); break; case 0x58/8: /* ACTV */ result = chip->active_voices; break; case 0x60/8: /* MODE */ result = chip->mode; break; case 0x68/8: /* PAR */ if (chip->port_read) result = (*chip->port_read)(); break; case 0x70/8: /* IRQV */ result = chip->irqv; break; case 0x78/8: /* PAGE */ result = chip->current_page; break; } return result;}INLINE UINT32 es5506_reg_read_high(struct ES5506Chip *chip, struct ES5506Voice *voice, offs_t offset){ UINT32 result = 0; switch (offset) { case 0x00/8: /* CR */ result = voice->control; voice->control &= ~CONTROL_IRQ; update_irq_state(chip); break; case 0x08/8: /* START */ result = voice->start; break; case 0x10/8: /* END */ result = voice->end; break; case 0x18/8: /* ACCUM */ result = voice->accum; break; case 0x20/8: /* O4(n-1) */ result = voice->o4n1 & 0x3ffff; break; case 0x28/8: /* O3(n-1) */ result = voice->o3n1 & 0x3ffff; break; case 0x30/8: /* O3(n-2) */ result = voice->o3n2 & 0x3ffff; break; case 0x38/8: /* O2(n-1) */ result = voice->o2n1 & 0x3ffff; break; case 0x40/8: /* O2(n-2) */ result = voice->o2n2 & 0x3ffff; break; case 0x48/8: /* O1(n-1) */ result = voice->o1n1 & 0x3ffff; break; case 0x50/8: /* W_ST */ result = chip->wst; break; case 0x58/8: /* W_END */ result = chip->wend; break; case 0x60/8: /* LR_END */ result = chip->lrend; break; case 0x68/8: /* PAR */ if (chip->port_read) result = (*chip->port_read)(); break; case 0x70/8: /* IRQV */ result = chip->irqv; break; case 0x78/8: /* PAGE */ result = chip->current_page; break; } return result;}static data8_t es5506_reg_read(struct ES5506Chip *chip, offs_t offset){ struct ES5506Voice *voice = &chip->voice[chip->current_page & 0x1f]; int shift = 8 * (offset & 3); /* only read on offset 0 */ if (shift != 0) return chip->read_latch >> (24 - shift); if (LOG_COMMANDS && eslog) fprintf(eslog, "read from %02x/%02x -> ", chip->current_page, offset / 4 * 8); /* force an update */ stream_update(chip->stream, 0); /* switch off the page and register */ if (chip->current_page < 0x20) chip->read_latch = es5506_reg_read_low(chip, voice, offset / 4); else if (chip->current_page < 0x40) chip->read_latch = es5506_reg_read_high(chip, voice, offset / 4); if (LOG_COMMANDS && eslog) fprintf(eslog, "%08x\n", chip->read_latch); /* return the high byte */ return chip->read_latch >> 24;}/********************************************************************************************** ES5506_data_0_r/ES5506_data_1_r -- handle a read from the status register***********************************************************************************************/READ_HANDLER( ES5506_data_0_r ){ int res; offset&=0x3f; res = es5506_reg_read(&es5506[0], offset>>1);#ifdef DUMP fprintf(stderr,"ess %x -> %x (pc:%6x)\n",offset>>1,res,s68000readPC());#endif return res;}READ_HANDLER( ES5506_data_1_r ){ offset&=0x3f; return es5506_reg_read(&es5506[1], offset>>1);}/********************************************************************************************** ES5506_data_0_w/ES5506_data_1_w -- handle a write to the current register***********************************************************************************************/WRITE_HANDLER( ES5506_data_0_w ){ offset&=0x3f; // How fascinating : these functions do not care about mem_mask ???! es5506_reg_write(&es5506[0], offset>>1, data);}WRITE_HANDLER( ES5506_data_1_w ){ offset&=0x3f; es5506_reg_write(&es5506[1], offset>>1, data);}/********************************************************************************************** ES5505_sh_start -- start emulation of the ES5505***********************************************************************************************/int ES5505_sh_start(const struct ES5505interface *intf){ struct ES5506interface es5506intf; memset(&es5506intf, 0, sizeof(es5506intf)); es5506intf.num = intf->num; memcpy(es5506intf.baseclock, intf->baseclock, sizeof(es5506intf.baseclock)); memcpy(es5506intf.region0, intf->region0, sizeof(es5506intf.region0)); memcpy(es5506intf.region1, intf->region1, sizeof(es5506intf.region1)); memcpy(es5506intf.mixing_level, intf->mixing_level, sizeof(es5506intf.mixing_level)); memcpy(es5506intf.irq_callback, intf->irq_callback, sizeof(es5506intf.irq_callback)); memcpy(es5506intf.read_port, intf->read_port, sizeof(es5506intf.read_port)); return ES5506_sh_start(&es5506intf);}/********************************************************************************************** ES5505_sh_stop -- stop emulation of the ES5506***********************************************************************************************/void ES5505_sh_stop(void){ ES5506_sh_stop();} /********************************************************************************************** es5505_reg_write -- handle a write to the selected ES5505 register***********************************************************************************************/INLINE void es5505_reg_write_low(struct ES5506Chip *chip, struct ES5506Voice *voice, offs_t offset, UINT16 data, UINT16 mem_mask){ //fprintf(stderr,"reg_write_low %x %d\n",offset,data); switch (offset) { case 0x00: /* CR */#if 1 // Notice : normally ACCESSING_LSB and MSB should be ALWAYS true. // I am not totally certain, so I leave the code this way for now //if (!(voice->control & CONTROL_IRQ)){ //fprintf(stderr,"voice %x old status %x... ",voice,voice->control); voice->control &= ~(CONTROL_STOPMASK | CONTROL_LOOPMASK | CONTROL_DIR); 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); //fprintf(stderr,"new status %x\n",voice->control); //} else //fprintf(stderr,"reject %x\n",voice->control);#else if (ACCESSING_LSB) { 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); } if (ACCESSING_MSB) { voice->control &= ~(CONTROL_CA0 | CONTROL_CA1 | CONTROL_LPMASK); voice->control |= ((data >> 2) & CONTROL_LPMASK) | ((data << 2) & (CONTROL_CA0 | CONTROL_CA1)); }#endif break; case 0x01: /* FC */ voice->freqcount = (voice->freqcount & ~0x001fe) | ((data & 0x00ff) << 1); voice->freqcount = (voice->freqcount & ~0x1fe00) | ((data & 0xff00) << 1); break; case 0x02: /* STRT (hi) */ voice->start = (voice->start & ~0x03fc0000) | ((data & 0x00ff) << 18); voice->start = (voice->start & ~0x7c000000) | ((data & 0x1f00) << 18); /* generate interrupt */ break; case 0x03: /* STRT (lo) */ voice->start = (voice->start & ~0x00000380) | ((data & 0x00e0) << 2); voice->start = (voice->start & ~0x0003fc00) | ((data & 0xff00) << 2); /* generate interrupt */ break; case 0x04: /* END (hi) */ voice->end = (voice->end & ~0x03fc0000) | ((data & 0x00ff) << 18); voice->end = (voice->end & ~0x7c000000) | ((data & 0x1f00) << 18); voice->control |= CONTROL_STOP0; /* generate interrupt */ break; case 0x05: /* END (lo) */ voice->end = (voice->end & ~0x00000380) | ((data & 0x00e0) << 2); voice->end = (voice->end & ~0x0003fc00) | ((data & 0xff00) << 2); voice->control |= CONTROL_STOP0; /* generate interrupt */ //if ((voice->control&3)==0 && voice->accum < voice->start){ //voice->control |= (CONTROL_IRQ | CONTROL_STOPMASK);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -