/*
 * Copyright (C) 2023-2024 nukeykt
 *
 * This file is part of YM2608-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.
 *
 *  YM2608/YM2610/YM2612 emulator.
 *  Thanks:
 *      Raki (ika-musume):
 *          YM2608B decap
 *      John McMaster (siliconpr0n.org):
 *          YM2610 decap
 *      HardWareMan:
 *          YM2612 decap
 *
 */
// #define FMOPNA_YM2608
// #define FMOPNA_YM2610
// #define FMOPNA_YM2612

#if !defined(FMOPNA_YM2608) && !defined(FMOPNA_YM2610) && !defined(FMOPNA_YM2612)
#error no chip type defined
#endif

typedef struct {
    int clk;
    int ic; // neg
    int cs; // neg
    int wr; // neg
    int rd; // neg
    int a0;
    int a1;
    int data;
    int test; // set to 1
#ifdef FMOPNA_YM2608
    int gpio_a;
    int gpio_b;
    int dt0;
    int dm;
    int ad;
    int da;
#endif
#ifdef FMOPNA_YM2610
    int rad;
    int pad;
#endif
}
#ifdef FMOPNA_YM2608
fmopna_input_t;
#elif defined (FMOPNA_YM2610)
fmopna_2610_input_t;
#else
fmopna_2612_input_t;
#endif

typedef struct {

#ifdef FMOPNA_YM2608
    fmopna_input_t input;
#elif defined (FMOPNA_YM2610)
    fmopna_2610_input_t input;
#else
    fmopna_2612_input_t input;
#endif

    int ic;

    int ic_latch1[2];
    int ic_latch2[2];
    int ic_latch3[2];
    int ic_check1;
    int ic_check3;
    int prescaler_latch[2];
#ifndef FMOPNA_YM2612
    int ic_check2;
#endif
#ifdef FMOPNA_YM2608
    int prescaler_sel[2];
#endif
    int pssel_l[15][2];
    int ic_latch_fm[2];

    int mclk1;
    int mclk2;

    int clk1;
    int clk2;

#ifndef FMOPNA_YM2612
    int aclk1;
    int aclk2;
    int bclk1;
    int bclk2;
    int cclk1;
    int cclk2;

    int dclk;

    int ssg_write0;
    int ssg_write1;
    int ssg_read1;

    int write2;
    int write3;

    int read2;
#endif
#ifdef FMOPNA_YM2608
    int read3;
#endif

    int read0;

    int write0_trig0;
    int write0_trig1;
    int write0_l[3];
    int write0_en;

    int write1_trig0;
    int write1_trig1;
    int write1_l[3];
    int write1_en;

#ifdef FMOPNA_YM2608
    int write2_trig0;
    int write2_trig1;
    int write2_l[3];
    int write2_en;
#endif

#ifndef FMOPNA_YM2612
    int write3_trig0;
    int write3_trig1;
    int write3_l[3];
    int write3_en;
#endif

    int data_l;

    int data_bus1;
    int data_bus2; // inverted

    int read_bus;

#ifdef FMOPNA_YM2608
    int addr_10[2];
    int addr_10h[2];
    int addr_12[2];
#endif
    int addr_21[2];
    int addr_22[2];
    int addr_24[2];
    int addr_25[2];
    int addr_26[2];
    int addr_27[2];
    int addr_28[2];
#ifdef FMOPNA_YM2608
    int addr_29[2];
    int addr_ff[2];
#endif
#ifdef FMOPNA_YM2610
    int addr_00[2];
    int addr_02[2];
    int addr_1c[2];
#endif
#ifdef FMOPNA_YM2612
    int addr_2a[2];
    int addr_2b[2];
    int addr_2c[2];
#endif

#ifdef FMOPNA_YM2608
    int reg_mask[2];
#endif
#ifndef FMOPNA_YM2612
    int reg_test_12[2];
#endif
    int reg_test_21[2];
    int reg_lfo[2];
    int reg_timer_a[2];
    int reg_timer_b[2];
    int reg_ch3[2];
    int reg_timer_a_load[2];
    int reg_timer_b_load[2];
    int reg_timer_a_enable[2];
    int reg_timer_b_enable[2];
    int reg_timer_a_reset[2];
    int reg_timer_b_reset[2];
#ifdef FMOPNA_YM2608
    int reg_sch[2];
    int reg_irq[2];
#endif
#ifdef FMOPNA_YM2610
    int reg_flags[2];
#endif
    int reg_kon_operator[2];
    int reg_kon_channel[2];
#ifdef FMOPNA_YM2612
    int reg_dac_en[2];
    int reg_dac_data[2];
    int reg_test_2c[2];
#endif
    int fm_address[2];
    int fm_data[2];
    int write_fm_address[2];
    int write_fm_data[2]; 
    int reg_cnt1[2];
    int reg_cnt2[2];
    int reg_cnt_sync;
    int reg_key_cnt1[2];
    int reg_key_cnt2[2];
#ifdef FMOPNA_YM2608
    int reg_cnt_rss[2];
    int reg_cnt_rss_of;
    int rss_18;
#endif
    int reg_kon_match;
    int reg_kon[4][2];
    int kon_comb;
    int reg_ch3_sel;
    int ch3_en;
    int ch3_csm;
    int ch3_csm_load;
    int reg_csm_l;
    int reg_sync_timer;
    int reg_sync_timer_l[2];
    int reg_sync_timer_load;

    int timer_a_cnt[2];
    int timer_a_of[2];
    int timer_a_load;
    int timer_a_reg_load;
    int timer_a_reg_load_l[2];
    int timer_a_status[2];
    int timer_b_subcnt[2];
    int timer_b_subcnt_of[2];
    int timer_b_cnt[2];
    int timer_b_of[2];
    int timer_b_load;
    int timer_b_reg_load;
    int timer_b_reg_load_l[2];
    int timer_b_status[2];

#ifndef FMOPNA_YM2612
    int irq_eos_l;
#endif
#ifdef FMOPNA_YM2608
    int irq_mask_eos;
    int irq_mask_brdy;
    int irq_mask_zero;
#endif

    int fm_is30;
    int fm_is40;
    int fm_is50;
    int fm_is60;
    int fm_is70;
    int fm_is80;
    int fm_is90;
    int fm_isa0;
    int fm_isa4;
    int fm_isa8;
    int fm_isac;
    int fm_isb0;
    int fm_isb4;

    int reg_a4[2];
    unsigned short reg_freq[2][6];
    int reg_ac[2];
    unsigned short reg_freq_3ch[2][6];
    unsigned char reg_connect_fb[2][6];
    unsigned char reg_b4[2][6];
    int fnum[4];
    int kcode[4];
    int ch_cnt_sync;
    int ch_cnt1[2];
    int ch_cnt2[2];
#ifdef FMOPNA_YM2608
    unsigned char reg_rss[2][6];
#endif
    unsigned char op_multi_dt[2][12][2];
    unsigned char op_tl[2][12][2];
    unsigned char op_ar_ks[2][12][2];
    unsigned char op_dr_a[2][12][2];
    unsigned char op_sr[2][12][2];
    unsigned char op_rr_sl[2][12][2];
    unsigned char op_ssg[2][12][2];

    int fsm_cnt1[2];
    int fsm_cnt2[2];
    int fsm_out[27];
    int fsm_op1_sel_l;
    int fsm_op2_sel_l;
    int fsm_op3_sel_l;
    int fsm_op4_sel_l;
    int fsm_connect;
    int alg_mod_op1_0_l;
    int alg_mod_op1_1_l;
    int alg_mod_op2_l;
    int alg_mod_prev_0_l;
    int alg_mod_prev_1_l;
    int alg_output_l;
    int alg_do_fb[2];
    int alg_load_fb;
#ifndef FMOPNA_YM2612
    int fsm_rss;
    int fsm_rss2;
#endif
    int fsm_sel0[2];
    int fsm_sel1[2];
    int fsm_sel2[2];
    int fsm_sel23[2];
    int fsm_sel_ch3[2];
#ifndef FMOPNA_YM2612
    int fsm_sel11[2];
    int fsm_sh1[2];
    int fsm_sh2[2];
#endif
#ifdef FMOPNA_YM2612
    int fsm_dac_ch6[2];
    int fsm_dac_load[2];
    int fsm_dac_out_sel[2];
#endif

    int lfo_sync[4];
    int lfo_subcnt[2];
    int lfo_subcnt_of;
    int lfo_cnt_rst;
    int lfo_cnt[2];
#ifdef FMOPNA_YM2608
    int lfo_cnt_of;
    int lfo_mode;
#endif
    int lfo_cnt_load;
    int lfo_fnum1;
    int lfo_fnum2;
    int lfo_shift;
    int lfo_sign;
    int lfo_pm;
    int lfo_fnum;
    int lfo_am;

    int pg_block;
    int pg_freq;
    int pg_dt_multi;
    int pg_dt_add;
    int pg_freqdt[2];
    int pg_multi[5];
    int pg_add[6];
    int pg_reset[4];
    int pg_phase[2][23];
    int pg_phase2[2];
    int pg_out;
    int pg_dbgsync;
#ifdef FMOPNA_YM2610
    int pg_dbgsync_l[2];
#endif
    int pg_dbg[2];
    int dt_add1;
    int dt_add2;
    int dt_enable[2];
    int dt_sum;
    int dt_blockmax[2];
    int dt_note[2];
    int dt_sign[2];

    int eg_sync;
    int eg_prescaler[2];
    int eg_prescaler_clock_l[2];
    int eg_clock_delay[2];
    int eg_ic[2];

    int eg_step[3];
    int eg_timer_step[2];

    int eg_timer[2];
    int eg_timer_sum[2];
    int eg_timer_carry[2];
    int eg_timer_mask[2];
    int eg_timer_masked[2];
    int eg_timer_test;
    int eg_timer_test_bit[2];
    int eg_timer_low_lock;
    int eg_shift_lock;

    int eg_rate_sel;
    int eg_rate_ar;
    int eg_rate_dr;
    int eg_rate_sr;
    int eg_rate_rr;
    int eg_rate;
    int eg_rate_nonzero[3];
    unsigned char eg_state[2][23];
    int eg_ks;
    int eg_ksv;
    int eg_rate2;
    int eg_ratenz;
    int eg_rate12;
    int eg_rate13;
    int eg_rate14;
    int eg_rate15;
    int eg_rate_low;
    int eg_rate_slow;
    int eg_rate_sum;
    int eg_maxrate[2];
    int eg_inc2;
    int eg_incsh0[2];
    int eg_incsh1[2];
    int eg_incsh2[2];
    int eg_incsh3[2];
    int eg_output;
    unsigned short eg_level[2][22];
    int eg_ssg_inv;
    int eg_ssg_enable[2];
    int eg_ssg_sign[2];
    int eg_ssg_holdup[2];
    int eg_ssg_pgreset[2];
    int eg_ssg_dir[2];
    int eg_ssg_egrepeat[2];
    int eg_key[2];
    int eg_kon_latch[2];
    int eg_kon_event;
    int eg_pg_reset[2];
    int eg_sl[2][2];
    int eg_tl[3][2];
    int eg_level_ssg[2];
    int eg_slreach;
    int eg_level_l[2];
    int eg_zeroreach;
    int eg_off;
    int eg_nextstate;
    int eg_state_l;
    int eg_mute;
    int eg_exp;
    int eg_linear;
    int eg_inc_total;
    int eg_nextlevel[2];
    int eg_istantattack;
    int eg_kon_csm[2];
    int eg_am_l[2];
    int eg_am_shift[2];
    int eg_of1;
    int eg_output_lfo;
    int eg_csm_tl;
    int eg_ch3_l[2];
    int eg_out;
    int eg_dbg_sync;
    int eg_debug[2];
    int eg_debug_inc;

    int op_phase1;
    int op_phase2;
    unsigned short op_mod[2][6];
    int op_phase_index;
    int op_sign[2];
    int op_logsin_base;
    int op_logsin_delta;
    int op_eglevel;
    int op_att;
    int op_shift[2];
    int op_pow_base;
    int op_pow_delta;
    int op_pow;
    int op_output[4];
    unsigned short op_op1_0[2][6];
    unsigned short op_op1_1[2][6];
    unsigned short op_op2[2][6];
    int op_loadfb;
    int op_loadop2;
    int op_mod_op1_0;
    int op_mod_op1_1;
    int op_mod_op2;
    int op_mod_prev_0;
    int op_mod_prev_1;
    int op_mod1;
    int op_mod2;
    int op_mod_sum;
    int op_do_fb;
    int op_fb;

#ifndef FMOPNA_YM2612
#ifdef FMOPNA_YM2608
    int ssg_prescaler1[2];
    int ssg_prescaler2[2];
#endif
    int ssg_div1[2];
    int ssg_div2[2];
    int ssg_div3[2];
    int ssg_clk;
    int ssg_clk1;
    int ssg_clk2;
    int ssg_ssg_addr;
    int ssg_address;
    int ssg_freq_a[2];
    int ssg_freq_b[2];
    int ssg_freq_c[2];
    int ssg_noise;
    int ssg_mode;
    int ssg_level_a;
    int ssg_level_b;
    int ssg_level_c;
    int ssg_env[2];
    int ssg_envmode;
    int ssg_envadd;
    int ssg_envcnt[2];
    int ssg_dir[2];
    int ssg_hold[2];
    int ssg_t2[2];
    int ssg_egtrig;
    int ssg_egtrig_s;
    int ssg_egtrig_rst;
    int ssg_eg_sel_l;
    int ssg_sel[2];
    int ssg_sel_freq;
    int ssg_freq_cnt[8];
    int ssg_cnt_of[2];
    int ssg_sign[2];
    int ssg_sign_toggle;
    int ssg_cnt_of_l;
    int ssg_freq_cnt2[8];
    int ssg_sel_freq_l;
    int ssg_cnt2_add;
    int ssg_sel_eg_l[2];
    int ssg_ch_of;
    int ssg_cnt_reload;
    int ssg_eg_of[2];
    int ssg_fr_rst_l;
    int ssg_noise_add;
    int ssg_noise_cnt[2];
    int ssg_noise_of_low;
    int ssg_noise_of;
    int ssg_test;
    int ssg_noise_step;
    int ssg_noise_lfsr[2];
    int ssg_noise_bit;


    int rss_cnt1[2];
    int rss_cnt1_sync;

    int rss_eclk1_l;
    int rss_eclk2_l;
    int rss_eclk1;
    int rss_eclk2;
    int rss_dclk_l;
    int rss_fclk_sel[2];
    int rss_fclk1;
    int rss_fclk2;
    int rss_cnt2[2];
    int rss_fmcnt[2];
    int rss_fmcnt_of;
    int rss_fmcnt_sync;
    int rss_params[2];
    int rss_tl_sel[2];
    int rss_tl[2];
    int rss_keydm[2];
    int rss_keymask[2];
    int rss_ic[2];
    int rss_key[2];
    int rss_stop[2];
    int rss_eos_l;
#ifdef FMOPNA_YM2608
    int rss_step;
    int rss_isend;
#endif

#ifdef FMOPNA_YM2610
    int rss_address[2];
    int rss_address_wr[2];
    int rss_data[2];
    int rss_data_wr[2];
    int rss_write08;
    int rss_write10;
    int rss_write18;
    int rss_write20;
    int rss_write28;
    unsigned char rss_reg_pan_tl[2][6];
    unsigned char rss_reg_start_l[2][6];
    unsigned char rss_reg_start_h[2][6];
    unsigned char rss_reg_stop_l[2][6];
    unsigned char rss_reg_stop_h[2][6];
    int rss_fm_match_l;
    int rss_params_start[3];
    int rss_params_start_h;
    int rss_params_stop[3];
    int rss_eos_load;
    int rss_rmpx[2];
    int rss_roe[4];
    int rss_rad_bus;
    int rss_stop_flag[2];
#endif

    int rss_accum[2];
    int rss_regs[2][17];

    int rss_delta_ix_load;
    int rss_delta_ix;
    int rss_ix_load;
    int rss_ix;
    int rss_cnt1_is1;
    int rss_nibble;
    int rss_tl_l;
    int rss_tl_shift[3];

    int rss_sample_load;
    int rss_sample;
    int rss_multi_ctrl[2];
    int rss_multi_accum[2];
    int rss_multi_accum_load;
    int rss_sample_multi;
    int rss_sample_shift_load;
    int rss_sample_shift;
    int rss_dbg_load;
    int rss_dbg_data;

    int rss_pan[3];

#ifdef FMOPNA_YM2608
    int ad_is6;
    int ad_is7;
    int ad_is8;
    int ad_isc;
    int ad_isd;
    int ad_ise;
    int ad_isf;
    int ad_reg_limit_l;
    int ad_reg_limit_h;
    int ad_reg_prescale_l;
    int ad_reg_prescale_h;
    int ad_reg_spoff;
    int ad_reg_memdata;
    int ad_reg_rec;
    int ad_reg_rom;
    int ad_reg_ramtype;
    int ad_reg_da_ad;
    int ad_reg_sample;
    int ad_sample_l[3];
    int ad_read_port_l[2];
    int ad_write_port_l[2];
    int ad_rw_l[2];
    int ad_rw_en;
    int ad_rec_start_l[2];
    int ad_limit_match[2];
    int ad_limit_match2[2];
    int ad_mem_sync[2];
    int ad_mem_sync_run;
    int ad_mem_ptr_store;
    int ad_mem_data_l1;
    int ad_mem_data_l2;
    int ad_mem_addr_bank;
    int ad_mem_data_bus;
    int ad_mem_bit_cnt[2];
    int ad_mem_shift_cnt0_l[2];
    int ad_brdy_set_l[2];
    int ad_mem_rw_en[2];
    int ad_mem_ucnt[2];
    int ad_mem_w22;
    int ad_dsp_ctrl10_l;
    int ad_dsp_alu_neg[2];
    int ad_ad_cnt1[2];
    int ad_ad_cmp_i;
    int ad_ad_shift;
    int ad_ad_w53[2];
    int ad_ad_w55;
    int ad_ad_w55_l[2];
    int ad_ad_w56;
    int ad_ad_buf;
    int ad_ad_input;
    int ad_ad_cnt2[2];
    int ad_ad_w57[3];
    int ad_ad_w58[3]; // sh2
    int ad_ad_w60;
    int ad_ad_w61[2]; // opo
    int ad_ad_w62[2];
    int ad_ad_w65_l;
    int ad_ad_w66[2];
    int ad_ad_w68;
    int ad_ad_cnt3[2];
    int ad_ad_cnt3_load;
    int ad_ad_cnt3_load_val;
    int ad_ad_cnt3_of[2];
    int ad_ad_cnt3_en[2];
    int ad_ad_quiet;
    int ad_comp_da;
    int ad_dsp_enc_bit;
    int ad_dsp_enc_bit_l[2];
    int ad_mem_we[2];
    int ad_mem_cas[2];
    int ad_mem_ras[2];
#else
    int ad_mem_pmpx[2];
    int ad_mem_poe[2];
#endif
    int ad_is0;
    int ad_is1;
    int ad_is2;
    int ad_is3;
    int ad_is4;
    int ad_is5;
    int ad_is9;
    int ad_isa;
    int ad_isb;
    int ad_reg_reset;
    int ad_reg_repeat;
    int ad_reg_start;
    int ad_reg_r;
    int ad_reg_l;
    int ad_reg_delta_l;
    int ad_reg_delta_h;
    int ad_reg_start_l;
    int ad_reg_start_h;
    int ad_reg_stop_l;
    int ad_reg_stop_h;
    int ad_reg_level;
    int ad_code_ptr[2];
    int ad_code_ctrl;
    int ad_code_ctrl_l;
    int ad_w2[2];
    int ad_w4[2];
    int ad_start_l[3];
    int ad_w2_l[2];
    int ad_code_end[2];
    int ad_addr_isend_l;
    int ad_addr_isend_l2[2];
    int ad_mem_ctrl;
    int ad_mem_ctrl_l;
    int ad_mem_code_ptr[2];
    int ad_end_sel[2];
    int ad_stop_match[2];
    int ad_stop_match2[2];
    int ad_start_sel[2];
    int ad_address_cnt[4][2];
    int ad_address_carry[2];
    int ad_mem_cond[2];
    int ad_mem_bus;
    int ad_mem_data_l3;
    int ad_mem_data_l4[2];
    int ad_mem_w7[2];
    int ad_mem_shift_cnt[2];
    int ad_mem_nibble;
    int ad_mem_w8[2];
    int ad_mem_nibble_msb;
    int ad_mem_nibble_load;
    int ad_mem_mem_en_l[2];
    int ad_code_ed_end[2];
    int ad_mem_mem_stop[2];
    int ad_mem_w10[2];
    int ad_w12[2];
    int ad_w13[2];
    int ad_mem_w15[2];
    int ad_mem_w17[2];
    int ad_mem_w20[2];
    int ad_mem_w21;
    int ad_mode6_l[2];
    int ad_dsp_bus;
    int ad_dsp_ctrl;
    int ad_dsp_delta_sel[2];
    int ad_dsp_w30_l[2];
    int ad_dsp_w31_l[2];
    int ad_dsp_w32;
    int ad_dsp_w32_l;
    int ad_dsp_w33;
    int ad_dsp_w34;
    int ad_dsp_w36[2];
    int ad_dsp_w35_l;
    int ad_dsp_cnt1[2];
    int ad_dsp_cnt1_run[2];
    int ad_dsp_mul_accm1[2];
    int ad_dsp_mul_accm1_add1;
    int ad_dsp_mul_accm1_add2;
    int ad_dsp_mul_accm1_c;
    int ad_dsp_mul_accm2;
    int ad_dsp_mul_accm2_add1;
    int ad_dsp_mul_accm2_add2;
    int ad_dsp_mul_accm2_load;
    int ad_dsp_w38[2];
    int ad_dsp_w40;
    int ad_dsp_w41[2];
    int ad_dsp_w43[2];
    int ad_dsp_w45;
    int ad_dsp_w46[2];
    int ad_output;
    int ad_dsp_cnt2[2];
    int ad_dsp_load_alu1[2];
    int ad_dsp_load_alu1_h;
    int ad_dsp_load_alu2[2];
    int ad_dsp_alu_in1;
    int ad_dsp_alu_in2;
    int ad_dsp_load_res[2];
    int ad_dsp_alu_res;
    int ad_dsp_alu_shift;
    int ad_dsp_alu_mask[2];
    int ad_dsp_carry_mode[2];
    int ad_dsp_alu_of;
    int ad_dsp_read_res[2];
    int ad_code_sync[3];
    int ad_dsp_w52[2];
    int ad_code_reg_id;
    int ad_dsp_regs[8];
    int ad_dsp_regs_o;
    int ad_set_eos;
    int ad_dsp_vol_o[2];
    int ad_dsp_sregs2[2][2];
    int ad_dsp_w69[2];
    int ad_mem_dir;

#ifdef FMOPNA_YM2608
    int ad_da_data;
    int ac_da_shift[2];
    int ac_da_w70[2];
    int ac_da_set[2];
    int opo_da[2];
    int opo_ad;
#endif

    int ac_fm_output;
    int ac_fm_output_en;
    int ac_fm_pan;
    int ac_fm_accm1[2];
    int ac_da_sync2;
    int ac_ad_output;
    int ac_da_sync;
    int ac_da_sync3[2];
    int ac_fm_accm2[2];
    int ac_rss_sum_l;
    int ac_rss_sum_r;
    int ac_rss_accm1[2];
    int ac_rss_accm2[2];
    int ac_rss_load;
    int ac_shifter[2];
    int ac_shifter_load_l;
    int ac_shifter_load_r;
    int ac_shifter_bit;
    int ac_shifter_top;
    int ac_opo;
    int sh1_l;
    int sh2_l;
    int opo_fm;

    int last_rss_sample;
#endif

    int busy_cnt[2];
    int busy_cnt_en[2];
    int status_timer_a;
    int status_timer_b;
    int eg_dbg;
#ifdef FMOPNA_YM2608
    int status_brdy;
    int status_zero;
    int brdy_flag;
    int zero_flag;
    int zero_set;
#endif
#ifdef FMOPNA_YM2610
    int flag_rss_0;
    int flag_rss_1;
    int flag_rss_2;
    int flag_rss_3;
    int flag_rss_4;
    int flag_rss_5;
    int status_rss_0;
    int status_rss_1;
    int status_rss_2;
    int status_rss_3;
    int status_rss_4;
    int status_rss_5;
#endif

#ifndef FMOPNA_YM2612
    int status_eos;
    int eos_flag;
    int eos_l[2];
    int eos_repeat;
#endif

#ifdef FMOPNA_YM2612
    int ch_op_output;
    int ch_op_add;
    int ch_accm_load;
    short ch_accm[2][6];
    short ch_buf[2][6];
    int ch_output;
    int ch_load[2];
    int ch_sel;
    int ch_dbg[2];
    int ch_ch6;
    int ch_pan;
    int o_mol;
    int o_mor;
    int o_test;
    int o_test_d;
#endif

#ifdef FMOPNA_YM2608
    int o_gpio_a;
    int o_gpio_a_d;
    int o_gpio_b;
    int o_gpio_b_d;
    int o_spoff;
    int o_a8;
    int o_romcs; // neg
    int o_mden;
    int o_we; // neg
    int o_cas; // neg
    int o_ras; // neg
    int o_dm;
    int o_dm_d;
#endif

#ifdef FMOPNA_YM2610
    int o_rmpx;
    int o_roe; // neg
    int o_rad;
    int o_rad_d;
    int o_ra8;
    int o_ra20;

    int o_pmpx;
    int o_poe; // neg
    int o_pad;
    int o_pad_d;
    int o_pa8;

    int ym2610b;
#endif

#ifndef FMOPNA_YM2612
    float o_analog;
    float o_analog_ch[3];
    int o_sh1;
    int o_sh2;
    int o_opo;
    int o_s;
#endif
    int o_irq_pull;
    int o_data;
    int o_data_d;

    int tm_w1;
}
#ifdef FMOPNA_YM2608
fmopna_t;
#elif defined (FMOPNA_YM2610)
fmopna_2610_t;
#else
fmopna_2612_t;
#endif

#ifdef FMOPNA_YM2608
void FMOPNA_Clock(fmopna_t* chip, int clk);
#elif defined (FMOPNA_YM2610)
void FMOPNA_2610_Clock(fmopna_2610_t* chip, int clk);
#else
void FMOPNA_2612_Clock(fmopna_2612_t* chip, int clk);
#endif

