-
Notifications
You must be signed in to change notification settings - Fork 6
/
fm.h
353 lines (318 loc) · 7.82 KB
/
fm.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
/*
* Copyright (C) 2022-2023 nukeykt
*
* This file is part of Nuked-MD.
*
* 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.
*
* YM3438 emulator.
* Thanks:
* John McMaster (siliconpr0n.org):
* Yamaha YM3438 & YM2610 decap and die shot.
* org, andkorzh, HardWareMan (emu-russia):
* help & support, YM2612 decap.
*
*/
#pragma once
#include <stdint.h>
#pragma pack(push, 1)
enum {
fm_flags_ym2612 = 1,
};
typedef struct {
int phi;
int ic;
} fm_prescaler_input_t;
typedef struct {
fm_prescaler_input_t input, input_old;
// clock
int ic_latch[2]; // 12
int ic_check_latch[2]; // 4
int prescaler_latch[2]; // 6
int phi1_latch[2];
int phi2_latch[2];
} fm_prescaler_t;
typedef struct {
int phi_phase;
int ic;
int rd;
int wr;
int cs;
int address;
int data;
int test;
int i_fsm_reset; // (chip->ic_check_latch[1] & 16) != 0;
} fm_input_t;
typedef struct {
int flags;
// input
fm_input_t input_old, input;
int i_phi1;
int i_phi2;
fm_prescaler_t prescaler;
// output
int dac_val;
int out_l;
int out_r;
// io
int write_addr_trig;
int write_addr_trig_sync;
int write_addr_dlatch;
int write_addr_sr[2];
int write_data_trig;
int write_data_trig_sync;
int write_data_dlatch;
int write_data_sr[2];
int data_latch;
int bank_latch;
int busy_cnt[2];
int busy_latch[2];
int io_ic_latch[2];
int write_fm_address[2];
int fm_address[2];
int write_fm_data[2];
int fm_data[2];
int status_timer_a_dlatch;
int status_timer_b_dlatch;
// mode registers
int write_mode_21[2];
int write_mode_22[2];
int write_mode_24[2];
int write_mode_25[2];
int write_mode_26[2];
int write_mode_27[2];
int write_mode_28[2];
int write_mode_2a[2];
int write_mode_2b[2];
int write_mode_2c[2];
int mode_test_21[2];
int mode_lfo_en[2];
int mode_lfo_freq[2];
int mode_timer_a_reg[2];
int mode_timer_b_reg[2];
int mode_ch3[2];
int mode_timer_a_load[2];
int mode_timer_a_enable[2];
int mode_timer_a_reset[2];
int mode_timer_b_load[2];
int mode_timer_b_enable[2];
int mode_timer_b_reset[2];
int mode_kon_operator[2];
int mode_kon_channel[2];
int mode_dac_data[2];
int mode_dac_en[2];
int mode_test_2c[2];
int mode_kon[4][2];
// operator registers
int slot_multi[2][4][2];
int slot_dt[2][3][2];
int slot_tl[2][7][2];
int slot_ar[2][5][2];
int slot_ks[2][2][2];
int slot_dr[2][5][2];
int slot_am[2][1][2];
int slot_sr[2][5][2];
int slot_rr[2][4][2];
int slot_sl[2][4][2];
int slot_ssg_eg[2][4][2];
// channel registers
int chan_fnum[11][2];
int chan_fnum_ch3[11][2];
int chan_block[3][2];
int chan_block_ch3[3][2];
int chan_a4[2];
int chan_ac[2];
int chan_connect[3][2];
int chan_fb[3][2];
int chan_pms[3][2];
int chan_ams[2][2];
int chan_pan[2][2];
int reg_cnt1[2];
int reg_cnt2[2];
// lfo
int lfo_cnt1[2];
int lfo_cnt2[2];
int lfo_dlatch;
int lfo_dlatch_load;
int lfo_inc_latch[2];
// pg
int pg_fnum[2][2];
int pg_kcode[2][2];
int pg_fnum_lfo1;
int pg_fnum_lfo2;
int pg_lfo_shift;
int pg_lfo_sign;
int pg_lfo;
int pg_freq1;
int pg_freq2;
int pg_freq3;
int pg_freq4;
int pg_freq5[2];
int pg_freq6;
int pg_freq_m1;
int pg_block;
int pg_dt[2];
int pg_detune[2];
int pg_multi[2][2];
int pg_multi2;
int pg_inc[2];
int pg_inc_mask[2];
int pg_phase[20][2];
int pg_reset_latch[2];
int pg_debug[2];
int pg_reset[2];
// eg
int eg_prescaler[2];
int eg_prescaler_clock_l[2];
int eg_prescaler_l;
int eg_clock_delay[2];
int eg_step[2];
int eg_timer_load;
int eg_timer[2];
int eg_timer_carry[2];
int eg_timer_mask[2];
int eg_timer_masked[2];
int eg_timer_low_lock;
int eg_shift_lock;
int eg_level[10][2];
int eg_level_latch[2];
int eg_level_latch_inv;
int eg_state[2][2];
int eg_ssg_dir[2];
int eg_ssg_inv[2];
int eg_ssg_holdup[2];
int eg_ssg_enable[2];
int eg_ssg_pgreset[2];
int eg_ssg_pgrepeat[2];
int eg_key[2];
int eg_rate_nonzero[2];
int eg_rate;
int eg_ksv;
int eg_rate2;
int eg_inc1;
int eg_inc2;
int eg_rate12;
int eg_rate13;
int eg_rate14;
int eg_rate15;
int eg_maxrate[2];
int eg_incsh0;
int eg_incsh1;
int eg_incsh2;
int eg_incsh3;
int eg_incsh_nonzero[2];
int eg_inc_total;
int eg_level_ssg[2];
int eg_sl[2][2];
int eg_nextlevel[2];
int eg_kon_csm[2];
int eg_kon_latch[2];
int eg_tl[2][2];
int eg_ams;
int eg_lfo[2];
int eg_ch3_latch[2];
int eg_out;
int eg_out_tl;
int eg_out_total;
int eg_debug[2];
// op
int op_mod[10][2];
int op_phase[2];
int op_logsin_base[2];
int op_logsin_delta[2];
int op_logsin_add_delta[2];
int op_atten[2];
int op_env[2];
int op_pow_base[2];
int op_pow_delta[2];
int op_pow_add_delta[2];
int op_shift[2];
int op_sign[2];
int op_output[2];
int op_op1[2][14][2];
int op_op2[14][2];
int op_mod_sum[2];
int op_dofeedback[2];
// accumulator
int ch_accm[9][2];
int ch_out[9][2];
int ch_out_dlatch;
int ch_out_pan_dlatch;
int ch_dac_load;
int ch_out_debug[2];
// timers
int timer_dlatch;
int timer_a_cnt[2];
int timer_a_load_latch[2];
int timer_a_load_old[2];
int timer_a_load_dlatch;
int timer_a_of[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_load_latch[2];
int timer_b_load_old[2];
int timer_b_load_dlatch;
int timer_b_of[2];
int timer_b_status[2];
int timer_csm_key_dlatch;
// fm algorithm
int alg_mod_op1_0;
int alg_mod_op1_1;
int alg_mod_op2;
int alg_mod_prev_0;
int alg_mod_prev_1;
int alg_output;
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;
// fsm
int fsm_cnt1[2];
int fsm_cnt2[2];
// fsm table output
int fsm_clock_eg;
int fsm_clock_timers1;
int fsm_clock_timers;
int fsm_op4_sel;
int fsm_op1_sel;
int fsm_op2_sel;
int fsm_op3_sel;
int fsm_sel2;
int fsm_sel23;
int fsm_ch3_sel;
int fsm_dac_load;
int fsm_dac_out_sel;
int fsm_dac_ch6;
// ym2612 FSM
int fsm_out[26];
int fsm_op4_sel_l;
int fsm_op1_sel_l;
int fsm_op2_sel_l;
int fsm_op3_sel_l;
int fsm_clock_eg_l;
int fsm_clock_timers1_l;
int fsm_clock_timers_l;
int fsm_sel23_l;
int fsm_ch3_sel_l;
int fsm_dac_ch6_l;
int fsm_dac_load_l;
int fsm_dac_out_sel_l;
int status_time;
int last_status;
} fm_t;
#pragma pack(pop)
int FM_ReadStatus(fm_t *chip);
void FM_Prescaler2(fm_prescaler_t *chip, int clk);
void FM_Clock2(fm_t *chip, int phi1, int phi2);