private static void OPN2_DoIO(ym3438_ chip) { chip.write_a_en = (chip.write_a & 0x03) == 0x01; chip.write_d_en = (chip.write_d & 0x03) == 0x01; chip.write_a <<= 1; chip.write_d <<= 1; //BUSY Counter chip.busy = chip.write_busy; chip.write_busy_cnt += 1; bool cnt5 = chip.write_busy_cnt >> 5 != 0 ? true : false; chip.write_busy = (chip.write_busy && !cnt5) || chip.write_d_en; chip.write_busy_cnt &= 0x1f; }
void OPN2_Write(ym3438_ chip, Bit32u port, Bit8u data) { port &= 3; chip.write_data = (Bit16u)(((port << 7) & 0x100) | data); if ((port & 1) != 0) { /* Data */ chip.write_d |= 1; } else { /* Address */ chip.write_a |= 1; } }
void OPN2_Reset(ym3438_ chip) { Bit32u i; chip = new ym3438_(); for (i = 0; i < 24; i++) { chip.eg_out[i] = 0x3ff; chip.eg_level[i] = 0x3ff; chip.eg_state[i] = (Bit8u)EG_PARAM.eg_num_release; chip.multi[i] = 1; } for (i = 0; i < 6; i++) { chip.pan_l[i] = 1; chip.pan_r[i] = 1; } }
public void OPN2_PhaseGenerate(ym3438_ chip) { Bit32u slot; /* Mask increment */ slot = (chip.cycles + 20) % 24; if (chip.pg_reset[slot] != 0) { chip.pg_inc[slot] = 0; } /* Phase step */ slot = (chip.cycles + 19) % 24; chip.pg_phase[slot] += chip.pg_inc[slot]; chip.pg_phase[slot] &= 0xfffff; if (chip.pg_reset[slot] != 0 || chip.mode_test_21[3]) { chip.pg_phase[slot] = 0; } }
void OPN2_Clock(ym3438_ chip, Bit32u[] buffer) { Bit32u slot = chip.cycles; chip.lfo_inc = (Bit8)(chip.mode_test_21[1] ? 1 : 0); chip.pg_read >>= 1; chip.eg_read[1] >>= 1; chip.eg_cycle++; /* Lock envelope generator timer value */ if (chip.cycles == 1 && chip.eg_quotient == 2) { if (chip.eg_cycle_stop != 0) { chip.eg_shift_lock = 0; } else { chip.eg_shift_lock = (Bit8u)(chip.eg_shift + 1); } chip.eg_timer_low_lock = (Bit8u)(chip.eg_timer & 0x03); } /* Cycle specific functions */ switch (chip.cycles) { case 0: chip.lfo_pm = (Bit8u)(chip.lfo_cnt >> 2); if ((chip.lfo_cnt & 0x40) != 0) { chip.lfo_am = (Bit8u)(chip.lfo_cnt & 0x3f); } else { chip.lfo_am = (Bit8u)(chip.lfo_cnt ^ 0x3f); } chip.lfo_am <<= 1; break; case 1: chip.eg_quotient++; chip.eg_quotient %= 3; chip.eg_cycle = 0; chip.eg_cycle_stop = 1; chip.eg_shift = 0; chip.eg_timer_inc |= (Bit8u)(chip.eg_quotient >> 1); chip.eg_timer = (Bit16u)(chip.eg_timer + chip.eg_timer_inc); chip.eg_timer_inc = (Bit8u)(chip.eg_timer >> 12); chip.eg_timer &= 0xfff; break; case 2: chip.pg_read = chip.pg_phase[21] & 0x3ff; chip.eg_read[1] = chip.eg_out[0]; break; case 13: chip.eg_cycle = 0; chip.eg_cycle_stop = 1; chip.eg_shift = 0; chip.eg_timer = (Bit16u)(chip.eg_timer + chip.eg_timer_inc); chip.eg_timer_inc = (Bit8u)(chip.eg_timer >> 12); chip.eg_timer &= 0xfff; break; case 23: chip.lfo_inc |= 1; break; } chip.eg_timer &= (Bit16u)(~((chip.mode_test_21[5] ? 1 : 0) << chip.eg_cycle)); if ((((chip.eg_timer >> chip.eg_cycle) | (chip.pin_test_in & chip.eg_custom_timer)) & chip.eg_cycle_stop) != 0) { chip.eg_shift = chip.eg_cycle; chip.eg_cycle_stop = 0; } OPN2_DoIO(chip); OPN2_DoTimerA(chip); OPN2_DoTimerB(chip); OPN2_KeyOn(chip); OPN2_ChOutput(chip); OPN2_ChGenerate(chip); OPN2_FMPrepare(chip); OPN2_FMGenerate(chip); OPN2_PhaseGenerate(chip); OPN2_PhaseCalcIncrement(chip); OPN2_EnvelopeADSR(chip); OPN2_EnvelopeGenerate(chip); OPN2_EnvelopeSSGEG(chip); OPN2_EnvelopePrepare(chip); /* Prepare fnum & block */ if (chip.mode_ch3 != 0) { /* Channel 3 special mode */ switch (slot) { case 1: /* OP1 */ chip.pg_fnum = chip.fnum_3ch[1]; chip.pg_block = chip.block_3ch[1]; chip.pg_kcode = chip.kcode_3ch[1]; break; case 7: /* OP3 */ chip.pg_fnum = chip.fnum_3ch[0]; chip.pg_block = chip.block_3ch[0]; chip.pg_kcode = chip.kcode_3ch[0]; break; case 13: /* OP2 */ chip.pg_fnum = chip.fnum_3ch[2]; chip.pg_block = chip.block_3ch[2]; chip.pg_kcode = chip.kcode_3ch[2]; break; case 19: /* OP4 */ default: chip.pg_fnum = chip.fnum[(chip.channel + 1) % 6]; chip.pg_block = chip.block[(chip.channel + 1) % 6]; chip.pg_kcode = chip.kcode[(chip.channel + 1) % 6]; break; } } else { chip.pg_fnum = chip.fnum[(chip.channel + 1) % 6]; chip.pg_block = chip.block[(chip.channel + 1) % 6]; chip.pg_kcode = chip.kcode[(chip.channel + 1) % 6]; } OPN2_UpdateLFO(chip); OPN2_DoRegWrite(chip); chip.cycles = (chip.cycles + 1) % 24; chip.channel = chip.cycles % 6; buffer[0] = (Bit16u)chip.mol; buffer[1] = (Bit16u)chip.mor; }
private static void OPN2_DoRegWrite(ym3438_ chip) { int i; Bit32u slot = chip.cycles % 12; Bit32u address; Bit32u channel = chip.channel; if (chip.write_fm_data) { if (ym3438_const.op_offset[slot] == (chip.address & 0x107)) { if ((chip.address & 0x08) != 0) { slot += 12; // OP2? OP4? } address = (Bit32u)chip.address & 0xf0; switch (address) { case 0x30: //DT MULTI chip.multi[slot] = (Bit8u)(chip.data & 0x0f); if (chip.multi[slot] == 0) { chip.multi[slot] = 1; } else { chip.multi[slot] <<= 1; } chip.dt[slot] = (Bit8u)((chip.data >> 4) & 0x07); break; case 0x40: //TL chip.tl[slot] = (Bit8u)(chip.data & 0x7f); break; case 0x50: // KS AR chip.ar[slot] = (Bit8u)(chip.data & 0x1f); chip.ks[slot] = (Bit8u)((chip.data >> 7) & 0x03); break; case 0x60: // AM DR chip.dr[slot] = (Bit8u)(chip.data & 0x1f); chip.am[slot] = (Bit8u)((chip.data >> 7) & 0x01); break; case 0x70: //SR chip.sr[slot] = (Bit8u)(chip.data & 0x1f); break; case 0x80: //SL RR chip.rr[slot] = (Bit8u)(chip.data & 0x0f); chip.sl[slot] = (Bit8u)((chip.data >> 4) & 0x0f); chip.sl[slot] |= (Bit8u)((chip.sl[slot] + 1) & 0x10); break; case 0x90: chip.ssg_eg[slot] = (Bit8u)(chip.data & 0x0f); break; default: break; } } if (ym3438_const.ch_offset[channel] == (chip.address & 0x103)) { address = (Bit32u)(chip.address & 0xfc); switch (address) { case 0xa0: //Fnum, Block, kcode chip.fnum[channel] = (Bit8u)((chip.data & 0xff) | ((chip.reg_a4 & 0x07) << 8)); chip.block[channel] = (Bit8u)((chip.reg_a4 >> 3) & 0x07); chip.kcode[channel] = (Bit8u)((chip.block[channel] << 2) | ym3438_const.fn_note[chip.fnum[channel] >> 7]); break; case 0xa4: // a4? chip.reg_a4 = (Bit8u)(chip.data & 0xff); break; case 0xa8: // fnum, block, kcode 3ch chip.fnum_3ch[channel] = (Bit8u)((chip.data & 0xff) | ((chip.reg_ac & 0x07) << 8)); chip.block_3ch[channel] = (Bit8u)((chip.reg_ac >> 3) & 0x07); chip.kcode_3ch[channel] = (Bit8u)((chip.block_3ch[channel] << 2) | ym3438_const.fn_note[chip.fnum_3ch[channel] >> 7]); break; case 0xac: //ac? chip.reg_ac = (Bit8u)(chip.data & 0xff); break; case 0xb0: // Connect FeedBack chip.connect[channel] = (Bit8u)(chip.data & 0x07); chip.fb[channel] = (Bit8u)((chip.data >> 3) & 0x07); break; case 0xb4: //Modulate Pan chip.pms[channel] = (Bit8u)(chip.data & 0x07); chip.ams[channel] = (Bit8u)((chip.data >> 4) & 0x03); chip.pan_l[channel] = (Bit8u)((chip.data >> 7) & 0x01); chip.pan_r[channel] = (Bit8u)((chip.data >> 6) & 0x01); break; default: break; } } } if (chip.write_a_en || chip.write_d_en) { if (chip.write_a_en) { // True? chip.write_fm_data = false; } if (chip.write_fm_address && chip.write_d_en) { chip.write_fm_data = true; } if (chip.write_a_en) { if ((chip.write_data & 0xf0) != 0x00) { chip.address = chip.write_data; chip.write_fm_address = true; } else { chip.write_fm_address = false; } } if (chip.write_d_en && (chip.write_data & 0x100) == 0) { switch (chip.address) { case 0x21: /* LSI test 1 */ for (i = 0; i < 8; i++) { chip.mode_test_21[i] = (((chip.write_data >> i) & 0x01) != 0 ? true : false); } break; case 0x22: /* LFO control */ if (((chip.write_data >> 3) & 0x01) != 0) { chip.lfo_en = 0x7f; } else { chip.lfo_en = 0; } chip.lfo_freq = (Bit8u)(chip.write_data & 0x07); break; case 0x24: /* Timer A */ chip.timer_a_reg &= 0x03; chip.timer_a_reg |= (Bit8u)((chip.write_data & 0xff) << 2); break; case 0x25: chip.timer_a_reg &= 0x3fc; chip.timer_a_reg |= (Bit8u)(chip.write_data & 0x03); break; case 0x26: /* Timer B */ chip.timer_b_reg = (Bit8u)(chip.write_data & 0xff); break; case 0x27: /* CSM, Timer control */ chip.mode_ch3 = (Bit8u)((chip.write_data & 0xc0) >> 6); chip.mode_csm = chip.mode_ch3 == 2; chip.timer_a_load = (Bit8u)(chip.write_data & 0x01); chip.timer_a_enable = (Bit8u)((chip.write_data >> 2) & 0x01); chip.timer_a_reset = (Bit8u)((chip.write_data >> 4) & 0x01); chip.timer_b_load = (Bit8u)((chip.write_data >> 1) & 0x01); chip.timer_b_enable = (Bit8u)((chip.write_data >> 3) & 0x01); chip.timer_b_reset = (Bit8u)((chip.write_data >> 5) & 0x01); break; case 0x28: /* Key on/off */ for (i = 0; i < 4; i++) { chip.mode_kon_operator[i] = (Bit8u)((chip.write_data >> (4 + i)) & 0x01); } if ((chip.write_data & 0x03) == 0x03) { /* Invalid address */ chip.mode_kon_channel = 0xff; } else { chip.mode_kon_channel = (Bit8u)((chip.write_data & 0x03) + ((chip.write_data >> 2) & 1) * 3); } break; case 0x2a: /* DAC data */ chip.dacdata &= 0x01; chip.dacdata |= (Bit8u)((chip.write_data ^ 0x80) << 1); break; case 0x2b: /* DAC enable */ chip.dacen = (Bit8u)(chip.write_data >> 7); break; case 0x2c: /* LSI test 2 */ for (i = 0; i < 8; i++) { chip.mode_test_2c[i] = ((chip.write_data >> i) & 0x01) == 1 ? true : false; } chip.dacdata &= 0x1fe; //Bit8u tmp = (Bit8u)(chip.mode_test_2c[3] ? 1 : 0); chip.dacdata |= (Bit8u)(chip.mode_test_2c[3] ? 1 : 0); //Bit8u tmp = chip.mode_test_2c[7] ? 0 : 1; chip.eg_custom_timer = (Bit8u)((chip.mode_test_2c[7] ? 0 : 1) & (chip.mode_test_2c[6] ? 1 : 0)); //todo break; default: break; } } if (chip.write_a_en) { chip.write_fm_mode_a = ((chip.write_data & 0xff) == 1 ? true : false); } } if (chip.write_fm_data) { chip.data = (Bit8u)(chip.write_data & 0xff); } }
void OPN2_EnvelopeADSR(ym3438_ chip) { Bit32u slot = (chip.cycles + 22) % 24; Bit8u nkon = chip.eg_kon_latch[slot]; Bit8u okon = chip.eg_kon[slot]; Bit8u kon_event; Bit8u koff_event; Bit8u eg_off; Bit16s level; Bit16s nextlevel = 0; Bit16s ssg_level; Bit8u nextstate = chip.eg_state[slot]; Bit16s inc = 0; chip.eg_read[0] = chip.eg_read_inc; chip.eg_read_inc = chip.eg_inc > 0; /* Reset phase generator */ chip.pg_reset[slot] = (nkon && !okon) || chip.eg_ssg_pgrst_latch[slot]; /* KeyOn/Off */ kon_event = (nkon && !okon) || (okon && chip.eg_ssg_repeat_latch[slot]); koff_event = okon && !nkon; ssg_level = level = (Bit16s)chip.eg_level[slot]; if (chip.eg_ssg_inv[slot] != 0) { /* Inverse */ ssg_level = 512 - level; ssg_level &= 0x3ff; } if (koff_event != 0) { level = ssg_level; } if (chip.eg_ssg_enable[slot] != 0) { eg_off = level >> 9; } else { eg_off = (level & 0x3f0) == 0x3f0; } nextlevel = level; if (kon_event != 0) { nextstate = EG_PARAM.eg_num_attack; /* Instant attack */ if (chip.eg_ratemax) { nextlevel = 0; } else if (chip.eg_state[slot] == EG_PARAM.eg_num_attack && level != 0 && chip.eg_inc && nkon) { inc = (~level << chip.eg_inc) >> 5; } } else { switch (chip.eg_state[slot]) { case EG_PARAM.eg_num_attack: if (level == 0) { nextstate = eg_num_decay; } else if (chip.eg_inc && !chip.eg_ratemax && nkon) { inc = (~level << chip.eg_inc) >> 5; } break; case EG_PARAM.eg_num_decay: if ((level >> 5) == chip.eg_sl[1]) { nextstate = eg_num_sustain; } else if (!eg_off && chip.eg_inc) { inc = 1 << (chip.eg_inc - 1); if (chip.eg_ssg_enable[slot]) { inc <<= 2; } } break; case EG_PARAM.eg_num_sustain: case EG_PARAM.eg_num_release: if (!eg_off && chip.eg_inc) { inc = 1 << (chip.eg_inc - 1); if (chip.eg_ssg_enable[slot]) { inc <<= 2; } } break; default: break; } if (!nkon) { nextstate = eg_num_release; } } if (chip.eg_kon_csm[slot]) { nextlevel |= chip.eg_tl[1] << 3; } /* Envelope off */ if (!kon_event && !chip.eg_ssg_hold_up_latch[slot] && chip.eg_state[slot] != eg_num_attack && eg_off) { nextstate = eg_num_release; nextlevel = 0x3ff; } nextlevel += inc; chip.eg_kon[slot] = chip.eg_kon_latch[slot]; chip.eg_level[slot] = (Bit16u)nextlevel & 0x3ff; chip.eg_state[slot] = nextstate; }
public void OPN2_PhaseCalcIncrement(ym3438_ chip) { Bit32u chan = chip.channel; Bit32u slot = chip.cycles; Bit32u fnum = chip.pg_fnum; Bit32u fnum_h = fnum >> 4; Bit32u fm; Bit32u basefreq; Bit8u lfo = chip.lfo_pm; Bit8u lfo_l = (Bit8u)(lfo & 0x0f); Bit8u pms = chip.pms[chan]; Bit8u dt = chip.dt[slot]; Bit8u dt_l = (Bit8u)(dt & 0x03); Bit8u detune = 0; Bit8u block, note; Bit8u sum, sum_h, sum_l; Bit8u kcode = (Bit8u)(chip.pg_kcode); fnum <<= 1; if ((lfo_l & 0x08) != 0) { lfo_l ^= 0x0f; } fm = (fnum_h >> ym3438_const.pg_lfo_sh1[pms, lfo_l]) + (fnum_h >> ym3438_const.pg_lfo_sh2[pms, lfo_l]); if (pms > 5) { fm <<= pms - 5; } fm >>= 2; if ((lfo & 0x10) != 0) { fnum -= fm; } else { fnum += fm; } fnum &= 0xfff; basefreq = (fnum << chip.pg_block) >> 2; /* Apply detune */ if (dt_l != 0) { if (kcode > 0x1c) { kcode = 0x1c; } block = (Bit8u)(kcode >> 2); note = (Bit8u)(kcode & 0x03); sum = (Bit8u)(block + 9 + (((dt_l == 3) ? 1 : 0) | (dt_l & 0x02))); sum_h = (Bit8u)(sum >> 1); sum_l = (Bit8u)(sum & 0x01); detune = (Bit8u)(ym3438_const.pg_detune[(sum_l << 2) | note] >> (9 - sum_h)); } if ((dt & 0x04) != 0) { basefreq -= detune; } else { basefreq += detune; } basefreq &= 0x1ffff; chip.pg_inc[slot] = (basefreq * chip.multi[slot]) >> 1; chip.pg_inc[slot] &= 0xfffff; }