furnace/extern/YMF276-LLE/fmopn2.c
tildearrow 892ee12d91 implement YMF276-LLE core
thanks LTVA
2024-03-15 20:16:41 -05:00

2344 lines
79 KiB
C

/*
* Copyright (C) 2022-2023 nukeykt
*
* This file is part of YMF276-LLE.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* YMF276/YM3438 emulator.
* Thanks:
* John McMaster (siliconpr0n.org):
* Yamaha YM3438 & YM2610 decap and die shot.
* org, andkorzh, HardWareMan (emu-russia):
* help & support, YMF276 and YM2612 decap.
*
*/
// YMF276/YM3438 core
#include <stdio.h>
#include <string.h>
#include "fmopn2.h"
enum {
eg_state_attack = 0,
eg_state_decay,
eg_state_sustain,
eg_state_release
};
static const int fm_algorithm[4][6][8] = {
{
{ 1, 1, 1, 1, 1, 1, 1, 1 }, /* OP1_0 */
{ 1, 1, 1, 1, 1, 1, 1, 1 }, /* OP1_1 */
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* OP2 */
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */
{ 0, 0, 0, 0, 0, 0, 0, 1 } /* Out */
},
{
{ 0, 1, 0, 0, 0, 1, 0, 0 }, /* OP1_0 */
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* OP1_1 */
{ 1, 1, 1, 0, 0, 0, 0, 0 }, /* OP2 */
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */
{ 0, 0, 0, 0, 0, 1, 1, 1 } /* Out */
},
{
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* OP1_0 */
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* OP1_1 */
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* OP2 */
{ 1, 0, 0, 1, 1, 1, 1, 0 }, /* Last operator */
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* Last operator */
{ 0, 0, 0, 0, 1, 1, 1, 1 } /* Out */
},
{
{ 0, 0, 1, 0, 0, 1, 0, 0 }, /* OP1_0 */
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* OP1_1 */
{ 0, 0, 0, 1, 0, 0, 0, 0 }, /* OP2 */
{ 1, 1, 0, 1, 1, 0, 0, 0 }, /* Last operator */
{ 0, 0, 1, 0, 0, 0, 0, 0 }, /* Last operator */
{ 1, 1, 1, 1, 1, 1, 1, 1 } /* Out */
}
};
void FMOPN2_ClockPhase1(fmopn2_t *chip);
void FMOPN2_Prescaler(fmopn2_t *chip)
{
if (!chip->pinput.phi)
{
int ic_check;
chip->ic_latch[0] = chip->ic_latch[1] << 1;
chip->ic_latch[0] |= chip->pinput.ic;
ic_check = (chip->ic_latch[1] & 0x800) == 0 && chip->pinput.ic;
chip->prescaler_latch[0] = chip->prescaler_latch[1] << 1;
chip->prescaler_latch[0] |= !ic_check && (chip->prescaler_latch[1] & 0x1f) == 0;
chip->ic_check_latch[0] = chip->ic_check_latch[1] << 1;
chip->ic_check_latch[0] |= ic_check;
chip->phi1_latch[0] = (chip->prescaler_latch[1] & 0x21) != 0;
chip->phi2_latch[0] = (chip->prescaler_latch[1] & 0xc) != 0;
if (!(chip->flags & fmopn2_flags_ym3438))
{
chip->dphi1_latch[0] = (chip->prescaler_latch[1] & 0x9) != 0;
chip->dphi2_latch[0] = (chip->prescaler_latch[1] & 0x24) != 0;
chip->dphi1_latch[2] = chip->dphi1_latch[1];
chip->dphi2_latch[2] = chip->dphi2_latch[1];
}
}
else
{
chip->ic_latch[1] = chip->ic_latch[0] & 0xfff;
chip->ic_check_latch[1] = chip->ic_check_latch[0] & 0xf;
chip->prescaler_latch[1] = chip->prescaler_latch[0] & 0x3f;
chip->phi1_latch[1] = chip->phi1_latch[0] & 0x1;
chip->phi2_latch[1] = chip->phi2_latch[0] & 0x1;
if (!(chip->flags & fmopn2_flags_ym3438))
{
chip->dphi1_latch[1] = chip->dphi1_latch[0];
chip->dphi2_latch[1] = chip->dphi2_latch[0];
chip->dphi1_latch[3] = chip->dphi1_latch[2];
}
}
chip->fsm_reset = (chip->ic_check_latch[1] & 16) != 0;
if (!(chip->flags & fmopn2_flags_ym3438))
{
chip->dclk1 = chip->dphi1_latch[1] && !chip->dphi1_latch[2];
chip->dclk2 = chip->dphi2_latch[1] && !chip->dphi2_latch[2];
}
}
void FMOPN2_YMF276DAC(fmopn2_t *chip)
{
chip->fsm_load_l = (chip->fsm_shifter_ctrl[1] & 0x20) != 0 && chip->i_phi2;
chip->fsm_load_r = (chip->fsm_shifter_ctrl[1] & 0x20000) != 0 && chip->i_phi2;
if (chip->dclk1)
{
chip->dac_shifter[0] = chip->dac_shifter[1] << 1;
if (chip->fsm_load_l)
chip->dac_shifter[0] |= (chip->ch_accm_l[1] >> 1);
if (chip->fsm_load_r)
chip->dac_shifter[0] |= (chip->ch_accm_r[1] >> 1);
}
if (chip->dclk2)
{
chip->dac_shifter[1] = chip->dac_shifter[0];
}
if (!chip->pinput.phi)
{
chip->fsm_lro_l2[0] = chip->fsm_lro_l2[1] << 1;
if (chip->fsm_lro_l[1] & 2)
chip->fsm_lro_l2[0] |= 1;
chip->fsm_wco_l2[0] = chip->fsm_wco_l2[1] << 1;
if (chip->fsm_wco_l[1] & 2)
chip->fsm_wco_l2[0] |= 1;
chip->dac_so_l[0] = chip->dac_so_l[1] << 1;
if (chip->dac_shifter[1] & 0x8000)
chip->dac_so_l[0] |= 1;
}
else
{
chip->fsm_lro_l2[1] = chip->fsm_lro_l2[0];
chip->fsm_wco_l2[1] = chip->fsm_wco_l2[0];
chip->dac_so_l[1] = chip->dac_so_l[0];
}
chip->o_bco = chip->dphi1_latch[2] || chip->dphi1_latch[3];
chip->o_wco = (chip->fsm_wco_l2[1] & 32) != 0;
chip->o_lro = (chip->fsm_lro_l2[1] & 32) != 0;
chip->o_so = (chip->dac_so_l[1] & 4) != 0;
}
void FMOPN2_HandleIO(fmopn2_t *chip)
{
int write_data = chip->input.cs && chip->input.wr && (chip->input.address & 1) == 1 && !chip->input.ic;
int write_addr = (chip->input.cs && chip->input.wr && (chip->input.address & 1) == 0) || chip->input.ic;
int read_enable = chip->input.cs && chip->input.rd && !chip->input.ic;
int io_dir = chip->input.cs && chip->input.rd && !chip->input.ic;
int data_enable = !io_dir && !chip->input.ic;
if (chip->input.cs && chip->input.wr)
{
chip->data_latch = chip->input.data;
chip->bank_latch = (chip->input.address >> 1) & 1;
}
if (write_addr)
chip->write_addr_trig = 1;
if (write_data)
chip->write_data_trig = 1;
if (!read_enable)
{
chip->status_timer_a_dlatch = chip->timer_a_status[1];
chip->status_timer_b_dlatch = chip->timer_b_status[1];
}
}
int FMOPN2_GetBus(fmopn2_t *chip)
{
int data = 0;
int io_dir = chip->input.cs && chip->input.rd && !chip->input.ic;
int data_enable = !io_dir && !chip->input.ic;
if (data_enable)
data = chip->data_latch;
if (chip->io_ic_latch[1])
data = 0;
return data;
}
int FMOPN2_ReadTest(fmopn2_t *chip)
{
if (chip->mode_test_2c[1] & 128)
return chip->fsm_sel23;
return 0; // FIXME: high impedance
}
int FMOPN2_ReadStatus(fmopn2_t *chip)
{
int io_dir = chip->input.cs && chip->input.rd && !chip->input.ic;
int read_enable = chip->input.cs && chip->input.rd && !chip->input.ic && (chip->input.address & 3) == 0;
int status;
int testdata = 0;
if (!io_dir)
return 0;
if (!read_enable)
{
return 0; // FIXME: floating bus
}
if (chip->mode_test_21[1] & 64)
{
testdata |= (chip->pg_debug[1] & 1) << 15;
if (chip->mode_test_21[1] & 1)
testdata |= ((chip->eg_debug[1] >> 9) & 1) << 14;
else
testdata |= (chip->eg_incsh_nonzero[1] & 1) << 14;
if (chip->mode_test_2c[1] & 16)
testdata |= chip->ch_out_debug[1] & 0x1ff;
else
testdata |= chip->op_output[1] & 0x3fff;
if (chip->mode_test_21[1] & 128)
status = testdata & 255;
else
status = testdata >> 8;
}
else
{
status = (chip->busy_latch[1] << 7) | (chip->status_timer_b_dlatch << 1) | chip->status_timer_a_dlatch;
}
return status;
}
void FMOPN2_FSM1(fmopn2_t *chip)
{
int i;
int connect = 0;
int reset = chip->input.i_fsm_reset;
chip->fsm_cnt1[0] = chip->fsm_cnt1[1] + 1;
if (reset || (chip->fsm_cnt1[1] & 2) != 0)
chip->fsm_cnt1[0] = 0;
chip->fsm_cnt2[0] = chip->fsm_cnt2[1];
if ((chip->fsm_cnt1[1] & 2) != 0)
chip->fsm_cnt2[0]++;
if (reset)
chip->fsm_cnt2[0] = 0;
if (!(chip->flags & fmopn2_flags_ym3438))
{
int cnt_comb = (chip->fsm_cnt2[1] << 2) | chip->fsm_cnt1[1];
chip->fsm_clock_eg_l = cnt_comb == 30;
chip->fsm_op1_sel_l = cnt_comb == 6 || cnt_comb == 8 || cnt_comb == 9 || cnt_comb == 10 || cnt_comb == 12 || cnt_comb == 13;
chip->fsm_sel1_l = cnt_comb == 0;
chip->fsm_sel2_l = cnt_comb == 1;
chip->fsm_sel23_l = cnt_comb == 29;
chip->fsm_ch3_sel_l = cnt_comb == 1 || cnt_comb == 9 || cnt_comb == 17 || cnt_comb == 25;
chip->fsm_dac_load_l = cnt_comb == 30 || cnt_comb == 4 || cnt_comb == 9 || cnt_comb == 14 || cnt_comb == 20 || cnt_comb == 9;
chip->fsm_dac_out_sel_l = cnt_comb == 14 || cnt_comb == 16 || cnt_comb == 17 || cnt_comb == 18 || cnt_comb == 20 || cnt_comb == 21 ||
cnt_comb == 22 || cnt_comb == 24 || cnt_comb == 25 || cnt_comb == 26 || cnt_comb == 28 || cnt_comb == 29;
chip->fsm_dac_ch6_l = cnt_comb == 4 || cnt_comb == 5 || cnt_comb == 6 || cnt_comb == 8;
chip->fsm_wco_l[0] = (chip->fsm_wco_l[1] << 1) | ((cnt_comb & 8) == 0);
chip->fsm_lro_l[0] = chip->fsm_lro_l[1] << 1;
if (((cnt_comb >> 3) ^ (cnt_comb >> 4)) & 1)
chip->fsm_lro_l[0] |= 1;
}
}
void FMOPN2_FSM2(fmopn2_t *chip)
{
int i, connect = 0;
int cnt_comb;
chip->fsm_cnt1[1] = chip->fsm_cnt1[0] & 0x3;
chip->fsm_cnt2[1] = chip->fsm_cnt2[0] & 0x7;
cnt_comb = (chip->fsm_cnt2[1] << 2) | chip->fsm_cnt1[1];
if (!(chip->flags & fmopn2_flags_ym3438))
{
chip->fsm_clock_eg = chip->fsm_clock_eg_l;
chip->fsm_op4_sel = cnt_comb == 0 || cnt_comb == 1 || cnt_comb == 2 || cnt_comb == 4 || cnt_comb == 5 || cnt_comb == 6;
chip->fsm_op1_sel = chip->fsm_op1_sel_l;
chip->fsm_op3_sel = cnt_comb == 16 || cnt_comb == 17 || cnt_comb == 18 || cnt_comb == 20 || cnt_comb == 21 || cnt_comb == 22;
chip->fsm_op2_sel = cnt_comb == 24 || cnt_comb == 25 || cnt_comb == 26 || cnt_comb == 28 || cnt_comb == 29 || cnt_comb == 30;
chip->fsm_sel2 = chip->fsm_sel2_l;
chip->fsm_sel23 = chip->fsm_sel23_l;
chip->fsm_ch3_sel = chip->fsm_ch3_sel_l;
chip->fsm_dac_load = chip->fsm_dac_load_l;
chip->fsm_dac_out_sel = chip->fsm_dac_out_sel_l;
chip->fsm_dac_ch6 = chip->fsm_dac_ch6_l;
chip->fsm_clock_timers = chip->fsm_sel2_l;
chip->fsm_clock_timers1 = chip->fsm_sel1_l;
chip->fsm_wco_l[1] = chip->fsm_wco_l[0];
chip->fsm_lro_l[1] = chip->fsm_lro_l[0];
}
else
{
chip->fsm_clock_eg = cnt_comb == 0;
chip->fsm_op4_sel = cnt_comb == 0 || cnt_comb == 1 || cnt_comb == 2 || cnt_comb == 4 || cnt_comb == 5 || cnt_comb == 6;
chip->fsm_op1_sel = cnt_comb == 8 || cnt_comb == 9 || cnt_comb == 10 || cnt_comb == 12 || cnt_comb == 13 || cnt_comb == 14;
chip->fsm_op3_sel = cnt_comb == 16 || cnt_comb == 17 || cnt_comb == 18 || cnt_comb == 20 || cnt_comb == 21 || cnt_comb == 22;
chip->fsm_op2_sel = cnt_comb == 24 || cnt_comb == 25 || cnt_comb == 26 || cnt_comb == 28 || cnt_comb == 29 || cnt_comb == 30;
chip->fsm_sel2 = cnt_comb == 2;
chip->fsm_sel23 = cnt_comb == 30;
chip->fsm_ch3_sel = cnt_comb == 2 || cnt_comb == 10 || cnt_comb == 18 || cnt_comb == 26;
chip->fsm_dac_load = cnt_comb == 0 || cnt_comb == 5 || cnt_comb == 10 || cnt_comb == 16 || cnt_comb == 21 || cnt_comb == 26;
chip->fsm_dac_out_sel = cnt_comb == 16 || cnt_comb == 17 || cnt_comb == 18 || cnt_comb == 20 || cnt_comb == 21 || cnt_comb == 22 ||
cnt_comb == 24 || cnt_comb == 25 || cnt_comb == 26 || cnt_comb == 28 || cnt_comb == 29 || cnt_comb == 30;
chip->fsm_dac_ch6 = cnt_comb == 5 || cnt_comb == 6 || cnt_comb == 8 || cnt_comb == 9;
chip->fsm_clock_timers = cnt_comb == 2;
chip->fsm_clock_timers1 = cnt_comb == 1;
}
for (i = 0; i < 3; i++)
connect |= ((chip->chan_connect[i][1] >> 5) & 1) << i;
chip->alg_mod_op1_0 = 0;
chip->alg_mod_op1_1 = 0;
chip->alg_mod_op2 = 0;
chip->alg_mod_prev_0 = 0;
chip->alg_mod_prev_1 = 0;
chip->alg_output = 0;
if (chip->fsm_op2_sel)
{
chip->alg_mod_op1_0 |= fm_algorithm[0][0][connect];
chip->alg_mod_op1_1 |= fm_algorithm[0][1][connect];
chip->alg_mod_op2 |= fm_algorithm[0][2][connect];
chip->alg_mod_prev_0 |= fm_algorithm[0][3][connect];
chip->alg_mod_prev_1 |= fm_algorithm[0][4][connect];
chip->alg_output |= fm_algorithm[2][5][connect];
}
if (chip->fsm_op4_sel)
{
chip->alg_mod_op1_0 |= fm_algorithm[1][0][connect];
chip->alg_mod_op1_1 |= fm_algorithm[1][1][connect];
chip->alg_mod_op2 |= fm_algorithm[1][2][connect];
chip->alg_mod_prev_0 |= fm_algorithm[1][3][connect];
chip->alg_mod_prev_1 |= fm_algorithm[1][4][connect];
chip->alg_output |= fm_algorithm[3][5][connect];
}
if (chip->fsm_op1_sel)
{
chip->alg_mod_op1_0 |= fm_algorithm[2][0][connect];
chip->alg_mod_op1_1 |= fm_algorithm[2][1][connect];
chip->alg_mod_op2 |= fm_algorithm[2][2][connect];
chip->alg_mod_prev_0 |= fm_algorithm[2][3][connect];
chip->alg_mod_prev_1 |= fm_algorithm[2][4][connect];
chip->alg_output |= fm_algorithm[0][5][connect];
}
if (chip->fsm_op3_sel)
{
chip->alg_mod_op1_0 |= fm_algorithm[3][0][connect];
chip->alg_mod_op1_1 |= fm_algorithm[3][1][connect];
chip->alg_mod_op2 |= fm_algorithm[3][2][connect];
chip->alg_mod_prev_0 |= fm_algorithm[3][3][connect];
chip->alg_mod_prev_1 |= fm_algorithm[3][4][connect];
chip->alg_output |= fm_algorithm[1][5][connect];
}
}
void FMOPN2_HandleIO1(fmopn2_t *chip)
{
int write_data_en = !chip->write_data_sr[1] && chip->write_data_dlatch;
int write_addr_en = !chip->write_addr_sr[1] && chip->write_addr_dlatch;
int busy_cnt = chip->busy_cnt[1] + chip->busy_latch[1];
int busy_of = (busy_cnt >> 5) & 1;
chip->write_addr_trig_sync = chip->write_addr_trig;
chip->write_data_trig_sync = chip->write_data_trig;
chip->write_addr_sr[0] = chip->write_addr_dlatch;
chip->write_data_sr[0] = chip->write_data_dlatch;
chip->busy_latch[0] = write_data_en || (chip->busy_latch[1] && !(chip->input.ic || busy_of));
if (chip->input.ic)
busy_cnt = 0;
chip->busy_cnt[0] = busy_cnt & 31;
chip->io_ic_latch[0] = chip->input.ic;
}
void FMOPN2_HandleIO2(fmopn2_t *chip)
{
chip->write_addr_dlatch = chip->write_addr_trig_sync;
if (chip->write_addr_dlatch)
chip->write_addr_trig = 0;
chip->write_data_dlatch = chip->write_data_trig_sync;
if (chip->write_data_dlatch)
chip->write_data_trig = 0;
chip->write_addr_sr[1] = chip->write_addr_sr[0] & 1;
chip->write_data_sr[1] = chip->write_data_sr[0] & 1;
chip->busy_cnt[1] = chip->busy_cnt[0] & 31;
chip->busy_latch[1] = chip->busy_latch[0] & 1;
chip->io_ic_latch[1] = chip->io_ic_latch[0] & 1;
}
void FMOPN2_DoShiftRegisters(fmopn2_t *chip, int sel)
{
int i, j;
int to = sel;
int from = sel ^ 1;
int rot = sel == 0 ? 1 : 0;
#define SLOT_ROTATE(x) rot ? ((x << 1) | ((x >> 11) & 1)) : x
#define CH_ROTATE(x) rot ? ((x << 1) | ((x >> 5) & 1)) : x
// slot registers
for (i = 0; i < 2; i++)
{
// multi
for (j = 0; j < 4; j++)
chip->slot_multi[i][j][to] = SLOT_ROTATE(chip->slot_multi[i][j][from]);
// dt
for (j = 0; j < 3; j++)
chip->slot_dt[i][j][to] = SLOT_ROTATE(chip->slot_dt[i][j][from]);
// tl
for (j = 0; j < 7; j++)
chip->slot_tl[i][j][to] = SLOT_ROTATE(chip->slot_tl[i][j][from]);
// ar
for (j = 0; j < 5; j++)
chip->slot_ar[i][j][to] = SLOT_ROTATE(chip->slot_ar[i][j][from]);
// ks
for (j = 0; j < 2; j++)
chip->slot_ks[i][j][to] = SLOT_ROTATE(chip->slot_ks[i][j][from]);
// dr
for (j = 0; j < 5; j++)
chip->slot_dr[i][j][to] = SLOT_ROTATE(chip->slot_dr[i][j][from]);
// am
for (j = 0; j < 1; j++)
chip->slot_am[i][j][to] = SLOT_ROTATE(chip->slot_am[i][j][from]);
// sr
for (j = 0; j < 5; j++)
chip->slot_sr[i][j][to] = SLOT_ROTATE(chip->slot_sr[i][j][from]);
// rr
for (j = 0; j < 4; j++)
chip->slot_rr[i][j][to] = SLOT_ROTATE(chip->slot_rr[i][j][from]);
// sl
for (j = 0; j < 4; j++)
chip->slot_sl[i][j][to] = SLOT_ROTATE(chip->slot_sl[i][j][from]);
// ssg eg
for (j = 0; j < 4; j++)
chip->slot_ssg_eg[i][j][to] = SLOT_ROTATE(chip->slot_ssg_eg[i][j][from]);
}
// channel registers
// fnum
for (j = 0; j < 11; j++)
chip->chan_fnum[j][to] = CH_ROTATE(chip->chan_fnum[j][from]);
// fnum ch3
for (j = 0; j < 11; j++)
chip->chan_fnum_ch3[j][to] = CH_ROTATE(chip->chan_fnum_ch3[j][from]);
// block
for (j = 0; j < 3; j++)
chip->chan_block[j][to] = CH_ROTATE(chip->chan_block[j][from]);
// block ch3
for (j = 0; j < 3; j++)
chip->chan_block_ch3[j][to] = CH_ROTATE(chip->chan_block_ch3[j][from]);
// connect
for (j = 0; j < 3; j++)
chip->chan_connect[j][to] = CH_ROTATE(chip->chan_connect[j][from]);
// fb
for (j = 0; j < 3; j++)
chip->chan_fb[j][to] = CH_ROTATE(chip->chan_fb[j][from]);
// pms
for (j = 0; j < 3; j++)
chip->chan_pms[j][to] = CH_ROTATE(chip->chan_pms[j][from]);
// ams
for (j = 0; j < 2; j++)
chip->chan_ams[j][to] = CH_ROTATE(chip->chan_ams[j][from]);
// pan
for (j = 0; j < 2; j++)
chip->chan_pan[j][to] = CH_ROTATE(chip->chan_pan[j][from]);
#undef SLOT_ROTATE
#undef CH_ROTATE
}
void FMOPN2_FMRegisters1(fmopn2_t *chip)
{
int i, j;
int write_data_en = !chip->write_data_sr[1] && chip->write_data_dlatch;
int write_addr_en = !chip->write_addr_sr[1] && chip->write_addr_dlatch;
int bus = FMOPN2_GetBus(chip);
int address = bus | (chip->bank_latch << 8);
int fm_write = (bus & 0xf0) != 0;
if (write_addr_en)
chip->write_fm_address[0] = fm_write;
else
chip->write_fm_address[0] = chip->write_fm_address[1];
if (chip->input.ic)
chip->fm_address[0] = 0;
else if (fm_write && write_addr_en)
chip->fm_address[0] = address;
else
chip->fm_address[0] = chip->fm_address[1];
chip->write_fm_data[0] = (chip->write_fm_address[1] && write_data_en) || (chip->write_fm_data[1] && !write_addr_en);
if (chip->input.ic)
chip->fm_data[0] = 0;
else if (chip->write_fm_address[1] && write_data_en)
chip->fm_data[0] = bus;
else
chip->fm_data[0] = chip->fm_data[1];
if (write_addr_en)
{
chip->write_mode_21[0] = address == 0x21;
chip->write_mode_22[0] = address == 0x22;
chip->write_mode_24[0] = address == 0x24;
chip->write_mode_25[0] = address == 0x25;
chip->write_mode_26[0] = address == 0x26;
chip->write_mode_27[0] = address == 0x27;
chip->write_mode_28[0] = address == 0x28;
chip->write_mode_2a[0] = address == 0x2a;
chip->write_mode_2b[0] = address == 0x2b;
chip->write_mode_2c[0] = address == 0x2c;
}
else
{
chip->write_mode_21[0] = chip->write_mode_21[1];
chip->write_mode_22[0] = chip->write_mode_22[1];
chip->write_mode_24[0] = chip->write_mode_24[1];
chip->write_mode_25[0] = chip->write_mode_25[1];
chip->write_mode_26[0] = chip->write_mode_26[1];
chip->write_mode_27[0] = chip->write_mode_27[1];
chip->write_mode_28[0] = chip->write_mode_28[1];
chip->write_mode_2a[0] = chip->write_mode_2a[1];
chip->write_mode_2b[0] = chip->write_mode_2b[1];
chip->write_mode_2c[0] = chip->write_mode_2c[1];
}
if (chip->input.ic)
{
chip->mode_test_21[0] = 0;
chip->mode_lfo_en[0] = 0;
chip->mode_lfo_freq[0] = 0;
chip->mode_timer_a_reg[0] = 0;
chip->mode_timer_b_reg[0] = 0;
chip->mode_ch3[0] = 0;
chip->mode_timer_a_load[0] = 0;
chip->mode_timer_a_enable[0] = 0;
chip->mode_timer_a_reset[0] = 0;
chip->mode_timer_b_load[0] = 0;
chip->mode_timer_b_enable[0] = 0;
chip->mode_timer_b_reset[0] = 0;
chip->mode_kon_operator[0] = 0;
chip->mode_kon_channel[0] = 0;
chip->mode_dac_data[0] = 0;
chip->mode_dac_en[0] = 0;
chip->mode_test_2c[0] = 0;
// slot registers
for (i = 0; i < 2; i++)
{
// multi
for (j = 0; j < 4; j++)
chip->slot_multi[i][j][0] &= ~1;
// dt
for (j = 0; j < 3; j++)
chip->slot_dt[i][j][0] &= ~1;
// tl
for (j = 0; j < 7; j++)
chip->slot_tl[i][j][0] &= ~1;
// ar
for (j = 0; j < 5; j++)
chip->slot_ar[i][j][0] &= ~1;
// ks
for (j = 0; j < 2; j++)
chip->slot_ks[i][j][0] &= ~1;
// dr
for (j = 0; j < 5; j++)
chip->slot_dr[i][j][0] &= ~1;
// am
for (j = 0; j < 1; j++)
chip->slot_am[i][j][0] &= ~1;
// sr
for (j = 0; j < 5; j++)
chip->slot_sr[i][j][0] &= ~1;
// rr
for (j = 0; j < 4; j++)
chip->slot_rr[i][j][0] &= ~1;
// sl
for (j = 0; j < 4; j++)
chip->slot_sl[i][j][0] &= ~1;
// ssg eg
for (j = 0; j < 4; j++)
chip->slot_ssg_eg[i][j][0] &= ~1;
}
// channel registers
// fn low
for (j = 0; j < 11; j++)
chip->chan_fnum[j][0] &= ~1;
// fn low ch3
for (j = 0; j < 11; j++)
chip->chan_fnum_ch3[j][0] &= ~1;
// block fn high
for (j = 0; j < 3; j++)
chip->chan_block[j][0] &= ~1;
// block fn high ch3
for (j = 0; j < 3; j++)
chip->chan_block_ch3[j][0] &= ~1;
// connect
for (j = 0; j < 3; j++)
chip->chan_connect[j][0] &= ~1;
// fb
for (j = 0; j < 3; j++)
chip->chan_fb[j][0] &= ~1;
// pms
for (j = 0; j < 3; j++)
chip->chan_pms[j][0] &= ~1;
// ams
for (j = 0; j < 2; j++)
chip->chan_ams[j][0] &= ~1;
// pan
for (j = 0; j < 2; j++)
chip->chan_pan[j][0] &= ~1;
chip->chan_a4[0] = 0;
chip->chan_ac[0] = 0;
}
else
{
if (write_data_en && chip->write_mode_21[1] && !chip->bank_latch)
chip->mode_test_21[0] = bus & 255;
else
chip->mode_test_21[0] = chip->mode_test_21[1];
if (write_data_en && chip->write_mode_22[1] && !chip->bank_latch)
{
chip->mode_lfo_en[0] = (bus >> 3) & 1;
chip->mode_lfo_freq[0] = bus & 7;
}
else
{
chip->mode_lfo_en[0] = chip->mode_lfo_en[1];
chip->mode_lfo_freq[0] = chip->mode_lfo_freq[1];
}
chip->mode_timer_a_reg[0] = 0;
if (write_data_en && chip->write_mode_24[1] && !chip->bank_latch)
chip->mode_timer_a_reg[0] |= (bus & 255) << 2;
else
chip->mode_timer_a_reg[0] |= chip->mode_timer_a_reg[1] & 0x3fc;
if (write_data_en && chip->write_mode_25[1] && !chip->bank_latch)
chip->mode_timer_a_reg[0] |= bus & 3;
else
chip->mode_timer_a_reg[0] |= chip->mode_timer_a_reg[1] & 0x3;
if (write_data_en && chip->write_mode_26[1] && !chip->bank_latch)
chip->mode_timer_b_reg[0] = bus & 255;
else
chip->mode_timer_b_reg[0] = chip->mode_timer_b_reg[1];
if (write_data_en && chip->write_mode_27[1] && !chip->bank_latch)
{
chip->mode_ch3[0] = (bus >> 6) & 3;
chip->mode_timer_a_load[0] = bus & 1;
chip->mode_timer_a_enable[0] = (bus >> 2) & 1;
chip->mode_timer_a_reset[0] = (bus >> 4) & 1;
chip->mode_timer_b_load[0] = (bus >> 1) & 1;
chip->mode_timer_b_enable[0] = (bus >> 3) & 1;
chip->mode_timer_b_reset[0] = (bus >> 5) & 1;
}
else
{
chip->mode_ch3[0] = chip->mode_ch3[1];
chip->mode_timer_a_load[0] = chip->mode_timer_a_load[1];
chip->mode_timer_a_enable[0] = chip->mode_timer_a_enable[1];
chip->mode_timer_a_reset[0] = 0;
chip->mode_timer_b_load[0] = chip->mode_timer_b_load[1];
chip->mode_timer_b_enable[0] = chip->mode_timer_b_enable[1];
chip->mode_timer_b_reset[0] = 0;
}
if (write_data_en && chip->write_mode_28[1] && !chip->bank_latch)
{
chip->mode_kon_operator[0] = (bus >> 4) & 15;
chip->mode_kon_channel[0] = bus & 15;
}
else
{
chip->mode_kon_operator[0] = chip->mode_kon_operator[1];
chip->mode_kon_channel[0] = chip->mode_kon_channel[1];
}
if (write_data_en && chip->write_mode_2a[1] && !chip->bank_latch)
chip->mode_dac_data[0] = (bus & 255) ^ 128;
else
chip->mode_dac_data[0] = chip->mode_dac_data[1];
if (write_data_en && chip->write_mode_2b[1] && !chip->bank_latch)
chip->mode_dac_en[0] = (bus >> 7) & 1;
else
chip->mode_dac_en[0] = chip->mode_dac_en[1];
if (write_data_en && chip->write_mode_2c[1] && !chip->bank_latch)
chip->mode_test_2c[0] = bus & 0xf8;
else
chip->mode_test_2c[0] = chip->mode_test_2c[1];
}
if (chip->write_fm_data[1] && (chip->fm_address[1]&3) == chip->reg_cnt1[1]
&& ((chip->fm_address[1]>>2)&1) == ((chip->reg_cnt2[1]>>1)&1) && ((chip->fm_address[1]>>8)&1) == (chip->reg_cnt2[1]&1))
{
int bank = (chip->fm_address[1]>>3)&1;
switch (chip->fm_address[1] & 0xf0)
{
case 0x30:
// multi
for (j = 0; j < 4; j++)
{
chip->slot_multi[bank][j][0] &= ~1;
chip->slot_multi[bank][j][0] |= (chip->fm_data[1] >> (j + 0)) & 1;
}
// dt
for (j = 0; j < 3; j++)
{
chip->slot_dt[bank][j][0] &= ~1;
chip->slot_dt[bank][j][0] |= (chip->fm_data[1] >> (j + 4)) & 1;
}
break;
case 0x40:
// tl
for (j = 0; j < 7; j++)
{
chip->slot_tl[bank][j][0] &= ~1;
chip->slot_tl[bank][j][0] |= (chip->fm_data[1] >> (j + 0)) & 1;
}
break;
case 0x50:
// ar
for (j = 0; j < 5; j++)
{
chip->slot_ar[bank][j][0] &= ~1;
chip->slot_ar[bank][j][0] |= (chip->fm_data[1] >> (j + 0)) & 1;
}
// ks
for (j = 0; j < 2; j++)
{
chip->slot_ks[bank][j][0] &= ~1;
chip->slot_ks[bank][j][0] |= (chip->fm_data[1] >> (j + 6)) & 1;
}
break;
case 0x60:
// dr
for (j = 0; j < 5; j++)
{
chip->slot_dr[bank][j][0] &= ~1;
chip->slot_dr[bank][j][0] |= (chip->fm_data[1] >> (j + 0)) & 1;
}
// am
for (j = 0; j < 1; j++)
{
chip->slot_am[bank][j][0] &= ~1;
chip->slot_am[bank][j][0] |= (chip->fm_data[1] >> (j + 7)) & 1;
}
break;
case 0x70:
// sr
for (j = 0; j < 5; j++)
{
chip->slot_sr[bank][j][0] &= ~1;
chip->slot_sr[bank][j][0] |= (chip->fm_data[1] >> (j + 0)) & 1;
}
break;
case 0x80:
// rr
for (j = 0; j < 4; j++)
{
chip->slot_rr[bank][j][0] &= ~1;
chip->slot_rr[bank][j][0] |= (chip->fm_data[1] >> (j + 0)) & 1;
}
// sl
for (j = 0; j < 4; j++)
{
chip->slot_sl[bank][j][0] &= ~1;
chip->slot_sl[bank][j][0] |= (chip->fm_data[1] >> (j + 4)) & 1;
}
break;
case 0x90:
// ssg eg
for (j = 0; j < 4; j++)
{
chip->slot_ssg_eg[bank][j][0] &= ~1;
chip->slot_ssg_eg[bank][j][0] |= (chip->fm_data[1] >> (j + 0)) & 1;
}
break;
}
}
if (chip->write_fm_data[1] && (chip->fm_address[1] & 3) == chip->reg_cnt1[1] && ((chip->fm_address[1] >> 8) & 1) == (chip->reg_cnt2[1] & 1))
{
switch (chip->fm_address[1] & 0xfc)
{
case 0xa0:
// fnum
for (j = 0; j < 8; j++)
{
chip->chan_fnum[j][0] &= ~1;
chip->chan_fnum[j][0] |= (chip->fm_data[1] >> (j + 0)) & 1;
}
for (j = 0; j < 3; j++)
{
chip->chan_fnum[8+j][0] &= ~1;
chip->chan_fnum[8+j][0] |= (chip->chan_a4[1] >> (j + 0)) & 1;
}
// block
for (j = 0; j < 3; j++)
{
chip->chan_block[j][0] &= ~1;
chip->chan_block[j][0] |= (chip->chan_a4[1] >> (j + 3)) & 1;
}
break;
case 0xa4:
chip->chan_a4[0] = chip->fm_data[1] & 0x3f;
break;
case 0xa8:
// fnum
for (j = 0; j < 8; j++)
{
chip->chan_fnum_ch3[j][0] &= ~1;
chip->chan_fnum_ch3[j][0] |= (chip->fm_data[1] >> (j + 0)) & 1;
}
for (j = 0; j < 3; j++)
{
chip->chan_fnum_ch3[8+j][0] &= ~1;
chip->chan_fnum_ch3[8+j][0] |= (chip->chan_ac[1] >> (j + 0)) & 1;
}
// block
for (j = 0; j < 3; j++)
{
chip->chan_block_ch3[j][0] &= ~1;
chip->chan_block_ch3[j][0] |= (chip->chan_ac[1] >> (j + 3)) & 1;
}
break;
case 0xac:
chip->chan_ac[0] = chip->fm_data[1] & 0x3f;
break;
case 0xb0:
// connect
for (j = 0; j < 3; j++)
{
chip->chan_connect[j][0] &= ~1;
chip->chan_connect[j][0] |= (chip->fm_data[1] >> (j + 0)) & 1;
}
// fb
for (j = 0; j < 3; j++)
{
chip->chan_fb[j][0] &= ~1;
chip->chan_fb[j][0] |= (chip->fm_data[1] >> (j + 3)) & 1;
}
break;
case 0xb4:
// pms
for (j = 0; j < 3; j++)
{
chip->chan_pms[j][0] &= ~1;
chip->chan_pms[j][0] |= (chip->fm_data[1] >> (j + 0)) & 1;
}
// ams
for (j = 0; j < 2; j++)
{
chip->chan_ams[j][0] &= ~1;
chip->chan_ams[j][0] |= (chip->fm_data[1] >> (j + 4)) & 1;
}
// pan
for (j = 0; j < 2; j++)
{
chip->chan_pan[j][0] &= ~1;
chip->chan_pan[j][0] |= !((chip->fm_data[1] >> (j + 6)) & 1);
}
break;
}
}
// keyon
chip->mode_kon[0][0] = chip->mode_kon[0][1] << 1;
chip->mode_kon[1][0] = chip->mode_kon[1][1] << 1;
chip->mode_kon[2][0] = chip->mode_kon[2][1] << 1;
chip->mode_kon[3][0] = chip->mode_kon[3][1] << 1;
if (chip->reg_cnt2[1] == ((chip->mode_kon_channel[1] >> 2) & 1) && chip->reg_cnt1[1] == (chip->mode_kon_channel[1] & 3))
{
chip->mode_kon[0][0] |= (chip->mode_kon_operator[1] >> 0) & 1;
chip->mode_kon[1][0] |= (chip->mode_kon_operator[1] >> 3) & 1;
chip->mode_kon[2][0] |= (chip->mode_kon_operator[1] >> 1) & 1;
chip->mode_kon[3][0] |= (chip->mode_kon_operator[1] >> 2) & 1;
}
else
{
if (!chip->input.ic)
chip->mode_kon[0][0] |= (chip->mode_kon[3][1] >> 5) & 1;
chip->mode_kon[1][0] |= (chip->mode_kon[0][1] >> 5) & 1;
chip->mode_kon[2][0] |= (chip->mode_kon[1][1] >> 5) & 1;
chip->mode_kon[3][0] |= (chip->mode_kon[2][1] >> 5) & 1;
}
}
void FMOPN2_FMRegisters2(fmopn2_t *chip)
{
chip->write_fm_address[1] = chip->write_fm_address[0];
chip->write_fm_data[1] = chip->write_fm_data[0];
chip->fm_address[1] = chip->fm_address[0];
chip->fm_data[1] = chip->fm_data[0];
chip->write_mode_21[1] = chip->write_mode_21[0];
chip->write_mode_22[1] = chip->write_mode_22[0];
chip->write_mode_24[1] = chip->write_mode_24[0];
chip->write_mode_25[1] = chip->write_mode_25[0];
chip->write_mode_26[1] = chip->write_mode_26[0];
chip->write_mode_27[1] = chip->write_mode_27[0];
chip->write_mode_28[1] = chip->write_mode_28[0];
chip->write_mode_2a[1] = chip->write_mode_2a[0];
chip->write_mode_2b[1] = chip->write_mode_2b[0];
chip->write_mode_2c[1] = chip->write_mode_2c[0];
chip->mode_test_21[1] = chip->mode_test_21[0];
chip->mode_lfo_en[1] = chip->mode_lfo_en[0];
chip->mode_lfo_freq[1] = chip->mode_lfo_freq[0];
chip->mode_timer_a_reg[1] = chip->mode_timer_a_reg[0];
chip->mode_timer_b_reg[1] = chip->mode_timer_b_reg[0];
chip->mode_ch3[1] = chip->mode_ch3[0];
chip->mode_timer_a_load[1] = chip->mode_timer_a_load[0];
chip->mode_timer_a_enable[1] = chip->mode_timer_a_enable[0];
chip->mode_timer_a_reset[1] = chip->mode_timer_a_reset[0];
chip->mode_timer_b_load[1] = chip->mode_timer_b_load[0];
chip->mode_timer_b_enable[1] = chip->mode_timer_b_enable[0];
chip->mode_timer_b_reset[1] = chip->mode_timer_b_reset[0];
chip->mode_kon_operator[1] = chip->mode_kon_operator[0];
chip->mode_kon_channel[1] = chip->mode_kon_channel[0];
chip->mode_dac_data[1] = chip->mode_dac_data[0];
chip->mode_dac_en[1] = chip->mode_dac_en[0];
chip->mode_test_2c[1] = chip->mode_test_2c[0];
chip->chan_a4[1] = chip->chan_a4[0];
chip->chan_ac[1] = chip->chan_ac[0];
chip->mode_kon[0][1] = chip->mode_kon[0][0];
chip->mode_kon[1][1] = chip->mode_kon[1][0];
chip->mode_kon[2][1] = chip->mode_kon[2][0];
chip->mode_kon[3][1] = chip->mode_kon[3][0];
}
void FMOPN2_Misc1(fmopn2_t *chip)
{
chip->reg_cnt1[0] = chip->reg_cnt1[1] + 1;
chip->reg_cnt2[0] = chip->reg_cnt2[1];
if (chip->reg_cnt1[1] & 2)
{
chip->reg_cnt1[0] = 0;
chip->reg_cnt2[0]++;
}
if (chip->fsm_sel23 || chip->input.ic)
{
chip->reg_cnt1[0] = 0;
chip->reg_cnt2[0] = 0;
}
}
void FMOPN2_Misc2(fmopn2_t *chip)
{
chip->reg_cnt1[1] = chip->reg_cnt1[0] & 3;
chip->reg_cnt2[1] = chip->reg_cnt2[0] & 7;
}
void FMOPN2_LFO1(fmopn2_t *chip)
{
static const int lfo_cycles[8] = {
108, 77, 71, 67, 62, 44, 8, 5
};
int inc = (chip->mode_test_21[1] & 2) != 0 || chip->fsm_sel23;
int freq = chip->mode_lfo_freq[1];
int of = (chip->lfo_cnt1[1] & lfo_cycles[freq]) == lfo_cycles[freq];
chip->lfo_cnt1[0] = chip->lfo_cnt1[1] + inc;
if (chip->input.ic || of)
chip->lfo_cnt1[0] = 0;
chip->lfo_cnt2[0] = chip->lfo_cnt2[1] + of;
if (!chip->mode_lfo_en[1])
chip->lfo_cnt2[0] = 0;
chip->lfo_inc_latch[0] = chip->fsm_sel23;
chip->lfo_dlatch_load = chip->lfo_inc_latch[1];
}
void FMOPN2_LFO2(fmopn2_t *chip)
{
chip->lfo_cnt1[1] = chip->lfo_cnt1[0] & 127;
chip->lfo_cnt2[1] = chip->lfo_cnt2[0] & 127;
chip->lfo_inc_latch[1] = chip->lfo_inc_latch[0];
if (chip->lfo_inc_latch[1] && !chip->lfo_dlatch_load)
chip->lfo_dlatch = chip->lfo_cnt2[1];
}
void FMOPN2_PhaseGenerator1(fmopn2_t *chip)
{
// Note table
static const int fn_note[16] = {
0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3
};
// LFO shift
static const int pg_lfo_sh1[8][8] = {
{ 7, 7, 7, 7, 7, 7, 7, 7 },
{ 7, 7, 7, 7, 7, 7, 7, 7 },
{ 7, 7, 7, 7, 7, 7, 1, 1 },
{ 7, 7, 7, 7, 1, 1, 1, 1 },
{ 7, 7, 7, 1, 1, 1, 1, 0 },
{ 7, 7, 1, 1, 0, 0, 0, 0 },
{ 7, 7, 1, 1, 0, 0, 0, 0 },
{ 7, 7, 1, 1, 0, 0, 0, 0 }
};
static const int pg_lfo_sh2[8][8] = {
{ 7, 7, 7, 7, 7, 7, 7, 7 },
{ 7, 7, 7, 7, 2, 2, 2, 2 },
{ 7, 7, 7, 2, 2, 2, 7, 7 },
{ 7, 7, 2, 2, 7, 7, 2, 2 },
{ 7, 7, 2, 7, 7, 7, 2, 7 },
{ 7, 7, 7, 2, 7, 7, 2, 1 },
{ 7, 7, 7, 2, 7, 7, 2, 1 },
{ 7, 7, 7, 2, 7, 7, 2, 1 }
};
#if 0
// YM2610 decap
static const int pg_lfo_sh2[8][8] = {
{ 7, 7, 7, 7, 7, 7, 7, 7 },
{ 7, 7, 7, 7, 2, 2, 2, 2 },
{ 7, 7, 7, 2, 2, 2, 7, 7 },
{ 7, 7, 2, 2, 7, 7, 2, 2 },
{ 7, 2, 2, 7, 7, 2, 2, 7 },
{ 7, 2, 7, 2, 7, 2, 2, 1 },
{ 7, 2, 7, 2, 7, 2, 2, 1 },
{ 7, 2, 7, 2, 7, 2, 2, 1 }
};
#endif
static const int pg_detune_add[4] = {
0, 8, 10, 11
};
static const int pg_detune[8] = { 16, 17, 19, 20, 22, 24, 27, 29 };
int i;
int fnum = 0;
int fnum_h;
int block = 0;
int pms = 0;
int dt = 0;
int dt_l = 0;
int dt_sum;
int dt_sum_l;
int dt_sum_h;
int kcode;
int multi = 0;
int lfo;
int ch3_sel = chip->reg_cnt1[1] == 1 && (chip->reg_cnt2[1] & 1) == 0 && chip->mode_ch3[1] != 0;
int op_sel = chip->reg_cnt2[1] >> 1;
int bank = (chip->reg_cnt2[1] >> 2) & 1;
int carry = 0;
int pg_inc;
int reset;
if (ch3_sel && op_sel == 0)
{
for (i = 0; i < 11; i++)
fnum |= ((chip->chan_fnum_ch3[i][1] >> 5) & 1) << i;
for (i = 0; i < 3; i++)
block |= ((chip->chan_block_ch3[i][1] >> 5) & 1) << i;
}
else if (ch3_sel && op_sel == 1)
{
for (i = 0; i < 11; i++)
fnum |= ((chip->chan_fnum_ch3[i][1] >> 0) & 1) << i;
for (i = 0; i < 3; i++)
block |= ((chip->chan_block_ch3[i][1] >> 0) & 1) << i;
}
else if (ch3_sel && op_sel == 2)
{
for (i = 0; i < 11; i++)
fnum |= ((chip->chan_fnum_ch3[i][1] >> 4) & 1) << i;
for (i = 0; i < 3; i++)
block |= ((chip->chan_block_ch3[i][1] >> 4) & 1) << i;
}
else
{
for (i = 0; i < 11; i++)
fnum |= ((chip->chan_fnum[i][1] >> 4) & 1) << i;
for (i = 0; i < 3; i++)
block |= ((chip->chan_block[i][1] >> 4) & 1) << i;
}
for (i = 0; i < 3; i++)
pms |= ((chip->chan_pms[i][1] >> 5) & 1) << i;
for (i = 0; i < 3; i++)
dt |= ((chip->slot_dt[bank][i][1] >> 11) & 1) << i;
for (i = 0; i < 4; i++)
multi |= ((chip->slot_multi[bank][i][1] >> 11) & 1) << i;
kcode = (block << 2) | fn_note[fnum >> 7];
chip->pg_kcode[0][0] = kcode;
chip->pg_kcode[1][0] = chip->pg_kcode[0][1];
chip->pg_fnum[0][0] = fnum;
chip->pg_fnum[1][0] = chip->pg_fnum[0][1];
lfo = (chip->lfo_dlatch >> 2) & 7;
if (chip->lfo_dlatch & 32)
lfo ^= 7;
fnum_h = chip->pg_fnum[0][1] >> 4;
chip->pg_fnum_lfo1 = fnum_h >> pg_lfo_sh1[pms][lfo];
chip->pg_fnum_lfo2 = fnum_h >> pg_lfo_sh2[pms][lfo];
chip->pg_lfo_shift = 2;
if (pms > 5)
chip->pg_lfo_shift = 7 - pms;
chip->pg_lfo_sign = (chip->lfo_dlatch >> 6) & 1;
chip->pg_freq1 = ((chip->pg_fnum[1][1] << 1) + chip->pg_lfo) & 0xfff;
block = chip->pg_kcode[1][1] >> 2;
chip->pg_block = block;
chip->pg_dt[0] = dt;
dt_l = chip->pg_dt[1] & 3;
kcode = chip->pg_kcode[1][1];
if (kcode > 28)
kcode = 28;
dt_sum = kcode + ((pg_detune_add[dt_l] + 1) << 2);
dt_sum_l = dt_sum & 7;
dt_sum_h = dt_sum >> 3;
chip->pg_detune[0] = dt_l ? pg_detune[dt_sum_l] >> (9 - dt_sum_h) : 0;
if (chip->pg_dt[1] & 0x04)
chip->pg_detune[0] = -chip->pg_detune[0];
chip->pg_freq3 = (chip->pg_freq2 + chip->pg_detune[1]) & 0x1ffff;
chip->pg_multi[0][0] = multi;
chip->pg_multi[1][0] = chip->pg_multi[0][1];
chip->pg_multi2 = chip->pg_multi[1][1];
chip->pg_inc[0] = chip->pg_freq4;
chip->pg_inc_mask[0] = chip->pg_inc[1];
if (chip->pg_reset[1] & 2)
chip->pg_inc_mask[0] = 0;
chip->pg_reset_latch[0] = (chip->pg_reset[1] & 2) != 0;
pg_inc = chip->pg_inc_mask[1];
reset = chip->pg_reset_latch[1] || (chip->mode_test_21[1] & 8) != 0;
for (i = 0; i < 20; i++)
{
if (!reset)
carry += (chip->pg_phase[i][1] >> 23) & 1;
carry += pg_inc & 1;
chip->pg_phase[i][0] = (chip->pg_phase[i][1] << 1) | (carry & 1);
pg_inc >>= 1;
carry >>= 1;
}
chip->pg_debug[0] = chip->pg_debug[1] >> 1;
if (chip->fsm_sel2)
{
for (i = 0; i < 10; i++)
{
chip->pg_debug[0] |= ((chip->pg_phase[i][1] >> 23) & 1) << i;
}
}
}
void FMOPN2_PhaseGenerator2(fmopn2_t *chip)
{
int i;
int block = chip->pg_kcode[1][0];
chip->pg_fnum[0][1] = chip->pg_fnum[0][0];
chip->pg_fnum[1][1] = chip->pg_fnum[1][0];
chip->pg_kcode[0][1] = chip->pg_kcode[0][0];
chip->pg_kcode[1][1] = chip->pg_kcode[1][0];
chip->pg_lfo = (chip->pg_fnum_lfo1 + chip->pg_fnum_lfo2) >> chip->pg_lfo_shift;
if (chip->pg_lfo_sign)
chip->pg_lfo = -chip->pg_lfo;
chip->pg_freq2 = (chip->pg_freq1 << chip->pg_block) >> 2;
chip->pg_dt[1] = chip->pg_dt[0];
chip->pg_detune[1] = chip->pg_detune[0];
chip->pg_multi[0][1] = chip->pg_multi[0][0];
chip->pg_multi[1][1] = chip->pg_multi[1][0];
if (!chip->pg_multi2)
chip->pg_freq4 = chip->pg_freq3 >> 1;
else
chip->pg_freq4 = chip->pg_freq3 * chip->pg_multi2;
chip->pg_inc[1] = chip->pg_inc[0];
chip->pg_inc_mask[1] = chip->pg_inc_mask[0];
chip->pg_reset_latch[1] = chip->pg_reset_latch[0];
for (i = 0; i < 20; i++)
{
chip->pg_phase[i][1] = chip->pg_phase[i][0];
}
chip->pg_debug[1] = chip->pg_debug[0];
}
void FMOPN2_EnvelopeGenerator1(fmopn2_t *chip)
{
int i;
int sum;
int add;
int timer_bit;
int timer_bit_masked;
int bank = (chip->reg_cnt2[1] >> 2) & 1;
int rate_sel;
int rate = 0;
int ks = 0;
int b0, b1;
int inc1;
int exp = 0;
int linear = 0;
int inc_total = 0;
int level = 0;
int level2 = 0;
int kon;
int kon2;
int okon;
int okon2;
int state;
int pg_reset;
int kon_event;
int ssg_eg = 0;
int ssg_inv_e = 0;
int ssg_dir = 0;
int ssg_inv = 0;
int ssg_holdup = 0;
int ssg_enable;
int ssg_pgreset = 0;
int ssg_pgrepeat = 0;
int eg_off;
int eg_slreach;
int sl = 0;
int nextlevel = 0;
int nextstate = eg_state_attack;
int tl = 0;
int istantattack = 0;
int eg_output;
int ams = 0;
int csm_kon;
static const int eg_stephi[4][4] = {
{ 0, 0, 0, 0 },
{ 1, 0, 0, 0 },
{ 1, 0, 1, 0 },
{ 1, 1, 1, 0 }
};
chip->eg_prescaler_clock_l[0] = chip->fsm_clock_eg;
chip->eg_prescaler[0] = chip->eg_prescaler[1] + chip->fsm_clock_eg;
if (((chip->eg_prescaler[1] & 2) != 0 && chip->fsm_clock_eg) || chip->input.ic)
chip->eg_prescaler[0] = 0;
chip->eg_step[0] = chip->eg_prescaler[1] >> 1;
chip->eg_clock_delay[0] = (chip->eg_clock_delay[1] << 1) | chip->fsm_clock_eg;
chip->eg_timer_load = chip->eg_step[1] && chip->eg_prescaler_clock_l[1];
sum = (chip->eg_timer[1] >> 11) & 1;
add = chip->eg_timer_carry[1];
if ((chip->eg_prescaler[1] & 2) != 0 && chip->eg_prescaler_clock_l[1])
add = 1;
sum += add;
chip->eg_timer_carry[0] = sum >> 1;
sum &= 1;
if (chip->input.ic || (chip->mode_test_21[1] & 32) != 0)
sum = 0;
chip->eg_timer[0] = (chip->eg_timer[1] << 1) | sum;
timer_bit = sum;
if (chip->mode_test_2c[1] & 64)
{
if (chip->mode_test_2c[1] & 128) // Assuming TEST pin is NC
timer_bit |= FMOPN2_ReadTest(chip);
else
timer_bit |= chip->input.test & 1;
}
chip->eg_timer_mask[0] = timer_bit | chip->eg_timer_mask[1];
if (chip->fsm_clock_eg || ((chip->eg_clock_delay[1]>>11) & 1) != 0 || chip->input.ic)
chip->eg_timer_mask[0] = 0;
timer_bit_masked = timer_bit;
if (chip->eg_timer_mask[1])
timer_bit_masked = 0;
chip->eg_timer_masked[0] = (chip->eg_timer_masked[1] << 1) | timer_bit_masked;
for (i = 0; i < 10; i++)
{
level2 |= ((chip->eg_level[i][1] >> 20) & 1) << i;
}
chip->eg_level_latch[0] = level2;
csm_kon = chip->fsm_ch3_sel && chip->timer_csm_key_dlatch;
kon2 = ((chip->mode_kon[3][1] >> 5) & 1) | csm_kon;
chip->eg_kon_latch[0] = (chip->eg_kon_latch[1] << 1) | kon2;
chip->eg_kon_csm[0] = (chip->eg_kon_csm[1] << 1) | csm_kon;
kon = (chip->eg_kon_latch[1] >> 1) & 1;
okon = (chip->eg_key[1] >> 23) & 1;
pg_reset = (kon && !okon) || (chip->eg_ssg_pgreset[1] & 2) != 0;
kon_event = (kon && !okon) || (okon && (chip->eg_ssg_pgrepeat[1] & 2) != 0);
chip->pg_reset[0] = (chip->pg_reset[1] << 1) | pg_reset;
if (chip->eg_ssg_pgreset[1] & 2)
chip->pg_reset[0] |= 1;
chip->eg_key[0] = (chip->eg_key[1] << 1) | kon;
okon2 = (chip->eg_key[1] >> 21) & 1;
for (i = 0; i < 4; i++)
ssg_eg |= ((chip->slot_ssg_eg[bank][i][1] >> 11) & 1) << i;
ssg_enable = (ssg_eg & 8) != 0;
ssg_inv_e = ssg_enable && (ssg_eg & 4) != 0;
if (ssg_enable)
{
if (okon2)
{
ssg_dir = (chip->eg_ssg_dir[1] >> 23) & 1;
if (level2 & 512)
{
if ((ssg_eg & 3) == 2)
ssg_dir ^= 1;
if ((ssg_eg & 3) == 3)
ssg_dir = 1;
}
}
if (kon2)
ssg_holdup = (ssg_eg & 7) == 3 || (ssg_eg & 7) == 5;
if (level2 & 512)
{
if ((ssg_eg & 3) == 0)
ssg_pgreset = 1;
if ((ssg_eg & 1) == 0)
ssg_pgrepeat = 1;
}
}
ssg_inv = okon2 & (((chip->eg_ssg_dir[1] >> 23) & 1) ^ ssg_inv_e);
chip->eg_ssg_dir[0] = (chip->eg_ssg_dir[1] << 1) | ssg_dir;
chip->eg_ssg_inv[0] = ssg_inv;
chip->eg_ssg_holdup[0] = (chip->eg_ssg_holdup[1] << 1) | ssg_holdup;
chip->eg_ssg_enable[0] = (chip->eg_ssg_enable[1] << 1) | ssg_enable;
chip->eg_ssg_pgreset[0] = (chip->eg_ssg_pgreset[1] << 1) | ssg_pgreset;
chip->eg_ssg_pgrepeat[0] = (chip->eg_ssg_pgrepeat[1] << 1) | ssg_pgrepeat;
chip->eg_level_ssg[0] = eg_output = chip->eg_ssg_inv[1] ? chip->eg_level_latch_inv : chip->eg_level_latch[1];
if (chip->mode_test_21[1] & 32)
eg_output = 0;
for (i = 0; i < 4; i++)
sl |= ((chip->slot_sl[bank][i][1] >> 11) & 1) << i;
if (sl == 15)
sl |= 16;
chip->eg_sl[0][0] = sl;
chip->eg_sl[1][0] = chip->eg_sl[0][1];
for (i = 0; i < 7; i++)
tl |= ((chip->slot_tl[bank][i][1] >> 11) & 1) << i;
chip->eg_tl[0][0] = tl;
chip->eg_tl[1][0] = chip->eg_tl[0][1];
b0 = (chip->eg_state[0][1] >> 21) & 1;
b1 = (chip->eg_state[1][1] >> 21) & 1;
rate_sel = b1 * 2 + b0;
if (okon2)
{
if (ssg_pgrepeat)
rate_sel = eg_state_attack;
}
else
{
if (kon2)
rate_sel = eg_state_attack;
}
switch (rate_sel)
{
case eg_state_attack:
for (i = 0; i < 5; i++)
rate |= ((chip->slot_ar[bank][i][1] >> 11) & 1) << i;
break;
case eg_state_decay:
for (i = 0; i < 5; i++)
rate |= ((chip->slot_dr[bank][i][1] >> 11) & 1) << i;
break;
case eg_state_sustain:
for (i = 0; i < 5; i++)
rate |= ((chip->slot_sr[bank][i][1] >> 11) & 1) << i;
break;
case eg_state_release:
rate = 1;
for (i = 0; i < 4; i++)
rate |= ((chip->slot_rr[bank][i][1] >> 11) & 1) << (i + 1);
break;
}
chip->eg_rate_nonzero[0] = rate != 0;
chip->eg_rate = rate;
for (i = 0; i < 2; i++)
ks |= ((chip->slot_ks[bank][i][1] >> 11) & 1) << i;
chip->eg_ksv = chip->pg_kcode[0][1] >> (ks ^ 3);
rate = chip->eg_rate2;
if (rate & 64)
rate = 63;
sum = (rate >> 2) + chip->eg_shift_lock;
inc1 = 0;
if (rate < 48 && chip->eg_rate_nonzero[1])
{
switch (sum & 15)
{
case 12:
inc1 = rate != 0;
break;
case 13:
inc1 = (rate >> 1) & 1;
break;
case 14:
inc1 = rate & 1;
break;
}
}
chip->eg_inc1 = inc1;
chip->eg_inc2 = eg_stephi[rate & 3][chip->eg_timer_low_lock];
chip->eg_rate12 = (rate & 60) == 48;
chip->eg_rate13 = (rate & 60) == 52;
chip->eg_rate14 = (rate & 60) == 56;
chip->eg_rate15 = (rate & 60) == 60;
chip->eg_maxrate[0] = (rate & 62) == 62;
chip->eg_prescaler_l = (chip->eg_prescaler[1] & 2) != 0;
chip->eg_incsh_nonzero[0] = chip->eg_incsh0 | chip->eg_incsh1 | chip->eg_incsh2 | chip->eg_incsh3;
if (okon && !kon)
{
level = chip->eg_level_ssg[1];
}
else
{
for (i = 0; i < 10; i++)
{
level |= ((chip->eg_level[i][1] >> 22) & 1) << i;
}
}
b0 = (chip->eg_state[0][1] >> 23) & 1;
b1 = (chip->eg_state[1][1] >> 23) & 1;
state = b1 * 2 + b0;
exp = kon && (state == eg_state_attack) && !chip->eg_maxrate[1] && level != 0;
eg_off = (chip->eg_ssg_enable[1] & 2) != 0 ? (level & 512) != 0 : (level & 0x3f0) == 0x3f0;
eg_slreach = (level >> 4) == (chip->eg_sl[1][1] << 1);
linear = !kon_event && !eg_off && (state == eg_state_sustain || state == eg_state_release);
linear |= !kon_event && !eg_off && !eg_slreach && state == eg_state_decay;
if (exp)
{
if (chip->eg_incsh0)
inc_total |= ~level >> 4;
if (chip->eg_incsh1)
inc_total |= ~level >> 3;
if (chip->eg_incsh2)
inc_total |= ~level >> 2;
if (chip->eg_incsh3)
inc_total |= ~level >> 1;
}
if (linear)
{
if (chip->eg_ssg_enable[1] & 2)
{
if (chip->eg_incsh0)
inc_total |= 4;
if (chip->eg_incsh1)
inc_total |= 8;
if (chip->eg_incsh2)
inc_total |= 16;
if (chip->eg_incsh3)
inc_total |= 32;
}
else
{
if (chip->eg_incsh0)
inc_total |= 1;
if (chip->eg_incsh1)
inc_total |= 2;
if (chip->eg_incsh2)
inc_total |= 4;
if (chip->eg_incsh3)
inc_total |= 8;
}
}
chip->eg_inc_total = inc_total;
istantattack = chip->eg_maxrate[1] && (!chip->eg_maxrate[1] || kon_event);
if (!istantattack)
nextlevel |= level;
if (chip->eg_kon_csm[1] & 2)
nextlevel |= chip->eg_tl[1][1] << 3;
if ((!kon_event && eg_off && (chip->eg_ssg_holdup[1] & 2) == 0 && state != eg_state_attack) || chip->input.ic)
{
nextlevel = 0x3ff;
nextstate |= eg_state_release;
}
if (!kon_event && state == eg_state_sustain)
{
nextstate |= eg_state_sustain;
}
if (!kon_event && state == eg_state_decay && !eg_slreach)
{
nextstate |= eg_state_decay;
}
if (!kon_event && state == eg_state_decay && eg_slreach)
{
nextstate |= eg_state_sustain;
}
if (!kon && !kon_event)
{
nextstate |= eg_state_release;
}
if (!kon_event && state == eg_state_release)
{
nextstate |= eg_state_release;
}
if (!kon_event && state == eg_state_attack && level == 0)
{
nextstate |= eg_state_decay;
}
if (chip->input.ic)
{
nextstate |= eg_state_release;
}
chip->eg_nextlevel[0] = nextlevel;
b0 = nextstate & 1;
b1 = (nextstate >> 1) & 1;
chip->eg_state[0][0] = (chip->eg_state[0][1] << 1) | b0;
chip->eg_state[1][0] = (chip->eg_state[1][1] << 1) | b1;
nextlevel = chip->eg_nextlevel[1];
for (i = 0; i < 10; i++)
{
chip->eg_level[i][0] = (chip->eg_level[i][1] << 1) | (nextlevel & 1);
nextlevel >>= 1;
}
if (chip->slot_am[bank][0][1] & (1<<11))
for (i = 0; i < 2; i++)
ams |= ((chip->chan_ams[i][1] >> 5) & 1) << i;
chip->eg_ams = ams;
if (chip->lfo_dlatch & 64)
chip->eg_lfo[0] = chip->lfo_dlatch & 63;
else
chip->eg_lfo[0] = chip->lfo_dlatch ^ 63;
chip->eg_ch3_latch[0] = chip->fsm_ch3_sel;
chip->eg_out_tl = chip->eg_tl[0][1];
if (chip->eg_ch3_latch[1] && chip->mode_ch3[1] == 2) // CSM
chip->eg_out_tl = 0;
chip->eg_out = eg_output + chip->eg_lfo[1];
chip->eg_debug[0] = chip->eg_debug[1] << 1;
if (chip->fsm_sel2)
chip->eg_debug[0] |= chip->eg_out_total;
}
void FMOPN2_EnvelopeGenerator2(fmopn2_t *chip)
{
int i;
int b0, b1, b2, b3;
static const int eg_am_shift[4] = {
7, 3, 1, 0
};
chip->eg_prescaler_clock_l[1] = chip->eg_prescaler_clock_l[0];
chip->eg_prescaler[1] = chip->eg_prescaler[0] & 3;
chip->eg_step[1] = chip->eg_step[0];
chip->eg_timer[1] = chip->eg_timer[0];
chip->eg_clock_delay[1] = chip->eg_clock_delay[0];
chip->eg_timer_carry[1] = chip->eg_timer_carry[0];
chip->eg_timer_mask[1] = chip->eg_timer_mask[0];
chip->eg_timer_masked[1] = chip->eg_timer_masked[0];
if (!chip->eg_timer_load && chip->eg_step[1] && chip->eg_prescaler_clock_l[1])
{
b0 = (chip->eg_timer[1] >> 11) & 1;
b1 = (chip->eg_timer[1] >> 10) & 1;
chip->eg_timer_low_lock = b1 * 2 + b0;
b0 = (chip->eg_timer_masked[1] & 0xaaa) != 0;
b1 = (chip->eg_timer_masked[1] & 0x666) != 0;
b2 = (chip->eg_timer_masked[1] & 0x1e1) != 0;
b3 = (chip->eg_timer_masked[1] & 0x1f) != 0;
chip->eg_shift_lock = b3 * 8 + b2 * 4 + b1 * 2 + b0;
}
chip->eg_rate_nonzero[1] = chip->eg_rate_nonzero[0];
chip->eg_rate2 = (chip->eg_rate << 1) + chip->eg_ksv;
chip->eg_maxrate[1] = chip->eg_maxrate[0];
chip->eg_incsh0 = 0;
chip->eg_incsh1 = 0;
chip->eg_incsh2 = 0;
chip->eg_incsh3 = 0;
if (chip->eg_prescaler_l)
{
chip->eg_incsh0 = chip->eg_inc1;
chip->eg_incsh3 = chip->eg_rate15;
if (!chip->eg_inc2)
{
chip->eg_incsh0 |= chip->eg_rate12;
chip->eg_incsh1 = chip->eg_rate13;
chip->eg_incsh2 = chip->eg_rate14;
}
else
{
chip->eg_incsh1 = chip->eg_rate12;
chip->eg_incsh2 = chip->eg_rate13;
chip->eg_incsh3 |= chip->eg_rate14;
}
}
chip->eg_incsh_nonzero[1] = chip->eg_incsh_nonzero[0];
chip->eg_kon_latch[1] = chip->eg_kon_latch[0];
chip->eg_level_ssg[1] = chip->eg_level_ssg[0];
chip->pg_reset[1] = chip->pg_reset[0];
chip->eg_ssg_dir[1] = chip->eg_ssg_dir[0];
chip->eg_ssg_inv[1] = chip->eg_ssg_inv[0];
chip->eg_ssg_holdup[1] = chip->eg_ssg_holdup[0];
chip->eg_ssg_enable[1] = chip->eg_ssg_enable[0];
chip->eg_ssg_pgreset[1] = chip->eg_ssg_pgreset[0];
chip->eg_ssg_pgrepeat[1] = chip->eg_ssg_pgrepeat[0];
chip->eg_level_latch[1] = chip->eg_level_latch[0];
chip->eg_level_latch_inv = (512 - chip->eg_level_latch[0]) & 0x3ff;
chip->eg_sl[0][1] = chip->eg_sl[0][0];
chip->eg_sl[1][1] = chip->eg_sl[1][0];
chip->eg_tl[0][1] = chip->eg_tl[0][0];
chip->eg_tl[1][1] = chip->eg_tl[1][0];
chip->eg_nextlevel[1] = chip->eg_nextlevel[0] + chip->eg_inc_total;
chip->eg_kon_csm[1] = chip->eg_kon_csm[0];
for (i = 0; i < 10; i++)
{
chip->eg_level[i][1] = chip->eg_level[i][0];
}
chip->eg_state[0][1] = chip->eg_state[0][0];
chip->eg_state[1][1] = chip->eg_state[1][0];
chip->eg_lfo[1] = (chip->eg_lfo[0] << 1) >> eg_am_shift[chip->eg_ams];
chip->eg_ch3_latch[1] = chip->eg_ch3_latch[0];
chip->eg_out_total = (chip->eg_out & 1023) + (chip->eg_out_tl << 3);
if ((chip->eg_out & 1024) != 0 || (chip->eg_out_total & 1024) != 0)
chip->eg_out_total = 1023;
chip->eg_debug[1] = chip->eg_debug[0];
chip->eg_key[1] = chip->eg_key[0];
}
void FMOPN2_Operator1(fmopn2_t *chip)
{
int i;
int carry = 0;
int phase = 0;
int quarter;
int index;
int atten = 0;
int output;
int mod1 = 0, mod2 = 0;
int mod;
int fb = 0;
static const int logsin[128] = {
0x6c3, 0x58b, 0x4e4, 0x471, 0x41a, 0x3d3, 0x398, 0x365, 0x339, 0x311, 0x2ed, 0x2cd, 0x2af, 0x293, 0x279, 0x261,
0x24b, 0x236, 0x222, 0x20f, 0x1fd, 0x1ec, 0x1dc, 0x1cd, 0x1be, 0x1b0, 0x1a2, 0x195, 0x188, 0x17c, 0x171, 0x166,
0x15b, 0x150, 0x146, 0x13c, 0x133, 0x129, 0x121, 0x118, 0x10f, 0x107, 0x0ff, 0x0f8, 0x0f0, 0x0e9, 0x0e2, 0x0db,
0x0d4, 0x0cd, 0x0c7, 0x0c1, 0x0bb, 0x0b5, 0x0af, 0x0a9, 0x0a4, 0x09f, 0x099, 0x094, 0x08f, 0x08a, 0x086, 0x081,
0x07d, 0x078, 0x074, 0x070, 0x06c, 0x068, 0x064, 0x060, 0x05c, 0x059, 0x055, 0x052, 0x04e, 0x04b, 0x048, 0x045,
0x042, 0x03f, 0x03c, 0x039, 0x037, 0x034, 0x031, 0x02f, 0x02d, 0x02a, 0x028, 0x026, 0x024, 0x022, 0x020, 0x01e,
0x01c, 0x01a, 0x018, 0x017, 0x015, 0x014, 0x012, 0x011, 0x00f, 0x00e, 0x00d, 0x00c, 0x00a, 0x009, 0x008, 0x007,
0x007, 0x006, 0x005, 0x004, 0x004, 0x003, 0x002, 0x002, 0x001, 0x001, 0x001, 0x001, 0x000, 0x000, 0x000, 0x000
};
static const int logsin_d[128] = {
0x196, 0x07c, 0x04a, 0x035, 0x029, 0x022, 0x01d, 0x019, 0x015, 0x013, 0x012, 0x00f, 0x00e, 0x00d, 0x00d, 0x00c,
0x00b, 0x00a, 0x00a, 0x009, 0x009, 0x009, 0x008, 0x007, 0x007, 0x007, 0x007, 0x006, 0x007, 0x006, 0x006, 0x005,
0x005, 0x005, 0x005, 0x005, 0x004, 0x005, 0x004, 0x004, 0x005, 0x004, 0x004, 0x003, 0x004, 0x003, 0x003, 0x003,
0x003, 0x004, 0x003, 0x003, 0x003, 0x003, 0x003, 0x003, 0x003, 0x002, 0x003, 0x003, 0x003, 0x003, 0x002, 0x002,
0x002, 0x002, 0x002, 0x002, 0x002, 0x002, 0x002, 0x002, 0x002, 0x002, 0x002, 0x001, 0x002, 0x002, 0x002, 0x001,
0x001, 0x001, 0x002, 0x002, 0x001, 0x001, 0x002, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001, 0x001,
0x001, 0x001, 0x001, 0x000, 0x001, 0x000, 0x001, 0x000, 0x001, 0x001, 0x000, 0x000, 0x001, 0x001, 0x001, 0x001,
0x000, 0x000, 0x000, 0x001, 0x000, 0x000, 0x001, 0x000, 0x001, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000
};
static const int pow[128] = {
0x3f5, 0x3ea, 0x3df, 0x3d4, 0x3c9, 0x3bf, 0x3b4, 0x3a9, 0x39f, 0x394, 0x38a, 0x37f, 0x375, 0x36a, 0x360, 0x356,
0x34c, 0x342, 0x338, 0x32e, 0x324, 0x31a, 0x310, 0x306, 0x2fd, 0x2f3, 0x2e9, 0x2e0, 0x2d6, 0x2cd, 0x2c4, 0x2ba,
0x2b1, 0x2a8, 0x29e, 0x295, 0x28c, 0x283, 0x27a, 0x271, 0x268, 0x25f, 0x257, 0x24e, 0x245, 0x23c, 0x234, 0x22b,
0x223, 0x21a, 0x212, 0x209, 0x201, 0x1f9, 0x1f0, 0x1e8, 0x1e0, 0x1d8, 0x1d0, 0x1c8, 0x1c0, 0x1b8, 0x1b0, 0x1a8,
0x1a0, 0x199, 0x191, 0x189, 0x181, 0x17a, 0x172, 0x16b, 0x163, 0x15c, 0x154, 0x14d, 0x146, 0x13e, 0x137, 0x130,
0x129, 0x122, 0x11b, 0x114, 0x10c, 0x106, 0x0ff, 0x0f8, 0x0f1, 0x0ea, 0x0e3, 0x0dc, 0x0d6, 0x0cf, 0x0c8, 0x0c2,
0x0bb, 0x0b5, 0x0ae, 0x0a8, 0x0a1, 0x09b, 0x094, 0x08e, 0x088, 0x082, 0x07b, 0x075, 0x06f, 0x069, 0x063, 0x05d,
0x057, 0x051, 0x04b, 0x045, 0x03f, 0x039, 0x033, 0x02d, 0x028, 0x022, 0x01c, 0x016, 0x011, 0x00b, 0x006, 0x000,
};
static const int pow_d[128] = {
0x005, 0x005, 0x005, 0x006, 0x006, 0x005, 0x005, 0x005, 0x005, 0x005, 0x005, 0x005, 0x005, 0x006, 0x005, 0x005,
0x005, 0x005, 0x005, 0x005, 0x005, 0x005, 0x005, 0x005, 0x005, 0x005, 0x005, 0x005, 0x005, 0x005, 0x004, 0x005,
0x004, 0x004, 0x005, 0x005, 0x005, 0x005, 0x005, 0x005, 0x005, 0x005, 0x004, 0x004, 0x004, 0x005, 0x004, 0x005,
0x004, 0x004, 0x004, 0x005, 0x004, 0x004, 0x005, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004,
0x004, 0x003, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x004, 0x003, 0x004, 0x004, 0x004,
0x003, 0x003, 0x003, 0x003, 0x004, 0x003, 0x003, 0x003, 0x003, 0x003, 0x004, 0x004, 0x003, 0x003, 0x004, 0x003,
0x003, 0x003, 0x003, 0x003, 0x003, 0x003, 0x004, 0x003, 0x003, 0x003, 0x003, 0x003, 0x003, 0x003, 0x003, 0x003,
0x003, 0x003, 0x003, 0x003, 0x003, 0x003, 0x003, 0x003, 0x002, 0x003, 0x003, 0x003, 0x003, 0x003, 0x002, 0x003,
};
for (i = 0; i < 10; i++)
{
carry += (chip->op_mod[i][1] >> 5) & 1;
carry += (chip->pg_phase[10 + i][1] >> 19) & 1;
phase += (carry & 1) << i;
carry >>= 1;
}
chip->op_phase[0] = phase;
chip->op_sign[0] = (chip->op_sign[1] << 1) | ((chip->op_phase[1] >> 9) & 1);
quarter = chip->op_phase[1] & 255;
if (chip->op_phase[1] & 256)
quarter ^= 255;
chip->op_logsin_add_delta[0] = (quarter & 1) == 0;
chip->op_logsin_base[0] = logsin[quarter >> 1];
chip->op_logsin_delta[0] = logsin_d[quarter >> 1];
chip->op_env[0] = chip->eg_out_total;
atten = chip->op_logsin_base[1];
if (chip->op_logsin_add_delta[1])
atten += chip->op_logsin_delta[1];
atten += chip->op_env[1] << 2;
chip->op_atten[0] = atten;
atten = chip->op_atten[1];
if (atten & 4096)
atten = 4095;
index = atten & 255;
chip->op_shift[0] = atten >> 8;
chip->op_pow_add_delta[0] = (index & 1) == 0;
chip->op_pow_base[0] = pow[index >> 1];
chip->op_pow_delta[0] = pow_d[index >> 1];
output = chip->op_pow_base[1];
if (chip->op_pow_add_delta[1])
output += chip->op_pow_delta[1];
output |= 0x400;
output = (output << 2) >> chip->op_shift[1];
if (chip->mode_test_21[1] & 16)
output ^= 1 << 13;
if (chip->op_sign[1] & 4)
{
output ^= 0x3fff;
output++;
}
chip->op_output[0] = output;
for (i = 0; i < 14; i++)
{
chip->op_op1[0][i][0] = chip->op_op1[0][i][1] << 1;
chip->op_op1[1][i][0] = chip->op_op1[1][i][1] << 1;
chip->op_op2[i][0] = chip->op_op2[i][1] << 1;
if (chip->fsm_op1_sel)
{
chip->op_op1[0][i][0] |= (chip->op_output[1] >> i) & 1;
chip->op_op1[1][i][0] |= (chip->op_op1[0][i][1] >> 5) & 1;
}
else
{
chip->op_op1[0][i][0] |= (chip->op_op1[0][i][1] >> 5) & 1;
chip->op_op1[1][i][0] |= (chip->op_op1[1][i][1] >> 5) & 1;
}
if (chip->fsm_op2_sel)
chip->op_op2[i][0] |= (chip->op_output[1] >> i) & 1;
else
chip->op_op2[i][0] |= (chip->op_op2[i][1] >> 5) & 1;
}
if (chip->alg_mod_op1_0)
{
for (i = 0; i < 14; i++)
mod2 |= ((chip->op_op1[0][i][1] >> 5) & 1) << i;
}
if (chip->alg_mod_op1_1)
{
for (i = 0; i < 14; i++)
mod1 |= ((chip->op_op1[1][i][1] >> 5) & 1) << i;
}
if (chip->alg_mod_op2)
{
for (i = 0; i < 14; i++)
mod1 |= ((chip->op_op2[i][1] >> 5) & 1) << i;
}
if (chip->alg_mod_prev_0)
{
mod2 |= chip->op_output[1];
}
if (chip->alg_mod_prev_1)
{
mod1 |= chip->op_output[1];
}
if (mod1 & (1 << 13))
mod1 |= 1 << 14;
if (mod2 & (1 << 13))
mod2 |= 1 << 14;
mod = (mod1 + mod2) >> 1;
mod &= 0x3fff;
chip->op_mod_sum[0] = mod;
chip->op_dofeedback[0] = chip->fsm_op2_sel;
if (chip->op_dofeedback[1])
{
for (i = 0; i < 3; i++)
fb |= (chip->chan_fb[i][1] & 1) << i;
if (!fb)
mod = 0;
else
{
mod = chip->op_mod_sum[1];
if (mod & (1 << 13))
mod |= ~0x3fff;
mod = mod >> (9 - fb);
}
}
else
mod = chip->op_mod_sum[1];
for (i = 0; i < 10; i++)
{
chip->op_mod[i][0] = (chip->op_mod[i][1] << 1) | (mod & 1);
mod >>= 1;
}
}
void FMOPN2_Operator2(fmopn2_t *chip)
{
int i;
for (i = 0; i < 10; i++)
{
chip->op_mod[i][1] = chip->op_mod[i][0];
}
for (i = 0; i < 14; i++)
{
chip->op_op1[0][i][1] = chip->op_op1[0][i][0];
chip->op_op1[1][i][1] = chip->op_op1[1][i][0];
chip->op_op2[i][1] = chip->op_op2[i][0];
}
chip->op_phase[1] = chip->op_phase[0];
chip->op_sign[1] = chip->op_sign[0];
chip->op_logsin_add_delta[1] = chip->op_logsin_add_delta[0];
chip->op_logsin_base[1] = chip->op_logsin_base[0];
chip->op_logsin_delta[1] = chip->op_logsin_delta[0];
chip->op_env[1] = chip->op_env[0];
chip->op_atten[1] = chip->op_atten[0];
chip->op_pow_add_delta[1] = chip->op_pow_add_delta[0];
chip->op_pow_base[1] = chip->op_pow_base[0];
chip->op_pow_delta[1] = chip->op_pow_delta[0];
chip->op_shift[1] = chip->op_shift[0];
chip->op_output[1] = chip->op_output[0];
chip->op_mod_sum[1] = chip->op_mod_sum[0];
chip->op_dofeedback[1] = chip->op_dofeedback[0];
}
void FMOPN2_YM3438Accumulator1(fmopn2_t *chip)
{
int i;
int sum;
int inp = 0;
int acc = 0;
int test_dac = (chip->mode_test_2c[1] & 32) != 0;
int load = test_dac || chip->fsm_op1_sel;
int acc_clear = load && !test_dac;
sum = test_dac;
if (chip->alg_output && !test_dac)
inp = (chip->op_output[1] >> 5) & 511;
if (!acc_clear)
for (i = 0; i < 9; i++)
acc += ((chip->ch_accm[i][1] >> 5) & 1) << i;
sum = test_dac + inp + acc;
sum &= 511;
if ((inp & 256) != 0 && (acc & 256) != 0 && (sum & 256) == 0)
sum = 256;
else if ((inp & 256) == 0 && (acc & 256) == 0 && (sum & 256) != 0)
sum = 255;
for (i = 0; i < 9; i++)
chip->ch_accm[i][0] = (chip->ch_accm[i][1] << 1) | ((sum >> i) & 1);
for (i = 0; i < 9; i++)
{
chip->ch_out[i][0] = chip->ch_out[i][1] << 1;
if (load)
chip->ch_out[i][0] |= (chip->ch_accm[i][1] >> 5) & 1;
else
chip->ch_out[i][0] |= (chip->ch_out[i][1] >> 5) & 1;
}
chip->ch_dac_load = chip->fsm_dac_load;
chip->ch_out_debug[0] = chip->ch_out_dlatch;
}
void FMOPN2_YM3438Accumulator2(fmopn2_t* chip)
{
int i;
int test_dac = (chip->mode_test_2c[1] & 32) != 0;
int do_out = 0;
int sign;
int out;
for (i = 0; i < 9; i++)
{
chip->ch_accm[i][1] = chip->ch_accm[i][0];
chip->ch_out[i][1] = chip->ch_out[i][0];
}
if ((chip->fsm_dac_load && !chip->ch_dac_load) || test_dac)
{
chip->ch_out_dlatch = 0;
if (chip->fsm_dac_out_sel || test_dac)
{
for (i = 0; i < 9; i++)
chip->ch_out_dlatch |= ((chip->ch_out[i][1] >> 5) & 1) << i;
}
else
{
for (i = 0; i < 9; i++)
chip->ch_out_dlatch |= ((chip->ch_out[i][1] >> 4) & 1) << i;
}
}
if ((chip->fsm_dac_ch6 && chip->mode_dac_en[1]) || test_dac)
{
chip->dac_val = chip->mode_dac_data[1] << 1;
chip->dac_val |= (chip->mode_test_2c[1] & 8) != 0;
}
else
chip->dac_val = chip->ch_out_dlatch;
if (chip->fsm_dac_load && !chip->ch_dac_load)
{
chip->ch_out_pan_dlatch = 0;
if (chip->fsm_dac_out_sel)
{
for (i = 0; i < 2; i++)
chip->ch_out_pan_dlatch |= (((chip->chan_pan[i][1] >> 5) & 1) ^ 1) << i;
}
else
{
for (i = 0; i < 2; i++)
chip->ch_out_pan_dlatch |= (((chip->chan_pan[i][1] >> 4) & 1) ^ 1) << i;
}
}
do_out = test_dac || !chip->fsm_dac_load;
if (do_out && (chip->ch_out_pan_dlatch & 2) != 0)
chip->out_l = chip->dac_val;
else
chip->out_l = 0;
if (do_out && (chip->ch_out_pan_dlatch & 1) != 0)
chip->out_r = chip->dac_val;
else
chip->out_r = 0;
if (chip->out_l & 256)
chip->out_l |= ~0x1ff;
if (chip->out_r & 256)
chip->out_r |= ~0x1ff;
chip->ch_out_debug[1] = chip->ch_out_debug[0];
}
void FMOPN2_YMF276Accumulator1(fmopn2_t *chip)
{
int i;
int sum1;
int sum2;
int sum;
int inp = 0;
int accm = 0;
int acc = 0;
int c;
int test_dac = (chip->mode_test_2c[1] & 32) != 0;
int test_dac2 = (chip->mode_test_2c[1] & 8) != 0;
int load = test_dac || chip->fsm_op1_sel;
int acc_clear = load && !test_dac;
int sel_dac = (chip->fsm_op1_sel_l2[1] & 16) != 0 && chip->fsm_op1_sel && chip->mode_dac_en[1];
int sel_fm = chip->fsm_op1_sel && !sel_dac;
int out = 0;
int pan = 0;
int acc_l = 0;
int acc_r = 0;
chip->osc_out = 0;
for (i = 0; i < 14; i++)
accm += ((chip->ch_accm[i][1] >> 5) & 1) << i;
if (chip->alg_output && !test_dac)
inp = chip->op_output[1] & 0x3fff;
if (test_dac2)
inp = 0x3fff;
if (!acc_clear)
acc = accm;
sum1 = (acc & 31) + (inp & 31) + (test_dac && !test_dac2);
c = ((sum1 & 32) != 0 || test_dac) && !test_dac2;
sum2 = (acc >> 5) + (inp >> 5) + c;
sum = ((sum2 & 511) << 5) | (sum1 & 31);
if ((inp & 0x2000) != 0 && (acc & 0x2000) != 0 && (sum & 0x2000) == 0)
sum = 0x2000;
else if ((inp & 0x2000) == 0 && (acc & 0x2000) == 0 && (sum & 0x2000) != 0)
sum = 0x1fff;
for (i = 0; i < 14; i++)
chip->ch_accm[i][0] = (chip->ch_accm[i][1] << 1) | ((sum >> i) & 1);
for (i = 0; i < 9; i++)
{
chip->ch_out[i][0] = chip->ch_out[i][1] << 1;
if (load)
chip->ch_out[i][0] |= (chip->ch_accm[i+5][1] >> 5) & 1;
else
chip->ch_out[i][0] |= (chip->ch_out[i][1] >> 5) & 1;
}
chip->ch_dac_load = chip->fsm_dac_load;
chip->ch_out_debug[0] = chip->ch_out_dlatch;
chip->fsm_op1_sel_l2[0] = (chip->fsm_op1_sel_l2[1] << 1) | chip->fsm_op1_sel;
chip->fsm_op1_sel_l3[0] = chip->fsm_op1_sel;
if (sel_dac)
chip->osc_out |= chip->mode_dac_data[1] << 6;
if (sel_fm)
chip->osc_out |= accm;
if (chip->osc_out & 0x2000)
chip->osc_out |= 0x1c000;
for (i = 0; i < 2; i++)
pan |= (((chip->chan_pan[i][1] >> 5) & 1) ^ 1) << i;
chip->fsm_shifter_ctrl[0] = chip->fsm_shifter_ctrl[1] << 1;
if (chip->fsm_op1_sel && !chip->fsm_op1_sel_l3[1])
{
acc_l = 0;
acc_r = 0;
chip->fsm_shifter_ctrl[0] |= 1;
}
else
{
acc_l = chip->ch_accm_l[1];
acc_r = chip->ch_accm_r[1];
}
chip->ch_accm_l[0] = acc_l + ((pan & 2) != 0 ? chip->osc_out : 0);
chip->ch_accm_r[0] = acc_r + ((pan & 1) != 0 ? chip->osc_out : 0);
}
void FMOPN2_YMF276Accumulator2(fmopn2_t *chip)
{
int i;
int test_dac = (chip->mode_test_2c[1] & 32) != 0;
for (i = 0; i < 14; i++)
{
chip->ch_accm[i][1] = chip->ch_accm[i][0];
}
for (i = 0; i < 9; i++)
{
chip->ch_out[i][1] = chip->ch_out[i][0];
}
if ((chip->fsm_dac_load && !chip->ch_dac_load) || test_dac)
{
chip->ch_out_dlatch = 0;
if (chip->fsm_dac_out_sel || test_dac)
{
for (i = 0; i < 9; i++)
chip->ch_out_dlatch |= ((chip->ch_out[i][1] >> 5) & 1) << i;
}
else
{
for (i = 0; i < 9; i++)
chip->ch_out_dlatch |= ((chip->ch_out[i][1] >> 4) & 1) << i;
}
}
chip->ch_out_debug[1] = chip->ch_out_debug[0];
chip->fsm_op1_sel_l2[1] = chip->fsm_op1_sel_l2[0];
chip->fsm_op1_sel_l3[1] = chip->fsm_op1_sel_l3[0];
chip->ch_accm_l[1] = chip->ch_accm_l[0];
chip->ch_accm_r[1] = chip->ch_accm_r[0];
chip->fsm_shifter_ctrl[1] = chip->fsm_shifter_ctrl[0];
}
void FMOPN2_Timers1(fmopn2_t *chip)
{
int time;
int test_timers = (chip->mode_test_21[1] & 4) != 0;
int reset;
int subcnt;
if (chip->timer_a_load_latch[1])
time = chip->mode_timer_a_reg[1];
else
time = chip->timer_a_cnt[1];
if ((chip->timer_a_load_dlatch && chip->fsm_clock_timers1) || test_timers)
time++;
reset = chip->mode_timer_a_reset[1] || chip->input.ic;
if (reset)
chip->timer_a_status[0] = 0;
else
chip->timer_a_status[0] = chip->timer_a_status[1] || (chip->timer_a_of[1] && chip->mode_timer_a_enable[1]);
chip->timer_a_load_old[0] = chip->timer_a_load_dlatch;
chip->timer_a_load_latch[0] = (!chip->timer_a_load_old[1] && chip->timer_a_load_dlatch) || chip->timer_a_of[1];
if (!chip->timer_a_load_dlatch)
chip->timer_a_cnt[0] = 0;
else
chip->timer_a_cnt[0] = time;
chip->timer_a_of[0] = (time & 1024) != 0;
subcnt = chip->timer_b_subcnt[1];
if (chip->fsm_clock_timers1)
subcnt++;
if (chip->input.ic)
chip->timer_b_subcnt[0] = 0;
else
chip->timer_b_subcnt[0] = subcnt;
chip->timer_b_subcnt_of[0] = (subcnt & 16) != 0;
if (chip->timer_b_load_latch[1])
time = chip->mode_timer_b_reg[1];
else
time = chip->timer_b_cnt[1];
if ((chip->timer_b_load_dlatch && chip->timer_b_subcnt_of[1]) || test_timers)
time++;
reset = chip->mode_timer_b_reset[1] || chip->input.ic;
if (reset)
chip->timer_b_status[0] = 0;
else
chip->timer_b_status[0] = chip->timer_b_status[1] || (chip->timer_b_of[1] && chip->mode_timer_b_enable[1]);
chip->timer_b_load_old[0] = chip->timer_b_load_dlatch;
chip->timer_b_load_latch[0] = (!chip->timer_b_load_old[1] && chip->timer_b_load_dlatch) || chip->timer_b_of[1];
if (!chip->timer_b_load_dlatch)
chip->timer_b_cnt[0] = 0;
else
chip->timer_b_cnt[0] = time;
chip->timer_b_of[0] = (time & 256) != 0;
chip->timer_dlatch = chip->fsm_clock_timers;
}
void FMOPN2_Timers2(fmopn2_t *chip)
{
int read_enable = chip->input.cs && chip->input.rd && !chip->input.ic;
chip->timer_a_load_latch[1] = chip->timer_a_load_latch[0];
chip->timer_a_load_old[1] = chip->timer_a_load_old[0];
chip->timer_a_cnt[1] = chip->timer_a_cnt[0] & 1023;
chip->timer_a_of[1] = chip->timer_a_of[0];
chip->timer_a_status[1] = chip->timer_a_status[0];
chip->timer_b_subcnt[1] = chip->timer_b_subcnt[0] & 15;
chip->timer_b_subcnt_of[1] = chip->timer_b_subcnt_of[0];
chip->timer_b_load_latch[1] = chip->timer_b_load_latch[0];
chip->timer_b_load_old[1] = chip->timer_b_load_old[0];
chip->timer_b_cnt[1] = chip->timer_b_cnt[0] & 255;
chip->timer_b_of[1] = chip->timer_b_of[0];
chip->timer_b_status[1] = chip->timer_b_status[0];
if (!chip->timer_dlatch && chip->fsm_clock_timers)
{
chip->timer_a_load_dlatch = chip->mode_timer_a_load[1];
chip->timer_b_load_dlatch = chip->mode_timer_b_load[1];
chip->timer_csm_key_dlatch = chip->mode_ch3[1] == 2 && ((!chip->timer_a_load_old[1] && chip->timer_a_load_dlatch) || chip->timer_a_of[1]);
}
if (!read_enable)
{
chip->status_timer_a_dlatch = chip->timer_a_status[1];
chip->status_timer_b_dlatch = chip->timer_b_status[1];
}
}
void FMOPN2_ClockPhase1(fmopn2_t *chip)
{
FMOPN2_DoShiftRegisters(chip, 0);
FMOPN2_HandleIO1(chip);
FMOPN2_FMRegisters1(chip);
FMOPN2_FSM1(chip);
FMOPN2_Misc1(chip);
FMOPN2_LFO1(chip);
FMOPN2_PhaseGenerator1(chip);
FMOPN2_EnvelopeGenerator1(chip);
FMOPN2_Operator1(chip);
if (!(chip->flags & fmopn2_flags_ym3438))
FMOPN2_YMF276Accumulator1(chip);
else
FMOPN2_YM3438Accumulator1(chip);
FMOPN2_Timers1(chip);
}
void FMOPN2_ClockPhase2(fmopn2_t *chip)
{
FMOPN2_DoShiftRegisters(chip, 1);
FMOPN2_HandleIO2(chip);
FMOPN2_FMRegisters2(chip);
FMOPN2_FSM2(chip);
FMOPN2_Misc2(chip);
FMOPN2_LFO2(chip);
FMOPN2_PhaseGenerator2(chip);
FMOPN2_EnvelopeGenerator2(chip);
FMOPN2_Operator2(chip);
if (!(chip->flags & fmopn2_flags_ym3438))
FMOPN2_YMF276Accumulator2(chip);
else
FMOPN2_YM3438Accumulator2(chip);
FMOPN2_Timers2(chip);
}
void FMOPN2_ClockFM(fmopn2_t *chip)
{
FMOPN2_HandleIO(chip);
if (chip->i_phi1)
{
FMOPN2_ClockPhase1(chip);
}
if (chip->i_phi2)
{
FMOPN2_ClockPhase2(chip);
}
}
void FMOPN2_Clock(fmopn2_t *chip, int clk)
{
chip->pinput.phi = clk;
if (memcmp(&chip->pinput, &chip->pinput_old, sizeof(chip->pinput)) != 0)
{
FMOPN2_Prescaler(chip);
chip->pinput_old = chip->pinput;
chip->input.i_fsm_reset = chip->fsm_reset;
if (chip->phi1_latch[1])
chip->input.phi_phase = 1;
if (chip->phi2_latch[1])
chip->input.phi_phase = 2;
chip->i_phi1 = chip->phi1_latch[1];
chip->i_phi2 = chip->phi2_latch[1];
}
if (memcmp(&chip->input, &chip->input_old, sizeof(chip->input)) != 0)
{
FMOPN2_ClockFM(chip);
chip->input_old = chip->input;
}
if (!(chip->flags & fmopn2_flags_ym3438))
FMOPN2_YMF276DAC(chip);
}